summaryrefslogtreecommitdiff
path: root/xmake/modules/core
diff options
context:
space:
mode:
authorruki <[email protected]>2025-01-25 00:59:17 +0800
committerruki <[email protected]>2025-01-25 00:59:17 +0800
commit35677f50e4eb8ecb5aabe70e6ce900e28fd0adc2 (patch)
treef88df0f22e606bc8bf4361f13059bd3cb00ab0ed /xmake/modules/core
parentd1b1492b07d370f9cf06414490fc489c1dda6ed8 (diff)
move has_flags.lua
Diffstat (limited to 'xmake/modules/core')
-rw-r--r--xmake/modules/core/tools/ar/has_flags.lua82
-rw-r--r--xmake/modules/core/tools/armasm64_msvc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/armasm_msvc/has_flags.lua97
-rw-r--r--xmake/modules/core/tools/armclang/has_flags.lua128
-rw-r--r--xmake/modules/core/tools/circle/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/cl/cfeatures.lua49
-rw-r--r--xmake/modules/core/tools/cl/cxxfeatures.lua151
-rw-r--r--xmake/modules/core/tools/cl/features.lua140
-rw-r--r--xmake/modules/core/tools/cl/has_flags.lua119
-rw-r--r--xmake/modules/core/tools/cl2000/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/cl6x/has_flags.lua121
-rw-r--r--xmake/modules/core/tools/clang/cfeatures.lua58
-rw-r--r--xmake/modules/core/tools/clang/cxxfeatures.lua132
-rw-r--r--xmake/modules/core/tools/clang/features.lua44
-rw-r--r--xmake/modules/core/tools/clang/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/clang_cl/has_flags.lua101
-rw-r--r--xmake/modules/core/tools/clangxx/features.lua23
-rw-r--r--xmake/modules/core/tools/clangxx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/cosmocc/has_flags.lua143
-rw-r--r--xmake/modules/core/tools/cosmocxx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/dmd/has_flags.lua119
-rw-r--r--xmake/modules/core/tools/dpcpp/cfeatures.lua22
-rw-r--r--xmake/modules/core/tools/dpcpp/cxxfeatures.lua22
-rw-r--r--xmake/modules/core/tools/dpcpp/features.lua22
-rw-r--r--xmake/modules/core/tools/dpcpp/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/emcc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/emxx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/fpc/has_flags.lua98
-rw-r--r--xmake/modules/core/tools/gcc/cfeatures.lua52
-rw-r--r--xmake/modules/core/tools/gcc/cxxfeatures.lua222
-rw-r--r--xmake/modules/core/tools/gcc/features.lua130
-rw-r--r--xmake/modules/core/tools/gcc/has_flags.lua134
-rw-r--r--xmake/modules/core/tools/gccgo/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/gdc/has_flags.lua118
-rw-r--r--xmake/modules/core/tools/gfortran/has_flags.lua117
-rw-r--r--xmake/modules/core/tools/go/has_flags.lua130
-rw-r--r--xmake/modules/core/tools/gxx/features.lua23
-rw-r--r--xmake/modules/core/tools/gxx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/icc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/icl/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/icpc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/icpx/features.lua23
-rw-r--r--xmake/modules/core/tools/icpx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/icx/cfeatures.lua22
-rw-r--r--xmake/modules/core/tools/icx/cxxfeatures.lua22
-rw-r--r--xmake/modules/core/tools/icx/features.lua22
-rw-r--r--xmake/modules/core/tools/icx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/ifort/has_flags.lua27
-rw-r--r--xmake/modules/core/tools/ifx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/ldc2/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/link/has_flags.lua121
-rw-r--r--xmake/modules/core/tools/ml/has_flags.lua105
-rw-r--r--xmake/modules/core/tools/ml64/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/nim/has_flags.lua98
-rw-r--r--xmake/modules/core/tools/nvc/features.lua23
-rw-r--r--xmake/modules/core/tools/nvc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/nvcc/has_flags.lua161
-rw-r--r--xmake/modules/core/tools/nvcxx/features.lua23
-rw-r--r--xmake/modules/core/tools/nvcxx/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/nvfortran/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/rc/has_flags.lua68
-rw-r--r--xmake/modules/core/tools/rustc/has_flags.lua116
-rw-r--r--xmake/modules/core/tools/sdcc/has_flags.lua123
-rw-r--r--xmake/modules/core/tools/swift_frontend/has_flags.lua22
-rw-r--r--xmake/modules/core/tools/swiftc/has_flags.lua101
-rw-r--r--xmake/modules/core/tools/tcc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/zig/has_flags.lua114
-rw-r--r--xmake/modules/core/tools/zig_cc/features.lua23
-rw-r--r--xmake/modules/core/tools/zig_cc/has_flags.lua23
-rw-r--r--xmake/modules/core/tools/zig_cxx/features.lua23
-rw-r--r--xmake/modules/core/tools/zig_cxx/has_flags.lua23
71 files changed, 4409 insertions, 0 deletions
diff --git a/xmake/modules/core/tools/ar/has_flags.lua b/xmake/modules/core/tools/ar/has_flags.lua
new file mode 100644
index 000000000..d4742e6e2
--- /dev/null
+++ b/xmake/modules/core/tools/ar/has_flags.lua
@@ -0,0 +1,82 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.ar.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = nil
+ try
+ {
+ function () os.runv(opt.program, {"--help"}) end,
+ catch
+ {
+ function (errors) arglist = errors end
+ }
+ }
+ if arglist then
+ local found = false
+ for arg in arglist:gmatch("%-r %[%-(%a+)%]") do
+ arg:gsub("%a", function (ch) allflags["-" .. ch] = true; allflags["-r" .. ch] = true; allflags["-" .. ch .. "r"] = true end)
+ found = true
+ end
+ if found then
+ allflags["-r"] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+
+ -- ok?
+ return allflags[flags[1]]
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+ return _check_from_arglist(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/armasm64_msvc/has_flags.lua b/xmake/modules/core/tools/armasm64_msvc/has_flags.lua
new file mode 100644
index 000000000..8fbab3d9f
--- /dev/null
+++ b/xmake/modules/core/tools/armasm64_msvc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.armasm_msvc.has_flags")
+
diff --git a/xmake/modules/core/tools/armasm_msvc/has_flags.lua b/xmake/modules/core/tools/armasm_msvc/has_flags.lua
new file mode 100644
index 000000000..f2aa5abed
--- /dev/null
+++ b/xmake/modules/core/tools/armasm_msvc/has_flags.lua
@@ -0,0 +1,97 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.armasm.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]:gsub("/", "-")]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "armasm_has_flags.asm")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, [[
+END]])
+ end
+
+ -- check it
+ local errors = nil
+ return try { function ()
+ local _, errs = os.iorunv(opt.program, table.join(flags, "-o", os.nuldev(), sourcefile), {envs = opt.envs})
+ if errs and #errs:trim() > 0 then
+ return false, errs
+ end
+ return true
+ end,
+ catch { function (errs) errors = errs end }
+ }, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/armclang/has_flags.lua b/xmake/modules/core/tools/armclang/has_flags.lua
new file mode 100644
index 000000000..0c358e10a
--- /dev/null
+++ b/xmake/modules/core/tools/armclang/has_flags.lua
@@ -0,0 +1,128 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ local has_target
+ for _, v in ipairs(argv) do
+ if v:startswith("-target=") then
+ has_target = true
+ break
+ end
+ end
+ if not has_target then
+ table.insert(argv, 1, "-mcpu=cortex-m3")
+ table.insert(argv, 1, "-target=arm-arm-none-eabi")
+ end
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+ local key = "core.tools.armclang." .. (islinker and "has_ldflags" or "has_cflags")
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = try {function () return os.iorunv(opt.program, {islinker and "-Wl,--help" or "--help"}, {envs = opt.envs}) end}
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ local flag = flags[1]
+ if islinker and flag then
+ if flag:startswith("-Wl,") then
+ flag = flag:match("-Wl,(.-),") or flag:sub(5)
+ end
+ end
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "armclang_has_flags" .. _get_extension(opt))
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}\n")
+ end
+
+ -- check flags for linker
+ local tmpfile = os.tmpfile()
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", tmpfile, sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-c", "-o", tmpfile, sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ opt = opt or {}
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if not opt.tryrun and _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
+
diff --git a/xmake/modules/core/tools/circle/has_flags.lua b/xmake/modules/core/tools/circle/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/circle/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/cl/cfeatures.lua b/xmake/modules/core/tools/cl/cfeatures.lua
new file mode 100644
index 000000000..9b043f7e1
--- /dev/null
+++ b/xmake/modules/core/tools/cl/cfeatures.lua
@@ -0,0 +1,49 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cfeatures.lua
+--
+
+-- set features
+function _set(feature, condition)
+ _g.features = _g.features or {}
+ _g.features[feature] = condition
+end
+
+-- get features
+function main()
+
+ -- init conditions
+ local msvc_minver = "_MSC_VER >= 1200"
+ local msvc_2005 = "_MSC_VER >= 1400"
+ local msvc_2010 = "_MSC_VER >= 1600"
+ local msvc_2019 = "_MSC_VER >= 1920"
+
+ -- set language standard supports
+ _set("c_std_89", msvc_2005)
+ _set("c_std_99", msvc_2019)
+
+ -- set features
+ _set("c_static_assert", msvc_2010)
+ _set("c_restrict", msvc_2005)
+ _set("c_variadic_macros", msvc_2005)
+ _set("c_function_prototypes", msvc_minver)
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/cl/cxxfeatures.lua b/xmake/modules/core/tools/cl/cxxfeatures.lua
new file mode 100644
index 000000000..c8b683e6f
--- /dev/null
+++ b/xmake/modules/core/tools/cl/cxxfeatures.lua
@@ -0,0 +1,151 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxfeatures.lua
+--
+
+-- set features
+function _set(feature, condition)
+ _g.features = _g.features or {}
+ _g.features[feature] = condition
+end
+
+-- get features
+--
+-- Reference: http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx
+-- http://blogs.msdn.com/b/vcblog/archive/2013/06/28/c-11-14-stl-features-fixes-and-breaking-changes-in-vs-2013.aspx
+-- http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx
+-- http://www.visualstudio.com/en-us/news/vs2015-preview-vs.aspx
+-- http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx
+-- http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
+-- https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-160
+--
+-- porting from Modules/Compiler/MSVC-CXX-FeatureTests.cmake
+--
+function main()
+
+ -- init conditions
+ local msvc_minver = "_MSC_VER >= 1200"
+ local msvc_60 = "_MSC_VER >= 1200"
+ local msvc_70 = "_MSC_VER >= 1300"
+ local msvc_71 = "_MSC_VER >= 1310"
+ local msvc_2005 = "_MSC_VER >= 1400"
+ local msvc_2008 = "_MSC_VER >= 1500"
+ local msvc_2010 = "_MSC_VER >= 1600"
+ local msvc_2012 = "_MSC_VER >= 1700"
+ local msvc_2013 = "_MSC_VER >= 1800"
+ local msvc_2015 = "_MSC_VER >= 1900"
+ local msvc_2017 = "_MSC_VER >= 1910"
+ local msvc_2019 = "_MSC_VER >= 1920"
+ local msvc_2022 = "_MSC_VER >= 1930"
+
+ -- set language standard supports
+ _set("cxx_std_98", msvc_2005)
+ _set("cxx_std_11", msvc_2015)
+ _set("cxx_std_14", msvc_2017)
+ _set("cxx_std_17", msvc_2019)
+ _set("cxx_std_20", msvc_2022)
+
+ -- VS version 15 (not 2015) introduces support for aggregate initializers.
+ _set("cxx_aggregate_default_initializers", "_MSC_FULL_VER >= 190024406")
+
+ -- VS 2015 Update 2 introduces support for variable templates.
+ -- https://www.visualstudio.com/en-us/news/vs2015-update2-vs.aspx
+ _set("cxx_variable_templates", "_MSC_FULL_VER >= 190023918")
+
+ _set("cxx_alignas", msvc_2015)
+ _set("cxx_alignof", msvc_2015)
+ _set("cxx_attributes", msvc_2015)
+ _set("cxx_attribute_deprecated", msvc_2015)
+ _set("cxx_binary_literals", msvc_2015)
+ _set("cxx_constexpr", msvc_2015)
+ _set("cxx_decltype_auto", msvc_2015)
+ _set("cxx_digit_separators", msvc_2015)
+ _set("cxx_func_identifier", msvc_2015)
+ _set("cxx_nonstatic_member_init", msvc_2015)
+ _set("cxx_defaulted_move_initializers", msvc_2015)
+ _set("cxx_generic_lambdas", msvc_2015)
+ _set("cxx_inheriting_constructors", msvc_2015)
+ _set("cxx_inline_namespaces", msvc_2015)
+ _set("cxx_lambda_init_captures", msvc_2015)
+ _set("cxx_noexcept", msvc_2015)
+ _set("cxx_return_type_deduction", msvc_2015)
+ _set("cxx_sizeof_member", msvc_2015)
+ _set("cxx_thread_local", msvc_2015)
+ _set("cxx_unicode_literals", msvc_2015)
+ _set("cxx_unrestricted_unions", msvc_2015)
+ _set("cxx_user_literals", msvc_2015)
+ _set("cxx_reference_qualified_functions", msvc_2015)
+
+ -- "The copies and moves don't interact precisely like the Standard says they
+ -- should. For example, deletion of moves is specified to also suppress
+ -- copies, but Visual C++ in Visual Studio 2013 does not."
+ -- http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx
+ -- lists this as 'partial' in 2013
+ _set("cxx_deleted_functions", msvc_2015)
+
+ -- http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx
+ -- Note 1. While previous version of VisualStudio said they supported these
+ -- they silently produced bad code, and are now marked as having partial
+ -- support in previous versions. The footnote says the support will be complete
+ -- in msvc 2015, so support the feature for that version, assuming that is true.
+ -- The blog post also says that VS 2013 Update 3 generates an error in cases
+ -- that previously produced bad code.
+ _set("cxx_generalized_initializers", "_MSC_FULL_VER >= 180030723")
+
+ -- Microsoft now states they support contextual conversions in 2013 and above.
+ -- See footnote 6 at:
+ -- http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx
+ _set("cxx_contextual_conversions", msvc_2013)
+ _set("cxx_default_function_template_args", msvc_2013)
+ _set("cxx_defaulted_functions", msvc_2013)
+ _set("cxx_delegating_constructors", msvc_2013)
+ _set("cxx_explicit_conversions", msvc_2013)
+ _set("cxx_raw_string_literals", msvc_2013)
+ _set("cxx_uniform_initialization", msvc_2013)
+ _set("cxx_alias_templates", msvc_2013)
+
+ -- Support is documented, but possibly partly broken:
+ -- https://msdn.microsoft.com/en-us/library/hh567368.aspx
+ -- http://thread.gmane.org/gmane.comp.lib.boost.devel/244986/focus=245333
+ _set("cxx_variadic_templates", msvc_2013)
+
+ _set("cxx_enum_forward_declarations", msvc_2012)
+ _set("cxx_final", msvc_2012)
+ _set("cxx_range_for", msvc_2012)
+ _set("cxx_strong_enums", msvc_2012)
+
+ _set("cxx_auto_type", msvc_2010)
+ _set("cxx_decltype", msvc_2010)
+ _set("cxx_extended_friend_declarations", msvc_2010)
+ _set("cxx_extern_templates", msvc_2010)
+ _set("cxx_lambdas", msvc_2010)
+ _set("cxx_local_type_template_args", msvc_2010)
+ _set("cxx_long_long_type", msvc_2010)
+ _set("cxx_nullptr", msvc_2010)
+ _set("cxx_override", msvc_2010)
+ _set("cxx_right_angle_brackets", msvc_2010)
+ _set("cxx_rvalue_references", msvc_2010)
+ _set("cxx_static_assert", msvc_2010)
+ _set("cxx_template_template_parameters", msvc_2010)
+ _set("cxx_trailing_return_types", msvc_2010)
+ _set("cxx_variadic_macros", msvc_2010)
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/cl/features.lua b/xmake/modules/core/tools/cl/features.lua
new file mode 100644
index 000000000..0957fd7ed
--- /dev/null
+++ b/xmake/modules/core/tools/cl/features.lua
@@ -0,0 +1,140 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+import("cfeatures")
+import("cxxfeatures")
+
+-- get macro defines
+function _get_macro_defines(snippets, extension, opt)
+
+ -- make an stub source file
+ local sourcefile = os.tmpfile() .. extension
+ local objectfile = sourcefile .. ".obj"
+ local binaryfile = sourcefile .. ".exe"
+ io.writefile(sourcefile, "#include <stdio.h>\n\nint main(int argc, char** argv)\n{\n" .. table.concat(table.wrap(snippets), "\n") .. "\nreturn 0;\n}\n")
+
+ -- get defines
+ local results = {}
+ local defines = try
+ {
+ function ()
+ os.runv(opt.program, table.join(opt.flags or {}, {"-nologo", "-Fo" .. objectfile, sourcefile, "-link", "-out:" .. binaryfile}), {envs = opt.envs})
+ return os.iorunv(binaryfile, {}, {envs = opt.envs})
+ end
+ }
+ if defines then
+ for _, define in ipairs(defines:split("\n")) do
+ results[define] = true
+ end
+ end
+
+ -- remove files
+ os.tryrm(sourcefile)
+ os.tryrm(objectfile)
+ os.tryrm(binaryfile)
+ return results
+end
+
+-- set feature with condition
+function _set_feature(feature, condition)
+
+ -- init features
+ _g.features = _g.features or {}
+
+ -- get feature kind
+ local kind = feature:match("^(%w-)_")
+ assert(kind, "unknown kind for the feature: %s", feature)
+
+ -- init language extensions
+ _g.extensions = _g.extensions or {c = ".c", cxx = ".cpp", objc = ".m", objcxx = ".mm"}
+
+ -- get extension
+ local extension = _g.extensions[kind]
+ assert(extension, "not supported kind for the feature: %s", feature)
+
+ -- make snippet
+ local snippet = format([[
+#if (%s)
+ printf("%s\n");
+#endif]], condition, feature)
+
+ -- init features with the given extension
+ local features = _g.features[extension] or {}
+ _g.features[extension] = features
+
+ -- set feature and snippet
+ features[feature] = snippet
+end
+
+-- set features
+function set_features(features)
+ for feature, condition in pairs(features) do
+ _set_feature(feature, condition)
+ end
+end
+
+-- check features
+function check_features(opt)
+
+ -- check features with all extensions
+ opt = opt or {}
+ local results = {}
+ for extension, features in pairs(_g.features) do
+
+ -- make snippets
+ local snippets = {}
+ for _, snippet in pairs(features) do
+ table.insert(snippets, snippet)
+ end
+
+ -- get defines
+ local defines = _get_macro_defines(snippets, extension, opt)
+
+ -- check features
+ for feature, _ in pairs(features) do
+ if defines[feature] then
+ results[feature] = true
+ end
+ end
+ end
+
+ -- ok?
+ return results
+end
+
+-- get features
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", flags = {}}
+--
+-- @return the features
+--
+function main(opt)
+
+ -- set features for c
+ set_features(cfeatures())
+
+ -- set features for c++
+ set_features(cxxfeatures())
+
+ -- check features
+ return check_features(opt)
+end
+
diff --git a/xmake/modules/core/tools/cl/has_flags.lua b/xmake/modules/core/tools/cl/has_flags.lua
new file mode 100644
index 000000000..d174d84e2
--- /dev/null
+++ b/xmake/modules/core/tools/cl/has_flags.lua
@@ -0,0 +1,119 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.language.language")
+import("core.cache.global_detectcache")
+
+-- attempt to check it from known flags
+function _check_from_knownargs(flags, opt)
+ local flag = flags[1]:gsub("/", "-")
+ if flag:startswith("-D") or
+ flag:startswith("-U") or
+ flag:startswith("-I") then
+ return true
+ end
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+ local key = "core.tools.cl.has_flags"
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = global_detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+ global_detectcache:set2(key, flagskey, allflags)
+ global_detectcache:save()
+ end
+ local flag = flags[1]:gsub("/", "-")
+ if flag:startswith("-D") or flag:startswith("-I") then
+ return true
+ end
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ return opt.flagkind == "cxxflags" and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n"
+ local sourcefile = os.tmpfile("cl_has_flags:" .. snippet) .. _get_extension(opt)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, snippet)
+ end
+
+ -- check it
+ local errors = nil
+ return try { function ()
+ local tmpdir = os.tmpdir()
+ local nuldev = os.nuldev()
+ local tmpfile
+ if not is_host("windows") then
+ tmpfile = os.tmpfile()
+ nuldev = tmpfile
+ end
+ local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. nuldev, sourcefile),
+ {envs = opt.envs, curdir = tmpdir}) -- we need to switch to tmpdir to avoid generating some tmp files, e.g. /Zi -> vc140.pdb
+ if tmpfile then
+ os.tryrm(tmpfile)
+ end
+ if errs and #errs:trim() > 0 then
+ return false, errs
+ end
+ return true
+ end,
+ catch { function (errs) errors = errs end }
+ }, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ opt = opt or {}
+ if not opt.tryrun then
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+ if _check_from_knownargs(flags, opt) then
+ return true
+ end
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/cl2000/has_flags.lua b/xmake/modules/core/tools/cl2000/has_flags.lua
new file mode 100644
index 000000000..5d331d6b1
--- /dev/null
+++ b/xmake/modules/core/tools/cl2000/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.cl6x.has_flags")
+
diff --git a/xmake/modules/core/tools/cl6x/has_flags.lua b/xmake/modules/core/tools/cl6x/has_flags.lua
new file mode 100644
index 000000000..a5f3f4b87
--- /dev/null
+++ b/xmake/modules/core/tools/cl6x/has_flags.lua
@@ -0,0 +1,121 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from known flags
+function _check_from_knownargs(flags, opt, islinker)
+ local flag = flags[1]
+ if not islinker then
+ if flag:startswith("-D") or
+ flag:startswith("-U") or
+ flag:startswith("-I") then
+ return true
+ end
+ end
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+ local key = "core.tools.cl6x." .. (islinker and "has_ldflags" or "has_cflags")
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = try {function () return os.iorunv(opt.program, {"--help"}, {envs = opt.envs}) end}
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ local flag = flags[1]
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n"
+ local sourcefile = os.tmpfile("cl6x_has_flags:" .. snippet) .. _get_extension(opt)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, snippet)
+ end
+
+ -- check flags for linker
+ local tmpfile = os.tmpfile()
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-z", "--output_file=" .. tmpfile, sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-c", "--output_file=" .. tmpfile, sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ opt = opt or {}
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if not opt.tryrun then
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+ if _check_from_knownargs(flags, opt, islinker) then
+ return true
+ end
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/clang/cfeatures.lua b/xmake/modules/core/tools/clang/cfeatures.lua
new file mode 100644
index 000000000..a6d10f6e1
--- /dev/null
+++ b/xmake/modules/core/tools/clang/cfeatures.lua
@@ -0,0 +1,58 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cfeatures.lua
+--
+
+-- imports
+import("core.tools.gcc.cfeatures")
+
+-- set features
+function _set(feature, condition)
+ _g.features[feature] = condition
+end
+
+-- get features
+function main()
+
+ -- init features
+ _g.features = cfeatures()
+
+ -- init conditions
+ -- clang -std=c11 -dM -E - < /dev/null | grep __STDC_VERSION__
+ local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 304"
+ local c17 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L"
+ local c11 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L"
+ local c99 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L"
+ local c90 = clang_minver
+
+ -- set language standard supports
+ _set("c_std_89", c90)
+ _set("c_std_99", c99)
+ _set("c_std_11", c11)
+ _set("c_std_17", c17)
+
+ -- set features
+ _set("c_static_assert", c11)
+ _set("c_restrict", c99)
+ _set("c_variadic_macros", c99)
+ _set("c_function_prototypes", c90)
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/clang/cxxfeatures.lua b/xmake/modules/core/tools/clang/cxxfeatures.lua
new file mode 100644
index 000000000..4a98a1e74
--- /dev/null
+++ b/xmake/modules/core/tools/clang/cxxfeatures.lua
@@ -0,0 +1,132 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxfeatures.lua
+--
+
+-- imports
+import("core.tools.gcc.cxxfeatures")
+
+-- set features
+function _set(feature, condition)
+ _g.features[feature] = condition
+end
+
+-- get features
+--
+-- @see http://clang.llvm.org/cxx_status.html
+--
+-- porting from Modules/Compiler/Clang-CXX-FeatureTests.cmake
+--
+function main()
+
+ -- init features
+ _g.features = cxxfeatures()
+
+ -- init conditions
+ -- clang -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus
+ local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 301"
+ local clang80_cxx20 = "((__clang_major__ * 100) + __clang_minor__) >= 800 && __cplusplus >= 202002L"
+ local clang50_cxx17 = "((__clang_major__ * 100) + __clang_minor__) >= 500 && __cplusplus >= 201703L"
+ local clang34_cxx14 = "((__clang_major__ * 100) + __clang_minor__) >= 304 && __cplusplus > 201103L"
+ local clang31_cxx11 = clang_minver .. " && __cplusplus >= 201103L"
+ local clang29_cxx11 = clang_minver .. " && __cplusplus >= 201103L"
+ local clang_cxx98 = clang_minver .. " && __cplusplus >= 199711L"
+
+ -- set language standard supports
+ _set("cxx_std_98", clang_cxx98)
+ _set("cxx_std_11", clang29_cxx11)
+ _set("cxx_std_14", clang34_cxx14)
+ _set("cxx_std_17", clang50_cxx17)
+ _set("cxx_std_20", clang80_cxx20)
+
+ -- set features for __has_feature()
+ local features_of_has_feature =
+ {
+ "cxx_alias_templates"
+ , "cxx_alignas"
+ , "cxx_attributes"
+ , "cxx_auto_type"
+ , "cxx_binary_literals"
+ , "cxx_constexpr"
+ , "cxx_contextual_conversions"
+ , "cxx_decltype"
+ , "cxx_default_function_template_args"
+ , "cxx_defaulted_functions"
+ , "cxx_delegating_constructors"
+ , "cxx_deleted_functions"
+ , "cxx_explicit_conversions"
+ , "cxx_generalized_initializers"
+ , "cxx_inheriting_constructors"
+ , "cxx_lambdas"
+ , "cxx_local_type_template_args"
+ , "cxx_noexcept"
+ , "cxx_nonstatic_member_init"
+ , "cxx_nullptr"
+ , "cxx_range_for"
+ , "cxx_raw_string_literals"
+ , "cxx_reference_qualified_functions"
+ , "cxx_relaxed_constexpr"
+ , "cxx_return_type_deduction"
+ , "cxx_rvalue_references"
+ , "cxx_static_assert"
+ , "cxx_strong_enums"
+ , "cxx_thread_local"
+ , "cxx_unicode_literals"
+ , "cxx_unrestricted_unions"
+ , "cxx_user_literals"
+ , "cxx_variable_templates"
+ , "cxx_variadic_templates"
+ , {"cxx_aggregate_default_initializers", "cxx_aggregate_nsdmi" }
+ , {"cxx_trailing_return_types", "cxx_trailing_return" }
+ , {"cxx_alignof", "cxx_alignas" }
+ , {"cxx_final", "cxx_override_control" }
+ , {"cxx_override", "cxx_override_control" }
+ , {"cxx_uniform_initialization", "cxx_generalized_initializers" }
+ , {"cxx_defaulted_move_initializers", "cxx_defaulted_functions" }
+ , {"cxx_lambda_init_captures", "cxx_init_captures" }
+ }
+ for _, feature in ipairs(features_of_has_feature) do
+ local name = feature
+ local test = feature
+ if type(feature) == "table" then
+ name = feature[1]
+ test = feature[2]
+ end
+ _set(name, clang_minver .. " && __has_feature(" .. test .. ")")
+ end
+
+ -- set features
+ _set("cxx_attribute_deprecated", clang34_cxx14) -- http://llvm.org/bugs/show_bug.cgi?id=19242
+ _set("cxx_decltype_auto", clang34_cxx14) -- http://llvm.org/bugs/show_bug.cgi?id=19698
+ _set("cxx_digit_separators", clang34_cxx14)
+ _set("cxx_generic_lambdas", clang34_cxx14) -- http://llvm.org/bugs/show_bug.cgi?id=19674
+ _set("cxx_enum_forward_declarations", clang31_cxx11)
+ _set("cxx_sizeof_member", clang31_cxx11)
+ _set("cxx_extended_friend_declarations", clang29_cxx11)
+ _set("cxx_extern_templates", clang29_cxx11)
+ _set("cxx_func_identifier", clang29_cxx11)
+ _set("cxx_inline_namespaces", clang29_cxx11)
+ _set("cxx_long_long_type", clang29_cxx11)
+ _set("cxx_right_angle_brackets", clang29_cxx11)
+ _set("cxx_variadic_macros", clang29_cxx11)
+ _set("cxx_template_template_parameters", clang_cxx98)
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/clang/features.lua b/xmake/modules/core/tools/clang/features.lua
new file mode 100644
index 000000000..c2e2bf523
--- /dev/null
+++ b/xmake/modules/core/tools/clang/features.lua
@@ -0,0 +1,44 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+import("cfeatures")
+import("cxxfeatures")
+
+-- get features
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", flags = {}}
+--
+-- @return the features
+--
+function main(opt)
+
+ -- set features for c
+ set_features(cfeatures())
+
+ -- set features for c++
+ set_features(cxxfeatures())
+
+ -- check features
+ return check_features(opt)
+end
+
+
diff --git a/xmake/modules/core/tools/clang/has_flags.lua b/xmake/modules/core/tools/clang/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/clang/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/clang_cl/has_flags.lua b/xmake/modules/core/tools/clang_cl/has_flags.lua
new file mode 100644
index 000000000..56d83998a
--- /dev/null
+++ b/xmake/modules/core/tools/clang_cl/has_flags.lua
@@ -0,0 +1,101 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.clang_cl.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]:gsub("/", "-")]
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- get extension
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ local extension = opt.program:endswith("++") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "clang_cl_has_flags" .. extension)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}\n")
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join("-Werror=unused-command-line-argument", flags, "-c", "-o", os.tmpfile(), sourcefile))
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/clangxx/features.lua b/xmake/modules/core/tools/clangxx/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/clangxx/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/clangxx/has_flags.lua b/xmake/modules/core/tools/clangxx/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/clangxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/cosmocc/has_flags.lua b/xmake/modules/core/tools/cosmocc/has_flags.lua
new file mode 100644
index 000000000..51a673a4e
--- /dev/null
+++ b/xmake/modules/core/tools/cosmocc/has_flags.lua
@@ -0,0 +1,143 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try {
+ function () os.runv(program, argv, table.join(opt or {}, {shell = true}))
+ return true
+ end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from known flags
+function _check_from_knownargs(flags, opt, islinker)
+ local flag = flags[1]
+ if not islinker then
+ if flag:startswith("-D") or
+ flag:startswith("-U") or
+ flag:startswith("-I") then
+ return true
+ end
+ end
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+ local key = "core.tools.cosmocc." .. (islinker and "has_ldflags" or "has_cflags")
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = try {function () return os.iorunv(opt.program, {islinker and "-Wl,--help" or "--help"}, {envs = opt.envs, shell = true}) end}
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ local flag = flags[1]
+ if islinker and flag then
+ if flag:startswith("-Wl,") then
+ flag = flag:match("-Wl,(.-),") or flag:sub(5)
+ end
+ end
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n"
+ local sourcefile = os.tmpfile("cosmocc_has_flags:" .. snippet) .. _get_extension(opt)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, snippet)
+ end
+ if is_host("windows") then
+ sourcefile = sourcefile:gsub("\\", "/")
+ end
+
+ -- check flags for linker
+ local tmpfile = os.tmpfile()
+ if is_host("windows") then
+ tmpfile = tmpfile:gsub("\\", "/")
+ end
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", tmpfile, sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-o", tmpfile, sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ opt = opt or {}
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if not opt.tryrun then
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+ if _check_from_knownargs(flags, opt, islinker) then
+ return true
+ end
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/cosmocxx/has_flags.lua b/xmake/modules/core/tools/cosmocxx/has_flags.lua
new file mode 100644
index 000000000..3181c0647
--- /dev/null
+++ b/xmake/modules/core/tools/cosmocxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.cosmocc.has_flags")
+
diff --git a/xmake/modules/core/tools/dmd/has_flags.lua b/xmake/modules/core/tools/dmd/has_flags.lua
new file mode 100644
index 000000000..c69c27166
--- /dev/null
+++ b/xmake/modules/core/tools/dmd/has_flags.lua
@@ -0,0 +1,119 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-L=<arg>" or "-L<arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-L=") or flags_str:startswith("-L-") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.dmd.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "dmd_has_flags.d")
+ local objectfile = path.join(os.tmpdir(), "detect", "dmd_has_flags.o")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "void main() {\n}")
+ end
+
+ -- init argv
+ local argv = table.join(flags, "-of" .. objectfile, sourcefile)
+ if not islinker then
+ table.insert(argv, 1, "-c")
+ end
+
+ -- check it
+ return _try_running(opt.program, argv)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/dpcpp/cfeatures.lua b/xmake/modules/core/tools/dpcpp/cfeatures.lua
new file mode 100644
index 000000000..9cc3928ce
--- /dev/null
+++ b/xmake/modules/core/tools/dpcpp/cfeatures.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cfeatures.lua
+--
+
+-- imports
+import("core.tools.clang.cfeatures")
diff --git a/xmake/modules/core/tools/dpcpp/cxxfeatures.lua b/xmake/modules/core/tools/dpcpp/cxxfeatures.lua
new file mode 100644
index 000000000..4c779fbb8
--- /dev/null
+++ b/xmake/modules/core/tools/dpcpp/cxxfeatures.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxfeatures.lua
+--
+
+-- imports
+import("core.tools.clang.cxxfeatures")
diff --git a/xmake/modules/core/tools/dpcpp/features.lua b/xmake/modules/core/tools/dpcpp/features.lua
new file mode 100644
index 000000000..8c04a299c
--- /dev/null
+++ b/xmake/modules/core/tools/dpcpp/features.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.clang.features")
diff --git a/xmake/modules/core/tools/dpcpp/has_flags.lua b/xmake/modules/core/tools/dpcpp/has_flags.lua
new file mode 100644
index 000000000..284736424
--- /dev/null
+++ b/xmake/modules/core/tools/dpcpp/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.clang.has_flags")
+
diff --git a/xmake/modules/core/tools/emcc/has_flags.lua b/xmake/modules/core/tools/emcc/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/emcc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/emxx/has_flags.lua b/xmake/modules/core/tools/emxx/has_flags.lua
new file mode 100644
index 000000000..b4d6369d6
--- /dev/null
+++ b/xmake/modules/core/tools/emxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.emcc.has_flags")
+
diff --git a/xmake/modules/core/tools/fpc/has_flags.lua b/xmake/modules/core/tools/fpc/has_flags.lua
new file mode 100644
index 000000000..8c4e68086
--- /dev/null
+++ b/xmake/modules/core/tools/fpc/has_flags.lua
@@ -0,0 +1,98 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.fpc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-h"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "fpc_has_flags.pas")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "program Hello;\nbegin\nend.")
+ end
+
+ -- check it
+ local binaryfile = os.tmpfile()
+ local ok, errors = _try_running(opt.program, table.join(flags, "-o" .. binaryfile, sourcefile))
+ os.tryrm(binaryfile)
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/gcc/cfeatures.lua b/xmake/modules/core/tools/gcc/cfeatures.lua
new file mode 100644
index 000000000..b9ebaa036
--- /dev/null
+++ b/xmake/modules/core/tools/gcc/cfeatures.lua
@@ -0,0 +1,52 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cfeatures.lua
+--
+
+-- set features
+function _set(feature, condition)
+ _g.features = _g.features or {}
+ _g.features[feature] = condition
+end
+
+-- get features
+function main()
+
+ -- init conditions
+ local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304"
+ local gcc10_c17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 1000 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L"
+ local gcc46_c11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L"
+ local gcc34_c99 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L"
+ local gcc_c90 = gcc_minver
+
+ -- set language standard supports
+ _set("c_std_89", gcc46_c90)
+ _set("c_std_99", gcc34_c99)
+ _set("c_std_11", gcc46_c11)
+ _set("c_std_17", gcc46_c17)
+
+ -- set features
+ _set("c_static_assert", gcc46_c11) -- GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it to 201000L
+ _set("c_restrict", gcc34_c99)
+ _set("c_variadic_macros", gcc34_c99)
+ _set("c_function_prototypes", gcc_c90)
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/gcc/cxxfeatures.lua b/xmake/modules/core/tools/gcc/cxxfeatures.lua
new file mode 100644
index 000000000..9d628522c
--- /dev/null
+++ b/xmake/modules/core/tools/gcc/cxxfeatures.lua
@@ -0,0 +1,222 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxfeatures.lua
+--
+
+-- set features
+function _set(feature, condition)
+ _g.features = _g.features or {}
+ _g.features[feature] = condition
+end
+
+-- get features
+--
+-- http://gcc.gnu.org/projects/cxx0x.html
+-- http://gcc.gnu.org/projects/cxx1y.html
+-- https://gcc.gnu.org/projects/cxx-status.html
+--
+-- porting from Modules/Compiler/GNU-CXX-FeatureTests.cmake
+--
+function main()
+
+ -- init conditions
+ -- gcc -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus
+ local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404"
+ local gcc90_cxx20 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 900 && __cplusplus >= 202002L"
+ local gcc70_cxx17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 700 && __cplusplus >= 201703L"
+ local gcc50_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L"
+ local gcc49_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L"
+ local gcc481_cxx11 = "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L"
+ local gcc48_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 408 && __cplusplus >= 201103L"
+ local gcc47_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && __cplusplus >= 201103L"
+ local gcc_cxx0x_defined = "(__cplusplus >= 201103L || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__))"
+ local gcc46_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && " .. gcc_cxx0x_defined
+ local gcc45_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 405 && " .. gcc_cxx0x_defined
+ local gcc44_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && " .. gcc_cxx0x_defined
+ local gcc43_cxx11 = gcc_minver .. " && " .. gcc_cxx0x_defined
+
+ -- set language standard supports
+ _set("cxx_std_98", gcc_minver)
+ _set("cxx_std_11", gcc43_cxx11)
+ _set("cxx_std_14", gcc49_cxx14)
+ _set("cxx_std_17", gcc70_cxx17)
+ _set("cxx_std_20", gcc90_cxx20)
+
+ -- set features
+ _set("cxx_variable_templates", gcc50_cxx14)
+ _set("cxx_relaxed_constexpr", gcc50_cxx14)
+ _set("cxx_aggregate_default_initializers", gcc50_cxx14)
+
+ -- GNU 4.9 in c++14 mode sets __cplusplus to 201300L, so don't test for the
+ -- correct value of it below.
+ -- https://patchwork.ozlabs.org/patch/382470/
+ _set("cxx_contextual_conversions", gcc49_cxx14)
+ _set("cxx_attribute_deprecated", gcc49_cxx14)
+ _set("cxx_decltype_auto", gcc49_cxx14)
+ _set("cxx_digit_separators", gcc49_cxx14)
+ _set("cxx_generic_lambdas", gcc49_cxx14)
+ _set("cxx_lambda_init_captures", gcc49_cxx14)
+
+ -- GNU 4.3 supports binary literals as an extension, but may warn about
+ -- use of extensions prior to GNU 4.9
+ -- http://stackoverflow.com/questions/16334024/difference-between-gcc-binary-literals-and-c14-ones
+ _set("cxx_binary_literals", gcc49_cxx14)
+
+ -- The feature below is documented as available in GNU 4.8 (by implementing an
+ -- earlier draft of the standard paper), but that version of the compiler
+ -- does not set __cplusplus to a value greater than 201103L until GNU 4.9:
+ -- http://gcc.gnu.org/onlinedocs/gcc-4.8.2/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
+ -- http://gcc.gnu.org/onlinedocs/gcc-4.9.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
+ -- So, CMake only reports availability for it with GNU 4.9 or later.
+ _set("cxx_return_type_deduction", gcc49_cxx14)
+
+ -- Introduced in GCC 4.8.1
+ _set("cxx_decltype_incomplete_return_types", gcc481_cxx11)
+ _set("cxx_reference_qualified_functions", gcc481_cxx11)
+
+ -- The alignof feature works with GNU 4.7 and -std=c++11, but it is documented
+ -- as available with GNU 4.8, so treat that as true.
+ _set("cxx_alignas", gcc48_cxx11)
+ _set("cxx_alignof", gcc48_cxx11)
+ _set("cxx_attributes", gcc48_cxx11)
+ _set("cxx_inheriting_constructors", gcc48_cxx11)
+ _set("cxx_thread_local", gcc48_cxx11)
+
+ _set("cxx_alias_templates", gcc47_cxx11)
+ _set("cxx_delegating_constructors", gcc47_cxx11)
+ _set("cxx_extended_friend_declarations", gcc47_cxx11)
+ _set("cxx_final", gcc47_cxx11)
+ _set("cxx_nonstatic_member_init", gcc47_cxx11)
+ _set("cxx_override", gcc47_cxx11)
+ _set("cxx_user_literals", gcc47_cxx11)
+
+ -- NOTE: C++11 was ratified in September 2011. GNU 4.7 is the first minor
+ -- release following that (March 2012), and the first minor release to
+ -- support -std=c++11. Prior to that, support for C++11 features is technically
+ -- experiemental and possibly incomplete (see for example the note below about
+ -- cxx_variadic_template_template_parameters)
+ -- GNU does not define __cplusplus correctly before version 4.7.
+ -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
+ -- __GXX_EXPERIMENTAL_CXX0X__ is defined in prior versions, but may not be
+ -- defined in the future.
+ _set("cxx_constexpr", gcc46_cxx11)
+ _set("cxx_defaulted_move_initializers", gcc46_cxx11)
+ _set("cxx_enum_forward_declarations", gcc46_cxx11)
+ _set("cxx_noexcept", gcc46_cxx11)
+ _set("cxx_nullptr", gcc46_cxx11)
+ _set("cxx_range_for", gcc46_cxx11)
+ _set("cxx_unrestricted_unions", gcc46_cxx11)
+
+ _set("cxx_explicit_conversions", gcc45_cxx11)
+ _set("cxx_lambdas", gcc45_cxx11)
+ _set("cxx_local_type_template_args", gcc45_cxx11)
+ _set("cxx_raw_string_literals", gcc45_cxx11)
+
+ _set("cxx_auto_type", gcc44_cxx11)
+ _set("cxx_defaulted_functions", gcc44_cxx11)
+ _set("cxx_deleted_functions", gcc44_cxx11)
+ _set("cxx_generalized_initializers", gcc44_cxx11)
+ _set("cxx_inline_namespaces", gcc44_cxx11)
+ _set("cxx_sizeof_member", gcc44_cxx11)
+ _set("cxx_strong_enums", gcc44_cxx11)
+ _set("cxx_trailing_return_types", gcc44_cxx11)
+ _set("cxx_unicode_literals", gcc44_cxx11)
+ _set("cxx_uniform_initialization", gcc44_cxx11)
+ _set("cxx_variadic_templates", gcc44_cxx11)
+
+ -- TODO: If features are ever recorded for GNU 4.3, there should possibly
+ -- be a new feature added like cxx_variadic_template_template_parameters,
+ -- which is implemented by GNU 4.4, but not 4.3. cxx_variadic_templates is
+ -- actually implemented by GNU 4.3, but variadic template template parameters
+ -- 'completes' it, so that is the version we record as having the variadic
+ -- templates capability in CMake. See
+ -- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf
+ -- TODO: Should be supported by GNU 4.3
+ _set("cxx_decltype", gcc43_cxx11)
+ _set("cxx_default_function_template_args", gcc43_cxx11)
+ _set("cxx_long_long_type", gcc43_cxx11)
+ _set("cxx_right_angle_brackets", gcc43_cxx11)
+ _set("cxx_rvalue_references", gcc43_cxx11)
+ _set("cxx_static_assert", gcc43_cxx11)
+
+ -- TODO: Should be supported since GNU 3.4?
+ _set("cxx_extern_templates", gcc_minver .. " && " .. gcc_cxx0x_defined)
+
+ -- TODO: Should be supported forever?
+ _set("cxx_func_identifier", gcc_minver .. " && " .. gcc_cxx0x_defined)
+ _set("cxx_variadic_macros", gcc_minver .. " && " .. gcc_cxx0x_defined)
+ _set("cxx_template_template_parameters", gcc_minver .. " && __cplusplus")
+
+ -- c++17 language features with predefined macros
+ -- https://en.cppreference.com/w/cpp/feature_test
+ local features_cxx17 = {
+ "__cpp_aggregate_bases",
+ "__cpp_aligned_new",
+ "__cpp_capture_star_this",
+ "__cpp_constexpr",
+ "__cpp_deduction_guides",
+ "__cpp_enumerator_attributes",
+ "__cpp_fold_expressions",
+ "__cpp_guaranteed_copy_elision",
+ "__cpp_hex_float",
+ "__cpp_if_constexpr",
+ "__cpp_inheriting_constructors",
+ "__cpp_inline_variables",
+ "__cpp_namespace_attributes",
+ "__cpp_noexcept_function_type",
+ "__cpp_nontype_template_args",
+ "__cpp_nontype_template_parameter_auto",
+ "__cpp_range_based_for",
+ "__cpp_static_assert",
+ "__cpp_structured_bindings",
+ "__cpp_template_template_args",
+ "__cpp_variadic_using"}
+ for _, feature in ipairs(features_cxx17) do
+ _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")")
+ end
+
+ -- c++20 language features with predefined macros
+ -- https://en.cppreference.com/w/cpp/feature_test
+ local features_cxx20 = {
+ "__cpp_aggregate_paren_init",
+ "__cpp_char8_t",
+ "__cpp_concepts",
+ "__cpp_conditional_explicit",
+ "__cpp_consteval",
+ "__cpp_constexpr",
+ "__cpp_constexpr_dynamic_alloc",
+ "__cpp_constexpr_in_decltype",
+ "__cpp_constinit",
+ "__cpp_deduction_guides",
+ "__cpp_designated_initializers",
+ "__cpp_generic_lambdas",
+ "__cpp_impl_coroutine",
+ "__cpp_impl_destroying_delete",
+ "__cpp_impl_three_way_comparison",
+ "__cpp_init_captures",
+ "__cpp_modules",
+ "__cpp_nontype_template_args",
+ "__cpp_using_enum"}
+ for _, feature in ipairs(features_cxx20) do
+ _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")")
+ end
+
+ -- get features
+ return _g.features
+end
+
diff --git a/xmake/modules/core/tools/gcc/features.lua b/xmake/modules/core/tools/gcc/features.lua
new file mode 100644
index 000000000..153cc3fb4
--- /dev/null
+++ b/xmake/modules/core/tools/gcc/features.lua
@@ -0,0 +1,130 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+import("cfeatures")
+import("cxxfeatures")
+import("core.language.language")
+
+-- get macro defines
+function _get_macro_defines(snippets, extension, opt)
+
+ -- make an stub source file
+ local sourcefile = os.tmpfile() .. extension
+ io.writefile(sourcefile, table.concat(table.wrap(snippets), "\n"))
+
+ -- get defines
+ local results = {}
+ local defines = try { function () return os.iorunv(opt.program, table.join(opt.flags or {}, {"-dM", "-E", sourcefile}), {envs = opt.envs}) end }
+ if defines then
+ for _, define in ipairs(defines:split("\n")) do
+ local name = define:match("#define%s+(.-)%s+")
+ if name then
+ results[name] = true
+ end
+ end
+ end
+ os.tryrm(sourcefile)
+ return results
+end
+
+-- set feature with condition
+function _set_feature(feature, condition)
+
+ -- init features
+ _g.features = _g.features or {}
+
+ -- get language kind
+ local langkind = feature:match("^(%w-)_")
+ assert(langkind, "unknown language kind for the feature: %s", feature)
+
+ -- get source kind from the language kind
+ local sourcekind = language.langkinds()[langkind]
+ assert(sourcekind, "unknown language kind: " .. langkind)
+
+ -- get extension
+ local extension = table.wrap(language.sourcekinds()[sourcekind])[1]
+ assert(extension, "not supported kind for the feature: %s", feature)
+
+ -- make snippet
+ local snippet = format([[
+#if (%s)
+# define %s 1
+#endif]], condition, feature)
+
+ -- init features with the given extension
+ local features = _g.features[extension] or {}
+ _g.features[extension] = features
+
+ -- set feature and snippet
+ features[feature] = snippet
+end
+
+-- set features
+function set_features(features)
+ for feature, condition in pairs(features) do
+ _set_feature(feature, condition)
+ end
+end
+
+-- check features
+function check_features(opt)
+
+ -- check features with all extensions
+ local results = {}
+ for extension, features in pairs(_g.features) do
+
+ -- make snippets
+ local snippets = {}
+ for _, snippet in pairs(features) do
+ table.insert(snippets, snippet)
+ end
+
+ -- get defines
+ local defines = _get_macro_defines(snippets, extension, opt)
+
+ -- check features
+ for feature, _ in pairs(features) do
+ if defines[feature] then
+ results[feature] = true
+ end
+ end
+ end
+ return results
+end
+
+-- get features
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", flags = {}}
+--
+-- @return the features
+--
+function main(opt)
+
+ -- set features for c
+ set_features(cfeatures())
+
+ -- set features for c++
+ set_features(cxxfeatures())
+
+ -- check features
+ return check_features(opt)
+end
+
diff --git a/xmake/modules/core/tools/gcc/has_flags.lua b/xmake/modules/core/tools/gcc/has_flags.lua
new file mode 100644
index 000000000..25d08be01
--- /dev/null
+++ b/xmake/modules/core/tools/gcc/has_flags.lua
@@ -0,0 +1,134 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from known flags
+function _check_from_knownargs(flags, opt, islinker)
+ local flag = flags[1]
+ if not islinker then
+ if flag:startswith("-D") or
+ flag:startswith("-U") or
+ flag:startswith("-I") then
+ return true
+ end
+ end
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+ local key = "core.tools.gcc." .. (islinker and "has_ldflags" or "has_cflags")
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = try {function () return os.iorunv(opt.program, {islinker and "-Wl,--help" or "--help"}, {envs = opt.envs}) end}
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ local flag = flags[1]
+ if islinker and flag then
+ if flag:startswith("-Wl,") then
+ flag = flag:match("-Wl,(.-),") or flag:sub(5)
+ end
+ end
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n"
+ local sourcefile = os.tmpfile("gcc_has_flags:" .. snippet) .. _get_extension(opt)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, snippet)
+ end
+
+ -- check flags for linker
+ local tmpfile = os.tmpfile()
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", tmpfile, sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-S", "-o", tmpfile, sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ opt = opt or {}
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if not opt.tryrun then
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+ if _check_from_knownargs(flags, opt, islinker) then
+ return true
+ end
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/gccgo/has_flags.lua b/xmake/modules/core/tools/gccgo/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/gccgo/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/gdc/has_flags.lua b/xmake/modules/core/tools/gdc/has_flags.lua
new file mode 100644
index 000000000..e4cc32f65
--- /dev/null
+++ b/xmake/modules/core/tools/gdc/has_flags.lua
@@ -0,0 +1,118 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "dcld" or toolkind == "dcsh"
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.gdc.has_flags"
+
+ -- make flags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all flags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "gdc_has_flags.d")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "void main()\n{}")
+ end
+
+ -- check flags for linker
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
+
diff --git a/xmake/modules/core/tools/gfortran/has_flags.lua b/xmake/modules/core/tools/gfortran/has_flags.lua
new file mode 100644
index 000000000..3552d4d45
--- /dev/null
+++ b/xmake/modules/core/tools/gfortran/has_flags.lua
@@ -0,0 +1,117 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("-ld") or toolkind:endswith("-sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.gfortran.has_flags"
+
+ -- make flags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all flags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "gfortran_has_flags.f90")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "program hello\n print *, \"Hello World!\"\nend program hello")
+ end
+
+ -- check flags for linker
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/go/has_flags.lua b/xmake/modules/core/tools/go/has_flags.lua
new file mode 100644
index 000000000..bf96a1f1f
--- /dev/null
+++ b/xmake/modules/core/tools/go/has_flags.lua
@@ -0,0 +1,130 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the tool kind is gcld or gcsh?
+ local toolkind = opt.toolkind or ""
+ return toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.go.has_flags"
+
+ -- make flags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all flags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- attempt to get argument list from the error info (help menu)
+ allflags = {}
+ try
+ {
+ function () os.runv(opt.program, {"tool", "compile", "--help"}) end,
+ catch
+ {
+ function (errors)
+ local arglist = errors
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+ end
+ }
+ }
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "go_has_flags.go")
+ local objectfile = path.join(os.tmpdir(), "detect", "go_has_flags.o")
+ local targetfile = path.join(os.tmpdir(), "detect", "go_has_flags.bin")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "package main\nfunc main() {\n}")
+ end
+
+ -- check flags for linker
+ if islinker then
+
+ -- compile a object file first
+ if not os.isfile(objectfile) and not _try_running(opt.program, table.join("tool", "compile", "-o", objectfile, sourcefile)) then
+ return false
+ end
+
+ -- check it
+ return _try_running(opt.program, table.join("tool", "link", flags, "-o", targetfile, objectfile))
+ end
+
+ -- check flags for compiler
+ return _try_running(opt.program, table.join("tool", "compile", flags, "-o", objectfile, sourcefile))
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/gxx/features.lua b/xmake/modules/core/tools/gxx/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/gxx/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/gxx/has_flags.lua b/xmake/modules/core/tools/gxx/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/gxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/icc/has_flags.lua b/xmake/modules/core/tools/icc/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/icc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/icl/has_flags.lua b/xmake/modules/core/tools/icl/has_flags.lua
new file mode 100644
index 000000000..ab189dfd0
--- /dev/null
+++ b/xmake/modules/core/tools/icl/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.cl.has_flags")
+
diff --git a/xmake/modules/core/tools/icpc/has_flags.lua b/xmake/modules/core/tools/icpc/has_flags.lua
new file mode 100644
index 000000000..a2d18c48f
--- /dev/null
+++ b/xmake/modules/core/tools/icpc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gxx.has_flags")
+
diff --git a/xmake/modules/core/tools/icpx/features.lua b/xmake/modules/core/tools/icpx/features.lua
new file mode 100644
index 000000000..7628827f1
--- /dev/null
+++ b/xmake/modules/core/tools/icpx/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.clang.features")
+
diff --git a/xmake/modules/core/tools/icpx/has_flags.lua b/xmake/modules/core/tools/icpx/has_flags.lua
new file mode 100644
index 000000000..284736424
--- /dev/null
+++ b/xmake/modules/core/tools/icpx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.clang.has_flags")
+
diff --git a/xmake/modules/core/tools/icx/cfeatures.lua b/xmake/modules/core/tools/icx/cfeatures.lua
new file mode 100644
index 000000000..9cc3928ce
--- /dev/null
+++ b/xmake/modules/core/tools/icx/cfeatures.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cfeatures.lua
+--
+
+-- imports
+import("core.tools.clang.cfeatures")
diff --git a/xmake/modules/core/tools/icx/cxxfeatures.lua b/xmake/modules/core/tools/icx/cxxfeatures.lua
new file mode 100644
index 000000000..4c779fbb8
--- /dev/null
+++ b/xmake/modules/core/tools/icx/cxxfeatures.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file cxxfeatures.lua
+--
+
+-- imports
+import("core.tools.clang.cxxfeatures")
diff --git a/xmake/modules/core/tools/icx/features.lua b/xmake/modules/core/tools/icx/features.lua
new file mode 100644
index 000000000..8c04a299c
--- /dev/null
+++ b/xmake/modules/core/tools/icx/features.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.clang.features")
diff --git a/xmake/modules/core/tools/icx/has_flags.lua b/xmake/modules/core/tools/icx/has_flags.lua
new file mode 100644
index 000000000..284736424
--- /dev/null
+++ b/xmake/modules/core/tools/icx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.clang.has_flags")
+
diff --git a/xmake/modules/core/tools/ifort/has_flags.lua b/xmake/modules/core/tools/ifort/has_flags.lua
new file mode 100644
index 000000000..df3acfe3e
--- /dev/null
+++ b/xmake/modules/core/tools/ifort/has_flags.lua
@@ -0,0 +1,27 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+if is_host("windows") then
+ inherit("core.tools.cl.has_flags")
+else
+ inherit("core.tools.gfortran.has_flags")
+end
+
diff --git a/xmake/modules/core/tools/ifx/has_flags.lua b/xmake/modules/core/tools/ifx/has_flags.lua
new file mode 100644
index 000000000..d1f745651
--- /dev/null
+++ b/xmake/modules/core/tools/ifx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.ifort.has_flags")
+
diff --git a/xmake/modules/core/tools/ldc2/has_flags.lua b/xmake/modules/core/tools/ldc2/has_flags.lua
new file mode 100644
index 000000000..81dd1e94a
--- /dev/null
+++ b/xmake/modules/core/tools/ldc2/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.dmd.has_flags")
+
diff --git a/xmake/modules/core/tools/link/has_flags.lua b/xmake/modules/core/tools/link/has_flags.lua
new file mode 100644
index 000000000..1f93b7979
--- /dev/null
+++ b/xmake/modules/core/tools/link/has_flags.lua
@@ -0,0 +1,121 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.global_detectcache")
+import("lib.detect.find_tool")
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+ local key = "core.tools.link.has_flags"
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+ local allflags = global_detectcache:get2(key, flagskey)
+ if not allflags then
+ allflags = {}
+ local arglist = nil
+ try {
+ function () os.runv(opt.program, {"-?"}, {envs = opt.envs}) end,
+ catch {
+ function (errors) arglist = errors end
+ }
+ }
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-"):lower()] = true
+ end
+ end
+ global_detectcache:set2(key, flagskey, allflags)
+ global_detectcache:save()
+ end
+ local flag = flags[1]:gsub("/", "-"):lower()
+ return allflags[flag]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local flags_str = table.concat(flags, " "):lower()
+ local winmain = flags_str:find("subsystem:windows")
+ local sourcefile = path.join(os.tmpdir(), "detect", (winmain and "winmain_" or "") .. "link_has_flags.c")
+ if not os.isfile(sourcefile) then
+ if winmain then
+ io.writefile(sourcefile, "int WinMain(void* instance, void* previnst, char** argv, int argc)\n{return 0;}\n")
+ else
+ io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}\n")
+ end
+ end
+
+ -- compile the source file
+ local objectfile = os.tmpfile() .. ".obj"
+ local binaryfile = os.tmpfile() .. ".exe"
+ local cl = find_tool("cl")
+ if cl then
+ os.runv(cl.program, {"-c", "-nologo", "-Fo" .. objectfile, sourcefile}, {envs = opt.envs})
+ end
+
+ -- try link it
+ local ok, errors = _try_running(opt.program, table.join(flags, "-nologo", "-out:" .. binaryfile, objectfile), {envs = opt.envs})
+ os.tryrm(objectfile)
+ os.tryrm(binaryfile)
+ return ok, errors
+end
+
+-- ignore some flags
+function _ignore_flags(flags)
+ local results = {}
+ for _, flag in ipairs(flags) do
+ flag = flag:lower()
+ if not flag:find("[%-/]def:.+%.def") and not flag:find("[%-/]export:") then
+ table.insert(results, flag)
+ end
+ end
+ return results
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- ignore some flags
+ flags = _ignore_flags(flags)
+ if #flags == 0 then
+ return true
+ end
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/ml/has_flags.lua b/xmake/modules/core/tools/ml/has_flags.lua
new file mode 100644
index 000000000..6eeb4e768
--- /dev/null
+++ b/xmake/modules/core/tools/ml/has_flags.lua
@@ -0,0 +1,105 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.ml.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]:gsub("/", "-")]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "ml_has_flags.asm")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, [[
+ifndef X64
+.686p
+.model flat, C
+endif
+.code
+end]])
+ end
+
+ -- check it
+ local errors = nil
+ return try { function ()
+ if opt.program:find("ml64", 1, true) then
+ table.insert(flags, "-DX64")
+ end
+ local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile), {envs = opt.envs})
+ if errs and #errs:trim() > 0 then
+ return false, errs
+ end
+ return true
+ end,
+ catch { function (errs) errors = errs end }
+ }, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/ml64/has_flags.lua b/xmake/modules/core/tools/ml64/has_flags.lua
new file mode 100644
index 000000000..323fd4d5e
--- /dev/null
+++ b/xmake/modules/core/tools/ml64/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.ml.has_flags")
+
diff --git a/xmake/modules/core/tools/nim/has_flags.lua b/xmake/modules/core/tools/nim/has_flags.lua
new file mode 100644
index 000000000..84ce412b7
--- /dev/null
+++ b/xmake/modules/core/tools/nim/has_flags.lua
@@ -0,0 +1,98 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.nim.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "nim_has_flags.nim")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "echo \"hello\"")
+ end
+
+ -- check it
+ local cachedir = os.tmpfile() .. ".dir"
+ local ok, errors = _try_running(opt.program, table.join("c", "-c", flags, "--nimcache:" .. cachedir, sourcefile))
+ os.tryrm(cachedir)
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/nvc/features.lua b/xmake/modules/core/tools/nvc/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/nvc/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/nvc/has_flags.lua b/xmake/modules/core/tools/nvc/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/nvc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/nvcc/has_flags.lua b/xmake/modules/core/tools/nvcc/has_flags.lua
new file mode 100644
index 000000000..347961e70
--- /dev/null
+++ b/xmake/modules/core/tools/nvcc/has_flags.lua
@@ -0,0 +1,161 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>" or "-Xlinker <arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") or flags_str:startswith("-Xlinker ") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("-ld") or toolkind:endswith("-sh")
+end
+
+-- try running
+function _try_running(program, argv, opt)
+ local errors = nil
+ return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- check for the builtin flags
+ local builtin_flags = {["-code"] = true,
+ ["--gpu-code"] = true,
+ ["-gencode"] = true,
+ ["--generate-code"] = true,
+ ["-arch"] = true,
+ ["--gpu-architecture"] = true,
+ ["-cudart=none"] = true,
+ ["--cudart=none"] = true}
+ if builtin_flags[flags[1]] then
+ return true
+ end
+
+ -- check for the builtin flag=value
+ local cudart_flags = {none = true, shared = true, static = true}
+ local builtin_flags_pair = {["-cudart"] = cudart_flags,
+ ["--cudart"] = cudart_flags}
+ if #flags > 1 and builtin_flags_pair[flags[1]] and builtin_flags_pair[flags[1]][flags[2]] then
+ return true
+ end
+
+ -- check from the `--help` menu, only for linker
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.nvcc.has_flags"
+
+ -- make flags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all flags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}\n"
+ local sourcefile = os.tmpfile("nvcc_has_flags:" .. snippet) .. ".cu"
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, snippet)
+ end
+
+ local args = table.join("-o", os.nuldev(), sourcefile)
+ if not islinker then
+ table.insert(args, 1, "-c")
+ end
+
+ -- avoid recursion
+ if flags[1] ~= "-allow-unsupported-compiler" then
+ -- add -allow-unsupported-compiler if supported to suppress error of unsupported compiler,
+ -- which caused all checks failed.
+ local allow_unsupported_compiler = _has_flags({"-allow-unsupported-compiler"}, opt)
+ if allow_unsupported_compiler then
+ table.insert(args, 1, "-allow-unsupported-compiler")
+ end
+ end
+
+ -- add architecture flags if cross compiling
+ if not is_arch(os.arch()) then
+ if is_arch(".+64.*") then
+ table.insert(args, 1, "-m64")
+ else
+ table.insert(args, 1, "-m32")
+ end
+ end
+
+ -- check flags
+ return _try_running(opt.program, table.join(flags, args), opt)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "cu"}
+--
+-- @return true or false
+--
+function _has_flags(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
+function main(...)
+ return _has_flags(...)
+end
+
diff --git a/xmake/modules/core/tools/nvcxx/features.lua b/xmake/modules/core/tools/nvcxx/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/nvcxx/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/nvcxx/has_flags.lua b/xmake/modules/core/tools/nvcxx/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/nvcxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/nvfortran/has_flags.lua b/xmake/modules/core/tools/nvfortran/has_flags.lua
new file mode 100644
index 000000000..d0447806f
--- /dev/null
+++ b/xmake/modules/core/tools/nvfortran/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gfortran.has_flags")
+
diff --git a/xmake/modules/core/tools/rc/has_flags.lua b/xmake/modules/core/tools/rc/has_flags.lua
new file mode 100644
index 000000000..a635a3f68
--- /dev/null
+++ b/xmake/modules/core/tools/rc/has_flags.lua
@@ -0,0 +1,68 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.rc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]:gsub("/", "-")]
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = ""}
+--
+-- @return true or false
+--
+function main(flags, opt)
+ return _check_from_arglist(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/rustc/has_flags.lua b/xmake/modules/core/tools/rustc/has_flags.lua
new file mode 100644
index 000000000..9072b1c35
--- /dev/null
+++ b/xmake/modules/core/tools/rustc/has_flags.lua
@@ -0,0 +1,116 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- is linker?
+function _islinker(flags, opt)
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-C linkarg=") then
+ return true
+ end
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.rustc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "rustc_has_flags.rs")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "fn main() {\n}")
+ end
+
+ -- check flags for linker
+ if islinker then
+ return _try_running(opt.program, table.join("--crate-type=bin", flags, "-o", os.tmpfile(), sourcefile), opt)
+ end
+
+ -- check flags for compiler
+ local objectfile = os.tmpfile() .. ".o"
+ local ok, errors = _try_running(opt.program, table.join("--emit", "obj", flags, "-o", objectfile, sourcefile))
+ os.tryrm(objectfile)
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/sdcc/has_flags.lua b/xmake/modules/core/tools/sdcc/has_flags.lua
new file mode 100644
index 000000000..e960fa8e1
--- /dev/null
+++ b/xmake/modules/core/tools/sdcc/has_flags.lua
@@ -0,0 +1,123 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the flags is "-Wl,<arg>"?
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-Wl,") then
+ return true
+ end
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh"
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.sdcc.has_flags"
+
+ -- make flags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all flags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- get extension
+ -- @note we need to detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ local extension = opt.program:endswith("++") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "sdcc_has_flags" .. extension)
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}\n")
+ end
+
+ -- check flags for linker
+ if islinker then
+ return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile))
+ end
+
+ -- check flags for compiler
+ -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage
+ return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile))
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/swift_frontend/has_flags.lua b/xmake/modules/core/tools/swift_frontend/has_flags.lua
new file mode 100644
index 000000000..eecb0ede7
--- /dev/null
+++ b/xmake/modules/core/tools/swift_frontend/has_flags.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.swiftc.has_flags")
diff --git a/xmake/modules/core/tools/swiftc/has_flags.lua b/xmake/modules/core/tools/swiftc/has_flags.lua
new file mode 100644
index 000000000..cf56da7c5
--- /dev/null
+++ b/xmake/modules/core/tools/swiftc/has_flags.lua
@@ -0,0 +1,101 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- try running
+function _try_running(...)
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.swiftc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "swiftc_has_flags.swift")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "")
+ end
+
+ -- check it
+ local objectfile = os.tmpfile() .. ".o"
+ local ok, errors = _try_running(opt.program, table.join(flags, "-o", objectfile, sourcefile))
+
+ -- remove files
+ os.tryrm(objectfile)
+
+ -- ok?
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/core/tools/tcc/has_flags.lua b/xmake/modules/core/tools/tcc/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/tcc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/zig/has_flags.lua b/xmake/modules/core/tools/zig/has_flags.lua
new file mode 100644
index 000000000..92aeb5c72
--- /dev/null
+++ b/xmake/modules/core/tools/zig/has_flags.lua
@@ -0,0 +1,114 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- is linker?
+function _islinker(flags, opt)
+
+ -- the tool kind is ld or sh?
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt, islinker)
+
+ -- only for compiler
+ if islinker or #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "core.tools.zig.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"build-obj", "--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt, islinker)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "zig_has_flags.zig")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "pub fn main() !void {}")
+ end
+
+ -- init argv
+ local argv = table.join(flags, "-femit-bin=" .. os.tmpfile(), sourcefile)
+ if islinker then
+ table.insert(argv, 1, "build-exe")
+ else
+ table.insert(argv, 1, "build-obj")
+ end
+
+ -- check it
+ return _try_running(opt.program, argv)
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt, islinker) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt, islinker)
+end
+
diff --git a/xmake/modules/core/tools/zig_cc/features.lua b/xmake/modules/core/tools/zig_cc/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/zig_cc/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/zig_cc/has_flags.lua b/xmake/modules/core/tools/zig_cc/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/zig_cc/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+
diff --git a/xmake/modules/core/tools/zig_cxx/features.lua b/xmake/modules/core/tools/zig_cxx/features.lua
new file mode 100644
index 000000000..08c822cfd
--- /dev/null
+++ b/xmake/modules/core/tools/zig_cxx/features.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file features.lua
+--
+
+-- imports
+inherit("core.tools.gcc.features")
+
diff --git a/xmake/modules/core/tools/zig_cxx/has_flags.lua b/xmake/modules/core/tools/zig_cxx/has_flags.lua
new file mode 100644
index 000000000..76744a133
--- /dev/null
+++ b/xmake/modules/core/tools/zig_cxx/has_flags.lua
@@ -0,0 +1,23 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file has_flags.lua
+--
+
+-- imports
+inherit("core.tools.gcc.has_flags")
+