如果我們要寫跨平台的c/c++**,很多時候需要處理由於不同編譯器對c/c++各個標準支援力度不同導致的相容性問題,一般通常的解決辦法是:自己在**中通過巨集去判斷各個編譯器的版本、內建巨集、標準庫巨集、__has_feature
等來檢測處理。
自己如果在**中按上述的方式檢測,會很繁瑣,尤其是像c++這種存在大量語法特性,如果一一檢測過來,工作量是非常大的。
通過構建工具預先檢測編譯特性
另外比較省事的方式,就是依賴構建工具提前做好檢測,然後把檢測結果作為巨集新增到編譯中去,這樣**只需要判斷對應的特性巨集是否存在,就可以進行處理了。
在cmake中就有類似的檢測機制,非常強大,因此xmake也對其進行了支援,提供更加靈活強大的編譯器特性預先檢測支援:
target("test")
on_load(function (target)
import("core.tool.compiler")
if compiler.has_features("cxx_constexpr") then
target:add("defines", "has_cxx_constexpr=1")
endend)
通過core.tool.compiler
模組的compiler.has_features介面,在xmake.lua
中預先判斷當前編譯期支援的語言特性,實現條件編譯。
上述**,在載入target的時候,判斷當前編譯器是否支援c++的常量表示式語法特性,如果支援則新增巨集定義:has_cxx_constexpr=1
。
我們也可以在判斷時候,追加一些引數控制編譯選項,例如上述特性需要c++11
支援,我們可以啟用它:
if compiler.has_features(, ) then
-- ok
end
通過上面的**可以看到,此介面是可以同時檢測多個特性的,返回值為實際支援的特性列表。
如果之前對這個target已經設定了c++11
,那麼我們也可以傳入target物件,繼承target的所有設定,甚至指定一些其他擴充套件編譯配置:
if compiler.has_features("cxx_constexpr", ) then
-- ok
end
批量編譯器特性檢測
c++的語言特性非常多,這個時候我們可以通過指令碼實現快速的批量檢測:
target("test")
on_load(function (target)
import("core.tool.compiler")
for feature, _ in pairs(compiler.features("cxx", )) do -- 傳入target在檢測特性時繼承target的所有編譯配置
target:add("defines", "has_feature_" .. feature)
endend)
上述**,會在載入target的時候,把當前編譯器對c++的所有支援特性,都新增到target的巨集定義中進行編譯,例如:-dhas_feature_cxx_constexpr
。
我們只需要在**中,通過判斷對應的特性巨集是否存在就行了:
#ifdef has_feature_cxx_constexpr
// todo
#endif
目前支援的所有c/c++編譯器特性列表,見:compiler.features
更加底層的檢測介面
如果我們要指定獲取具體哪個編譯器的特性支援,則需要更加底層的介面支援了,例如:
import("lib.detect.has_features")
local features = has_features("clang", "cxx_constexpr")
local features = has_features("clang", , , program = "xcrun -sdk macosx clang"})
local features = has_features("clang", , )
lib.detect.has_features屬於探測模組的介面,可以指定需要檢測的工具名,例如這裡通過傳入clang,只對clang編譯器進行檢測。
當然此介面,還可以檢測其他非編譯器的工具特性,更加的通用。
通過自定義c/c++**片段來檢測特性
對於一些複雜的編譯器特性,連compiler.has_features都無法檢測到的時候,可以通過自定義**片段嘗試編譯來檢測它。
import("lib.detect.check_cxsnippets")
local ok = check_cxsnippets("constexpr int f(int x) constexpr int x = f(5); static_assert(x == 15);", )
上述**通過自定義乙個constexpr的測試**,去檢測c++11的constexpr支援。
此介面是detect.has_cfuncs, detect.has_cincludes和detect.has_ctypes等介面的通用版本,也更加底層。
因此我們可以用它來檢測:types, functions, includes 還有 links,或者是組合起來一起檢測。
第乙個引數為**片段列表,一般用於一些自定義特性的檢測,如果為空,則可以僅僅檢測可選引數中條件,例如:
local ok = check_cxsnippets(", "void test2() {}"}, , includes = "stdio.h", funcs = })
上面那個呼叫,會去同時檢測types, includes和funcs是否都滿足,如果通過返回true。
原文出處:
Java編譯器與雙鎖檢測
jre5 public class lazysingleton2 return m instance getinstance class 在上面的下劃線處會出現問題。無法保證編譯器為物件分配記憶體之後,是直接將物件的引用賦值給m instance 還是將物件初始化之後才將引用賦值給 m instan...
如何檢測編譯器的大小端
大端模式 所謂的大端模式,是指資料的高位,儲存在記憶體的低位址中,而資料的低位,儲存在記憶體的高位址中,這樣的儲存模式有點兒類似於把資料當作字串順序處理 位址由小向大增加,而資料從高位往低位放 小端模式 所謂的小端模式,是指資料的高位儲存在記憶體的高位址中,而數 據的低位儲存在記憶體的低位址中,這種...
GCC編譯器的使用
看下面的例子 test.c include main char str i like linux i advices you jion in the linux world printf s n str exit 0 使用gcc編譯 輸入gcc c test.c得到目標檔案test.o。c命令表示對...