diff options
| author | ruki <[email protected]> | 2021-08-10 07:39:59 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-10 07:39:59 +0800 |
| commit | 9ded547a6374dcf77b5bd385af5359d4e96f3c22 (patch) | |
| tree | 98fe9942a10ce358824aa8a8d389bfc1ecb9c31e | |
| parent | ae33b24ea5ecb6608168e869bb8ee94e0f674c98 (diff) | |
| parent | 119b04dfa9e6971f324ba65d94737ad7eb31bc83 (diff) | |
Merge pull request #1562 from xmake-io/runsnippet
Support to run c/c++ snippets for option
| -rw-r--r-- | tests/apis/check_xxx/config.h.in | 2 | ||||
| -rw-r--r-- | tests/apis/check_xxx/xmake.lua | 4 | ||||
| -rw-r--r-- | xmake/core/base/interpreter.lua | 17 | ||||
| -rw-r--r-- | xmake/core/base/scopeinfo.lua | 16 | ||||
| -rw-r--r-- | xmake/core/project/option.lua | 150 | ||||
| -rw-r--r-- | xmake/includes/check_csnippets.lua | 30 | ||||
| -rw-r--r-- | xmake/includes/check_cxxsnippets.lua | 30 | ||||
| -rw-r--r-- | xmake/modules/lib/detect/check_cxsnippets.lua | 53 |
8 files changed, 255 insertions, 47 deletions
diff --git a/tests/apis/check_xxx/config.h.in b/tests/apis/check_xxx/config.h.in index c5e178b44..0c7d9ebf8 100644 --- a/tests/apis/check_xxx/config.h.in +++ b/tests/apis/check_xxx/config.h.in @@ -8,3 +8,5 @@ ${define HAS_SETJMP} ${define HAS_CONSTEXPR} ${define HAS_CONSEXPR_AND_STATIC_ASSERT} ${define HAS_SSE2} +${define HAS_LONG_8} +${define PTR_SIZE} diff --git a/tests/apis/check_xxx/xmake.lua b/tests/apis/check_xxx/xmake.lua index a2a5fa0b1..2a9916954 100644 --- a/tests/apis/check_xxx/xmake.lua +++ b/tests/apis/check_xxx/xmake.lua @@ -13,6 +13,8 @@ target("test") check_ctypes("HAS_WCHAR", "wchar_t") check_cincludes("HAS_STRING_H", "string.h") + check_csnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0 : -1;", {tryrun = true}) + check_csnippets("INT_SIZE", 'printf("%d", sizeof(int)); return 0;', {output = true, number = true}) configvar_check_cincludes("HAS_STRING_AND_STDIO_H", {"string.h", "stdio.h"}) configvar_check_ctypes("HAS_WCHAR_AND_FLOAT", {"wchar_t", "float"}) configvar_check_links("HAS_PTHREAD", {"pthread", "m", "dl"}) @@ -21,3 +23,5 @@ target("test") configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr", {languages = "c++11"}) configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"}) configvar_check_cflags("HAS_SSE2", "-msse2") + configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) + configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 2f26e20ce..ecfcc7270 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -1225,13 +1225,19 @@ function interpreter:api_register_set_dictionary(scope_kind, ...) assert(self) -- define implementation - local implementation = function (self, scope, name, dict_or_key, value) + local implementation = function (self, scope, name, dict_or_key, value, extra_config) -- check if type(dict_or_key) == "table" then scope[name] = dict_or_key elseif type(dict_or_key) == "string" and value ~= nil then scope[name] = {[dict_or_key] = value} + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("set_%s(%s): invalid value type!", name, type(dict)) @@ -1249,14 +1255,21 @@ function interpreter:api_register_add_dictionary(scope_kind, ...) assert(self) -- define implementation - local implementation = function (self, scope, name, dict_or_key, value) + local implementation = function (self, scope, name, dict_or_key, value, extra_config) -- check scope[name] = scope[name] or {} if type(dict_or_key) == "table" then table.join2(scope[name], dict_or_key) + extra_config = value elseif type(dict_or_key) == "string" and value ~= nil then scope[name][dict_or_key] = value + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("add_%s(%s): invalid value type!", name, type(dict)) diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 70755e14a..1f07e236f 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -238,7 +238,7 @@ function _instance:_api_add_keyvalues(name, key, ...) end -- set the api dictionary to the scope info -function _instance:_api_set_dictionary(name, dict_or_key, value) +function _instance:_api_set_dictionary(name, dict_or_key, value, extra_config) -- get the scope info local scope = self._INFO @@ -252,6 +252,12 @@ function _instance:_api_set_dictionary(name, dict_or_key, value) scope[name] = dict elseif type(dict_or_key) == "string" and value ~= nil then scope[name] = {[dict_or_key] = self:_api_handle(value)} + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("%s:set(%s, ...): invalid value type!", self:kind(), name, type(dict)) @@ -259,7 +265,7 @@ function _instance:_api_set_dictionary(name, dict_or_key, value) end -- add the api dictionary to the scope info -function _instance:_api_add_dictionary(name, dict_or_key, value) +function _instance:_api_add_dictionary(name, dict_or_key, value, extra_config) -- get the scope info local scope = self._INFO @@ -274,6 +280,12 @@ function _instance:_api_add_dictionary(name, dict_or_key, value) table.join2(scope[name], dict) elseif type(dict_or_key) == "string" and value ~= nil then scope[name][dict_or_key] = self:_api_handle(value) + -- save extra config + if extra_config and table.is_dictionary(extra_config) then + scope["__extra_" .. name] = scope["__extra_" .. name] or {} + local extrascope = scope["__extra_" .. name] + extrascope[dict_or_key] = extra_config + end else -- error os.raise("%s:add(%s, ...): invalid value type!", self:kind(), name, type(dict)) diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 93d25990f..e9a2ef20d 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -68,22 +68,23 @@ function _instance:_clear() option._cache():set(self:name(), nil) end --- check option conditions -function _instance:_do_check() +-- check snippets +function _instance:_do_check_cxsnippts(snippets) -- import check_cxsnippets() self._check_cxsnippets = self._check_cxsnippets or sandbox_module.import("lib.detect.check_cxsnippets", {anonymous = true}) -- check for c and c++ - local passed = nil + local passed = 0 + local result_output for _, kind in ipairs({"c", "cxx"}) do -- get conditions - local links = self:get("links") - local snippets = self:get(kind .. "snippets") - local types = self:get(kind .. "types") - local funcs = self:get(kind .. "funcs") - local includes = self:get(kind .. "includes") + local links = self:get("links") + local snippets = self:get(kind .. "snippets") + local types = self:get(kind .. "types") + local funcs = self:get(kind .. "funcs") + local includes = self:get(kind .. "includes") -- TODO it is deprecated local snippet = self:get(kind .. "snippet") @@ -100,23 +101,98 @@ function _instance:_do_check() sourcekind = "cc" end - -- check it - local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets, {target = self, sourcekind = sourcekind, types = types, funcs = funcs, includes = includes}) - if not ok then - return false, results_or_errors + -- split snippets + local snippets_build = {} + local snippets_tryrun = {} + local snippets_output = {} + if snippets then + for name, snippet in pairs(snippets) do + if self:extraconf(kind .. "snippets", name, "output") then + snippets_output[name] = snippet + elseif self:extraconf(kind .. "snippets", name, "tryrun") then + snippets_tryrun[name] = snippet + else + snippets_build[name] = snippet + end + end + if #table.keys(snippets_output) > 1 then + return false, -1, string.format("option(%s): only support for only one snippet with output!", self:name()) + end + end + + -- check snippets (run with output) + if #table.keys(snippets_output) > 0 then + local ok, results_or_errors, output = sandbox.load(self._check_cxsnippets, snippets_output, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes, + tryrun = true, output = true}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + result_output = output + else + passed = -1 + break + end end - -- passed? - if results_or_errors then - passed = true - else - passed = false - break + -- check snippets (run only) + if passed == 0 and #table.keys(snippets_tryrun) > 0 then + local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_tryrun, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes, + tryrun = true}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + else + passed = -1 + break + end + end + + -- check snippets (build only) + if passed == 0 or #table.keys(snippets_build) > 0 then + local ok, results_or_errors = sandbox.load(self._check_cxsnippets, snippets_build, { + target = self, + sourcekind = sourcekind, + types = types, + funcs = funcs, + includes = includes}) + if not ok then + return false, -1, results_or_errors + end + + -- passed or no passed? + if results_or_errors then + passed = 1 + else + passed = -1 + break + end end end end + return true, passed, result_output +end - -- check features +-- check features +function _instance:_do_check_features() + local passed = 0 local features = self:get("features") if features then @@ -127,23 +203,49 @@ function _instance:_do_check() features = table.wrap(features) local features_supported = self._core_tool_compiler.has_features(features, {target = self}) if features_supported and #features_supported == #features then - passed = true + passed = 1 end -- trace if baseoption.get("verbose") or baseoption.get("diagnosis") then for _, feature in ipairs(features) do - utils.cprint("${dim}checking for feature(%s) ... %s", feature, passed and "${color.success}${text.success}" or "${color.nothing}${text.nothing}") + utils.cprint("${dim}checking for feature(%s) ... %s", feature, passed > 0 and "${color.success}${text.success}" or "${color.nothing}${text.nothing}") end end end + return true, passed +end - -- enable this option if be passed +-- check option conditions +function _instance:_do_check() + + -- check snippets + local ok, passed, errors = self:_do_check_cxsnippts() + if not ok then + return false, errors + end + + -- get snippet output + local output if passed then - self:enable(true) + output = errors end - -- ok + -- check features + if passed == 0 then + ok, passed, errors = self:_do_check_features() + if not ok then + return false, errors + end + end + + -- enable this option if be passed + if passed > 0 then + self:enable(true) + if output then + self:set_value(output) + end + end return true end diff --git a/xmake/includes/check_csnippets.lua b/xmake/includes/check_csnippets.lua index 6cd4ccdc9..06fdc842e 100644 --- a/xmake/includes/check_csnippets.lua +++ b/xmake/includes/check_csnippets.lua @@ -23,13 +23,17 @@ -- e.g. -- -- check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");", {includes = "stdio.h"}) +-- check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) option(optname) - add_csnippets(definition, snippets) - add_defines(definition) + add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) + if not opt.output then + add_defines(definition) + end if opt.links then add_links(opt.links) end @@ -51,6 +55,17 @@ function check_csnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + if opt.number then + option:add("defines", definition .. "=" .. tonumber(option:value())) + else + option:add("defines", definition .. "=\"" .. option:value() .. "\"") + end + end + end) + end option_end() add_options(optname) end @@ -60,13 +75,15 @@ end -- e.g. -- -- configvar_check_csnippets("HAS_STATIC_ASSERT", "_Static_assert(1, \"\");", {includes = "stdio.h"}) +-- configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_csnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - add_csnippets(definition, snippets) + add_csnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) set_configvar(defname, defval or 1) if opt.links then add_links(opt.links) @@ -89,6 +106,13 @@ function configvar_check_csnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + end + end) + end option_end() add_options(optname) end diff --git a/xmake/includes/check_cxxsnippets.lua b/xmake/includes/check_cxxsnippets.lua index 2e906100b..8f0f6f64d 100644 --- a/xmake/includes/check_cxxsnippets.lua +++ b/xmake/includes/check_cxxsnippets.lua @@ -23,13 +23,17 @@ -- e.g. -- -- check_cxxsnippets("HAS_STATIC_ASSERT", "static_assert(1, \"\");") +-- check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) option(optname) - add_cxxsnippets(definition, snippets) - add_defines(definition) + add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) + if not opt.output then + add_defines(definition) + end if opt.links then add_links(opt.links) end @@ -51,6 +55,17 @@ function check_cxxsnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + if opt.number then + option:add("defines", definition .. "=" .. tonumber(option:value())) + else + option:add("defines", definition .. "=\"" .. option:value() .. "\"") + end + end + end) + end option_end() add_options(optname) end @@ -60,13 +75,15 @@ end -- e.g. -- -- configvar_check_cxxsnippets("HAS_STATIC_ASSERT", "static_assert(1, \"\");") +-- configvar_check_cxxsnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) +-- configvar_check_cxxsnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true}) -- function configvar_check_cxxsnippets(definition, snippets, opt) opt = opt or {} local optname = "__" .. (opt.name or definition) local defname, defval = unpack(definition:split('=')) option(optname) - add_cxxsnippets(definition, snippets) + add_cxxsnippets(definition, snippets, {tryrun = opt.tryrun, output = opt.output}) set_configvar(defname, defval or 1) if opt.links then add_links(opt.links) @@ -89,6 +106,13 @@ function configvar_check_cxxsnippets(definition, snippets, opt) if opt.warnings then set_warnings(opt.warnings) end + if opt.output then + after_check(function (option) + if option:value() then + option:set("configvar", defname, opt.number and tonumber(option:value()) or option:value()) + end + end) + end option_end() add_options(optname) end diff --git a/xmake/modules/lib/detect/check_cxsnippets.lua b/xmake/modules/lib/detect/check_cxsnippets.lua index aa728e27b..5352301b0 100644 --- a/xmake/modules/lib/detect/check_cxsnippets.lua +++ b/xmake/modules/lib/detect/check_cxsnippets.lua @@ -77,7 +77,11 @@ function _sourcecode(snippets, opt) -- add includes local sourcecode = "" - for _, include in ipairs(opt.includes) do + local includes = table.wrap(opt.includes) + if opt.tryrun and opt.output then + table.insert(includes, "stdio.h") + end + for _, include in ipairs(includes) do sourcecode = format("%s\n#include <%s>", sourcecode, include) end sourcecode = sourcecode .. "\n" @@ -88,11 +92,13 @@ function _sourcecode(snippets, opt) end sourcecode = sourcecode .. "\n" - -- add snippets - for _, snippet in pairs(snippets) do - sourcecode = sourcecode .. "\n" .. snippet + -- add snippets (build only) + if not opt.tryrun then + for _, snippet in pairs(snippets) do + sourcecode = sourcecode .. "\n" .. snippet + end + sourcecode = sourcecode .. "\n" end - sourcecode = sourcecode .. "\n" -- enter main function sourcecode = sourcecode .. "int main(int argc, char** argv)\n{\n" @@ -102,10 +108,19 @@ function _sourcecode(snippets, opt) sourcecode = format("%s\n %s;", sourcecode, _funccode(funcinfo)) end - -- leave main function - sourcecode = sourcecode .. "\n return 0;\n}\n" - - -- done + -- add snippets (tryrun) + if opt.tryrun then + for _, snippet in pairs(snippets) do + sourcecode = sourcecode .. "\n" .. snippet + end + if opt.output then + sourcecode = sourcecode .. "\nfflush(stdout);\n" + end + sourcecode = sourcecode .. "\n}\n" -- we need return exit code in snippet + else + -- leave main function + sourcecode = sourcecode .. "\n return 0;\n}\n" + end return sourcecode end @@ -116,7 +131,8 @@ end -- e.g. -- { verbose = false, target = [target|option], sourcekind = "[cc|cxx]" -- , types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"} --- , configs = {defines = "xx", cxflags = ""}} +-- , configs = {defines = "xx", cxflags = ""} +-- , tryrun = true, output = true} -- -- funcs: -- sigsetjmp @@ -189,19 +205,30 @@ function main(snippets, opt) -- @note cannot cache result, all conditions will be changed -- attempt to compile it local errors = nil - local ok = try + local ok, output = try { function () if option.get("diagnosis") then cprint("${dim}> %s", compiler.compcmd(sourcefile, objectfile, opt)) end compiler.compile(sourcefile, objectfile, opt) - if #links > 0 then + if #links > 0 or opt.tryrun then if option.get("diagnosis") then cprint("${dim}> %s", linker.linkcmd("binary", {"cc", "cxx"}, objectfile, binaryfile, opt)) end linker.link("binary", {"cc", "cxx"}, objectfile, binaryfile, opt) end + if opt.tryrun then + if opt.output then + local output = os.iorun(binaryfile) + if output then + output = output:trim() + end + return true, output + else + os.vrun(binaryfile) + end + end return true end, catch { function (errs) errors = errs end } @@ -238,6 +265,6 @@ function main(snippets, opt) if errors and option.get("diagnosis") and #tostring(errors) > 0 then cprint("${color.warning}checkinfo:${clear dim} %s", errors) end - return ok + return ok, output end |
