summaryrefslogtreecommitdiff
path: root/xmake/modules/lib/detect/check_cxsnippets.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2017-07-05 20:48:55 +0800
committerruki <[email protected]>2017-07-05 20:48:55 +0800
commit6e0271d2e38f9b4d48ec271af225f71a0faa4f49 (patch)
tree3411187f6d73ad5d0e254aa9d681ea94e7ce9915 /xmake/modules/lib/detect/check_cxsnippets.lua
parenta8d5da851d1d469587adea086c65d61ae20c50ef (diff)
rename has_cxsnippets to check_vxsnippets
Diffstat (limited to 'xmake/modules/lib/detect/check_cxsnippets.lua')
-rw-r--r--xmake/modules/lib/detect/check_cxsnippets.lua227
1 files changed, 227 insertions, 0 deletions
diff --git a/xmake/modules/lib/detect/check_cxsnippets.lua b/xmake/modules/lib/detect/check_cxsnippets.lua
new file mode 100644
index 000000000..812d55c08
--- /dev/null
+++ b/xmake/modules/lib/detect/check_cxsnippets.lua
@@ -0,0 +1,227 @@
+--!The Make-like Build Utility based on Lua
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you 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 - 2017, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file check_cxsnippets.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.tool.linker")
+import("core.tool.compiler")
+import("core.language.language")
+
+-- get function name
+--
+-- sigsetjmp
+-- sigsetjmp((void*)0, 0)
+-- sigsetjmp{sigsetjmp((void*)0, 0);}
+-- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}
+--
+function _funcname(funcinfo)
+
+ -- parse function name
+ local name = string.match(funcinfo, "(.+){.+}")
+ if name == nil then
+ local pos = funcinfo:find("%(")
+ if pos then
+ name = funcinfo:sub(1, pos - 1)
+ else
+ name = funcinfo
+ end
+ end
+
+ -- ok
+ return name:trim()
+end
+
+-- get function code
+--
+-- sigsetjmp
+-- sigsetjmp((void*)0, 0)
+-- sigsetjmp{sigsetjmp((void*)0, 0);}
+-- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}
+--
+function _funccode(funcinfo)
+
+ -- parse function code
+ local code = string.match(funcinfo, ".+{(.+)}")
+ if code == nil then
+ local pos = funcinfo:find("%(")
+ if pos then
+ code = funcinfo
+ else
+ code = string.format("volatile void* p%s = (void*)&%s;", funcinfo, funcinfo)
+ end
+ end
+
+ -- ok
+ return code
+end
+
+-- make source code
+function _sourcecode(snippets, opt)
+
+ -- add includes
+ local sourcecode = ""
+ for _, include in ipairs(opt.includes) do
+ sourcecode = format("%s\n#include <%s>", sourcecode, include)
+ end
+ sourcecode = sourcecode .. "\n"
+
+ -- add types
+ for _, typename in ipairs(opt.types) do
+ sourcecode = format("%s\ntypedef %s __type_%s;", sourcecode, typename, typename:gsub("[^%a]", "_"))
+ end
+ sourcecode = sourcecode .. "\n"
+
+ -- add snippets
+ for _, snippet in ipairs(snippets) do
+ sourcecode = sourcecode .. "\n" .. snippet
+ end
+ sourcecode = sourcecode .. "\n"
+
+ -- enter main function
+ sourcecode = sourcecode .. "int main(int argc, char** argv)\n{\n"
+
+ -- add funcs
+ for _, funcinfo in ipairs(opt.funcs) do
+ sourcecode = format("%s\n %s;", sourcecode, _funccode(funcinfo))
+ end
+
+ -- leave main function
+ sourcecode = sourcecode .. "\n return 0;\n}\n"
+
+ -- done
+ return sourcecode
+end
+
+-- check the given c snippets?
+--
+-- @param snippets the snippets
+-- @param opt the argument options
+-- .e.g
+-- { verbose = false, target = [target|option], sourcekind = "[cc|cxx]"
+-- , types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}}
+--
+-- funcs:
+-- sigsetjmp
+-- sigsetjmp((void*)0, 0)
+-- sigsetjmp{sigsetjmp((void*)0, 0);}
+-- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}
+--
+-- @return true or false
+--
+-- @code
+-- local ok = check_cxsnippets("void test() {}")
+-- local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
+-- @endcode
+--
+function main(snippets, opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- init snippets
+ snippets = snippets or {}
+
+ -- get links
+ local links = table.wrap(opt.links)
+ if opt.target then
+ table.join2(links, opt.target:get("links"))
+ end
+
+ -- get types
+ local types = table.wrap(opt.types)
+
+ -- get includes
+ local includes = table.wrap(opt.includes)
+
+ -- get funcs
+ local funcs = {}
+ for _, funcinfo in ipairs(opt.funcs) do
+ table.insert(funcs, _funcname(funcinfo))
+ end
+
+ -- make source code
+ local sourcecode = _sourcecode(snippets, opt)
+
+ -- get c/c++ extension
+ local extension = ".c"
+ if opt.sourcekind then
+ extension = table.wrap(language.sourcekinds()[opt.sourcekind])[1] or ".c"
+ end
+
+ -- make the source file
+ local sourcefile = os.tmpfile() .. extension
+ local objectfile = os.tmpfile() .. ".o"
+ local binaryfile = os.tmpfile() .. ".b"
+ io.writefile(sourcefile, sourcecode)
+
+ -- @note cannot cache result, all conditions will be changed
+ -- attempt to compile it
+ local ok = try
+ {
+ function ()
+ compiler.compile(sourcefile, objectfile, opt)
+ if #links > 0 then
+ linker.link("binary", {"cc", "cxx"}, objectfile, binaryfile, opt)
+ end
+ return true
+ end,
+ catch
+ {
+ function (errors)
+ if option.get("verbose") then
+ cprint("${red}%s", errors)
+ end
+ end
+ }
+ }
+
+ -- remove some files
+ os.tryrm(sourcefile)
+ os.tryrm(objectfile)
+ os.tryrm(binaryfile)
+
+ -- trace
+ if opt.verbose or option.get("verbose") then
+ local kind = ifelse(sourcekind == "cc", "c", "c++")
+ if #includes > 0 then
+ cprint("checking for the %s includes %s ... %s", kind, table.concat(includes, ", "), ifelse(ok, "${green}ok", "${red}no"))
+ end
+ if #types > 0 then
+ cprint("checking for the %s types %s ... %s", kind, table.concat(types, ", "), ifelse(ok, "${green}ok", "${red}no"))
+ end
+ if #funcs > 0 then
+ cprint("checking for the %s funcs %s ... %s", kind, table.concat(funcs, ", "), ifelse(ok, "${green}ok", "${red}no"))
+ end
+ if #links > 0 then
+ cprint("checking for the %s links %s ... %s", kind, table.concat(links, ", "), ifelse(ok, "${green}ok", "${red}no"))
+ end
+ for _, snippet in ipairs(snippets) do
+ cprint("checking for the %s snippet %s ... %s", kind, snippet:sub(1, 16), ifelse(ok, "${green}ok", "${red}no"))
+ end
+ end
+
+ -- ok?
+ return ok
+end
+