diff options
| author | ruki <[email protected]> | 2025-01-25 00:59:17 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-01-25 00:59:17 +0800 |
| commit | 35677f50e4eb8ecb5aabe70e6ce900e28fd0adc2 (patch) | |
| tree | f88df0f22e606bc8bf4361f13059bd3cb00ab0ed /xmake/modules/core | |
| parent | d1b1492b07d370f9cf06414490fc489c1dda6ed8 (diff) | |
move has_flags.lua
Diffstat (limited to 'xmake/modules/core')
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") + |
