diff options
| author | ruki <[email protected]> | 2017-07-04 20:44:59 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-07-04 20:44:59 +0800 |
| commit | b753a04049557b83e19e3a1f555c4a01b549ac2f (patch) | |
| tree | 5a149597a6cd3e1022dda01581f776b400d37f91 | |
| parent | 4e87aeb64724f77a5d78907bdb4707a255715622 (diff) | |
| parent | 09eb1c7424d281e454cfffda6a65718a9e284cd8 (diff) | |
merge from dev
169 files changed, 4897 insertions, 2353 deletions
diff --git a/.travis.yml b/.travis.yml index e7e12f2b2..ae11d601d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,8 @@ script: - scripts/get.sh __local__ - source ~/.xmake/profile - xmake lua versioninfo - - xmake f -m coverage -P core - - xmake -P core + - xmake f -m coverage -P core + - xmake -v -P core - export XMAKE_PROGRAM_DIR=$PWD/xmake - core/build/xmake lua versioninfo - echo "require('luacov.runner').init({['statsfile']='$PWD/luacov.stats.out',['reportfile']='$PWD/luacov.report.out'})" > tmp diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c14cc6d6..11327afc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,12 @@ * [#83](https://github.com/tboox/xmake/issues/83): Add `add_csnippet` and `add_cxxsnippet` into `option` for detecting some compiler features. * [#83](https://github.com/tboox/xmake/issues/83): Add user extension modules to detect program, libraries and files. -* Add `find_program`, `find_file` and `find_library` module interfaces. +* Add `find_program`, `find_file`, `find_library`, `find_tool` and `find_package` module interfaces. * Add `net.*` and `devel.*` extension modules * Add `val()` api to get the value of builtin-variable, .e.g `val("host")`, `val("env PATH")`, `val("shell echo hello")` and `val("reg HKEY_LOCAL_MACHINE\\XX;Value")` * Support to compile the microsoft resource file (.rc) +* Add `has_flags` module interfaces. +* Add `option.on_check`, `option.after_check` and `option.before_check` api ### Changes @@ -23,12 +25,16 @@ * Improve `xxx_script` in `xmake.lua` to support pattern match, .e.g `on_build("iphoneos|arm*", function (target) end)` * improve builtin-variables to support to get the value envirnoment and registry * Improve to detect vstudio sdk and cross toolchains envirnoment +* [#71](https://github.com/tboox/xmake/issues/71): Improve to detect compiler and linker from env vars +* Improve the option detection (cache and multi-jobs) and increase 70% speed +* [#129](https://github.com/tboox/xmake/issues/129): Check link deps and cache the target file ### Bugs fixed * Fix `try-catch-finally` * Fix interpreter bug when parsing multi-level subdirs * [#115](https://github.com/tboox/xmake/pull/115): Fix the path problem of the install script `get.sh` +* Fix cache bug for import() ## v2.1.4 @@ -304,10 +310,12 @@ * [#83](https://github.com/tboox/xmake/issues/83): 添加 `add_csnippet`,`add_cxxsnippet`到`option`来检测一些编译器特性 * [#83](https://github.com/tboox/xmake/issues/83): 添加用户扩展模块去探测程序,库文件以及其他主机环境 -* 添加`find_program`, `find_file` 和 `find_library` 等模块接口 +* 添加`find_program`, `find_file`, `find_library`, `find_tool`和`find_package` 等模块接口 * 添加`net.*`和`devel.*`扩展模块 * 添加`val()`接口去获取内置变量,例如:`val("host")`, `val("env PATH")`, `val("shell echo hello")` and `val("reg HKEY_LOCAL_MACHINE\\XX;Value")` * 增加对微软.rc资源文件的编译支持,当在windows上编译时,可以增加资源文件了 +* 增加`has_flags`模块接口 +* 添加`option.on_check`, `option.after_check` 和 `option.before_check` 接口 ### 改进 @@ -321,12 +329,16 @@ * 改进`xxx_script`工程描述api,支持多平台模式选择, 例如:`on_build("iphoneos|arm*", function (target) end)` * 改进内置变量,支持环境变量和注册表数据的获取 * 改进vstudio环境和交叉工具链的探测 +* [#71](https://github.com/tboox/xmake/issues/71): 改进从环境变量中探测链接器和编译器 +* 改进option选项检测,通过多任务检测,提升70%的检测速度 +* [#129](https://github.com/tboox/xmake/issues/129): 检测链接依赖,如果源文件没有改变,就不必重新链接目标文件了 ### Bugs修复 * 修复`try-catch-finally` * 修复解释器bug,解决当加载多级子目录时,根域属性设置不对 * [#115](https://github.com/tboox/xmake/pull/115): 修复安装脚本`get.sh`的路径问题 +* 修复`import()`导入接口的缓存问题 ## v2.1.4 diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c index e1638e1ab..7f1acfbd0 100644 --- a/core/src/xmake/machine.c +++ b/core/src/xmake/machine.c @@ -99,7 +99,6 @@ tb_int_t xm_winreg_query(lua_State* lua); #endif // the string functions -tb_int_t xm_string_strcmp(lua_State* lua); tb_int_t xm_string_endswith(lua_State* lua); tb_int_t xm_string_startswith(lua_State* lua); @@ -172,8 +171,7 @@ static luaL_Reg const g_path_functions[] = // the string functions static luaL_Reg const g_string_functions[] = { - { "strcmp", xm_string_strcmp } -, { "endswith", xm_string_endswith } + { "endswith", xm_string_endswith } , { "startswith", xm_string_startswith } , { tb_null, tb_null } }; diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index efc32d94d..e9f5badce 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -45,7 +45,6 @@ xmake_C_FILES += \ path/translate \ path/is_absolute \ winreg/query \ - string/strcmp \ string/endswith \ string/startswith \ process/open \ diff --git a/core/src/xmake/process/waitlist.c b/core/src/xmake/process/waitlist.c index 3e5d20aa0..b577c87f4 100644 --- a/core/src/xmake/process/waitlist.c +++ b/core/src/xmake/process/waitlist.c @@ -71,7 +71,7 @@ tb_int_t xm_process_waitlist(lua_State* lua) if (count <= 0 || count > 64) { // error - lua_pushfstring(lua, "invalid process count(%ld) for process.waitlist", count); + lua_pushfstring(lua, "invalid process count(%d) for process.waitlist", count); lua_error(lua); return 0; } diff --git a/core/src/xmake/string/endswith.c b/core/src/xmake/string/endswith.c index 241e59254..8de61e2bb 100644 --- a/core/src/xmake/string/endswith.c +++ b/core/src/xmake/string/endswith.c @@ -49,9 +49,9 @@ tb_int_t xm_string_endswith(lua_State* lua) tb_char_t const* suffix = luaL_checklstring(lua, 2, &suffix_size); tb_check_return_val(string && suffix, 0); - // done string:endswith(suffix) - if (string_size >= suffix_size) - lua_pushboolean(lua, !tb_strcmp(string + string_size - suffix_size, suffix)); + // string:endswith(suffix)? + lua_pushboolean(lua, string_size >= suffix_size && !tb_strcmp(string + string_size - suffix_size, suffix)); + // ok return 1; diff --git a/core/src/xmake/string/startswith.c b/core/src/xmake/string/startswith.c index 84766e5ca..de039dede 100644 --- a/core/src/xmake/string/startswith.c +++ b/core/src/xmake/string/startswith.c @@ -48,7 +48,7 @@ tb_int_t xm_string_startswith(lua_State* lua) tb_char_t const* prefix = luaL_checklstring(lua, 2, &prefix_size); tb_check_return_val(string && prefix, 0); - // done string:startswith(prefix) + // string:startswith(prefix)? lua_pushboolean(lua, !tb_strncmp(string, prefix, (tb_size_t)prefix_size)); // ok diff --git a/core/src/xmake/string/strcmp.c b/core/src/xmake/string/strcmp.c deleted file mode 100644 index 2ad06f27d..000000000 --- a/core/src/xmake/string/strcmp.c +++ /dev/null @@ -1,57 +0,0 @@ -/*!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 strcmp.c - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "strcmp" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ - -// string:strcmp(s1, s2) -tb_int_t xm_string_strcmp(lua_State* lua) -{ - // check - tb_assert_and_check_return_val(lua, 0); - - // get the strings - tb_char_t const* s1 = luaL_checkstring(lua, 1); - tb_char_t const* s2 = luaL_checkstring(lua, 2); - tb_check_return_val(s1 && s2, 0); - - // compare them - lua_pushinteger(lua, tb_strcmp(s1, s2)); - - // ok - return 1; -} diff --git a/scripts/installer.nsi b/scripts/installer.nsi index e2deebfc0..f4dd014b5 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -44,6 +44,13 @@ RequestExecutionLevel admin !insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+; Finish Pages
+
+!define MUI_FINISHPAGE_LINK "Donate $$5"
+!define MUI_FINISHPAGE_LINK_LOCATION "http://xmake.io/pages/donation.html#donate"
+!insertmacro MUI_PAGE_FINISH
;--------------------------------
; Languages
@@ -53,13 +60,13 @@ RequestExecutionLevel admin ;--------------------------------
; Version Information
-VIProductVersion "2.1.4.0402"
+VIProductVersion "2.1.5.0630"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "XMake"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "website: http://www.xmake.io"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "The TBOOX Open Source Group"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright 2015-2017 tboox.org"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "The Make-like Build Utility based on Lua"
-VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "2.1.4"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "2.1.5"
;--------------------------------
diff --git a/tests/build.lua b/tests/build.lua index 226fddacf..fa8b59e2a 100644 --- a/tests/build.lua +++ b/tests/build.lua @@ -4,6 +4,9 @@ import("privilege.sudo") -- main entry function main(argv) + -- check global config + os.exec("xmake g -c") + -- generic? os.exec("xmake m -b") os.exec("xmake f -c") diff --git a/tests/modules/lib/detect/test.lua b/tests/modules/lib/detect/test.lua new file mode 100755 index 000000000..c44084ddc --- /dev/null +++ b/tests/modules/lib/detect/test.lua @@ -0,0 +1,14 @@ +import("lib.detect.find_toolname") + +function main() + assert(find_toolname("xcrun -sdk macosx clang") == "clang") + assert(find_toolname("xcrun -sdk macosx clang++") == "clangxx") + assert(find_toolname("/usr/bin/arm-linux-gcc") == "gcc") + assert(find_toolname("/usr/bin/arm-linux-g++") == "gxx") + assert(find_toolname("/usr/bin/arm-linux-ar") == "ar") + assert(find_toolname("link.exe -lib") == "link") + assert(find_toolname("arm-android-clang++") == "clangxx") + assert(find_toolname("pkg-config") == "pkg_config") + assert(find_toolname("gcc-5") == "gcc") +end + diff --git a/tests/modules/string/test.lua b/tests/modules/string/test.lua index b2e7a23c7..98c76661f 100644 --- a/tests/modules/string/test.lua +++ b/tests/modules/string/test.lua @@ -1,4 +1,5 @@ function main() - assert(string.less("awd","dwa")) - assert(not string.less("dwa","awd")) + assert(not ("rc"):endswith("xcadas")) + assert(("aaaccc"):endswith("ccc")) + assert(("aaaccc"):startswith("aaa")) end diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/kinds/binary.lua index b7dd5f512..52baad2a3 100644 --- a/xmake/actions/build/kinds/binary.lua +++ b/xmake/actions/build/kinds/binary.lua @@ -34,6 +34,11 @@ function _build_from_objects(target, buildinfo) -- build objects object.build(target, buildinfo) + -- the object files are not modified? + if not buildinfo.objects_modified then + return + end + -- expand object files with *.o/obj local objectfiles = {} for _, objectfile in ipairs(target:objectfiles()) do @@ -67,7 +72,7 @@ function _build_from_objects(target, buildinfo) end -- link it - linker.link(objectfiles, targetfile, target) + linker.link(target:get("kind"), target:sourcekinds(), objectfiles, targetfile, {target = target}) end -- build target from sources @@ -89,11 +94,11 @@ function _build_from_sources(target, buildinfo, sourcebatch, sourcekind) -- trace verbose info if verbose then - print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, target, sourcekind)) + print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind})) end -- build it - compiler.build(sourcebatch.sourcefiles, targetfile, target, sourcekind) + compiler.build(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind}) end -- build binary target diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua index aa738108d..513cb2b9e 100644 --- a/xmake/actions/build/kinds/object.lua +++ b/xmake/actions/build/kinds/object.lua @@ -24,11 +24,10 @@ -- imports import("core.base.option") -import("core.tool.tool") import("core.tool.compiler") import("core.tool.extractor") import("core.project.config") -import("detect.tool.find_ccache") +import("detect.tools.find_ccache") -- build the object from the *.[o|obj] source file function _build_from_object(target, sourcefile, objectfile, percent) @@ -75,7 +74,7 @@ function _build_from_static(target, sourcefile, objectfile, percent) end -- build object -function _build_object(target, buildinfo, index, sourcebatch) +function _build_object(target, buildinfo, index, sourcebatch, ccache) -- get the object and source with the given index local sourcefile = sourcebatch.sourcefiles[index] @@ -141,15 +140,12 @@ function _build_object(target, buildinfo, index, sourcebatch) return end + -- the object files are modified + buildinfo.objects_modified = true + -- is verbose? local verbose = option.get("verbose") - -- get ccache - local ccache = nil - if config.get("ccache") then - ccache = find_ccache() - end - -- trace percent info if verbose then cprint("${green}[%02d%%]:${dim} %scompiling.$(mode) %s", percent, ifelse(ccache, "ccache ", ""), sourcefile) @@ -159,15 +155,15 @@ function _build_object(target, buildinfo, index, sourcebatch) -- trace verbose info if verbose then - print(compiler.compcmd(sourcefile, objectfile, target)) + print(compiler.compcmd(sourcefile, objectfile, {target = target})) end -- complie it - compiler.compile(sourcefile, objectfile, incdepfile, target) + compiler.compile(sourcefile, objectfile, {incdepfiles = incdepfile, target = target}) end -- build each objects from the given source batch -function _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs) +function _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs, ccache) -- run build jobs for each source file local curdir = os.curdir() @@ -177,7 +173,7 @@ function _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs) os.cd(curdir) -- build object - _build_object(target, buildinfo, index, sourcebatch) + _build_object(target, buildinfo, index, sourcebatch, ccache) end, #sourcebatch.sourcefiles, jobs) @@ -186,7 +182,7 @@ function _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs) end -- compile source files to single object at the same time -function _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs) +function _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs, ccache) -- is verbose? local verbose = option.get("verbose") @@ -196,12 +192,6 @@ function _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs) local objectfiles = sourcebatch.objectfiles local incdepfiles = sourcebatch.incdepfiles - -- get ccache - local ccache = nil - if config.get("ccache") then - ccache = find_ccache() - end - -- trace percent info for index, sourcefile in ipairs(sourcefiles) do @@ -218,11 +208,11 @@ function _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs) -- trace verbose info if verbose then - print(compiler.compcmd(sourcefiles, objectfiles, target, sourcekind)) + print(compiler.compcmd(sourcefiles, objectfiles, {target = target, sourcekind = sourcekind})) end -- complie them - compiler.compile(sourcefiles, objectfiles, incdepfiles, target, sourcekind) + compiler.compile(sourcefiles, objectfiles, {incdepfiles = incdepfiles, target = target, sourcekind = sourcekind}) -- update object index _g.sourceindex = _g.sourceindex + #sourcebatch.sourcefiles @@ -238,6 +228,12 @@ function build(target, buildinfo) -- get the max job count local jobs = tonumber(option.get("jobs") or "4") + -- get ccache + local ccache = nil + if config.get("ccache") then + ccache = find_ccache() + end + -- build source batches for sourcekind, sourcebatch in pairs(target:sourcebatches()) do @@ -245,12 +241,12 @@ function build(target, buildinfo) if type(sourcebatch.objectfiles) == "string" then -- build single object - _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs) + _build_single_object(target, buildinfo, sourcekind, sourcebatch, jobs, ccache) else -- build each objects - _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs) + _build_each_objects(target, buildinfo, sourcekind, sourcebatch, jobs, ccache) end end end diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/kinds/shared.lua index ab2cd40b0..d4fa90257 100644 --- a/xmake/actions/build/kinds/shared.lua +++ b/xmake/actions/build/kinds/shared.lua @@ -34,6 +34,11 @@ function _build_from_objects(target, buildinfo) -- build objects object.build(target, buildinfo) + -- the object files are not modified? + if not buildinfo.objects_modified then + return + end + -- make headers local srcheaders, dstheaders = target:headerfiles() if srcheaders and dstheaders then @@ -80,7 +85,7 @@ function _build_from_objects(target, buildinfo) end -- link it - linker.link(objectfiles, targetfile, target) + linker.link(target:get("kind"), target:sourcekinds(), objectfiles, targetfile, {target = target}) end -- build target from sources @@ -102,11 +107,11 @@ function _build_from_sources(target, buildinfo, sourcebatch, sourcekind) -- trace verbose info if verbose then - print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, target, sourcekind)) + print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind})) end -- build it - compiler.build(sourcebatch.sourcefiles, targetfile, target, sourcekind) + compiler.build(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind}) end -- build shared target diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/kinds/static.lua index 6dcacbd30..9b73742a3 100644 --- a/xmake/actions/build/kinds/static.lua +++ b/xmake/actions/build/kinds/static.lua @@ -34,6 +34,11 @@ function _build_from_objects(target, buildinfo) -- build objects object.build(target, buildinfo) + -- the object files are not modified? + if not buildinfo.objects_modified then + return + end + -- make headers local srcheaders, dstheaders = target:headerfiles() if srcheaders and dstheaders then @@ -80,7 +85,7 @@ function _build_from_objects(target, buildinfo) end -- link it - linker.link(objectfiles, targetfile, target) + linker.link(target:get("kind"), target:sourcekinds(), objectfiles, targetfile, {target = target}) end -- build target from sources @@ -102,11 +107,11 @@ function _build_from_sources(target, buildinfo, sourcebatch, sourcekind) -- trace verbose info if verbose then - print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, target, sourcekind)) + print(compiler.buildcmd(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind})) end -- build it - compiler.build(sourcebatch.sourcefiles, targetfile, target, sourcekind) + compiler.build(sourcebatch.sourcefiles, targetfile, {target = target, sourcekind = sourcekind}) end -- build static target diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua index 18df4afb9..95ea22206 100644 --- a/xmake/actions/build/main.lua +++ b/xmake/actions/build/main.lua @@ -27,9 +27,8 @@ import("core.base.option") import("core.project.task") import("core.project.config") import("core.project.project") -import("core.project.cache") +import("core.project.cache", {nocache = true}) import("core.platform.platform") -import("core.tool.tool") import("builder") -- main diff --git a/xmake/actions/config/main.lua b/xmake/actions/config/main.lua index 2f5edceba..07588378c 100644 --- a/xmake/actions/config/main.lua +++ b/xmake/actions/config/main.lua @@ -28,8 +28,8 @@ import("core.project.config") import("core.project.global") import("core.project.project") import("core.platform.platform") -import("core.project.cache") -import("lib.detect.clear_cache") +import("core.project.cache", {nocache = true}) +import("lib.detect.cache", {alias = "detectcache"}) import("scanner") import("configheader") @@ -234,7 +234,7 @@ function main() cache.set("rebuild", true) -- clear detect cache - clear_cache() + detectcache.clear() end -- merge the cached configure @@ -277,10 +277,8 @@ function main() configheader.make() end - -- trace - if recheck or option.get("verbose") then - - -- dump it + -- dump config + if option.get("verbose") then config.dump() end diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua index 39bb5f225..58af78d66 100644 --- a/xmake/core/_xmake_main.lua +++ b/xmake/core/_xmake_main.lua @@ -33,13 +33,10 @@ xmake._VERSION_SHORT = _VERSION_SHORT xmake._PROGRAM_DIR = _PROGRAM_DIR xmake._PROGRAM_FILE = _PROGRAM_FILE xmake._PROJECT_DIR = _PROJECT_DIR -xmake._CORE_DIR = _PROGRAM_DIR .. "/core" -xmake._TOOLS_DIR = _PROGRAM_DIR .. "/tools" -xmake._TEMPLATES_DIR = _PROGRAM_DIR .. "/templates" xmake._PROJECT_FILE = "xmake.lua" -- init package path -package.path = xmake._CORE_DIR .. "/?.lua;" .. package.path +package.path = xmake._PROGRAM_DIR .. "/core/?.lua;" .. package.path -- load modules local main = require("main") diff --git a/xmake/core/base/filter.lua b/xmake/core/base/filter.lua index f9744bf61..9dd146ac6 100644 --- a/xmake/core/base/filter.lua +++ b/xmake/core/base/filter.lua @@ -31,6 +31,10 @@ local table = require("base/table") local utils = require("base/utils") local string = require("base/string") +-- globals +local escape_table1 = {["$"] = "\001", ["("] = "\002", [")"] = "\003", ["%"] = "\004"} +local escape_table2 = {["\001"] = "$", ["\002"] = "(", ["\003"] = ")", ["\004"] = "%"} + -- new filter instance function filter.new() @@ -155,10 +159,19 @@ function filter:handle(value) -- check assert(type(value) == "string") + -- escape "%$", "%(", "%)", "%%" to "\001", "\002", "\003", "\004" + value = value:gsub("%%([%$%(%)%%])", function (ch) return escape_table1[ch] end) + -- filter the builtin variables return (value:gsub("%$%((.-)%)", function (variable) + + -- escape "%$", "%(", "%)", "%%" to "$", "(", ")", "%" + variable = variable:gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end) + + -- get variable value return self:get(variable) or "" - end)) + + end):gsub("[\001\002\003\004]", function (ch) return escape_table2[ch] end)) end -- return module: filter diff --git a/xmake/core/base/interpreter.lua b/xmake/core/base/interpreter.lua index 5c51b35e4..c23fa8457 100644 --- a/xmake/core/base/interpreter.lua +++ b/xmake/core/base/interpreter.lua @@ -700,7 +700,7 @@ function interpreter.new() instance:api_register(nil, "set_xmakever", interpreter.api_builtin_set_xmakever) -- load builtin module files - local builtin_module_files = os.match(path.join(xmake._CORE_DIR, "sandbox/modules/interpreter/*.lua")) + local builtin_module_files = os.match(path.join(os.programdir(), "core/sandbox/modules/interpreter/*.lua")) if builtin_module_files then for _, builtin_module_file in ipairs(builtin_module_files) do diff --git a/xmake/core/base/option.lua b/xmake/core/base/option.lua index a2388c91e..e780656d4 100644 --- a/xmake/core/base/option.lua +++ b/xmake/core/base/option.lua @@ -479,7 +479,7 @@ function option.init(menu) end -- init the default value - for _, o in ipairs(option._taskmenu().options) do + for _, o in ipairs(table.wrap(option._taskmenu().options)) do -- the long name local longname = option._longname(o[2]) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 5c7ca78e2..6616c2849 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -442,7 +442,7 @@ function os.tmpfile() return path.join(os.tmpdir(), "_" .. (os.uuid():gsub("-", ""))) end --- run shell +-- run command function os.run(cmd) -- parse arguments @@ -455,23 +455,23 @@ function os.run(cmd) return os.runv(argv[1], table.slice(argv, 2)) end --- run shell with arguments list -function os.runv(shellname, argv) +-- run command with arguments list +function os.runv(program, argv) -- make temporary log file local log = os.tmpfile() -- execute it - local ok = os.execv(shellname, argv, log, log) + local ok = os.execv(program, argv, log, log) if ok ~= 0 then -- make errors local errors = io.readfile(log) if not errors or #errors == 0 then if argv ~= nil then - errors = string.format("runv(%s %s) failed(%d)!", shellname, table.concat(argv, ' '), ok) + errors = string.format("runv(%s %s) failed(%d)!", program, table.concat(argv, ' '), ok) else - errors = string.format("runv(%s) failed(%d)!", shellname, ok) + errors = string.format("runv(%s) failed(%d)!", program, ok) end end @@ -489,7 +489,7 @@ function os.runv(shellname, argv) return true end --- execute shell +-- execute command function os.exec(cmd, outfile, errfile) -- parse arguments @@ -502,12 +502,31 @@ function os.exec(cmd, outfile, errfile) return os.execv(argv[1], table.slice(argv, 2), outfile, errfile) end --- execute shell with arguments list -function os.execv(shellname, argv, outfile, errfile) +-- execute command with arguments list +-- +-- program: "clang", "xcrun -sdk macosx clang", "~/dir/test\ xxx/clang" +-- filename: "clang", "xcrun"", "~/dir/test\ xxx/clang" +-- +function os.execv(program, argv, outfile, errfile) + + -- init arguments + local args = os.argw(argv) + + -- is not executable program file? + local filename = program + if not os.isexec(program) then + + -- parse the filename and arguments, .e.g "xcrun -sdk macosx clang" + local splitinfo = program:split("%s") + filename = splitinfo[1] + if #splitinfo > 1 then + args = table.join(table.slice(splitinfo, 2), args) + end + end -- open command local ok = -1 - local proc = process.openv(shellname, os.argw(argv), outfile, errfile) + local proc = process.openv(filename, args, outfile, errfile) if proc ~= nil then -- wait process @@ -546,7 +565,7 @@ function os.execv(shellname, argv, outfile, errfile) return ok end --- run shell and return output and error data +-- run command and return output and error data function os.iorun(cmd) -- parse arguments @@ -559,15 +578,15 @@ function os.iorun(cmd) return os.iorunv(argv[1], table.slice(argv, 2)) end --- run shell with arguments and return output and error data -function os.iorunv(shellname, argv) +-- run command with arguments and return output and error data +function os.iorunv(program, argv) -- make temporary output and error file local outfile = os.tmpfile() local errfile = os.tmpfile() -- run command - local ok = os.execv(shellname, argv, outfile, errfile) + local ok = os.execv(program, argv, outfile, errfile) -- get output and error data local outdata = io.readfile(outfile) @@ -595,7 +614,7 @@ function os.raise(msg, ...) end end --- is executable program? +-- is executable program file? function os.isexec(filepath) -- check @@ -677,23 +696,28 @@ function os.addenv(name, ...) -- append values return os.setenv(name, table.concat({...}, seperator) .. seperator .. (os.getenv(name) or "")) - end -- get the program directory function os.programdir() - - -- get it return xmake._PROGRAM_DIR end -- get the program file function os.programfile() - - -- get it return xmake._PROGRAM_FILE end +-- get the project directory +function os.projectdir() + return xmake._PROJECT_DIR +end + +-- get the project file +function os.projectfile() + return xmake._PROJECT_FILE +end + -- get version info function os.versioninfo() diff --git a/xmake/core/base/process.lua b/xmake/core/base/process.lua index 8cf96b2ea..76af563b4 100644 --- a/xmake/core/base/process.lua +++ b/xmake/core/base/process.lua @@ -101,53 +101,51 @@ function process.runjobs(jobfunc, total, comax, timeout, timer) -- wait processes local tasks_finished = {} local procs_count = #procs + local procs_infos = nil if procs_count > 0 then - - -- wait them - local count, procinfos = process.waitlist(procs, utils.ifelse(procs_count < comax and index <= total, 0, timeout)) + local count = -1 + count, procs_infos = process.waitlist(procs, utils.ifelse(#tasks < comax and index <= total, 0, timeout)) if count < 0 then return false, string.format("wait processes(%d) failed(%d)", #procs, count) end + end - -- timer is triggered? call timer - if timer and os.mclock() - time > timeout then - timer(indices) - time = os.mclock() - end - - -- wait ok - for _, procinfo in ipairs(procinfos) do - - -- the process info - local proc = procinfo[1] - local procid = procinfo[2] - local status = procinfo[3] - - -- check - assert(procs[procid] == proc) - - -- resume this task - local job_task = tasks[procid] - local ok, job_proc_or_errors = coroutine.resume(job_task, 1, status) - if not ok then - return false, job_proc_or_errors - end + -- timer is triggered? call timer + if timer and os.mclock() - time > timeout then + timer(indices) + time = os.mclock() + end - -- the other process is pending for this task? - if coroutine.status(job_task) ~= "dead" then + -- append fake procs_infos for coroutine.yield() + procs_infos = procs_infos or {} + for taskid = #procs + 1, #tasks do + table.insert(procs_infos, {nil, taskid, 0}) + end - -- check - assert(job_proc_or_errors) + -- wait ok + for _, procinfo in ipairs(procs_infos) do + + -- the process info + local proc = procinfo[1] + local taskid = procinfo[2] + local status = procinfo[3] - -- update the pending process - procs[procid] = job_proc_or_errors + -- check + assert(procs[taskid] == proc) - -- this task has been finised? - else + -- resume this task + local job_task = tasks[taskid] + local ok, job_proc_or_errors = coroutine.resume(job_task, 1, status) + if not ok then + return false, job_proc_or_errors + end - -- mark this task as finised - tasks_finished[procid] = true - end + -- the other process is pending for this task? + if coroutine.status(job_task) ~= "dead" then + procs[taskid] = job_proc_or_errors + else + -- mark this task as finished? + tasks_finished[taskid] = true end end @@ -156,18 +154,26 @@ function process.runjobs(jobfunc, total, comax, timeout, timer) local procs_pending = {} local indices_pending = {} for taskid, job_task in ipairs(tasks) do - if not tasks_finished[taskid] then + if not tasks_finished[taskid] and procs[taskid] ~= nil then -- for coroutine.yield(proc) in os.execv table.insert(tasks_pending, job_task) table.insert(procs_pending, procs[taskid]) table.insert(indices_pending, indices[taskid]) end end + for taskid, job_task in ipairs(tasks) do + if not tasks_finished[taskid] and procs[taskid] == nil then -- for coroutine.yield() + table.insert(tasks_pending, job_task) + table.insert(indices_pending, indices[taskid]) + end + end tasks = tasks_pending procs = procs_pending indices = indices_pending -- produce tasks - while #tasks < comax and index <= total do + tasks_pending = {} + indices_pending = {} + while (#tasks + #tasks_pending) < comax and index <= total do -- new task local job_task = coroutine.create(jobfunc) @@ -180,20 +186,24 @@ function process.runjobs(jobfunc, total, comax, timeout, timer) -- add pending tasks if coroutine.status(job_task) ~= "dead" then - - -- check - assert(job_proc_or_errors) - - -- put task and proc to the pendings tasks - table.insert(tasks, job_task) - table.insert(procs, job_proc_or_errors) - table.insert(indices, index) + if job_proc_or_errors ~= nil then -- for coroutine.yield(proc) in os.execv + table.insert(tasks, job_task) + table.insert(procs, job_proc_or_errors) + table.insert(indices, index) + else + table.insert(tasks_pending, job_task) + table.insert(indices_pending, index) + end end -- next index index = index + 1 end + -- append pending tasks without process + table.join2(tasks, tasks_pending) + table.join2(indices, indices_pending) + until #tasks == 0 -- ok diff --git a/xmake/core/base/string.lua b/xmake/core/base/string.lua index f54f7b1a3..97945851e 100644 --- a/xmake/core/base/string.lua +++ b/xmake/core/base/string.lua @@ -131,13 +131,6 @@ function string.join(items, sep) return str end --- less than -function string:less(other) - - -- < ? - return string.strcmp(self, other) < 0 -end - -- try to format function string.tryformat(format, ...) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 7e8438b8d..023166f69 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -315,9 +315,6 @@ end -- remove repeat from the given array function table.unique(array) - -- check - assert(array) - -- remove repeat if type(array) == "table" then diff --git a/xmake/core/language/language.lua b/xmake/core/language/language.lua index c860b1a2a..dbe66b6b8 100644 --- a/xmake/core/language/language.lua +++ b/xmake/core/language/language.lua @@ -82,15 +82,11 @@ end -- get the language menu function _instance:menu() - - -- get it return self._INFO.menu end -- get the language name function _instance:name() - - -- get it return self._NAME end @@ -119,15 +115,11 @@ end -- get the source kinds function _instance:sourcekinds() - - -- get it return self._INFO.sourcekinds end -- get the source flags function _instance:sourceflags() - - -- get it return self._INFO.sourceflags end @@ -137,8 +129,6 @@ end -- {binary = "ld", static = "ar", shared = "sh"} -- function _instance:targetkinds() - - -- get it return self._INFO.targetkinds end @@ -658,7 +648,7 @@ function language.targetkinds() -- merge all for each language local targetkinds = {} for name, instance in pairs(languages) do - for targetkind, linkerkind in pairs(instance:targetkinds()) do + for targetkind, linkerkind in pairs(table.wrap(instance:targetkinds())) do targetkinds[targetkind] = targetkinds[targetkind] or {} table.insert(targetkinds[targetkind], linkerkind) end diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua index 76ff5ff93..26852b60e 100644 --- a/xmake/core/platform/platform.lua +++ b/xmake/core/platform/platform.lua @@ -241,13 +241,13 @@ end -- function platform.tool(toolkind) - -- attempt to get it from config first - local toolpath = config.get(toolkind) - if toolpath ~= nil then - return toolpath + -- attempt to get program from config first + local program = config.get(toolkind) + if program then + return program else - -- check the tool path + -- check it first local check = platform.get("check") if check then check("config", toolkind) diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua index 72cc0d750..501f9ce69 100644 --- a/xmake/core/project/option.lua +++ b/xmake/core/project/option.lua @@ -26,18 +26,19 @@ local option = option or {} -- load modules -local io = require("base/io") -local os = require("base/os") -local path = require("base/path") -local table = require("base/table") -local utils = require("base/utils") -local option_ = require("base/option") -local config = require("project/config") -local cache = require("project/cache") -local linker = require("tool/linker") -local compiler = require("tool/compiler") -local sandbox = require("sandbox/sandbox") -local language = require("language/language") +local io = require("base/io") +local os = require("base/os") +local path = require("base/path") +local table = require("base/table") +local utils = require("base/utils") +local option_ = require("base/option") +local config = require("project/config") +local cache = require("project/cache") +local linker = require("tool/linker") +local compiler = require("tool/compiler") +local sandbox = require("sandbox/sandbox") +local language = require("language/language") +local import = require("sandbox/modules/import") -- get cache function option._cache() @@ -54,370 +55,92 @@ function option._cache() return option._CACHE end --- check link -function option:_check_link(sourcefile, objectfile, targetfile) +-- check option for c/c++ +function option:_cx_check() - -- check - assert(sourcefile and objectfile and targetfile) - - -- update source kinds - self._SOURCEKINDS = language.sourcekind_of(sourcefile) - - -- load the linker instance - local instance = linker.load("binary", self._SOURCEKINDS) - if not instance then - return false - end - - -- attempt to link it - return instance:link(objectfile, targetfile, self) -end - --- check include -function option:_check_include(include, srcpath, objpath) - - -- check - assert(srcpath and objpath) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then - return false - end - - -- make include - if include then - srcfile:print("#include <%s>\n", include) - end - - -- make the main function header - srcfile:print("int main(int argc, char** argv)") - srcfile:print("{") - srcfile:print(" return 0;") - srcfile:print("}") - - -- exit this file - srcfile:close() - - -- load the compiler instance - local instance = compiler.load(language.sourcekind_of(srcpath)) - if not instance then - return false - end - - -- attempt to compile it - return instance:compile(srcpath, objpath, nil, self) -end - --- check function -function option:_check_function(checkcode, srcpath, objpath) - - -- check - assert(checkcode) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then - return false - end - - -- get source kind - local sourcekind = language.sourcekind_of(srcpath) - - -- load the compiler instance - local instance = compiler.load(sourcekind) - if not instance then - return false - end - - -- make includes - local includes = nil - if sourcekind == "cc" then includes = self:get("cincludes") - elseif sourcekind == "cxx" then includes = self:get("cxxincludes") - end - if includes then - for _, include in ipairs(table.wrap(includes)) do - srcfile:print("#include <%s>", include) - end - srcfile:print("") - end - - -- make the main function header - srcfile:print("int main(int argc, char** argv)") - srcfile:print("{") - - -- make check code - srcfile:print(" %s;", checkcode) - - -- make the main function tailer - srcfile:print(" return 0;") - srcfile:print("}") - - -- exit this file - srcfile:close() - - -- attempt to compile it - return instance:compile(srcpath, objpath, nil, self) -end - --- check type -function option:_check_type(typename, srcpath, objpath) + -- import has_cxsnippets() + self._has_cxsnippets = self._has_cxsnippets or import("lib.detect.has_cxsnippets") - -- check - assert(typename) - - -- open the checking source file - local srcfile = io.open(srcpath, "w") - if not srcfile then - return false - end - - -- get source kind - local sourcekind = language.sourcekind_of(srcpath) - - -- load the compiler instance - local instance = compiler.load(sourcekind) - if not instance then - return false - end - - -- make includes - local includes = nil - if sourcekind == "cc" then includes = self:get("cincludes") - elseif sourcekind == "cxx" then includes = self:get("cxxincludes") - end - if includes then - for _, include in ipairs(table.wrap(includes)) do - srcfile:print("#include <%s>", include) - end - srcfile:print("") - end - - -- make the main function header - srcfile:print("int main(int argc, char** argv)") - srcfile:print("{") - - -- make interfaces - srcfile:print(" typedef %s __type_xxx;", typename) - - -- make the main function tailer - srcfile:print(" return 0;") - srcfile:print("}") - - -- exit this file - srcfile:close() - - -- attempt to compile it - return instance:compile(srcpath, objpath, nil, self) -end - --- check snippet -function option:_check_snippet(snippet, srcpath, objpath) - - -- check - assert(snippet) + -- check for c and c++ + for _, kind in ipairs({"c", "cxx"}) do - -- get source kind - local sourcekind = language.sourcekind_of(srcpath) + -- get conditions + local snippets = self:get(kind .. "snippet") + local types = self:get(kind .. "types") + local funcs = self:get(kind .. "funcs") + local links = self:get(kind .. "links") + local includes = self:get(kind .. "includes") - -- load the compiler instance - local instance = compiler.load(sourcekind) - if not instance then - return false - end - - -- write snippet to source file - if not io.writefile(srcpath, snippet) then - return false - end - - -- attempt to compile it - return instance:compile(srcpath, objpath, nil, self) -end - --- check option for checking links -function option:_check_links(cfile, objectfile, targetfile) - - -- get links - local links = self:get("links") - if not links then - return true - end - - -- the links string - local links_str = table.concat(table.wrap(links), ", ") - - -- this links has been checked? - option._CHECKED_LINKS = option._CHECKED_LINKS or {} - if option._CHECKED_LINKS[links_str] then - return true - end - - -- only for compile a object file - local ok, errors = self:_check_include(nil, cfile, objectfile) - - -- check link - if ok then ok, errors = self:_check_link(cfile, objectfile, targetfile) end - - -- trace - utils.cprint("checking for the links %s ... %s", links_str, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok and option_.get("verbose") then - utils.cprint("${red}" .. (errors or "")) - end - - -- cache the result - option._CHECKED_LINKS[links_str] = ok - - -- ok? - return ok -end + -- need check it? + if snippets or types or funcs or links or includes then --- check option for checking includes -function option:_check_includes(kind, file, objectfile) + -- init source kind + local sourcekind = kind + if kind == "c" then + sourcekind = "cc" + end - -- done - for _, include in ipairs(table.wrap(self:get(kind .. "includes"))) do - - -- this include has been checked? - option._CHECKED_INCLUDES = option._CHECKED_INCLUDES or {} - if option._CHECKED_INCLUDES[include] then return true end - - -- check include - local ok, errors = self:_check_include(include, file, objectfile) + -- check it + local ok, results_or_errors = sandbox.load(self._has_cxsnippets, snippets, {target = self, sourcekind = sourcekind, types = types, funcs = funcs, includes = includes}) + if not ok then + return false, results_or_errors + end - -- trace - utils.cprint("checking for the %s include %s ... %s", kind, include, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok and option_.get("verbose") then - utils.cprint("${red}" .. (errors or "")) + -- not pass? + if not results_or_errors then + return false + end end - - -- cache the result - option._CHECKED_INCLUDES[include] = ok - - -- failed - if not ok then return false end end -- ok return true end --- check option for checking functions -function option:_check_functions(kind, file, objectfile, targetfile) - - -- done - for _, checkinfo in ipairs(table.wrap(self:get(kind .. "funcs"))) do - - -- parse the check code - local checkname, checkcode = option.checkinfo(checkinfo) - assert(checkname and checkcode) +-- on check +function option:_on_check() - -- check function - local ok, errors = self:_check_function(checkcode, file, objectfile) + -- get check script + local check = self:get("check") + if check then - -- check link - if ok and self:get("links") then ok, errors = self:_check_link(file, objectfile, targetfile) end - - -- trace - utils.cprint("checking for the %s function %s ... %s", kind, checkname, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok and option_.get("verbose") then - utils.cprint("${red}" .. (errors or "")) + -- check it + local ok, results_or_errors = sandbox.load(check, self) + if not ok then + return false, results_or_errors + else + return results_or_errors end - - -- failed - if not ok then return false end end - - -- ok - return true end --- check option for checking types -function option:_check_types(kind, file, objectfile, targetfile) - - -- done - for _, t in ipairs(table.wrap(self:get(kind .. "types"))) do - - -- check type - local ok, errors = self:_check_type(t, file, objectfile) +-- check option +function option:_check() - -- trace - utils.cprint("checking for the %s type %s ... %s", kind, t, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok and option_.get("verbose") then - utils.cprint("${red}" .. (errors or "")) + -- check it + local ok = nil + local errors = nil + for _, check in ipairs({self._on_check, self._cx_check}) do + ok, errors = check(self) + if ok ~= nil then + break end - - -- failed - if not ok then return false end end - -- ok - return true -end - --- check option for checking snippets -function option:_check_snippets(kind, file, objectfile, targetfile) - - -- done - for name, snippet in pairs(table.wrap(self:get(kind .. "snippet"))) do - - -- check snippet - local ok, errors = self:_check_snippet(snippet, file, objectfile) - - -- trace - utils.cprint("checking for the %s snippet %s ... %s", kind, name, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok and option_.get("verbose") then - utils.cprint("${red}" .. (errors or "")) - end - - -- failed - if not ok then return false end + -- get name + local name = self:name() + if name:startswith("__") then + name = name:sub(3) end - -- ok - return true -end - --- check option -function option:_check_condition() - - -- the files - local cfile = os.tmpfile() .. ".c" - local cxxfile = os.tmpfile() .. ".cpp" - local objectfile = os.tmpfile() .. ".obj" - local targetfile = os.tmpfile() .. ".bin" - - -- check links - if not self:_check_links(cfile, objectfile, targetfile) then return false end - - -- check types - if not self:_check_types("c", cfile, objectfile, targetfile) then return false end - if not self:_check_types("cxx", cxxfile, objectfile, targetfile) then return false end - - -- check csnippets - if not self:_check_snippets("c", cfile, objectfile, targetfile) then return false end - if not self:_check_snippets("cxx", cxxfile, objectfile, targetfile) then return false end - - -- check includes and functions - if self:get("cincludes") or self:get("cxxincludes") then - - -- check includes - if not self:_check_includes("c", cfile, objectfile) then return false end - if not self:_check_includes("cxx", cxxfile, objectfile) then return false end - - -- check functions - if not self:_check_functions("c", cfile, objectfile, targetfile) then return false end - if not self:_check_functions("cxx", cxxfile, objectfile, targetfile) then return false end + -- trace + utils.cprint("checking for the %s ... %s", name, utils.ifelse(ok, "${green}ok", "${red}no")) + if not ok and errors then + os.raise(errors) end - -- remove files - os.rm(cfile) - os.rm(cxxfile) - os.rm(objectfile) - os.rm(targetfile) - - -- ok - return true + -- ok? + return ok end -- attempt to check option @@ -437,6 +160,13 @@ function option:check(force) default = self:get("enable") end + -- before and after check + local check_before = self:get("check_before") + local check_after = self:get("check_after") + if check_before then + check_before(self) + end + -- need check? (only force to check the automatical option without the default value) if config.get(name) == nil or (default == nil and force) then @@ -450,7 +180,7 @@ function option:check(force) self:save() -- check option as boolean switch automatically if the default value not exists - elseif default == nil and self:_check_condition() then + elseif default == nil and self:_check() then -- enable this option config.set(name, true) @@ -473,17 +203,57 @@ function option:check(force) self:save() end + -- after check + if check_after then + check_after(self) + end + -- checked self._CHECKED = true end +-- this option is enabled? +function option:enabled() + return config.get(self:name()) +end + +-- dump this option +function option:dump() + table.dump(self._INFO) +end + -- get the option info function option:get(infoname) - - -- get it return self._INFO[infoname] end +-- set the value to the option info +function option:set(name_or_info, ...) + if type(name_or_info) == "string" then + local args = ... + if args ~= nil then + self._INFO[name_or_info] = table.unique(table.join(...)) + else + self._INFO[name_or_info] = nil + end + elseif type(name_or_info) == "table" and #name_or_info == 0 then + for name, info in pairs(name_or_info) do + self:set(name, info) + end + end +end + +-- add the value to the option info +function option:add(name_or_info, ...) + if type(name_or_info) == "string" then + self._INFO[name_or_info] = table.unique(table.join2(table.wrap(self._INFO[name_or_info]), ...)) + elseif type(name_or_info) == "table" and #name_or_info == 0 then + for name, info in pairs(name_or_info) do + self:add(name, info) + end + end +end + -- get option deps function option:deps() -- TODO in the future @@ -493,22 +263,23 @@ end -- save the option info to the cache function option:save() - -- save it + -- clear scripts for caching to file + self:set("check", nil) + self:set("check_after", nil) + self:set("check_before", nil) + + -- save this option to cache option._cache():set(self:name(), self._INFO) option._cache():flush() end -- clear the option info for cache function option:clear() - - -- clear it option._cache():set(self:name(), nil) end -- get the option name function option:name() - - -- get it return self._NAME end @@ -533,43 +304,5 @@ function option.load(name) return instance end --- get the kinds of sourcefiles -function option:sourcekinds() - - -- cached? return it directly - if self._SOURCEKINDS then - return self._SOURCEKINDS - end - - -- ok? - return {"cc", "cxx"} -end - --- get function name and check code --- --- sigsetjmp --- sigsetjmp((void*)0, 0) --- sigsetjmp{sigsetjmp((void*)0, 0);} --- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);} --- -function option.checkinfo(checkinfo) - - -- parse name and code - local name, code = string.match(checkinfo, "(.+){(.+)}") - if code == nil then - local pos = checkinfo:find("%(") - if pos then - name = checkinfo:sub(1, pos - 1) - code = checkinfo - else - name = checkinfo - code = string.format("volatile void* p%s = (void*)&%s;", name, name) - end - end - - -- ok - return name:trim(), code -end - -- return module return option diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 649d41141..4368a7220 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -31,6 +31,7 @@ local io = require("base/io") local path = require("base/path") local utils = require("base/utils") local table = require("base/table") +local process = require("base/process") local deprecated = require("base/deprecated") local interpreter = require("base/interpreter") local target = require("project/target") @@ -40,7 +41,6 @@ local option = require("project/option") local package = require("project/package") local deprecated_project = require("project/deprecated/project") local platform = require("platform/platform") -local environment = require("platform/environment") local language = require("language/language") local sandbox_os = require("sandbox/modules/os") @@ -265,6 +265,12 @@ function project._interpreter() , "target.after_package" , "target.after_install" , "target.after_uninstall" + -- option.before_xxx + , "option.before_check" + -- option.on_xxx + , "option.on_check" + -- option.after_xxx + , "option.after_check" -- target.on_xxx , "task.on_run" } @@ -358,52 +364,12 @@ end -- get the project file function project.file() - - -- get it - return xmake._PROJECT_FILE + return os.projectfile() end -- get the project directory function project.directory() - - -- get it - return xmake._PROJECT_DIR -end - --- check the project -function project.check(force) - - -- enter the project directory - local ok, errors = os.cd(project.directory()) - if not ok then - return false, errors - end - - -- load the options from the the project file - local options, errors = project.options(true) - if not options then - return false, errors - end - - -- enter toolchains environment - environment.enter("toolchains") - - -- check all options - for _, opt in pairs(options) do - opt:check(force) - end - - -- leave toolchains environment - environment.leave("toolchains") - - -- leave the project directory - ok, errors = os.cd("-") - if not ok then - return false, errors - end - - -- ok - return true + return os.projectdir() end -- get the project info from the given name @@ -521,7 +487,7 @@ function project.options(enable_filter) instance._INFO = optioninfo -- save it - options[optionname] = instance + table.insert(options,instance) end -- ok? @@ -579,7 +545,7 @@ function project.menu() -- arrange options by category local options_by_category = {} - for name, opt in pairs(options) do + for _, opt in ipairs(options) do -- make the category local category = "default" @@ -587,7 +553,7 @@ function project.menu() options_by_category[category] = options_by_category[category] or {} -- append option to the current category - options_by_category[category][name] = opt + options_by_category[category][opt:name()] = opt end -- make menu by category diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index bfb986123..ebc778c3a 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -66,26 +66,49 @@ function target.new(name, info) end -- get the target info -function target:get(infoname) +function target:get(name) + return self._INFO[name] +end - -- check - assert(self and self._INFO and infoname) +-- set the value to the target info +function target:set(name_or_info, ...) + if type(name_or_info) == "string" then + local args = ... + if args ~= nil then + self._INFO[name_or_info] = table.unique(table.join(...)) + else + self._INFO[name_or_info] = nil + end + elseif type(name_or_info) == "table" and #name_or_info == 0 then + for name, info in pairs(name_or_info) do + self:set(name, info) + end + end +end - -- get it - return self._INFO[infoname] +-- add the value to the target info +function target:add(name_or_info, ...) + if type(name_or_info) == "string" then + self._INFO[name_or_info] = table.unique(table.join2(table.wrap(self._INFO[name_or_info]), ...)) + elseif type(name_or_info) == "table" and #name_or_info == 0 then + for name, info in pairs(name_or_info) do + self:add(name, info) + end + end +end + +-- dump this target +function target:dump() + table.dump(self._INFO) end -- get the target name function target:name() - - -- get it return self._NAME end -- get the base name of target file function target:basename() - - -- get it return self:get("basename") end @@ -114,14 +137,14 @@ end function target:linkcmd(objectfiles) -- make command - return self:linker():linkcmd(objectfiles or self:objectfiles(), self:targetfile(), self) + return self:linker():linkcmd(objectfiles or self:objectfiles(), self:targetfile(), {target = self}) end -- make link flags for the given target function target:linkflags() -- make flags - return self:linker():linkflags(self) + return self:linker():linkflags({target = self}) end -- get target deps @@ -362,10 +385,6 @@ function target:objectfile(sourcefile) local objectdir = self:objectdir() assert(objectdir and type(objectdir) == "string") - -- make object file - -- full file name(not base) to avoid name-clash of object file - local objectfile = string.format("%s/%s/%s/%s", objectdir, self:name(), path.directory(sourcefile), target.filename(path.filename(sourcefile), "object")) - -- translate path -- -- .e.g @@ -378,10 +397,11 @@ function target:objectfile(sourcefile) -- -- we need replace '..' to '__' in this case -- - objectfile = (path.translate(objectfile):gsub("%.%.", "__")) + local sourcedir = path.directory(sourcefile):gsub("%.%.", "__") - -- ok? - return objectfile + -- make object file + -- full file name(not base) to avoid name-clash of object file + return string.format("%s/%s/%s/%s", objectdir, self:name(), sourcedir, target.filename(path.filename(sourcefile), "object")) end -- get the object files diff --git a/xmake/core/project/template.lua b/xmake/core/project/template.lua index a306bf622..cbc1551a8 100644 --- a/xmake/core/project/template.lua +++ b/xmake/core/project/template.lua @@ -90,7 +90,7 @@ function template._replace(macros, macrofiles) -- make all files local files = {} for _, macrofile in ipairs(table.wrap(macrofiles)) do - local matchfiles = os.match(macrofile) + local matchfiles = os.files(macrofile) if matchfiles then table.join2(files, matchfiles) end @@ -114,7 +114,7 @@ function template.languages() local list = {} -- get the language list - local languages = os.match(xmake._TEMPLATES_DIR .. "/*", true) + local languages = os.dirs(path.join(os.programdir(), "templates", "*")) if languages then for _, v in ipairs(languages) do table.insert(list, path.basename(v)) @@ -137,7 +137,7 @@ function template.templates(language) -- load all templates local templates = {} - local templatefiles = os.match(string.format("%s/%s/**/template.lua", xmake._TEMPLATES_DIR, language)) + local templatefiles = os.files(path.join(os.programdir(), "templates", language, "**", "template.lua")) if templatefiles then -- load template @@ -159,7 +159,7 @@ function template.templates(language) end -- sort templates - table.sort(templates, function(a, b) return a.description:less(b.description) end) + table.sort(templates, function(a, b) return a.description < b.description end) -- ok? return templates diff --git a/xmake/core/sandbox/modules/import.lua b/xmake/core/sandbox/modules/import.lua index 885378750..5317efa6e 100644 --- a/xmake/core/sandbox/modules/import.lua +++ b/xmake/core/sandbox/modules/import.lua @@ -103,7 +103,7 @@ function sandbox_import._loadfile(filepath, instance) if not result then return nil, errors end - + -- ok return result, instance:script() end @@ -128,19 +128,16 @@ function sandbox_import._find(dir, name) name = sandbox_import._modulepath(name) assert(name) - -- load the single module? - local module = nil - if os.isfile(path.join(dir, name .. ".lua")) then - return true + -- get module key + local key = path.join(dir, name) - -- load modules - elseif os.isdir(path.join(dir, name)) then - return true + -- the single module? + if os.isfile(key .. ".lua") then + return path.absolute(key) + -- modules? + elseif os.isdir(key) then + return path.absolute(key) end - - -- not found - return false - end -- load module @@ -240,6 +237,11 @@ end -- import module -- +-- @param name the module name, .e.g core.platform +-- @param args the arguments, .e.g {alias = "", rootdir = "", inherit = false, anonymous = false, nocache = false} +-- +-- @return the module instance +-- -- .e.g -- -- import("core.platform") @@ -260,7 +262,7 @@ end -- => inherit the all interfaces of core.platform to the current scope -- -- local test = import("test", {rootdir = "/tmp/xxx", anonymous = true}) --- => only return imported module and do not cache it +-- => only return imported module -- -- @note the polymiorphism is not supported for import.inherit mode now. -- @@ -272,6 +274,10 @@ function sandbox_import.import(name, args) -- the arguments args = args or {} + -- init module cache + sandbox_import._MODULES = sandbox_import._MODULES or {} + local modules = sandbox_import._MODULES + -- get the parent scope local scope_parent = getfenv(2) assert(scope_parent) @@ -285,12 +291,6 @@ function sandbox_import.import(name, args) -- the imported name local imported_name = args.alias or modulename - -- this module has been imported? - local module = rawget(scope_parent, imported_name) - if module ~= nil then - return module - end - -- get the current sandbox instance local instance = sandbox.instance() assert(instance) @@ -300,7 +300,7 @@ function sandbox_import.import(name, args) assert(rootdir) -- the sandbox modules directory - local modules_sandbox_dir = path.join(xmake._CORE_DIR, "sandbox/modules/import") + local modules_sandbox_dir = path.join(os.programdir(), "core/sandbox/modules/import") -- the extension modules directory local modules_extension_dir = path.join(os.programdir(), "modules") @@ -311,18 +311,39 @@ function sandbox_import.import(name, args) -- init module directories local modules_directories = { - rootdir -- load module from the given root directory first - , path.join(global.directory(), "modules") -- load module from the user global modules directory - , path.join(xmake._PROGRAM_DIR, "modules") -- load module from the extension modules directory - , path.join(xmake._CORE_DIR, "sandbox/modules/import") -- load module from the sandbox core modules directory + rootdir -- load module from the given root directory first + , path.join(global.directory(), "modules") -- load module from the user global modules directory + , path.join(os.programdir(), "modules") -- load module from the extension modules directory + , path.join(os.programdir(), "core/sandbox/modules/import") -- load module from the sandbox core modules directory } -- load module - local module = nil local errors = nil + local module = nil + local modulekey = nil for idx, moduledir in ipairs(modules_directories) do - if sandbox_import._find(moduledir, name) then - module, errors = sandbox_import._load(moduledir, name, utils.ifelse(idx < #modules_directories, instance, nil)) -- last modules need not fork sandbox + + -- find module and key + modulekey = sandbox_import._find(moduledir, name) + if modulekey then + + -- load it from cache first + local moduleinfo = modules[modulekey] + if moduleinfo and not args.nocache and not args.inherit then + module = moduleinfo[1] + errors = moduleinfo[2] + else + -- load it from the script file + module, errors = sandbox_import._load(moduledir, name, utils.ifelse(idx < #modules_directories, instance, nil)) -- last modules need not fork sandbox + + -- cache this module + if not args.nocache then + modules[modulekey] = {module, errors} + end + end + + -- end + break end end diff --git a/xmake/core/sandbox/modules/import/core/platform/platform.lua b/xmake/core/sandbox/modules/import/core/platform/platform.lua index 2dee562f1..e4175aaaa 100644 --- a/xmake/core/sandbox/modules/import/core/platform/platform.lua +++ b/xmake/core/sandbox/modules/import/core/platform/platform.lua @@ -63,10 +63,16 @@ end -- get the current platform configure function sandbox_core_platform.get(name, plat) - - -- get the given platform configure return platform.get(name, plat) end +-- get the platform tool from the kind +-- +-- .e.g cc, cxx, mm, mxx, as, ar, ld, sh, .. +-- +function sandbox_core_platform.tool(toolkind) + return platform.tool(toolkind) +end + -- return module return sandbox_core_platform diff --git a/xmake/core/sandbox/modules/import/core/project/cache.lua b/xmake/core/sandbox/modules/import/core/project/cache.lua index 4d2879c09..066ae4d03 100644 --- a/xmake/core/sandbox/modules/import/core/project/cache.lua +++ b/xmake/core/sandbox/modules/import/core/project/cache.lua @@ -22,8 +22,8 @@ -- @file cache.lua -- --- define module, @note cannot be cached, a new instance in each sandbox module -local sandbox_core_project_cache = {} +-- define module +local sandbox_core_project_cache = sandbox_core_project_cache or {} -- load modules local cache = require("project/cache") diff --git a/xmake/core/sandbox/modules/import/core/project/history.lua b/xmake/core/sandbox/modules/import/core/project/history.lua index c19607f88..b205afdf9 100644 --- a/xmake/core/sandbox/modules/import/core/project/history.lua +++ b/xmake/core/sandbox/modules/import/core/project/history.lua @@ -22,8 +22,8 @@ -- @file history.lua -- --- define module, @note cannot be cached, a new instance in each sandbox module -local sandbox_core_project_history = {} +-- define module +local sandbox_core_project_history = sandbox_core_project_history or {} -- load modules local os = require("base/os") diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 2b5643e90..164d79fe0 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -26,10 +26,12 @@ local sandbox_core_project = sandbox_core_project or {} -- load modules -local table = require("base/table") -local config = require("project/config") -local project = require("project/project") -local raise = require("sandbox/modules/raise") +local table = require("base/table") +local config = require("project/config") +local project = require("project/project") +local sandbox = require("sandbox/sandbox") +local raise = require("sandbox/modules/raise") +local environment = require("platform/environment") -- load project function sandbox_core_project.load() @@ -44,8 +46,36 @@ end -- check project options function sandbox_core_project.check(force) - -- check it - local ok, errors = project.check(force) + -- enter the project directory + local ok, errors = os.cd(project.directory()) + if not ok then + raise(errors) + end + + -- load the options from the the project file + local options, errors = project.options(true) + if not options then + raise(errors) + end + + -- get sandbox instance + local instance = sandbox.instance() + assert(instance) + + -- enter toolchains environment + environment.enter("toolchains") + + -- check all options + ok, errors = process.runjobs(instance:fork(function (index) options[index]:check(force) end):script(), #options, 4) + if not ok then + raise(errors) + end + + -- leave toolchains environment + environment.leave("toolchains") + + -- leave the project directory + ok, errors = os.cd("-") if not ok then raise(errors) end diff --git a/xmake/core/sandbox/modules/import/core/tool/compiler.lua b/xmake/core/sandbox/modules/import/core/tool/compiler.lua index fb753aed3..a6ebc45f6 100644 --- a/xmake/core/sandbox/modules/import/core/tool/compiler.lua +++ b/xmake/core/sandbox/modules/import/core/tool/compiler.lua @@ -46,9 +46,13 @@ function sandbox_core_tool_compiler.feature(sourcekind, name) end -- make command for compiling source file -function sandbox_core_tool_compiler.compcmd(sourcefiles, objectfile, target, sourcekind) +function sandbox_core_tool_compiler.compcmd(sourcefiles, objectfile, opt) + + -- init options + opt = opt or {} -- get source kind if only one source file + local sourcekind = opt.sourcekind if not sourcekind and type(sourcefiles) == "string" then sourcekind = language.sourcekind_of(sourcefiles) end @@ -58,15 +62,19 @@ function sandbox_core_tool_compiler.compcmd(sourcefiles, objectfile, target, sou if not instance then raise(errors) end - + -- make command - return instance:compcmd(sourcefiles, objectfile, target) + return instance:compcmd(sourcefiles, objectfile, opt) end -- compile source files -function sandbox_core_tool_compiler.compile(sourcefiles, objectfile, incdepfile, target, sourcekind) +function sandbox_core_tool_compiler.compile(sourcefiles, objectfile, opt) + + -- init options + opt = opt or {} -- get source kind if only one source file + local sourcekind = opt.sourcekind if not sourcekind and type(sourcefiles) == "string" then sourcekind = language.sourcekind_of(sourcefiles) end @@ -78,16 +86,17 @@ function sandbox_core_tool_compiler.compile(sourcefiles, objectfile, incdepfile, end -- compile it - local ok, errors = instance:compile(sourcefiles, objectfile, incdepfile, target) + local ok, errors = instance:compile(sourcefiles, objectfile, opt) if not ok then raise(errors) end end --- make compiling flags for the given target -function sandbox_core_tool_compiler.compflags(sourcefiles, target, sourcekind) +-- make compiling flags +function sandbox_core_tool_compiler.compflags(sourcefiles, opt) -- get source kind if only one source file + local sourcekind = opt.sourcekind if not sourcekind and type(sourcefiles) == "string" then sourcekind = language.sourcekind_of(sourcefiles) end @@ -99,13 +108,14 @@ function sandbox_core_tool_compiler.compflags(sourcefiles, target, sourcekind) end -- make flags - return instance:compflags(target) + return instance:compflags(opt) end -- make command for building source file -function sandbox_core_tool_compiler.buildcmd(sourcefiles, targetfile, target, sourcekind) +function sandbox_core_tool_compiler.buildcmd(sourcefiles, targetfile, opt) -- get source kind if only one source file + local sourcekind = opt.sourcekind if not sourcekind and type(sourcefiles) == "string" then sourcekind = language.sourcekind_of(sourcefiles) end @@ -117,13 +127,14 @@ function sandbox_core_tool_compiler.buildcmd(sourcefiles, targetfile, target, so end -- make command - return instance:buildcmd(sourcefiles, target:targetkind(), targetfile, target) + return instance:buildcmd(sourcefiles, targetfile, opt) end -- build source files -function sandbox_core_tool_compiler.build(sourcefiles, targetfile, target, sourcekind) +function sandbox_core_tool_compiler.build(sourcefiles, targetfile, opt) -- get source kind if only one source file + local sourcekind = opt.sourcekind if not sourcekind and type(sourcefiles) == "string" then sourcekind = language.sourcekind_of(sourcefiles) end @@ -135,7 +146,7 @@ function sandbox_core_tool_compiler.build(sourcefiles, targetfile, target, sourc end -- build it - local ok, errors = instance:build(sourcefiles, target:targetkind(), targetfile, target) + local ok, errors = instance:build(sourcefiles, targetfile, opt) if not ok then raise(errors) end diff --git a/xmake/core/sandbox/modules/import/core/tool/linker.lua b/xmake/core/sandbox/modules/import/core/tool/linker.lua index b785f2c50..7b95d8b7c 100644 --- a/xmake/core/sandbox/modules/import/core/tool/linker.lua +++ b/xmake/core/sandbox/modules/import/core/tool/linker.lua @@ -31,42 +31,42 @@ local linker = require("tool/linker") local raise = require("sandbox/modules/raise") -- make command for linking target file -function sandbox_core_tool_linker.linkcmd(objectfiles, targetfile, target) +function sandbox_core_tool_linker.linkcmd(targetkind, sourcekinds, objectfiles, targetfile, opt) -- get the linker instance - local instance, errors = linker.load(target:get("kind"), target:sourcekinds()) + local instance, errors = linker.load(targetkind, sourcekinds) if not instance then raise(errors) end -- make command - return instance:linkcmd(objectfiles, targetfile, target) + return instance:linkcmd(objectfiles, targetfile, opt) end -- make link flags for the given target -function sandbox_core_tool_linker.linkflags(target) - +function sandbox_core_tool_linker.linkflags(targetkind, sourcekinds, opt) + -- get the linker instance - local instance, errors = linker.load(target:get("kind"), target:sourcekinds()) + local instance, errors = linker.load(targetkind, sourcekinds) if not instance then raise(errors) end -- make flags - return instance:linkflags(target) + return instance:linkflags(opt) end -- link target file -function sandbox_core_tool_linker.link(objectfiles, targetfile, target) +function sandbox_core_tool_linker.link(targetkind, sourcekinds, objectfiles, targetfile, opt) -- get the linker instance - local instance, errors = linker.load(target:get("kind"), target:sourcekinds()) + local instance, errors = linker.load(targetkind, sourcekinds) if not instance then raise(errors) end -- link it - local ok, errors = instance:link(objectfiles, targetfile, target) + local ok, errors = instance:link(objectfiles, targetfile, opt) if not ok then raise(errors) end diff --git a/xmake/core/sandbox/modules/import/core/tool/tool.lua b/xmake/core/sandbox/modules/import/core/tool/tool.lua deleted file mode 100644 index 9fbc68ced..000000000 --- a/xmake/core/sandbox/modules/import/core/tool/tool.lua +++ /dev/null @@ -1,49 +0,0 @@ ---!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 tool.lua --- - --- define module -local sandbox_core_tool = sandbox_core_tool or {} - --- load modules -local tool = require("tool/tool") -local config = require("project/config") -local platform = require("platform/platform") -local raise = require("sandbox/modules/raise") - --- get the tool shell name -function sandbox_core_tool.shellname(name) - - -- get it - return platform.tool(name) -end - --- check the tool and return the absolute path if exists -function sandbox_core_tool.check(shellname, dirs, check) - - -- check it - return tool.check(shellname, dirs, check) -end - --- return module -return sandbox_core_tool diff --git a/xmake/core/sandbox/modules/import/lib/detect/clear_cache.lua b/xmake/core/sandbox/modules/import/lib/detect/cache.lua index 81cca369e..82d9c60bc 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/clear_cache.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/cache.lua @@ -19,11 +19,11 @@ -- Copyright (C) 2015 - 2017, TBOOX Open Source Group. -- -- @author ruki --- @file clear_cache.lua +-- @file cache.lua -- -- define module -local sandbox_lib_detect_clear_cache = sandbox_lib_detect_clear_cache or {} +local sandbox_lib_detect_cache = sandbox_lib_detect_cache or {} -- load modules local os = require("base/os") @@ -36,15 +36,61 @@ local project = require("project/project") local sandbox = require("sandbox/sandbox") local raise = require("sandbox/modules/raise") --- clear detect cache +-- get detect cache instance +function sandbox_lib_detect_cache._instance() + + -- get it + local detectcache = sandbox_lib_detect_cache._INSTANCE or cache(utils.ifelse(os.isfile(project.file()), "local.detect", "memory.detect")) + sandbox_lib_detect_cache._INSTANCE = detectcache + + -- ok? + return detectcache +end + +-- load detect cache -- -- @param name the cache name. .e.g find_program, find_programver, .. -- -function sandbox_lib_detect_clear_cache.main(name) +function sandbox_lib_detect_cache.load(name) -- get detect cache - local detectcache = cache(utils.ifelse(os.isfile(project.file()), "local.detect", "memory.detect")) + local detectcache = sandbox_lib_detect_cache._instance() + -- attempt to get result from cache first + local cacheinfo = detectcache:get(name) + if cacheinfo == nil then + cacheinfo = {} + detectcache:set(name, cacheinfo) + end + + -- ok? + return cacheinfo +end + +-- save detect cache +-- +-- @param name the cache name. .e.g find_program, find_programver, .. +-- @param info the cache info +-- +function sandbox_lib_detect_cache.save(name, info) + + -- get detect cache + local detectcache = sandbox_lib_detect_cache._instance() + + -- save cache info + detectcache:set(name, info) + detectcache:flush() +end + +-- clear detect cache +-- +-- @param name the cache name. .e.g find_program, find_programver, .. +-- +function sandbox_lib_detect_cache.clear(name) + + -- get detect cache + local detectcache = sandbox_lib_detect_cache._instance() + -- clear cache info if name then detectcache:set(name, {}) @@ -55,4 +101,4 @@ function sandbox_lib_detect_clear_cache.main(name) end -- return module -return sandbox_lib_detect_clear_cache +return sandbox_lib_detect_cache diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua new file mode 100644 index 000000000..e4c6c00d4 --- /dev/null +++ b/xmake/core/sandbox/modules/import/lib/detect/find_directory.lua @@ -0,0 +1,106 @@ +--!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 find_directory.lua +-- + +-- define module +local sandbox_lib_detect_find_directory = sandbox_lib_detect_find_directory or {} + +-- load modules +local os = require("base/os") +local path = require("base/path") +local utils = require("base/utils") +local table = require("base/table") +local raise = require("sandbox/modules/raise") +local vformat = require("sandbox/modules/vformat") + +-- find directory +-- +-- @param name the directory name +-- @param pathes the search pathes (.e.g dirs, pathes, winreg pathes) +-- @param opt the options, .e.g {suffixes = {"/aa", "/bb"}} +-- +-- @return the directory path +-- +-- @code +-- +-- local dir = find_directory("bin", { "/usr", "/usr/local"}) +-- local dir = find_directory("xxx/test", { "/usr/include", "/usr/local/include/**"}) +-- local dir = find_directory("xxx/test", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"}) +-- local dir = find_directory("xxx/test/dir*", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end}) +-- +-- @endcode +-- +function sandbox_lib_detect_find_directory.main(name, pathes, opt) + + -- init options + opt = opt or {} + + -- init pathes + pathes = table.wrap(pathes) + + -- append suffixes to pathes + local suffixes = table.wrap(opt.suffixes) + if #suffixes > 0 then + local pathes_new = {} + for _, parent in ipairs(pathes) do + for _, suffix in ipairs(suffixes) do + table.insert(pathes_new, path.join(parent, suffix)) + end + end + pathes = pathes_new + end + + -- find file + local result = nil + for _, _path in ipairs(pathes) do + + -- format path for builtin variables + if type(_path) == "function" then + local ok, results = sandbox.load(_path) + if ok then + _path = results or "" + else + raise(results) + end + else + _path = vformat(_path) + end + + -- directory exists? + for _, dir in ipairs(os.dirs(path.join(_path, name))) do + result = dir + break + end + + -- found? + if result then + break + end + end + + -- ok? + return result +end + +-- return module +return sandbox_lib_detect_find_directory diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua index ae61faa40..e647f1869 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_file.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_file.lua @@ -36,7 +36,8 @@ local vformat = require("sandbox/modules/vformat") -- find file -- -- @param name the file name --- @param pathes the program pathes (.e.g dirs, pathes, winreg pathes) +-- @param pathes the search pathes (.e.g dirs, pathes, winreg pathes) +-- @param opt the options, .e.g {suffixes = {"/aa", "/bb"}} -- -- @return the file path -- @@ -49,11 +50,29 @@ local vformat = require("sandbox/modules/vformat") -- -- @endcode -- -function sandbox_lib_detect_find_file.main(name, pathes) +function sandbox_lib_detect_find_file.main(name, pathes, opt) + + -- init options + opt = opt or {} + + -- init pathes + pathes = table.wrap(pathes) + + -- append suffixes to pathes + local suffixes = table.wrap(opt.suffixes) + if #suffixes > 0 then + local pathes_new = {} + for _, parent in ipairs(pathes) do + for _, suffix in ipairs(suffixes) do + table.insert(pathes_new, path.join(parent, suffix)) + end + end + pathes = pathes_new + end -- find file local result = nil - for _, _path in ipairs(table.wrap(pathes)) do + for _, _path in ipairs(pathes) do -- format path for builtin variables if type(_path) == "function" then diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua index 4b386f947..fbf3cf3c6 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua @@ -31,13 +31,9 @@ local path = require("base/path") local utils = require("base/utils") local table = require("base/table") local target = require("project/target") -local config = require("project/config") local raise = require("sandbox/modules/raise") local import = require("sandbox/modules/import") - --- import sandbox modules -import("lib.detect.find_file") -import("detect.tool.find_pkg_config") +local find_file = import("lib.detect.find_file") -- get link name from the file name function sandbox_lib_detect_find_library._link(filename) @@ -57,64 +53,30 @@ end -- find library -- -- @param names the library names --- @param pathes the library pathes --- @param kinds the library kinds, .e.g {"static", "shared"} +-- @param pathes the search pathes +-- @param opt the options, .e.g {kind = "static/shared", suffixes = {"/aa", "/bb"}} -- -- @return {kind = "static", link = "crypto", linkdir = "/usr/local/lib", filename = "libcrypto.a"} -- -- @code -- --- local library = find_library("crypto") -- local library = find_library({"crypto", "cryp*"}, {"/usr/lib", "/usr/local/lib"}) +-- local library = find_library(crypto, {"/usr/lib", "/usr/local/lib"}, {kind = "static"}) -- -- @endcode -- -function sandbox_lib_detect_find_library.main(names, paths, kinds) +function sandbox_lib_detect_find_library.main(names, pathes, opt) - -- init pathes - pathes = table.wrap(pathes) + -- init options + opt = opt or {} -- init kinds - kinds = kinds or {"static", "shared"} - - -- get current platform - local plat = config.get("plat") or os.host() - - -- get current architecture - local arch = config.get("arch") or os.arch() - - -- attempt to add search pathes from pkg-config - local pkg_config = find_pkg_config() - if pkg_config then - for _, name in ipairs(table.wrap(names)) do - - -- attempt to get -L/xxx/dir - local ok, libs_only_L = os.iorunv(pkg_config, {"--libs-only-L", name}) - if not ok and not name:startswith("lib") then - ok, libs_only_L = os.iorunv(pkg_config, {"--libs-only-L", "lib" .. name}) - end - - -- add linkdir to pathes - if libs_only_L then - local linkdir = (libs_only_L:match("%-L(.+)") or ""):trim() - if os.isdir(linkdir) then - table.insert(pathes, linkdir) - break - end - end - end - end - - -- add default search pathes on pc host - if plat == "macosx" or (plat == "linux" and arch == os.arch()) then - table.insert(pathes, "/usr/local/lib") - table.insert(pathes, "/usr/lib") - end + kinds = opt.kind or {"static", "shared"} -- find library file from the given pathes for _, name in ipairs(table.wrap(names)) do for _, kind in ipairs(table.wrap(kinds)) do - local filepath = find_file(target.filename(name, kind), pathes) + local filepath = find_file(target.filename(name, kind), pathes, opt) if filepath then local filename = path.filename(filepath) return {kind = kind, filename = filename, linkdir = path.directory(filepath), link = sandbox_lib_detect_find_library._link(filename)} diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_package.lua b/xmake/core/sandbox/modules/import/lib/detect/find_package.lua index a225945b7..626f652cd 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_package.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_package.lua @@ -31,10 +31,18 @@ local path = require("base/path") local utils = require("base/utils") local table = require("base/table") local option = require("base/option") -local cache = require("project/cache") +local config = require("project/config") local project = require("project/project") local raise = require("sandbox/modules/raise") local import = require("sandbox/modules/import") +local cache = require("sandbox/modules/import/lib/detect/cache") +local pkg_config = import("lib.detect.pkg_config") + +-- find package from project package directories +function sandbox_lib_detect_find_package._find_from_project_packagedirs(name, opt) + + -- TODO +end -- find package from repositories function sandbox_lib_detect_find_package._find_from_repositories(name, opt) @@ -42,21 +50,75 @@ function sandbox_lib_detect_find_package._find_from_repositories(name, opt) -- TODO in repo branch end --- find package from modules (detect.package.find_xxx) +-- find package from modules (detect.packages.find_xxx) function sandbox_lib_detect_find_package._find_from_modules(name, opt) - -- "detect.package.find_xxx" exists? - if os.isfile(path.join(os.programdir(), "modules", "detect", "package", "find_" .. name .. ".lua")) then - local find_package = import("detect.package.find_" .. name, {anonymous = true}) + -- "detect.packages.find_xxx" exists? + if os.isfile(path.join(os.programdir(), "modules", "detect", "packages", "find_" .. name .. ".lua")) then + local find_package = import("detect.packages.find_" .. name) if find_package then return find_package(opt) end end end --- find package from system -function sandbox_lib_detect_find_package._find_from_system(name, opt) - -- TODO +-- find package from pkg-config +function sandbox_lib_detect_find_package._find_from_pkg_config(name, opt) + return pkg_config.find(name, opt) +end + +-- find package from system directories +function sandbox_lib_detect_find_package._find_from_systemdirs(name, opt) + + -- cannot get the version of package + if opt.version then + return + end + + -- add default search pathes on pc host + local pathes = {} + if opt.plat == "linux" or opt.plat == "macosx" then + table.insert(pathes, "/usr/local/lib") + table.insert(pathes, "/usr/lib") + table.insert(pathes, "/opt/local/lib") + table.insert(pathes, "/opt/lib") + if opt.plat == "linux" and opt.arch == "x86_64" then + table.insert(pathes, "/usr/local/lib/x86_64-linux-gnu") + table.insert(pathes, "/usr/lib/x86_64-linux-gnu") + end + end + + -- attempt to get links from pkg-config + local pkginfo = nil + local links = opt.links + if not links then + pkginfo = pkg_config.info(name) + if pkginfo then + links = pkginfo.links + end + end + + -- import find_library + local find_library = import("lib.detect.find_library") + + -- find library + local result = nil + for _, link in ipairs(table.wrap(links)) do + local libinfo = find_library(link, pathes) + if libinfo then + result = result or {} + result.links = table.join(result.links or {}, libinfo.link) + result.linkdirs = table.join(result.linkdirs or {}, libinfo.linkdir) + end + end + + -- not found? only add links + if not result and pkginfo and pkginfo.links then + result = {links = pkginfo.links} + end + + -- ok + return result end -- find package @@ -65,42 +127,65 @@ function sandbox_lib_detect_find_package._find(name, opt) -- init find scripts local findscripts = { - sandbox_lib_detect_find_package._find_from_repositories + sandbox_lib_detect_find_package._find_from_project_packagedirs + , sandbox_lib_detect_find_package._find_from_repositories , sandbox_lib_detect_find_package._find_from_modules - , sandbox_lib_detect_find_package._find_from_system } + -- find package from the current host platform + if opt.plat == os.host() and opt.arch == os.arch() then + table.insert(findscripts, sandbox_lib_detect_find_package._find_from_pkg_config) + table.insert(findscripts, sandbox_lib_detect_find_package._find_from_systemdirs) + end + -- find it + local result = nil for _, find in ipairs(findscripts) do - local package = find(name, opt) - if package then - return package + result = find(name, opt) + if result then + break end end + + -- remove repeat + if result then + result.linkdirs = table.unique(result.linkdirs) + result.includedirs = table.unique(result.includedirs) + end + + -- ok? + return result end -- find package -- -- @param name the package name --- @param opt the package options. e.g. {version = ">1.0.1", pathes = {"/usr/lib"}} +-- @param opt the package options. e.g. {plat = "iphoneos", arch = "arm64", version = "1.0.1", pathes = {"/usr/lib"}, links = {"ssl"}, includes = {"ssl.h"}} -- --- @return {links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}, version = "1.0.2"} +-- @return {links = {"ssl", "crypto", "z"}, linkdirs = {"/usr/local/lib"}, includedirs = {"/usr/local/include"}} -- -- @code -- -- local package = find_package("openssl") --- local package = find_package("openssl", {version = ">1.0.1"}) --- local package = find_package("openssl", {pathes = {"/usr/lib", "/usr/local/lib", "/usr/local/include"}, version = ">1.0.1"}) +-- local package = find_package("openssl", {version = "1.0.1"}) +-- local package = find_package("openssl", {plat = "iphoneos"}) +-- local package = find_package("openssl", {pathes = {"/usr/lib", "/usr/local/lib", "/usr/local/include"}, version = "1.0.1"}) +-- local package = find_package("openssl", {pathes = {"/usr/lib", "/usr/local/lib", "/usr/local/include"}, links = {"ssl", "crypto"}, includes = {"ssl.h"}}) -- -- @endcode -- function sandbox_lib_detect_find_package.main(name, opt) - -- get detect cache - local detectcache = cache(utils.ifelse(os.isfile(project.file()), "local.detect", "memory.detect")) - + -- init options + opt = opt or {} + opt.plat = opt.plat or config.get("plat") or os.host() + opt.arch = opt.arch or config.get("arch") or os.arch() + + -- init cache key + local key = "find_package_" .. opt.plat .. "_" .. opt.arch + -- attempt to get result from cache first - local cacheinfo = detectcache:get("find_package") or {} + local cacheinfo = cache.load(key) local result = cacheinfo[name] if result ~= nil then return utils.ifelse(result, result, nil) @@ -113,8 +198,7 @@ function sandbox_lib_detect_find_package.main(name, opt) cacheinfo[name] = utils.ifelse(result, result, false) -- save cache info - detectcache:set("find_program", cacheinfo) - detectcache:flush() + cache.save(key, cacheinfo) -- trace if option.get("verbose") then diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua index 2b94b33fc..bb5a7d280 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_path.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_path.lua @@ -35,24 +35,45 @@ local vformat = require("sandbox/modules/vformat") -- find path -- -- @param name the path name --- @param pathes the program pathes (.e.g dirs, pathes, winreg pathes) +-- @param pathes the search pathes (.e.g dirs, pathes, winreg pathes) +-- @param opt the options, .e.g {suffixes = {"/aa", "/bb"}} -- -- @return the path -- -- @code -- -- local p = find_path("include/test.h", { "/usr", "/usr/local"}) +-- -> /usr/local ("/usr/local/include/test.h") +-- -- local p = find_path("include/*.h", { "/usr", "/usr/local/**"}) -- local p = find_path("lib/xxx", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name)"}) -- local p = find_path("lib/xxx", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\XXXX;Name"):match("\"(.-)\"") end}) -- -- @endcode -- -function sandbox_lib_detect_find_path.main(name, pathes) +function sandbox_lib_detect_find_path.main(name, pathes, opt) + + -- init options + opt = opt or {} + + -- init pathes + pathes = table.wrap(pathes) + + -- append suffixes to pathes + local suffixes = table.wrap(opt.suffixes) + if #suffixes > 0 then + local pathes_new = {} + for _, parent in ipairs(pathes) do + for _, suffix in ipairs(suffixes) do + table.insert(pathes_new, path.join(parent, suffix)) + end + end + pathes = pathes_new + end -- find file local result = nil - for _, _path in ipairs(table.wrap(pathes)) do + for _, _path in ipairs(pathes) do -- format path for builtin variables if type(_path) == "function" then @@ -66,17 +87,9 @@ function sandbox_lib_detect_find_path.main(name, pathes) _path = vformat(_path) end - -- get file path - local filepath = nil - if os.isfile(_path) then - filepath = _path - else - filepath = path.join(_path, name) - end - -- path exists? - for _, p in ipairs(os.filedirs(filepath)) do - result = p + for _, p in ipairs(os.filedirs(path.join(_path, name))) do + result = _path break end diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua index a14b67648..e38a3414c 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua @@ -31,11 +31,14 @@ local path = require("base/path") local table = require("base/table") local utils = require("base/utils") local option = require("base/option") -local cache = require("project/cache") local project = require("project/project") local sandbox = require("sandbox/sandbox") local raise = require("sandbox/modules/raise") local vformat = require("sandbox/modules/vformat") +local cache = require("sandbox/modules/import/lib/detect/cache") + +-- globals +local checking = nil -- check program function sandbox_lib_detect_find_program._check(program, check) @@ -123,7 +126,7 @@ end -- find program -- -- @param name the program name --- @param pathes the program pathes (.e.g dirs, pathes, winreg pathes) +-- @param pathes the program pathes (.e.g dirs, pathes, winreg pathes, script pathes) -- @param check the check script or command -- -- @return the program name or path @@ -131,21 +134,26 @@ end -- @code -- -- local program = find_program("ccache") --- local program = find_program("ccache", { "/usr/bin", "/usr/local/bin"}) --- local program = find_program("ccache", { "/usr/bin", "/usr/local/bin"}, "--help") -- simple check command: ccache --help --- local program = find_program("ccache", { "/usr/bin", "/usr/local/bin"}, function (program) os.run("%s -h", program) end) --- local program = find_program("ccache", { "$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}) --- local program = find_program("ccache", { "$(env PATH)", function () return val("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger"):match("\"(.-)\"") end}) +-- local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}) +-- local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, "--help") -- simple check command: ccache --help +-- local program = find_program("ccache", {"/usr/bin", "/usr/local/bin"}, function (program) os.run("%s -h", program) end) +-- local program = find_program("ccache", {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}) +-- local program = find_program("ccache", {"$(env PATH)", function () return "/usr/local/bin" end}) -- -- @endcode -- function sandbox_lib_detect_find_program.main(name, pathes, check) - -- get detect cache - local detectcache = cache(utils.ifelse(os.isfile(project.file()), "local.detect", "memory.detect")) - + -- @note avoid detect the same program in the same time leading to deadlock if running in the coroutine (.e.g ccache) + local coroutine_running = coroutine.running() + if coroutine_running then + while checking ~= nil and checking == name do + coroutine.yield() + end + end + -- attempt to get result from cache first - local cacheinfo = detectcache:get("find_program") or {} + local cacheinfo = cache.load("find_program") local result = cacheinfo[name] if result ~= nil then return utils.ifelse(result, result, nil) @@ -153,18 +161,19 @@ function sandbox_lib_detect_find_program.main(name, pathes, check) -- add default search pathes if os.host() ~= "windows" then - pathes = table.join(table.wrap(pathes), "/usr/local/lib", "/usr/lib") + pathes = table.join(table.wrap(pathes), "/usr/local/bin", "/usr/bin") end -- find executable program + checking = utils.ifelse(coroutine_running, name, nil) result = sandbox_lib_detect_find_program._find(name, pathes, check) + checking = nil -- cache result cacheinfo[name] = utils.ifelse(result, result, false) -- save cache info - detectcache:set("find_program", cacheinfo) - detectcache:flush() + cache.save("find_program", cacheinfo) -- trace if option.get("verbose") then diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua b/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua index 50eb72cef..b54b03899 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua @@ -31,10 +31,10 @@ local path = require("base/path") local table = require("base/table") local utils = require("base/utils") local option = require("base/option") -local cache = require("project/cache") local project = require("project/project") local sandbox = require("sandbox/sandbox") local raise = require("sandbox/modules/raise") +local cache = require("sandbox/modules/import/lib/detect/cache") -- find program version -- @@ -54,11 +54,8 @@ local raise = require("sandbox/modules/raise") -- function sandbox_lib_detect_find_programver.main(program, command, parse) - -- get detect cache - local detectcache = cache(utils.ifelse(os.isfile(project.file()), "local.detect", "memory.detect")) - -- attempt to get result from cache first - local cacheinfo = detectcache:get("find_programver") or {} + local cacheinfo = cache.load("find_programver") local result = cacheinfo[program] if result ~= nil then return utils.ifelse(result, result, nil) @@ -93,8 +90,7 @@ function sandbox_lib_detect_find_programver.main(program, command, parse) cacheinfo[program] = utils.ifelse(result, result, false) -- save cache info - detectcache:set("find_program", cacheinfo) - detectcache:flush() + cache.save("find_programver", cacheinfo) -- ok? return result diff --git a/xmake/core/sandbox/modules/inherit.lua b/xmake/core/sandbox/modules/inherit.lua index cf22abcec..2ec1e2e29 100644 --- a/xmake/core/sandbox/modules/inherit.lua +++ b/xmake/core/sandbox/modules/inherit.lua @@ -30,10 +30,16 @@ local import = require("sandbox/modules/import") -- we can access all super interfaces by _super -- -- @note the polymiorphism is not supported for import.inherit mode now. -function sandbox_inherit(name) +function sandbox_inherit(name, args) + + -- init args + args = args or {} + + -- mark as inherit + args.inherit = true -- import and inherit it - return import(name, {inherit = true}) + return import(name, args) end -- load module diff --git a/xmake/core/sandbox/modules/interpreter/os.lua b/xmake/core/sandbox/modules/interpreter/os.lua index b11e6bcb4..b956726eb 100644 --- a/xmake/core/sandbox/modules/interpreter/os.lua +++ b/xmake/core/sandbox/modules/interpreter/os.lua @@ -30,17 +30,21 @@ local string = require("base/string") local sandbox_os = sandbox_os or {} -- export some readonly interfaces -sandbox_os.date = os.date -sandbox_os.time = os.time -sandbox_os.mtime = os.mtime -sandbox_os.mclock = os.mclock -sandbox_os.getenv = os.getenv -sandbox_os.isdir = os.isdir -sandbox_os.isfile = os.isfile -sandbox_os.exists = os.exists -sandbox_os.curdir = os.curdir -sandbox_os.tmpdir = os.tmpdir -sandbox_os.uuid = os.uuid +sandbox_os.date = os.date +sandbox_os.time = os.time +sandbox_os.mtime = os.mtime +sandbox_os.mclock = os.mclock +sandbox_os.getenv = os.getenv +sandbox_os.isdir = os.isdir +sandbox_os.isfile = os.isfile +sandbox_os.exists = os.exists +sandbox_os.curdir = os.curdir +sandbox_os.tmpdir = os.tmpdir +sandbox_os.programdir = os.programdir +sandbox_os.programfile = os.programfile +sandbox_os.projectdir = os.projectdir +sandbox_os.projectfile = os.projectfile +sandbox_os.uuid = os.uuid -- match files function sandbox_os.files(pattern, ...) diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index 90312ae2a..7f53818e4 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -48,6 +48,8 @@ sandbox_os.nuldev = os.nuldev sandbox_os.emptydir = os.emptydir sandbox_os.programdir = os.programdir sandbox_os.programfile = os.programfile +sandbox_os.projectdir = os.projectdir +sandbox_os.projectfile = os.projectfile sandbox_os.versioninfo = os.versioninfo -- copy file or directory @@ -224,13 +226,6 @@ function sandbox_os.tmpfile() return tmpfile end --- get the tools directory -function sandbox_os.toolsdir() - - -- get it - return xmake._TOOLS_DIR -end - -- get the script directory function sandbox_os.scriptdir() @@ -246,7 +241,7 @@ function sandbox_os.scriptdir() return rootdir end --- quietly run shell +-- quietly run command function sandbox_os.run(cmd, ...) -- make command @@ -259,20 +254,20 @@ function sandbox_os.run(cmd, ...) end end --- quietly run shell with arguments list -function sandbox_os.runv(shellname, argv) +-- quietly run command with arguments list +function sandbox_os.runv(program, argv) - -- make shellname - shellname = vformat(shellname) + -- make program + program = vformat(program) -- run it - local ok, errors = os.runv(shellname, argv) + local ok, errors = os.runv(program, argv) if not ok then os.raise(errors) end end --- quietly run shell and echo verbose info if [-v|--verbose] option is enabled +-- quietly run command and echo verbose info if [-v|--verbose] option is enabled function sandbox_os.vrun(cmd, ...) -- echo command @@ -284,19 +279,19 @@ function sandbox_os.vrun(cmd, ...) utils.ifelse(option.get("verbose"), sandbox_os.exec, sandbox_os.run)(cmd, ...) end --- quietly run shell with arguments list and echo verbose info if [-v|--verbose] option is enabled -function sandbox_os.vrunv(shellname, argv) +-- quietly run command with arguments list and echo verbose info if [-v|--verbose] option is enabled +function sandbox_os.vrunv(program, argv) -- echo command if option.get("verbose") then - print(vformat(shellname), table.concat(argv, " ")) + print(vformat(program), table.concat(argv, " ")) end -- run it - utils.ifelse(option.get("verbose"), sandbox_os.execv, sandbox_os.runv)(shellname, argv) + utils.ifelse(option.get("verbose"), sandbox_os.execv, sandbox_os.runv)(program, argv) end --- run shell and return output and error data +-- run command and return output and error data function sandbox_os.iorun(cmd, ...) -- make command @@ -312,14 +307,14 @@ function sandbox_os.iorun(cmd, ...) return outdata, errdata end --- run shell and return output and error data -function sandbox_os.iorunv(shellname, argv) +-- run command and return output and error data +function sandbox_os.iorunv(program, argv) - -- make shellname - shellname = vformat(shellname) + -- make program + program = vformat(program) -- run it - local ok, outdata, errdata = os.iorunv(shellname, argv) + local ok, outdata, errdata = os.iorunv(program, argv) if not ok then os.raise(errdata) end @@ -328,7 +323,7 @@ function sandbox_os.iorunv(shellname, argv) return outdata, errdata end --- execute shell +-- execute command function sandbox_os.exec(cmd, ...) -- make command @@ -341,19 +336,19 @@ function sandbox_os.exec(cmd, ...) end end --- execute shell with arguments list -function sandbox_os.execv(shellname, argv) +-- execute command with arguments list +function sandbox_os.execv(program, argv) - -- make shellname - shellname = vformat(shellname) + -- make program + program = vformat(program) -- run it - local ok = os.execv(shellname, argv) + local ok = os.execv(program, argv) if ok ~= 0 then if argv ~= nil then - os.raise("execv(%s %s) failed(%d)!", shellname, table.concat(argv, ' '), ok) + os.raise("execv(%s %s) failed(%d)!", program, table.concat(argv, ' '), ok) else - os.raise("execv(%s) failed(%d)!", shellname, ok) + os.raise("execv(%s) failed(%d)!", program, ok) end end end diff --git a/xmake/core/sandbox/modules/string.lua b/xmake/core/sandbox/modules/string.lua index 3079c6e23..2506ae35e 100644 --- a/xmake/core/sandbox/modules/string.lua +++ b/xmake/core/sandbox/modules/string.lua @@ -23,6 +23,7 @@ -- -- load modules +local utils = require("base/utils") local string = require("base/string") local sandbox = require("sandbox/sandbox") @@ -46,12 +47,14 @@ function sandbox_string.vformat(format, ...) local instance = sandbox.instance() assert(instance) - -- ignore %$(...) - format = format:gsub("%%%$", "__$__") - -- format string if exists arguments local result = format if #{...} > 0 then + + -- escape "%$", "%(", "%)", "%%" to '$', '(', ')', '%%' + format = format:gsub("%%([%$%(%)%%])", function (ch) return utils.ifelse(ch ~= "%", "%%" .. ch, "%%%%") end) + + -- try to format it result = string.format(format, ...) end assert(result) @@ -62,9 +65,6 @@ function sandbox_string.vformat(format, ...) result = filter:handle(result) end - -- escape to $(...) - result = result:gsub("__%$__", "$") - -- ok? return result end diff --git a/xmake/core/sandbox/modules/utils.lua b/xmake/core/sandbox/modules/utils.lua index 80a21aef8..f72da0423 100644 --- a/xmake/core/sandbox/modules/utils.lua +++ b/xmake/core/sandbox/modules/utils.lua @@ -76,7 +76,8 @@ function sandbox_utils.print(format, ...) end, catch { - function () + function (errors) + print(errors) -- print multi-variables with raw lua action sandbox_utils._print(format, unpack(args)) end diff --git a/xmake/core/sandbox/sandbox.lua b/xmake/core/sandbox/sandbox.lua index 77b7003e2..a706e6da2 100644 --- a/xmake/core/sandbox/sandbox.lua +++ b/xmake/core/sandbox/sandbox.lua @@ -107,7 +107,7 @@ function sandbox._new() table.inherit2(instance, sandbox) -- load builtin module files - local builtin_module_files = os.match(path.join(xmake._CORE_DIR, "sandbox/modules/*.lua")) + local builtin_module_files = os.match(path.join(os.programdir(), "core/sandbox/modules/*.lua")) if builtin_module_files then for _, builtin_module_file in ipairs(builtin_module_files) do @@ -134,19 +134,8 @@ function sandbox._new() end end - -- save instance - setmetatable(instance._PUBLIC, { __index = function (tbl, key) - if type(key) == "string" and key == "_SANDBOX" and rawget(tbl, "_SANDBOX_READABLE") then - return instance - end - return rawget(tbl, key) - end - , __newindex = function (tbl, key, val) - if type(key) == "string" and (key == "_SANDBOX" or key == "_SANDBOX_READABLE") then - return - end - rawset(tbl, key, val) - end}) + -- bind instance to the public script envirnoment + instance:bind(instance._PUBLIC) -- ok? return instance @@ -192,7 +181,34 @@ function sandbox.load(script, ...) return xpcall(script, sandbox._traceback, ...) end --- fork a new sandbox from the given sandbox +-- bind self instance to the given script or envirnoment +function sandbox:bind(script_or_env) + + -- get envirnoment + local env = script_or_env + if type(script_or_env) == "function" then + env = getfenv(script_or_env) + end + + -- bind instance to the script envirnoment + setmetatable(env, { __index = function (tbl, key) + if type(key) == "string" and key == "_SANDBOX" and rawget(tbl, "_SANDBOX_READABLE") then + return self + end + return rawget(tbl, key) + end + , __newindex = function (tbl, key, val) + if type(key) == "string" and (key == "_SANDBOX" or key == "_SANDBOX_READABLE") then + return + end + rawset(tbl, key, val) + end}) + + -- ok + return script_or_env +end + +-- fork a new sandbox from the self sandbox function sandbox:fork(script, rootdir) -- invalid script? @@ -254,7 +270,6 @@ function sandbox:import() -- ok return module - end -- get script from the given sandbox diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 43bed8bfa..9143fcbee 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -76,8 +76,8 @@ function builder:_mapflag(flag, mapflags) end end - -- check it - if self:check(flag) then + -- has this flag? + if self:has_flags(flag) then return flag end end @@ -103,9 +103,9 @@ function builder:_mapflags(flags) else - -- check flags + -- has flags? for _, flag in pairs(flags) do - if self:check(flag) then + if self:has_flags(flag) then table.insert(results, flag) end end @@ -194,6 +194,13 @@ function builder:_addflags_from_targetdeps(results, target, flagname) end end +-- add flags from the argument option +function builder:_addflags_from_argument(flags, args) + for _, flagkind in ipairs(self:_flagkinds()) do + table.join2(flags, self:_mapflags(args[flagkind])) + end +end + -- add flags (named) from the language function builder:_addflags_from_language(flags, target) @@ -261,8 +268,8 @@ function builder:_addflags_from_language(flags, target) for _, flagvalue in ipairs(table.wrap(getter(flagname))) do -- map and check flag - local flag = mapper(flagvalue, target, self:_targetkind()) - if flag and flag ~= "" and (not checkstate or self:check(flag)) then + local flag = mapper(self:_tool(), flagvalue, target, self:_targetkind()) + if flag and flag ~= "" and (not checkstate or self:has_flags(flag)) then table.join2(flags, flag) end end @@ -270,11 +277,29 @@ function builder:_addflags_from_language(flags, target) end end +-- get tool name +function builder:name() + return self:_tool():name() +end + +-- get tool kind +function builder:kind() + return self:_tool():kind() +end + +-- get tool program +function builder:program() + return self:_tool():program() +end + -- get properties of the tool function builder:get(name) + return self:_tool():get(name) +end - -- get it - return self:_tool().get(name) +-- has flags? +function builder:has_flags(flags) + return self:_tool():has_flags(flags) end -- get the format of the given target kind @@ -297,40 +322,5 @@ function builder:feature(name) end end --- check the given flags -function builder:check(flags) - - -- the builder tool - local ctool = self:_tool() - - -- no check? - if not ctool.check then - return true - end - - -- have been checked? return it directly - self._CHECKED = self._CHECKED or {} - if self._CHECKED[flags] ~= nil then - return self._CHECKED[flags] - end - - -- check it - local ok, errors = sandbox.load(ctool.check, flags) - - -- trace - if option.get("verbose") then - utils.cprint("checking for the flags %s ... %s", flags, utils.ifelse(ok, "${green}ok", "${red}no")) - if not ok then - utils.cprint("${red}" .. errors or "") - end - end - - -- save the checked result - self._CHECKED[flags] = ok - - -- ok? - return ok -end - -- return module return builder diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index a550564da..622ed946b 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -50,7 +50,7 @@ end function compiler:_addflags_from_platform(flags, targetkind) -- add flags - local toolkind = self:get("kind") + local toolkind = self:kind() for _, flagkind in ipairs(self:_flagkinds()) do -- add flags for platform @@ -124,67 +124,119 @@ function compiler.load(sourcekind) return instance end --- build the source files -function compiler:build(sourcefiles, targetkind, targetfile, target) +-- build the source files (compile and link) +function compiler:build(sourcefiles, targetfile, opt) + + -- init options + opt = opt or {} + + -- make flags + local flags = self:compflags(opt) + if opt.target then + flags = flags .. " " .. (opt.target:linkflags()) + end + + -- get target kind + local targetkind = opt.targetkind + if not targetkind and opt.target then + targetkind = opt.target:get("kind") + end -- get it - return sandbox.load(self:_tool().build, sourcefiles, targetkind, targetfile, (self:compflags(target)) .. " " .. (target:linkflags())) + return sandbox.load(self:_tool().build, self:_tool(), sourcefiles, targetkind or "binary", targetfile, flags) end --- get the build command -function compiler:buildcmd(sourcefiles, targetkind, targetfile, target) +-- get the build command (compile and link) +function compiler:buildcmd(sourcefiles, targetfile, opt) + + -- init options + opt = opt or {} + + -- make flags + local flags = self:compflags(opt) + if opt.target then + flags = flags .. " " .. (opt.target:linkflags()) + end + + -- get target kind + local targetkind = opt.targetkind + if not targetkind and opt.target then + targetkind = opt.target:get("kind") + end -- get it - return self:_tool().buildcmd(sourcefiles, targetkind, targetfile, (self:compflags(target) .. " " .. (target:linkflags()))) + return self:_tool():buildcmd(sourcefiles, targetkind or "binary", targetfile, flags) end -- compile the source files -function compiler:compile(sourcefiles, objectfile, incdepfile, target) +function compiler:compile(sourcefiles, objectfile, opt) + + -- init options + opt = opt or {} -- compile it - return sandbox.load(self:_tool().compile, sourcefiles, objectfile, incdepfile, (self:compflags(target))) + return sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.incdepfiles, (self:compflags(opt))) end -- get the compile command -function compiler:compcmd(sourcefiles, objectfile, target) - - -- get it - return self:_tool().compcmd(sourcefiles, objectfile, (self:compflags(target))) +function compiler:compcmd(sourcefiles, objectfile, opt) + return self:_tool():compcmd(sourcefiles, objectfile, (self:compflags(opt))) end -- get the compling flags -function compiler:compflags(target) +function compiler:compflags(opt) - -- no target? - if not target then - return "", {} - end + -- init options + opt = opt or {} + + -- get target + local target = opt.target -- get the target key - local key = tostring(target) + local key = nil + if target then + key = tostring(target) + end -- get it directly from cache dirst - self._FLAGS = self._FLAGS or {} - local flags_cached = self._FLAGS[key] - if flags_cached then - return flags_cached[1], flags_cached[2] + if key then + self._FLAGS = self._FLAGS or {} + local flags_cached = self._FLAGS[key] + if flags_cached then + return flags_cached[1], flags_cached[2] + end + end + + -- get target kind + local targetkind = opt.targetkind + if not targetkind and target then + targetkind = target:get("kind") end -- add flags from the configure local flags = {} self:_addflags_from_config(flags) - -- add flags from the target - self:_addflags_from_target(flags, target) - + -- add flags for the target + if target then + self:_addflags_from_target(flags, target) + end + -- add flags (named) from language - self:_addflags_from_language(flags, target) + if target then + self:_addflags_from_language(flags, target) + end + + -- add flags for the argument + self:_addflags_from_argument(flags, opt) -- add flags from the platform - self:_addflags_from_platform(flags, target:get("kind")) + if target then + self:_addflags_from_platform(flags, targetkind) + end -- add flags from the compiler - self:_addflags_from_compiler(flags, target:get("kind")) + self:_addflags_from_compiler(flags, targetkind) -- remove repeat flags = table.unique(flags) @@ -193,7 +245,9 @@ function compiler:compflags(target) local flags_str = table.concat(flags, " "):trim() -- save flags - self._FLAGS[key] = {flags_str, flags} + if key then + self._FLAGS[key] = {flags_str, flags} + end -- get it return flags_str, flags diff --git a/xmake/core/tool/extractor.lua b/xmake/core/tool/extractor.lua index 1149e31aa..480005c68 100644 --- a/xmake/core/tool/extractor.lua +++ b/xmake/core/tool/extractor.lua @@ -38,8 +38,6 @@ local tool = require("tool/tool") -- get the current tool function extractor:_tool() - - -- get it return self._TOOL end @@ -72,16 +70,12 @@ end -- get properties of the tool function extractor:get(name) - - -- get it - return self:_tool().get(name) + return self:_tool():get(name) end -- extract the library file function extractor:extract(libraryfile, objectdir) - - -- extract it - return sandbox.load(self:_tool().extract, libraryfile, objectdir) + return sandbox.load(self:_tool().extract, self:_tool(), libraryfile, objectdir) end -- return module diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua index 0ddf3165b..e1d091edb 100644 --- a/xmake/core/tool/linker.lua +++ b/xmake/core/tool/linker.lua @@ -44,25 +44,27 @@ local compiler = require("tool/compiler") function linker:_addflags_from_platform(flags, targetkind) -- add flags - local toolkind = self:get("kind") + local toolkind = self:kind() for _, flagkind in ipairs(self:_flagkinds()) do -- attempt to add special lanugage flags first, .e.g gc-ldflags, dc-arflags table.join2(flags, platform.get(toolkind .. 'flags') or platform.get(flagkind)) -- attempt to add special lanugage flags first for target kind, .e.g gc-ldflags, dc-arflags - local targetflags = platform.get(targetkind) or {} - table.join2(flags, targetflags[toolkind .. 'flags'] or targetflags[flagkind]) + if targetkind then + local targetflags = platform.get(targetkind) or {} + table.join2(flags, targetflags[toolkind .. 'flags'] or targetflags[flagkind]) + end end end -- add flags from the compiler -function linker:_addflags_from_compiler(flags, targetkind, sourcekinds) +function linker:_addflags_from_compiler(flags, targetkind) -- make flags local flags_of_compiler = {} - local toolkind = self:get("kind") - for _, sourcekind in ipairs(table.wrap(sourcekinds)) do + local toolkind = self:kind() + for _, sourcekind in ipairs(self._SOURCEKINDS) do -- load compiler local instance, errors = compiler.load(sourcekind) @@ -87,7 +89,7 @@ end function linker:_addflags_from_linker(flags) -- add flags - local toolkind = self:get("kind") + local toolkind = self:kind() for _, flagkind in ipairs(self:_flagkinds()) do -- attempt to add special lanugage flags first, .e.g gc-ldflags, dc-arflags @@ -162,6 +164,9 @@ function linker.load(targetkind, sourcekinds) -- init target kind instance._TARGETKIND = targetkind + -- init source kinds + instance._SOURCEKINDS = sourcekinds + -- init flag kinds instance._FLAGKINDS = {linkerinfo.linkerflag} @@ -173,52 +178,71 @@ function linker.load(targetkind, sourcekinds) end -- link the target file -function linker:link(objectfiles, targetfile, target) - - -- link it - return sandbox.load(self:_tool().link, table.concat(table.wrap(objectfiles), " "), self:_targetkind(), targetfile, (self:linkflags(target))) +function linker:link(objectfiles, targetfile, opt) + return sandbox.load(self:_tool().link, self:_tool(), table.concat(table.wrap(objectfiles), " "), self:_targetkind(), targetfile, (self:linkflags(opt))) end -- get the link command -function linker:linkcmd(objectfiles, targetfile, target) - - -- get it - return self:_tool().linkcmd(table.concat(table.wrap(objectfiles), " "), self:_targetkind(), targetfile, (self:linkflags(target))) +function linker:linkcmd(objectfiles, targetfile, opt) + return self:_tool():linkcmd(table.concat(table.wrap(objectfiles), " "), self:_targetkind(), targetfile, (self:linkflags(opt))) end -- get the link flags -function linker:linkflags(target) +function linker:linkflags(opt) - -- no target? - if not target then - return "", {} - end + -- init options + opt = opt or {} + + -- get target + local target = opt.target -- get the target key - local key = tostring(target) + local key = nil + if target then + key = tostring(target) + end -- get it directly from cache dirst - self._FLAGS = self._FLAGS or {} - local flags_cached = self._FLAGS[key] - if flags_cached then - return flags_cached[1], flags_cached[2] + if key then + self._FLAGS = self._FLAGS or {} + local flags_cached = self._FLAGS[key] + if flags_cached then + return flags_cached[1], flags_cached[2] + end + end + + -- get target kind + local targetkind = opt.targetkind + if not targetkind and target then + targetkind = target:get("kind") end -- add flags from the configure local flags = {} self:_addflags_from_config(flags) - -- add flags from the target - self:_addflags_from_target(flags, target) - + -- add flags for the target + if target then + self:_addflags_from_target(flags, target) + end + -- add flags (named) from language - self:_addflags_from_language(flags, target) + if target then + self:_addflags_from_language(flags, target) + end + + -- add flags for the argument + self:_addflags_from_argument(flags, opt) -- add flags from the platform - self:_addflags_from_platform(flags, target:get("kind")) + if target then + self:_addflags_from_platform(flags, targetkind) + end -- add flags from the compiler - self:_addflags_from_compiler(flags, target:get("kind"), target:sourcekinds()) + if target then + self:_addflags_from_compiler(flags, targetkind) + end -- add flags from the linker self:_addflags_from_linker(flags) @@ -230,7 +254,9 @@ function linker:linkflags(target) local flags_str = table.concat(flags, " "):trim() -- save flags - self._FLAGS[key] = {flags_str, flags} + if key then + self._FLAGS[key] = {flags_str, flags} + end -- get it return flags_str, flags diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index 7b139b12b..67c95cc24 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -13,7 +13,7 @@ -- 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 +-- See the License for the specific tool governing permissions and -- limitations under the License. -- -- Copyright (C) 2015 - 2017, TBOOX Open Source Group. @@ -24,202 +24,75 @@ -- define module local tool = tool or {} +local _instance = _instance or {} -- load modules -local os = require("base/os") -local path = require("base/path") -local utils = require("base/utils") -local table = require("base/table") -local string = require("base/string") -local filter = require("base/filter") -local config = require("project/config") -local global = require("project/global") -local sandbox = require("sandbox/sandbox") -local platform = require("platform/platform") +local os = require("base/os") +local path = require("base/path") +local utils = require("base/utils") +local table = require("base/table") +local string = require("base/string") +local sandbox = require("sandbox/sandbox") +local platform = require("platform/platform") +local import = require("sandbox/modules/import") --- the directories of tools -function tool._directories(name) - - -- the directories - return { path.join(config.directory(), "tools") - , path.join(global.directory(), "tools") - , path.join(xmake._PROGRAM_DIR, "tools") - } -end - --- match the tool name -function tool._match(name, toolname) - - -- match full? ok - if name == toolname then return 100 end - - -- match the last word? ok - if name:find(toolname .. "$") then return 80 end - - -- contains it? ok - if name:find(toolname, 1, true) then return 30 end - - -- not matched - return 0 -end - --- find tool from the given root directory and name -function tool._find(root, name) - - -- attempt to get it directly first - local filepath = string.format("%s/%s.lua", root, name) - if os.isfile(filepath) then - return filepath - end - - -- make the lower name - name = name:lower() - - -- remove arguments: -xxx or --xxx - name = (name:gsub("%s%-+%w+", " ")) - - -- get the last name by ' ': xxx xxx toolname - local names = name:split("%s") - if #names > 0 then - name = names[#names] - end - - -- get the last name by '-': xxx-xxx-toolname - local names = name:split("%-") - if #names > 0 then - name = names[#names] - end - - -- remove suffix: ".xxx" - name = (name:gsub("%.%w+", "")) - - -- get all tool files - local file_ok = nil - local score_maxn = 0 - local files = os.match(string.format("%s/*.lua", root)) - for _, file in ipairs(files) do - - -- the tool name - local toolname = path.basename(file) - - -- found it? - if toolname and toolname ~= "tool" then - - -- match score - local score = tool._match(name, toolname:lower()) - - -- ok? - if score >= 100 then return file end - - -- select the file with the max score - if score > score_maxn then - file_ok = file - score_maxn = score - end - end - end - - -- ok? - return file_ok -end - --- load the given tool from the given shell name -function tool._load(shellname, kind) - - -- calculate the cache key - local key = shellname .. (kind or "") - - -- get it directly from cache dirst - tool._TOOLS = tool._TOOLS or {} - if tool._TOOLS[key] then - return tool._TOOLS[key] - end - - -- find the tool script path - local toolpath = nil - local toolname = path.filename(shellname) - for _, dir in ipairs(tool._directories()) do - - -- find this directory - toolpath = tool._find(dir, toolname) - if toolpath then - break - end +-- new an instance +function _instance.new(kind, name, program) + -- import "core.tools.xxx" + local toolclass = nil + if os.isfile(path.join(os.programdir(), "modules", "core", "tools", name .. ".lua")) then + toolclass = import("core.tools." .. name) end - -- not exists? - if not toolpath or not os.isfile(toolpath) then - return nil, string.format("%s not found!", shellname) + -- not found? + if not toolclass then + return nil, string.format("cannot import \"core.tool.%s\" module!", name) end - -- load script - local script, errors = loadfile(toolpath) - if script then + -- new an instance + local instance = table.inherit(_instance, toolclass) - -- make sandbox instance with the given script - local instance, errors = sandbox.new(script, nil, path.directory(toolpath)) - if not instance then - return nil, errors - end + -- save name, kind and program + instance._NAME = name + instance._KIND = kind + instance._PROGRAM = program - -- import the tool module - local module, errors = instance:import() - if not module then + -- init instance + if instance.init then + local ok, errors = sandbox.load(instance.init, instance) + if not ok then return nil, errors end - - -- init the tool module - if module.init then - module.init(shellname, kind) - end - - -- save tool to the cache - tool._TOOLS[key] = module - - -- ok? - return module end - -- failed - return nil, errors + -- ok + return instance end --- check the shellname -function tool._check(shellname, check) - - -- uses the passed checker - if check ~= nil then +-- get the tool name +function _instance:name() + return self._NAME +end - -- check it - local ok, errors = sandbox.load(check, shellname) - if not ok then - utils.verror(errors) - end +-- get the tool kind +function _instance:kind() + return self._KIND +end - -- ok? - return ok - end - - -- load the tool module - local module, errors = tool._load(shellname) - if not module then - utils.verror(errors) - end +-- get the tool program +function _instance:program() + return self._PROGRAM +end - -- no checker? attempt to run it directly - if not module or not module.check then - return 0 == os.exec(shellname, os.nuldev(), os.nuldev()) - end +-- has the given flag? +function _instance:has_flags(flag) - -- check it - local ok, errors = sandbox.load(module.check) - if not ok then - utils.verror(errors) - end + -- import has_flags() + self._has_flags = self._has_flags or import("lib.detect.has_flags") - -- ok? - return ok + -- has flags? + return self._has_flags(self:name(), flag, {program = self:program()}) end -- load the given tool from the given kind @@ -230,51 +103,44 @@ end -- function tool.load(kind) - -- get the shell name - local shellname = platform.tool(kind) - if not shellname then + -- get it directly from cache dirst + tool._TOOLS = tool._TOOLS or {} + if tool._TOOLS[kind] then + return tool._TOOLS[kind] + end + + -- get the tool program + local program = platform.tool(kind) + if not program then return nil, string.format("cannot get tool for %s", kind) end - - -- load it - return tool._load(shellname, kind) -end --- check the tool and return the absolute path if exists -function tool.check(shellname, dirs, check) + -- import find_toolname() + tool._find_toolname = tool._find_toolname or import("lib.detect.find_toolname") - -- check - assert(shellname) + -- get the tool name from the program + local ok, name_or_errors = sandbox.load(tool._find_toolname, program) + if not ok then + return nil, name_or_errors + end - -- attempt to get result from cache first - tool._CHECKINFO = tool._CHECKINFO or {} - local result = tool._CHECKINFO[shellname] - if result then - return result + -- get name + local name = name_or_errors + if not name then + return nil, string.format("cannot find tool name for %s", program) end - -- attempt to check it directly - if tool._check(shellname, check) then - tool._CHECKINFO[shellname] = shellname - return shellname + -- new an instance + local instance, errors = _instance.new(kind, name, program) + if not instance then + return nil, errors end - -- attempt to check it from the given directories - if not path.is_absolute(shellname) then - for _, dir in ipairs(table.wrap(dirs)) do + -- save instance to the cache + tool._TOOLS[kind] = instance - -- the tool path - local toolpath = path.join(dir, shellname) - if os.isexec(toolpath) then - - -- check it - if tool._check(toolpath, check) then - tool._CHECKINFO[shellname] = toolpath - return toolpath - end - end - end - end + -- ok + return instance end -- return module diff --git a/xmake/languages/c++/api.lua b/xmake/languages/c++/api.lua index 8937ddf74..d116fdeac 100644 --- a/xmake/languages/c++/api.lua +++ b/xmake/languages/c++/api.lua @@ -22,34 +22,57 @@ -- @file api.lua -- --- imports -import("core.project.option") +-- get function name and function info +-- +-- sigsetjmp +-- sigsetjmp((void*)0, 0) +-- sigsetjmp{sigsetjmp((void*)0, 0);} +-- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);} +-- +function _funcinfo(func) + + -- parse name and code + local name, code = string.match(func, "(.+){(.+)}") + if code == nil then + local pos = func:find("%(") + if pos then + name = func:sub(1, pos - 1) + code = func + else + name = func + code = string.format("volatile void* p%s = (void*)&%s;", name, name) + end + end + + -- ok + return name:trim(), code +end -- add c function -function _api_add_cfunc(interp, module, alias, links, includes, checkinfo) +function _api_add_cfunc(interp, module, alias, links, includes, func) - -- parse the check code - local checkname, checkcode = option.checkinfo(checkinfo) + -- parse the function info + local funcname, funccode = _funcinfo(func) -- make the option name local name = nil if module ~= nil then - name = format("__%s_%s", module, checkname) + name = format("__%s_%s", module, funcname) else - name = format("__%s", checkname) + name = format("__%s", funcname) end -- uses the alias name if alias ~= nil then - checkname = alias + funcname = alias end -- make the option define local define = nil if module ~= nil then - define = format("$(prefix)_%s_HAVE_%s", module:upper(), checkname:upper()) + define = format("$(prefix)_%s_HAVE_%s", module:upper(), funcname:upper()) else - define = format("$(prefix)_HAVE_%s", checkname:upper()) + define = format("$(prefix)_HAVE_%s", funcname:upper()) end -- save the current scope @@ -58,7 +81,7 @@ function _api_add_cfunc(interp, module, alias, links, includes, checkinfo) -- check option interp:api_call("option", name) interp:api_call("set_category", "cfuncs") - interp:api_call("add_cfuncs", checkinfo) + interp:api_call("add_cfuncs", func) if links then interp:api_call("add_links", links) end if includes then interp:api_call("add_cincludes", includes) end interp:api_call("add_defines_h_if_ok", define) @@ -74,36 +97,36 @@ end function _api_add_cfuncs(interp, module, links, includes, ...) -- done - for _, checkinfo in ipairs({...}) do - _api_add_cfunc(interp, module, nil, links, includes, checkinfo) + for _, func in ipairs({...}) do + _api_add_cfunc(interp, module, nil, links, includes, func) end end -- add c++ function -function _api_add_cxxfunc(interp, module, alias, links, includes, checkinfo) +function _api_add_cxxfunc(interp, module, alias, links, includes, func) - -- parse the check code - local checkname, checkcode = option.checkinfo(checkinfo) + -- parse the function info + local funcname, funccode = _funcinfo(func) -- make the option name local name = nil if module ~= nil then - name = format("__%s_%s", module, checkname) + name = format("__%s_%s", module, funcname) else - name = format("__%s", checkname) + name = format("__%s", funcname) end -- uses the alias name if alias ~= nil then - checkname = alias + funcname = alias end -- make the option define local define = nil if module ~= nil then - define = format("$(prefix)_%s_HAVE_%s", module:upper(), checkname:upper()) + define = format("$(prefix)_%s_HAVE_%s", module:upper(), funcname:upper()) else - define = format("$(prefix)_HAVE_%s", checkname:upper()) + define = format("$(prefix)_HAVE_%s", funcname:upper()) end -- save the current scope @@ -112,7 +135,7 @@ function _api_add_cxxfunc(interp, module, alias, links, includes, checkinfo) -- check option interp:api_call("option", name) interp:api_call("set_category", "cxxfuncs") - interp:api_call("add_cxxfuncs", checkinfo) + interp:api_call("add_cxxfuncs", func) if links then interp:api_call("add_links", links) end if includes then interp:api_call("add_cxxincludes", includes) end interp:api_call("add_defines_h_if_ok", define) @@ -128,8 +151,8 @@ end function _api_add_cxxfuncs(interp, module, links, includes, ...) -- done - for _, checkinfo in ipairs({...}) do - _api_add_cxxfunc(interp, module, nil, links, includes, checkinfo) + for _, func in ipairs({...}) do + _api_add_cxxfunc(interp, module, nil, links, includes, func) end end diff --git a/xmake/tools/ar.lua b/xmake/modules/core/tools/ar.lua index e870aa866..9d7ddabeb 100644 --- a/xmake/tools/ar.lua +++ b/xmake/modules/core/tools/ar.lua @@ -26,28 +26,21 @@ import("core.tool.compiler") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "ar" - - -- save the tool kind - _g.kind = kind or "ar" - -- init arflags _g.arflags = { "-cr" } - end -- get the property -function get(name) +function get(self, name) -- get it return _g[name] end -- make the strip flag -function strip(level) +function strip(self, level) -- the maps local maps = @@ -61,17 +54,17 @@ function strip(level) end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) -- check assert(targetkind == "static") -- make it - return format("%s %s %s %s", _g.shellname, flags, targetfile, objectfiles) + return format("%s %s %s %s", self:program(), flags, targetfile, objectfiles) end -- link the library file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- check assert(targetkind == "static", "the target kind: %s is not support for ar", targetkind) @@ -80,11 +73,11 @@ function link(objectfiles, targetkind, targetfile, flags) os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end -- extract the static library to object directory -function extract(libraryfile, objectdir) +function extract(self, libraryfile, objectdir) -- make the object directory first os.mkdir(objectdir) @@ -96,11 +89,11 @@ function extract(libraryfile, objectdir) local olddir = os.cd(objectdir) -- extract it - os.run("%s -x %s", _g.shellname, libraryfile) + os.run("%s -x %s", self:program(), libraryfile) -- check repeat object name local repeats = {} - local objectfiles = os.iorun("%s -t %s", _g.shellname, libraryfile) + local objectfiles = os.iorun("%s -t %s", self:program(), libraryfile) for _, objectfile in ipairs(objectfiles:split('\n')) do if repeats[objectfile] then raise("object name(%s) conflicts in library: %s", objectfile, libraryfile) @@ -112,29 +105,3 @@ function extract(libraryfile, objectdir) os.cd(olddir) end --- check the given flags -function check(flags) - - -- make an stub source file - local libraryfile = os.tmpfile() .. ".a" - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".c" - io.writefile(sourcefile, "int test(void)\n{return 0;}") - - -- make flags - local arflags = table.concat(_g.arflags, " ") - if flags then - arflags = arflags .. " " .. flags - end - - -- compile it - compiler.compile(sourcefile, objectfile) - - -- check it - link(objectfile, "static", libraryfile, arflags) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) - os.rm(libraryfile) -end diff --git a/xmake/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 7781d619d..b55948ecd 100644 --- a/xmake/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -26,14 +26,8 @@ import("core.project.project") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "cl.exe" - - -- save kind - _g.kind = kind - -- init cxflags _g.cxflags = { "-nologo", "-Gd", "-MP4", "-D_MBCS", "-D_CRT_SECURE_NO_WARNINGS"} @@ -92,35 +86,21 @@ function init(shellname, kind) end -- get the property -function get(name) +function get(self, name) -- get it return _g[name] end -- make the symbol flag -function nf_symbol(level, target) - - -- check -FS flags - if _g._FS == nil then - local ok = try - { - function () - check("-ZI -FS -Fd" .. os.tmpfile() .. ".pdb") - return true - end - } - if ok then - _g._FS = true - end - end +function nf_symbol(self, level, target) -- debug? generate *.pdb file local flags = "" if level == "debug" then if target and target.symbolfile then flags = "-ZI -Fd" .. target:symbolfile() - if _g._FS then + if self:has_flags("-ZI -FS -Fd" .. os.tmpfile() .. ".pdb") then flags = "-FS " .. flags end else @@ -133,7 +113,7 @@ function nf_symbol(level, target) end -- make the warning flag -function nf_warning(level) +function nf_warning(self, level) -- the maps local maps = @@ -150,7 +130,7 @@ function nf_warning(level) end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -168,7 +148,7 @@ function nf_optimize(level) end -- make the vector extension flag -function nf_vectorext(extension) +function nf_vectorext(self, extension) -- the maps local maps = @@ -184,7 +164,7 @@ function nf_vectorext(extension) end -- make the language flag -function nf_language(stdname) +function nf_language(self, stdname) -- the stdc maps local cmaps = @@ -198,7 +178,7 @@ function nf_language(stdname) -- select maps local maps = cmaps - if _g.kind == "cxx" or _g.kind == "mxx" then + if self:kind() == "cxx" or self:kind() == "mxx" then maps = {} end @@ -207,35 +187,27 @@ function nf_language(stdname) end -- make the define flag -function nf_define(macro) - - -- make it +function nf_define(self, macro) return "-D" .. macro:gsub("\"", "\\\"") end -- make the undefine flag -function nf_undefine(macro) - - -- make it +function nf_undefine(self, macro) return "-U" .. macro end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I" .. dir end -- make the complie command -function _compcmd1(sourcefile, objectfile, flags) - - -- make it - return format("%s -c %s -Fo%s %s", _g.shellname, flags, objectfile, sourcefile) +function _compcmd1(self, sourcefile, objectfile, flags) + return format("%s -c %s -Fo%s %s", self:program(), flags, objectfile, sourcefile) end -- complie the source file -function _compile1(sourcefile, objectfile, incdepfile, flags) +function _compile1(self, sourcefile, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) @@ -249,7 +221,7 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) local outdata = try { function () - return os.iorun(_compcmd1(sourcefile, objectfile, flags)) + return os.iorun(_compcmd1(self, sourcefile, objectfile, flags)) end, catch @@ -299,38 +271,23 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) +function compcmd(self, sourcefiles, objectfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - return _compcmd1(sourcefiles, objectfile, flags) + return _compcmd1(self, sourcefiles, objectfile, flags) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - _compile1(sourcefiles, objectfile, incdepfile, flags) + _compile1(self, sourcefiles, objectfile, incdepfile, flags) end --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".obj" - local sourcefile = os.tmpfile() .. ".c" - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") - - -- check it - os.run("%s -c %s -Fo%s %s", _g.shellname, ifelse(flags, flags, ""), objectfile, sourcefile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) -end diff --git a/xmake/tools/clang.lua b/xmake/modules/core/tools/clang.lua index eb7c4b058..f391b101e 100644 --- a/xmake/tools/clang.lua +++ b/xmake/modules/core/tools/clang.lua @@ -26,10 +26,10 @@ inherit("gcc") -- init it -function init(shellname, kind) +function init(self) -- init super - _super.init(shellname or "clang", kind) + _super.init(self) -- init shflags _super._g.shflags = { "-dynamiclib", "-fPIC" } @@ -42,11 +42,10 @@ function init(shellname, kind) -- init flags map _super._g.mapflags["-s"] = "-Wl,-S" _super._g.mapflags["-S"] = "-Wl,-S" - end -- make the strip flag -function nf_strip(level) +function nf_strip(self, level) -- the maps local maps = diff --git a/xmake/tools/clang++.lua b/xmake/modules/core/tools/clangxx.lua index b9545995d..3e31ac92e 100644 --- a/xmake/tools/clang++.lua +++ b/xmake/modules/core/tools/clangxx.lua @@ -25,11 +25,4 @@ -- inherit clang inherit("clang") --- init it -function init(shellname, kind) - - -- init super - _super.init(shellname or "clang++", kind) - -end diff --git a/xmake/tools/dmd.lua b/xmake/modules/core/tools/dmd.lua index bd6b67379..02178577e 100644 --- a/xmake/tools/dmd.lua +++ b/xmake/modules/core/tools/dmd.lua @@ -23,20 +23,13 @@ -- -- imports -import("core.tool.tool") import("core.base.option") import("core.project.config") import("core.project.project") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "dmd" - - -- save the kind - _g.kind = kind - -- init arflags _g.arflags = { "-lib" } @@ -55,14 +48,12 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -80,7 +71,7 @@ function nf_optimize(level) end -- make the strip flag -function nf_strip(level) +function nf_strip(self, level) -- the maps local maps = @@ -94,7 +85,7 @@ function nf_strip(level) end -- make the symbol flag -function nf_symbol(level) +function nf_symbol(self, level) -- the maps local maps = @@ -108,7 +99,7 @@ function nf_symbol(level) end -- make the warning flag -function nf_warning(level) +function nf_warning(self, level) -- the maps local maps = @@ -125,7 +116,7 @@ function nf_warning(level) end -- make the vector extension flag -function nf_vectorext(extension) +function nf_vectorext(self, extension) -- the maps local maps = @@ -139,101 +130,55 @@ function nf_vectorext(extension) end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I" .. dir end -- make the link flag -function nf_link(lib) - - -- make it +function nf_link(self, lib) return "-L-l" .. lib end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-L-L" .. dir end -- make the rpathdir flag -function nf_rpathdir(dir) - - -- check this flag +function nf_rpathdir(self, dir) local flag = "-L-rpath=" .. dir - if _g._RPATH == nil then - _g._RPATH = try - { - function () - check(flag, true) - return true - end - } - end - - -- ok? - if _g._RPATH then + if self:has_flags(flag) then return flag end end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) - - -- make it - return format("%s %s -of%s %s", _g.shellname, flags, targetfile, objectfiles) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) + return format("%s %s -of%s %s", self:program(), flags, targetfile, objectfiles) end -- link the target file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) - - -- make it - return format("%s -c %s -of%s %s", _g.shellname, flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) +function compcmd(self, sourcefiles, objectfile, flags) + return format("%s -c %s -of%s %s", self:program(), flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.run(compcmd(sourcefiles, objectfile, flags)) + os.run(compcmd(self, sourcefiles, objectfile, flags)) end --- check the given flags -function check(flags, trylink) - - -- make an stub source file - local binaryfile = os.tmpfile() .. ".b" - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".d" - - -- make stub code - io.writefile(sourcefile, "void main() {\n}") - - -- check it, need check compflags and linkflags - if trylink then - os.run("%s %s -of%s %s", _g.shellname, ifelse(flags, flags, ""), binaryfile, sourcefile) - else - os.run("%s -c %s -of%s %s", _g.shellname, ifelse(flags, flags, ""), binaryfile, sourcefile) - end - - -- remove files - os.tryrm(binaryfile) - os.tryrm(objectfile) - os.tryrm(sourcefile) -end diff --git a/xmake/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 94bc201ed..4071ba100 100644 --- a/xmake/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -23,20 +23,13 @@ -- -- imports -import("core.tool.tool") import("core.base.option") import("core.project.config") import("core.project.project") -import("detect.tool.find_ccache") +import("detect.tools.find_ccache") -- init it -function init(shellname, kind) - - -- save the shell name - _g.shellname = shellname or "gcc" - - -- save the kind - _g.kind = kind +function init(self) -- init mxflags _g.mxflags = { "-fmessage-length=0" @@ -50,8 +43,15 @@ function init(shellname, kind) _g.shflags = { "-shared", "-fPIC" } -- init cxflags for the kind: shared - _g.shared = {} - _g.shared.cxflags = {"-fPIC"} + _g.shared = {} + _g.shared.cxflags = {"-fPIC"} + + -- suppress warning for clang (gcc -> clang on macosx) + if self:has_flags("-Qunused-arguments") then + _g.cxflags = {"-Qunused-arguments"} + _g.mxflags = {"-Qunused-arguments"} + _g.asflags = {"-Qunused-arguments"} + end -- init flags map _g.mapflags = @@ -75,14 +75,14 @@ function init(shellname, kind) end -- get the property -function get(name) +function get(self, name) -- get it return _g[name] end -- make the strip flag -function nf_strip(level) +function nf_strip(self, level) -- the maps local maps = @@ -96,7 +96,7 @@ function nf_strip(level) end -- make the symbol flag -function nf_symbol(level) +function nf_symbol(self, level) -- the maps local maps = @@ -110,7 +110,7 @@ function nf_symbol(level) end -- make the warning flag -function nf_warning(level) +function nf_warning(self, level) -- the maps local maps = @@ -127,7 +127,7 @@ function nf_warning(level) end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -145,7 +145,7 @@ function nf_optimize(level) end -- make the vector extension flag -function nf_vectorext(extension) +function nf_vectorext(self, extension) -- the maps local maps = @@ -165,7 +165,7 @@ function nf_vectorext(extension) end -- make the language flag -function nf_language(stdname) +function nf_language(self, stdname) -- the stdc maps local cmaps = @@ -197,9 +197,9 @@ function nf_language(stdname) -- select maps local maps = cmaps - if _g.kind == "cxx" or _g.kind == "mxx" then + if self:kind() == "cxx" or self:kind() == "mxx" then maps = cxxmaps - elseif _g.kind == "sc" then + elseif self:kind() == "sc" then maps = {} end @@ -208,87 +208,59 @@ function nf_language(stdname) end -- make the define flag -function nf_define(macro) - - -- make it +function nf_define(self, macro) return "-D" .. macro:gsub("\"", "\\\"") end -- make the undefine flag -function nf_undefine(macro) - - -- make it +function nf_undefine(self, macro) return "-U" .. macro end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I" .. dir end -- make the link flag -function nf_link(lib) - - -- make it +function nf_link(self, lib) return "-l" .. lib end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-L" .. dir end -- make the rpathdir flag -function nf_rpathdir(dir) - - -- check this flag - local flag = "-Wl,-rpath=" .. dir - if _g._RPATH == nil then - _g._RPATH = try - { - function () - check(flag, true) - return true - end - } - end - - -- ok? - if _g._RPATH then +function nf_rpathdir(self, dir) + if self:has_flags("-Wl,-rpath=" .. dir) then return flag end end -- make the framework flag -function nf_framework(framework) - - -- make it +function nf_framework(self, framework) return "-framework " .. framework end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) - - -- make it - return format("%s -o %s %s %s", _g.shellname, targetfile, objectfiles, flags) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) + return format("%s -o %s %s %s", self:program(), targetfile, objectfiles, flags) end -- link the target file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end -- make the complie command -function _compcmd1(sourcefile, objectfile, flags) +function _compcmd1(self, sourcefile, objectfile, flags) -- get ccache local ccache = nil @@ -297,7 +269,7 @@ function _compcmd1(sourcefile, objectfile, flags) end -- make it - local command = format("%s -c %s -o %s %s", _g.shellname, flags, objectfile, sourcefile) + local command = format("%s -c %s -o %s %s", self:program(), flags, objectfile, sourcefile) if ccache then command = ccache:append(command, " ") end @@ -307,7 +279,7 @@ function _compcmd1(sourcefile, objectfile, flags) end -- complie the source file -function _compile1(sourcefile, objectfile, incdepfile, flags) +function _compile1(self, sourcefile, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) @@ -316,7 +288,7 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) try { function () - local outdata, errdata = os.iorun(_compcmd1(sourcefile, objectfile, flags)) + local outdata, errdata = os.iorun(_compcmd1(self, sourcefile, objectfile, flags)) return (outdata or "") .. (errdata or "") end, catch @@ -340,13 +312,13 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) } -- generate includes file - if incdepfile and _g.kind ~= "as" then + if incdepfile and self:kind() ~= "as" then -- the temporary file local tmpfile = os.tmpfile() -- generate it - os.run("%s -c -MM %s -o %s %s", _g.shellname, flags or "", tmpfile, sourcefile) + os.run("%s -c -MM %s -o %s %s", self:program(), flags or "", tmpfile, sourcefile) -- translate it local results = {} @@ -368,46 +340,22 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) +function compcmd(self, sourcefiles, objectfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - return _compcmd1(sourcefiles, objectfile, flags) + return _compcmd1(self, sourcefiles, objectfile, flags) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - _compile1(sourcefiles, objectfile, incdepfile, flags) -end - --- check the given flags -function check(flags, trylink) - - -- make an stub source file - local binaryfile = os.tmpfile() .. ".b" - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".c" .. ifelse(_g.kind == "cxx", "pp", "") - - -- make stub code - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") - - -- check it, need check compflags and linkflags - if trylink then - os.run("%s %s -o %s %s", _g.shellname, ifelse(flags, flags, ""), binaryfile, sourcefile) - else - os.run("%s -c %s -o %s %s", _g.shellname, ifelse(flags, flags, ""), binaryfile, sourcefile) - end - - -- remove files - os.tryrm(binaryfile) - os.tryrm(objectfile) - os.tryrm(sourcefile) + _compile1(self, sourcefiles, objectfile, incdepfile, flags) end diff --git a/xmake/core/sandbox/modules/import/core/project/option.lua b/xmake/modules/core/tools/gccgo.lua index be9cb810f..41f941cf4 100644 --- a/xmake/core/sandbox/modules/import/core/project/option.lua +++ b/xmake/modules/core/tools/gccgo.lua @@ -19,22 +19,10 @@ -- Copyright (C) 2015 - 2017, TBOOX Open Source Group. -- -- @author ruki --- @file option.lua +-- @file gccgo.lua -- --- define module -local sandbox_core_project_option = sandbox_core_project_option or {} +-- inherit gcc +inherit("gcc") --- load modules -local option = require("project/option") -local raise = require("sandbox/modules/raise") --- parse checkinfo -function sandbox_core_project_option.checkinfo(checkinfo) - - -- parse it - return option.checkinfo(checkinfo) -end - --- return module -return sandbox_core_project_option diff --git a/xmake/tools/gdc.lua b/xmake/modules/core/tools/gdc.lua index 64b36c2b9..3682de49e 100644 --- a/xmake/tools/gdc.lua +++ b/xmake/modules/core/tools/gdc.lua @@ -25,11 +25,5 @@ -- inherit dmd inherit("dmd") --- init it -function init(shellname, kind) - - -- init super - _super.init(shellname or "gdc", kind) -end diff --git a/xmake/tools/go.lua b/xmake/modules/core/tools/go.lua index 472ff84ff..a3b49c8c4 100644 --- a/xmake/tools/go.lua +++ b/xmake/modules/core/tools/go.lua @@ -23,20 +23,13 @@ -- -- imports -import("core.tool.tool") import("core.base.option") import("core.project.config") import("core.project.project") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "go" - - -- save the kind - _g.kind = kind - -- init arflags _g.arflags = { "grc" } @@ -52,14 +45,12 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -77,7 +68,7 @@ function nf_optimize(level) end -- make the symbol flag -function nf_symbol(level, target, mapkind) +function nf_symbol(self, level, target, mapkind) -- only for compiler if mapkind ~= "object" then @@ -96,7 +87,7 @@ function nf_symbol(level, target, mapkind) end -- make the strip flag -function nf_strip(level) +function nf_strip(self, level) -- the maps local maps = @@ -110,71 +101,48 @@ function nf_strip(level) end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I " .. dir end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-L " .. dir end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) -- make it if targetkind == "static" then - return format("%s tool pack %s %s %s", _g.shellname, flags, targetfile, objectfiles) + return format("%s tool pack %s %s %s", self:program(), flags, targetfile, objectfiles) else - return format("%s tool link %s -o %s %s", _g.shellname, flags, targetfile, objectfiles) + return format("%s tool link %s -o %s %s", self:program(), flags, targetfile, objectfiles) end end -- link the target file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) - - -- make it - return format("%s tool compile %s -o %s %s", _g.shellname, flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) +function compcmd(self, sourcefiles, objectfile, flags) + return format("%s tool compile %s -o %s %s", self:program(), flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.run(compcmd(sourcefiles, objectfile, flags)) + os.run(compcmd(self, sourcefiles, objectfile, flags)) end --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".go" - - -- make stub code - io.writefile(sourcefile, "package main\nfunc main() {\n}") - - -- check it - os.run("%s tool compile %s -o %s %s", _g.shellname, ifelse(flags, flags, ""), objectfile, sourcefile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) -end diff --git a/xmake/tools/g++.lua b/xmake/modules/core/tools/gxx.lua index f37bdb05a..2c73c5473 100644 --- a/xmake/tools/g++.lua +++ b/xmake/modules/core/tools/gxx.lua @@ -25,11 +25,4 @@ -- inherit gcc inherit("gcc") --- init it -function init(shellname, kind) - - -- init super - _super.init(shellname or "g++", kind) - -end diff --git a/xmake/tools/ldc.lua b/xmake/modules/core/tools/ldc.lua index 531d319be..b36fd446e 100644 --- a/xmake/tools/ldc.lua +++ b/xmake/modules/core/tools/ldc.lua @@ -26,10 +26,10 @@ inherit("dmd") -- init it -function init(shellname, kind) +function init(self) -- init super - _super.init(shellname or "ldc", kind) + _super.init(self) -- init shflags _super._g.shflags = { "-shared" } diff --git a/xmake/tools/lib.lua b/xmake/modules/core/tools/lib.lua index 7b0a851e8..a193b8788 100644 --- a/xmake/tools/lib.lua +++ b/xmake/modules/core/tools/lib.lua @@ -22,31 +22,21 @@ -- @file lib.lua -- --- init it -function init(shellname, kind) - - -- save the shell name - _g.shellname = shellname or "lib.exe" - - -- save the tool kind - _g.kind = kind -end - -- get the property -function get(name) +function get(self, name) -- get it return _g[name] end -- extract the static library to object directory -function extract(libraryfile, objectdir) +function extract(self, libraryfile, objectdir) -- make the object directory first os.mkdir(objectdir) -- list object files - local objectfiles = os.iorun("%s -nologo -list %s", _g.shellname, libraryfile) + local objectfiles = os.iorun("%s -nologo -list %s", self:program(), libraryfile) -- extrace all object files for _, objectfile in ipairs(objectfiles:split('\n')) do @@ -68,28 +58,9 @@ function extract(libraryfile, objectdir) end -- extract it - os.run("%s -nologo -extract:%s -out:%s %s", _g.shellname, objectfile, outputfile, libraryfile) + os.run("%s -nologo -extract:%s -out:%s %s", self:program(), objectfile, outputfile, libraryfile) end end end --- check the given flags -function check(flags) - - -- make an stub source file - local libfile = os.tmpfile() .. ".lib" - local objfile = os.tmpfile() .. ".obj" - local srcfile = os.tmpfile() .. ".c" - io.writefile(srcfile, "int test(void)\n{return 0;}") - - -- check it - os.run("cl -c -Fo%s %s", objfile, srcfile) - os.run("link -lib -out:%s %s", libfile, objfile) - os.run("%s %s -list %s", _g.shellname, ifelse(flags, flags, ""), libfile) - - -- remove files - os.rm(objfile) - os.rm(srcfile) - os.rm(libfile) -end diff --git a/xmake/tools/link.lua b/xmake/modules/core/tools/link.lua index aa99377fb..f41a093d4 100644 --- a/xmake/tools/link.lua +++ b/xmake/modules/core/tools/link.lua @@ -26,14 +26,8 @@ import("core.project.config") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "link.exe" - - -- save the tool kind - _g.kind = kind - -- the architecture local arch = config.get("arch") @@ -68,18 +62,17 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the symbol flag -function nf_symbol(level, target) +function nf_symbol(self, level, target) -- debug? generate *.pdb file local flags = "" - if level == "debug" then + local targetkind = target:get("kind") + if level == "debug" and (targetkind == "binary" or targetkind == "shared") then if target and target.symbolfile then flags = "-debug -pdb:" .. target:symbolfile() else @@ -92,30 +85,26 @@ function nf_symbol(level, target) end -- make the link flag -function nf_link(lib) - - -- make it +function nf_link(self, lib) return lib .. ".lib" end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-libpath:" .. dir end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) -- make it - local cmd = format("%s %s -out:%s %s", _g.shellname, flags, targetfile, objectfiles) + local cmd = format("%s %s -out:%s %s", self:program(), flags, targetfile, objectfiles) -- too long? if #cmd > 4096 then local argfile = targetfile .. ".arg" io.printf(argfile, "%s -out:%s %s", flags, targetfile, objectfiles) - cmd = format("%s @%s", _g.shellname, argfile) + cmd = format("%s @%s", self:program(), argfile) end -- ok? @@ -123,42 +112,12 @@ function linkcmd(objectfiles, targetkind, targetfile, flags) end -- link the target file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) -end - --- check the given flags -function check(flags) - - -- -def:"xxx.def"? pass directly - if flags and flags:lower():find("def:") then - return - end - - -- make an stub source file - local binaryfile = os.tmpfile() .. ".exe" - local objectfile = os.tmpfile() .. ".obj" - local sourcefile = os.tmpfile() .. ".c" - - -- main entry - if flags and flags:lower():find("subsystem:windows") then - io.writefile(sourcefile, "int WinMain(void* instance, void* previnst, char** argv, int argc)\n{return 0;}") - else - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") - end - - -- check it - os.run("cl -c -Fo%s %s", objectfile, sourcefile) - os.run("%s %s -out:%s %s", _g.shellname, ifelse(flags, flags, ""), binaryfile, objectfile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) - os.rm(binaryfile) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end diff --git a/xmake/tools/ml.lua b/xmake/modules/core/tools/ml.lua index d8ddaee29..74a8fc364 100644 --- a/xmake/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -23,16 +23,10 @@ -- -- init it -function init(shellname, kind) +function init(self) - -- save name - _g.shellname = shellname or "ml.exe" - - -- save kind - _g.kind = kind - -- init asflags - if _g.shellname:find("64") then + if self:program():find("64") then _g.asflags = { "-nologo"} else _g.asflags = { "-nologo", "-Gd"} @@ -66,14 +60,12 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the warning flag -function nf_warning(level) +function nf_warning(self, level) -- the maps local maps = @@ -90,75 +82,52 @@ function nf_warning(level) end -- make the define flag -function nf_define(macro) - - -- make it +function nf_define(self, macro) return "-D" .. macro:gsub("\"", "\\\"") end -- make the undefine flag -function nf_undefine(macro) - - -- make it +function nf_undefine(self, macro) return "-U" .. macro end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I" .. dir end -- make the complie command -function _compcmd1(sourcefile, objectfile, flags) - - -- make it - return format("%s -c %s -Fo%s %s", _g.shellname, flags, objectfile, sourcefile) +function _compcmd1(self, sourcefile, objectfile, flags) + return format("%s -c %s -Fo%s %s", self:program(), flags, objectfile, sourcefile) end -- complie the source file -function _compile1(sourcefile, objectfile, incdepfile, flags) +function _compile1(self, sourcefile, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.run(_compcmd1(sourcefile, objectfile, flags)) + os.run(_compcmd1(self, sourcefile, objectfile, flags)) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) +function compcmd(self, sourcefiles, objectfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - return _compcmd1(sourcefiles, objectfile, flags) + return _compcmd1(self, sourcefiles, objectfile, flags) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - _compile1(sourcefiles, objectfile, incdepfile, flags) -end --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".obj" - local sourcefile = os.tmpfile() .. ".asm" - io.writefile(sourcefile, "end") - - -- check it - os.run("%s -c %s -Fo%s %s", _g.shellname, ifelse(flags, flags, ""), objectfile, sourcefile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) + _compile1(self, sourcefiles, objectfile, incdepfile, flags) end diff --git a/xmake/modules/core/tools/ml64.lua b/xmake/modules/core/tools/ml64.lua new file mode 100644 index 000000000..899ba9972 --- /dev/null +++ b/xmake/modules/core/tools/ml64.lua @@ -0,0 +1,28 @@ +--!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 ml64.lua +-- + +-- inherit ml +inherit("ml") + + diff --git a/xmake/tools/rc.lua b/xmake/modules/core/tools/rc.lua index eb2d5fa05..a76d7493d 100644 --- a/xmake/tools/rc.lua +++ b/xmake/modules/core/tools/rc.lua @@ -27,58 +27,42 @@ import("core.base.option") import("core.project.project") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "rc.exe" - - -- save kind - _g.kind = kind - -- init features _g.features = { - ["object:sources"] = false + ["object:sources"] = false } end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the define flag -function nf_define(macro) - - -- make it +function nf_define(self, macro) return "-d" .. macro:gsub("\"", "\\\"") end -- make the undefine flag -function nf_undefine(macro) - - -- make it +function nf_undefine(self, macro) return "-u" .. macro end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-I" .. dir end -- make the complie command -function _compcmd1(sourcefile, objectfile, flags) - - -- make it - return format("%s %s -Fo%s %s", _g.shellname, flags, objectfile, sourcefile) +function _compcmd1(self, sourcefile, objectfile, flags) + return format("%s %s -Fo%s %s", self:program(), flags, objectfile, sourcefile) end -- complie the source file -function _compile1(sourcefile, objectfile, incdepfile, flags) +function _compile1(self, sourcefile, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) @@ -87,7 +71,7 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) try { function () - local outdata, errdata = os.iorun(_compcmd1(sourcefile, objectfile, flags)) + local outdata, errdata = os.iorun(_compcmd1(self, sourcefile, objectfile, flags)) return (outdata or "") .. (errdata or "") end, catch @@ -112,38 +96,23 @@ function _compile1(sourcefile, objectfile, incdepfile, flags) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) +function compcmd(self, sourcefiles, objectfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - return _compcmd1(sourcefiles, objectfile, flags) + return _compcmd1(self, sourcefiles, objectfile, flags) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - _compile1(sourcefiles, objectfile, incdepfile, flags) + _compile1(self, sourcefiles, objectfile, incdepfile, flags) end --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".res" - local sourcefile = os.tmpfile() .. ".rc" - io.writefile(sourcefile, "#define RESID 1") - - -- check it - os.run("%s -fo%s %s", _g.shellname, objectfile, sourcefile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) -end diff --git a/xmake/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index 44e117d3f..e480624d9 100644 --- a/xmake/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -23,20 +23,13 @@ -- -- imports -import("core.tool.tool") import("core.base.option") import("core.project.config") import("core.project.project") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "rustc" - - -- save the kind - _g.kind = kind - -- init arflags _g.arflags = { "--crate-type=lib" } @@ -61,14 +54,12 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -86,7 +77,7 @@ function nf_optimize(level) end -- make the symbol flag -function nf_symbol(level) +function nf_symbol(self, level) -- the maps local maps = @@ -100,60 +91,37 @@ function nf_symbol(level) end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-L " .. dir end -- make the build command -function buildcmd(sourcefiles, targetkind, targetfile, flags) - - -- make it - return format("%s %s -o %s %s", _g.shellname, flags, targetfile, table.concat(sourcefiles, " ")) +function buildcmd(self, sourcefiles, targetkind, targetfile, flags) + return format("%s %s -o %s %s", self:program(), flags, targetfile, table.concat(sourcefiles, " ")) end -- build the target file -function build(sourcefiles, targetkind, targetfile, flags) +function build(self, sourcefiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- build it - os.run(buildcmd(sourcefiles, targetkind, targetfile, flags)) + os.run(buildcmd(self, sourcefiles, targetkind, targetfile, flags)) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) - - -- make it - return format("%s --emit obj %s -o %s %s", _g.shellname, flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) +function compcmd(self, sourcefiles, objectfile, flags) + return format("%s --emit obj %s -o %s %s", self:program(), flags, objectfile, table.concat(table.wrap(sourcefiles), " ")) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.run(compcmd(sourcefiles, objectfile, flags)) + os.run(compcmd(self, sourcefiles, objectfile, flags)) end --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".rs" - - -- make stub code - io.writefile(sourcefile, "fn main() {\n}") - - -- check it - os.run("%s --emit obj %s -o %s %s", _g.shellname, ifelse(flags, flags, ""), objectfile, sourcefile) - - -- remove files - os.rm(objectfile) - os.rm(sourcefile) -end diff --git a/xmake/tools/swiftc.lua b/xmake/modules/core/tools/swiftc.lua index 8a52125e4..e1c18934e 100644 --- a/xmake/tools/swiftc.lua +++ b/xmake/modules/core/tools/swiftc.lua @@ -23,19 +23,12 @@ -- -- imports -import("core.tool.tool") import("core.project.config") -import("detect.tool.find_ccache") +import("detect.tools.find_ccache") -- init it -function init(shellname, kind) +function init(self) - -- save the shell name - _g.shellname = shellname or "swiftc" - - -- init kind - _g.kind = kind - -- init flags map _g.mapflags = { @@ -71,14 +64,12 @@ function init(shellname, kind) end -- get the property -function get(name) - - -- get it +function get(self, name) return _g[name] end -- make the strip flag -function nf_strip(level) +function nf_strip(self, level) -- the maps local maps = @@ -92,7 +83,7 @@ function nf_strip(level) end -- make the symbol flag -function nf_symbol(level) +function nf_symbol(self, level) -- the maps local maps = @@ -105,7 +96,7 @@ function nf_symbol(level) end -- make the warning flag -function nf_warning(level) +function nf_warning(self, level) -- the maps local maps = @@ -122,7 +113,7 @@ function nf_warning(level) end -- make the optimize flag -function nf_optimize(level) +function nf_optimize(self, level) -- the maps local maps = @@ -140,7 +131,7 @@ function nf_optimize(level) end -- make the vector extension flag -function nf_vectorext(extension) +function nf_vectorext(self, extension) -- the maps local maps = @@ -160,66 +151,52 @@ function nf_vectorext(extension) end -- make the includedir flag -function nf_includedir(dir) - - -- make it +function nf_includedir(self, dir) return "-Xcc -I" .. dir end -- make the define flag -function nf_define(macro) - - -- make it +function nf_define(self, macro) return "-Xcc -D" .. macro:gsub("\"", "\\\"") end -- make the undefine flag -function nf_undefine(macro) - - -- make it +function nf_undefine(self, macro) return "-Xcc -U" .. macro end -- make the framework flag -function nf_framework(framework) - - -- make it +function nf_framework(self, framework) return "-framework" .. framework end -- make the link flag -function nf_link(lib) - - -- make it +function nf_link(self, lib) return "-l" .. lib end -- make the linkdir flag -function nf_linkdir(dir) - - -- make it +function nf_linkdir(self, dir) return "-L" .. dir end -- make the link command -function linkcmd(objectfiles, targetkind, targetfile, flags) - - -- make it - return format("%s -o %s %s %s", _g.shellname, targetfile, objectfiles, flags) +function linkcmd(self, objectfiles, targetkind, targetfile, flags) + return format("%s -o %s %s %s", self:program(), targetfile, objectfiles, flags) end -- link the target file -function link(objectfiles, targetkind, targetfile, flags) +function link(self, objectfiles, targetkind, targetfile, flags) -- ensure the target directory os.mkdir(path.directory(targetfile)) -- link it - os.run(linkcmd(objectfiles, targetkind, targetfile, flags)) + os.run(linkcmd(self, objectfiles, targetkind, targetfile, flags)) end -- make the compile command -function _compcmd1(sourcefile, objectfile, flags) +function _compcmd1(self, sourcefile, objectfile, flags) -- get ccache local ccache = nil @@ -228,7 +205,7 @@ function _compcmd1(sourcefile, objectfile, flags) end -- make it - local command = format("%s -c %s -o %s %s", _g.shellname, flags, objectfile, sourcefile) + local command = format("%s -c %s -o %s %s", self:program(), flags, objectfile, sourcefile) if ccache then command = ccache:append(command, " ") end @@ -238,38 +215,32 @@ function _compcmd1(sourcefile, objectfile, flags) end -- complie the source file -function _compile1(sourcefile, objectfile, incdepfile, flags) +function _compile1(self, sourcefile, objectfile, incdepfile, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) -- compile it - os.run(_compcmd1(sourcefile, objectfile, flags)) + os.run(_compcmd1(self, sourcefile, objectfile, flags)) end -- make the complie command -function compcmd(sourcefiles, objectfile, flags) +function compcmd(self, sourcefiles, objectfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - return _compcmd1(sourcefiles, objectfile, flags) + return _compcmd1(self, sourcefiles, objectfile, flags) end -- complie the source file -function compile(sourcefiles, objectfile, incdepfile, flags) +function compile(self, sourcefiles, objectfile, incdepfile, flags) -- only support single source file now assert(type(sourcefiles) ~= "table", "'object:sources' not support!") -- for only single source file - _compile1(sourcefiles, objectfile, incdepfile, flags) + _compile1(self, sourcefiles, objectfile, incdepfile, flags) end --- check the given flags -function check(flags) - - -- check it - os.run("%s -h", _g.shellname) -end diff --git a/xmake/modules/detect/packages/find_openssl.lua b/xmake/modules/detect/packages/find_openssl.lua new file mode 100644 index 000000000..9efe76370 --- /dev/null +++ b/xmake/modules/detect/packages/find_openssl.lua @@ -0,0 +1,74 @@ +--!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 find_openssl.lua +-- + +-- imports +import("lib.detect.find_path") +import("lib.detect.find_library") + +-- find openssl +-- +-- @param opt the package options. e.g. see the options of find_package() +-- +-- @return see the return value of find_package() +-- +function main(opt) + + -- for windows platform + -- + -- http://www.slproweb.com/products/Win32OpenSSL.html + -- + if opt.plat == "windows" then + + -- init bits + local bits = ifelse(opt.arch == "x64", "64", "32") + + -- init search pathes + local pathes = {"$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL %(" .. bits .. "-bit%)_is1;Inno Setup: App Path)", + "$(env PROGRAMFILES)/OpenSSL", + "$(env PROGRAMFILES)/OpenSSL-Win" .. bits, + "C:/OpenSSL", + "C:/OpenSSL-Win" .. bits} + + -- find library + local result = {links = {}, linkdirs = {}, includedirs = {}} + for _, name in ipairs({"libssl", "libcrypto"}) do + local linkinfo = find_library(name, pathes, {suffixes = "lib"}) + if linkinfo then + table.insert(result.links, linkinfo.link) + table.insert(result.linkdirs, linkinfo.linkdir) + end + end + + -- not found? + if #result.links ~= 2 then + return + end + + -- find include + table.insert(result.includedirs, find_path("openssl/ssl.h", pathes, {suffixes = "include"})) + + -- ok + return result + end +end diff --git a/xmake/modules/detect/packages/find_zlib.lua b/xmake/modules/detect/packages/find_zlib.lua new file mode 100644 index 000000000..49cc3e83a --- /dev/null +++ b/xmake/modules/detect/packages/find_zlib.lua @@ -0,0 +1,81 @@ +--!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 find_zlib.lua +-- + +-- imports +import("lib.detect.find_path") +import("lib.detect.find_library") + +-- find zlib +-- +-- @param opt the package options. e.g. see the options of find_package() +-- +-- @return see the return value of find_package() +-- +function main(opt) + + -- for windows platform + -- + -- http://gnuwin32.sourceforge.net/packages/zlib.html + -- + if opt.plat == "windows" then + + -- init search pathes + local pathes = {"$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath)", + "$(env PROGRAMFILES)/GnuWin32", + "$(env PROGRAMFILES)/zlib"} + + -- find library + local result = {links = {}, linkdirs = {}, includedirs = {}} + local linkinfo = find_library("zlib", pathes, {suffixes = "lib"}) + if not linkinfo then + return + end + + -- save link and directory + table.insert(result.links, linkinfo.link) + table.insert(result.linkdirs, linkinfo.linkdir) + + -- find include + local includedir = find_path("zlib.h", pathes, {suffixes = "include"}) + if includedir then + + -- save include directory + table.insert(result.includedirs, includedir) + + -- match version + if opt.version then + local zlib_h = io.readfile(path.join(includedir, "zlib.h")) + if zlib_h then + local version = zlib_h:match("#define ZLIB_VERSION \"(%d+%.?%d+%.?%d+)\"") + if version ~= opt.version then + return + end + end + end + end + + -- ok + return result + end +end diff --git a/xmake/modules/detect/sdk/find_cross_toolchains.lua b/xmake/modules/detect/sdks/find_cross_toolchains.lua index 0e989d6e7..0e989d6e7 100644 --- a/xmake/modules/detect/sdk/find_cross_toolchains.lua +++ b/xmake/modules/detect/sdks/find_cross_toolchains.lua diff --git a/xmake/modules/detect/sdk/find_ndk_sdkvers.lua b/xmake/modules/detect/sdks/find_ndk_sdkvers.lua index 16ad5eca7..16ad5eca7 100644 --- a/xmake/modules/detect/sdk/find_ndk_sdkvers.lua +++ b/xmake/modules/detect/sdks/find_ndk_sdkvers.lua diff --git a/xmake/modules/detect/sdk/find_ndk_toolchains.lua b/xmake/modules/detect/sdks/find_ndk_toolchains.lua index f7d5b7430..f7d5b7430 100644 --- a/xmake/modules/detect/sdk/find_ndk_toolchains.lua +++ b/xmake/modules/detect/sdks/find_ndk_toolchains.lua diff --git a/xmake/modules/detect/sdk/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 1a06d1e90..fb09d915d 100644 --- a/xmake/modules/detect/sdk/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -64,6 +64,12 @@ function _load_vcvarsall(vcvarsall, arch) end end + -- get sdk version + local include = variables["include"] + if include then + variables["sdkver"] = include:match("Windows Kits\\%d+\\include\\(%d+%.%d+%.%d+%.%d+)\\") + end + -- ok return variables end diff --git a/xmake/modules/detect/sdk/find_xcode_dir.lua b/xmake/modules/detect/sdks/find_xcode_dir.lua index 65e5b4f31..728ba1245 100644 --- a/xmake/modules/detect/sdk/find_xcode_dir.lua +++ b/xmake/modules/detect/sdks/find_xcode_dir.lua @@ -23,7 +23,7 @@ -- -- imports -import("lib.detect.find_path") +import("lib.detect.find_directory") -- find xcode directory -- @@ -36,5 +36,5 @@ import("lib.detect.find_path") -- @endcode -- function main() - return find_path("Xcode.app", {"/Applications"}) or find_path("Xcode*.app", {"/Applications"}) + return find_directory("Xcode.app", {"/Applications"}) or find_directory("Xcode*.app", {"/Applications"}) end diff --git a/xmake/modules/detect/sdk/find_xcode_sdkvers.lua b/xmake/modules/detect/sdks/find_xcode_sdkvers.lua index fb479208c..a8ef1a816 100644 --- a/xmake/modules/detect/sdk/find_xcode_sdkvers.lua +++ b/xmake/modules/detect/sdks/find_xcode_sdkvers.lua @@ -24,7 +24,7 @@ -- imports import("core.project.config") -import("detect.sdk.find_xcode_dir") +import("detect.sdks.find_xcode_dir") -- find xcode sdk versions for the given platform -- diff --git a/xmake/modules/detect/tools/ar/has_flag.lua b/xmake/modules/detect/tools/ar/has_flag.lua new file mode 100644 index 000000000..5358e3e0a --- /dev/null +++ b/xmake/modules/detect/tools/ar/has_flag.lua @@ -0,0 +1,84 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt) + + -- make cache key + local key = "detect.tools.ar.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + 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) flags["-" .. ch] = true; flags["-r" .. ch] = true; flags["-" .. ch .. "r"] = true end) + found = true + end + if found then + flags["-r"] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag] +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + return _check_from_arglist(flag, opt) +end + diff --git a/xmake/modules/detect/tools/cl/has_flag.lua b/xmake/modules/detect/tools/cl/has_flag.lua new file mode 100644 index 000000000..1f6e370e3 --- /dev/null +++ b/xmake/modules/detect/tools/cl/has_flag.lua @@ -0,0 +1,98 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt) + + -- make cache key + local key = "detect.tools.cl.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = os.iorunv(opt.program, {"-?"}) + if arglist then + for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do + flags[arg:gsub("/", "-")] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag:gsub("/", "-")] +end + +-- try running to check flag +function _check_try_running(flag, opt) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "cl_has_flag.c") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + end + + -- check it + return try { function () + local _, errors = os.iorunv(opt.program, {"-c", "-nologo", flag, "-Fo" .. os.nuldev(), sourcefile}) + if errors and #errors:trim() > 0 then + return false + end + return true + end + } +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt) +end + diff --git a/xmake/modules/detect/package/find_openssl.lua b/xmake/modules/detect/tools/clang/has_flag.lua index fb1af8c6a..0cb83600e 100644 --- a/xmake/modules/detect/package/find_openssl.lua +++ b/xmake/modules/detect/tools/clang/has_flag.lua @@ -19,19 +19,9 @@ -- Copyright (C) 2015 - 2017, TBOOX Open Source Group. -- -- @author ruki --- @file find_openssl.lua +-- @file has_flag.lua -- -- imports -import("lib.detect.find_file") -import("lib.detect.find_library") +inherit("detect.tools.gcc.has_flag") --- find openssl --- --- @param opt the package options. e.g. see the options of find_package() --- --- @return see the return value of find_package() --- -function main(opt) - -- TODO -end diff --git a/xmake/modules/detect/tools/clangxx/has_flag.lua b/xmake/modules/detect/tools/clangxx/has_flag.lua new file mode 100644 index 000000000..0cb83600e --- /dev/null +++ b/xmake/modules/detect/tools/clangxx/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flag") + diff --git a/xmake/modules/detect/tools/dmd/has_flag.lua b/xmake/modules/detect/tools/dmd/has_flag.lua new file mode 100644 index 000000000..719551523 --- /dev/null +++ b/xmake/modules/detect/tools/dmd/has_flag.lua @@ -0,0 +1,118 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- is linker? +function _islinker(flag, opt) + + -- the flag is "-L=<arg>" or "-L<arg>"? + if flag:startswith("-L=") or flag: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 + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt, islinker) + + -- only for compiler + if islinker then + return + end + + -- make cache key + local key = "detect.tools.dmd.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = os.iorunv(opt.program, {"--help"}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + flags[arg] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag] +end + +-- try running to check flag +function _check_try_running(flag, opt, islinker) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "dmd_has_flag.d") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "void main() {\n}") + end + + -- init argv + local argv = {flag, "-of" .. os.nuldev(), sourcefile} + if not islinker then + table.insert(argv, 1, "-c") + end + + -- check it + return try { function () os.runv(opt.program, argv); return true end } +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- is linker? + local islinker = _islinker(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt, islinker) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt, islinker) +end + diff --git a/xmake/modules/detect/tool/find_7z.lua b/xmake/modules/detect/tools/find_7z.lua index 58a4ea24e..bc5c3d340 100644 --- a/xmake/modules/detect/tool/find_7z.lua +++ b/xmake/modules/detect/tools/find_7z.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("7z", {}, "--help") + local program = find_program(opt.program or "7z", opt.pathes, opt.check or "--help") -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_ar.lua b/xmake/modules/detect/tools/find_ar.lua new file mode 100644 index 000000000..6bbf840c5 --- /dev/null +++ b/xmake/modules/detect/tools/find_ar.lua @@ -0,0 +1,70 @@ +--!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 find_ar.lua +-- + +-- imports +import("core.tool.compiler") +import("lib.detect.find_program") + +-- check +function _check(program) + + -- make an stub source file + local libraryfile = os.tmpfile() .. ".a" + local objectfile = os.tmpfile() .. ".o" + local sourcefile = os.tmpfile() .. ".c" + io.writefile(sourcefile, "int test(void)\n{return 0;}") + + -- compile it + compiler.compile(sourcefile, objectfile) + + -- archive it + os.runv(program, {"-cr", libraryfile, objectfile}) + + -- remove files + os.rm(objectfile) + os.rm(sourcefile) + os.rm(libraryfile) +end + +-- find ar +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local ar = find_ar() +-- local ar, version = find_ar({program = "xcrun -sdk macosx g++", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + return find_program(opt.program or "ar", opt.pathes, opt.check or _check) +end diff --git a/xmake/modules/detect/tools/find_brew.lua b/xmake/modules/detect/tools/find_brew.lua new file mode 100644 index 000000000..e4c07403f --- /dev/null +++ b/xmake/modules/detect/tools/find_brew.lua @@ -0,0 +1,58 @@ +--!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 find_brew.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find brew +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local brew = find_brew() +-- local brew, version = find_brew({version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "brew", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_ccache.lua b/xmake/modules/detect/tools/find_ccache.lua index faf45da53..9e4fe4aa6 100644 --- a/xmake/modules/detect/tool/find_ccache.lua +++ b/xmake/modules/detect/tools/find_ccache.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("ccache") + local program = find_program(opt.program or "ccache", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_cl.lua b/xmake/modules/detect/tools/find_cl.lua new file mode 100644 index 000000000..3ab7cf5c1 --- /dev/null +++ b/xmake/modules/detect/tools/find_cl.lua @@ -0,0 +1,59 @@ +--!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 find_cl.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find cl +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local cl = find_cl() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "cl.exe", opt.pathes, opt.check or function (program) os.run(program) end) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, function () local _, info = os.iorun(program); return info end, + function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tools/find_clang.lua b/xmake/modules/detect/tools/find_clang.lua new file mode 100644 index 000000000..5e1dc95d4 --- /dev/null +++ b/xmake/modules/detect/tools/find_clang.lua @@ -0,0 +1,58 @@ +--!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 find_clang.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find clang +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local clang = find_clang() +-- local clang, version = find_clang({program = "xcrun -sdk macosx clang", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "clang", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/find_clangxx.lua b/xmake/modules/detect/tools/find_clangxx.lua new file mode 100644 index 000000000..77e80304f --- /dev/null +++ b/xmake/modules/detect/tools/find_clangxx.lua @@ -0,0 +1,58 @@ +--!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 find_clangxx.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find clang++ +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local clangxx = find_clangxx() +-- local clangxx, version = find_clangxx({program = "xcrun -sdk macosx clang++", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "clang++", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_curl.lua b/xmake/modules/detect/tools/find_curl.lua index 3b49247ef..a5ba49e20 100644 --- a/xmake/modules/detect/tool/find_curl.lua +++ b/xmake/modules/detect/tools/find_curl.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("curl") + local program = find_program(opt.program or "curl", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_dmd.lua b/xmake/modules/detect/tools/find_dmd.lua new file mode 100644 index 000000000..f244c0ad0 --- /dev/null +++ b/xmake/modules/detect/tools/find_dmd.lua @@ -0,0 +1,57 @@ +--!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 find_dmd.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find dmd +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local dmd = find_dmd() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "dmd", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "--version", function (output) return output:match("v(%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_doxygen.lua b/xmake/modules/detect/tools/find_doxygen.lua index 3b3a6bee4..5824c574c 100644 --- a/xmake/modules/detect/tool/find_doxygen.lua +++ b/xmake/modules/detect/tools/find_doxygen.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("doxygen", { "/usr/bin", "/usr/local/bin"}) + local program = find_program(opt.program or "doxygen", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_gcc.lua b/xmake/modules/detect/tools/find_gcc.lua new file mode 100644 index 000000000..d7cbce7d2 --- /dev/null +++ b/xmake/modules/detect/tools/find_gcc.lua @@ -0,0 +1,58 @@ +--!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 find_gcc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find gcc +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local gcc = find_gcc() +-- local gcc, version = find_gcc({program = "xcrun -sdk macosx gcc", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "gcc", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/find_gccgo.lua b/xmake/modules/detect/tools/find_gccgo.lua new file mode 100644 index 000000000..a12be3067 --- /dev/null +++ b/xmake/modules/detect/tools/find_gccgo.lua @@ -0,0 +1,57 @@ +--!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 find_gogccgo.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find gccgo +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local gccgo = find_gccgo() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "gccgo", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "--version", function (output) return output:match("%s(%d+%.?%d+%.?%d+)%s") end) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_gdb.lua b/xmake/modules/detect/tools/find_gdb.lua index ff206288c..3e698022a 100644 --- a/xmake/modules/detect/tool/find_gdb.lua +++ b/xmake/modules/detect/tools/find_gdb.lua @@ -46,7 +46,7 @@ function main(opt) opt = opt or {} -- find program - local program = find_program(opt.program or "gdb") + local program = find_program(opt.program or "gdb", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_gdc.lua b/xmake/modules/detect/tools/find_gdc.lua new file mode 100644 index 000000000..a2b2b4c9a --- /dev/null +++ b/xmake/modules/detect/tools/find_gdc.lua @@ -0,0 +1,57 @@ +--!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 find_gdc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find gdc +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local gdc = find_gdc() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "gdc", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "--version", function (output) return output:match("%s(%d+%.?%d+%.?%d+)%s") end) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_git.lua b/xmake/modules/detect/tools/find_git.lua index 12f08978d..b21455b0c 100644 --- a/xmake/modules/detect/tool/find_git.lua +++ b/xmake/modules/detect/tools/find_git.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("git") + local program = find_program(opt.program or "git", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_go.lua b/xmake/modules/detect/tools/find_go.lua new file mode 100644 index 000000000..0b1b9103e --- /dev/null +++ b/xmake/modules/detect/tools/find_go.lua @@ -0,0 +1,57 @@ +--!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 find_go.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find go +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local go = find_go() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "go", opt.pathes, opt.check or "version") + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "version") + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/find_gxx.lua b/xmake/modules/detect/tools/find_gxx.lua new file mode 100644 index 000000000..5ab35fa44 --- /dev/null +++ b/xmake/modules/detect/tools/find_gxx.lua @@ -0,0 +1,58 @@ +--!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 find_gxx.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find g++ +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local gxx = find_gxx() +-- local gxx, version = find_gxx({program = "xcrun -sdk macosx g++", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "g++", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_gzip.lua b/xmake/modules/detect/tools/find_gzip.lua index d1b286bba..95d364971 100644 --- a/xmake/modules/detect/tool/find_gzip.lua +++ b/xmake/modules/detect/tools/find_gzip.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("gzip") + local program = find_program(opt.program or "gzip", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_ldc2.lua b/xmake/modules/detect/tools/find_ldc2.lua new file mode 100644 index 000000000..8b2f42c5d --- /dev/null +++ b/xmake/modules/detect/tools/find_ldc2.lua @@ -0,0 +1,57 @@ +--!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 find_ldc2.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find ldc2 +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local ldc2 = find_ldc2() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "ldc2", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "--version", function (output) return output:match("%((%d+%.?%d*%.?%d*.-)%)") end) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/find_lib.lua b/xmake/modules/detect/tools/find_lib.lua new file mode 100644 index 000000000..107c33cbb --- /dev/null +++ b/xmake/modules/detect/tools/find_lib.lua @@ -0,0 +1,77 @@ +--!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 find_lib.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find lib +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local lib = find_lib() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local verinfo = nil + local program = find_program(opt.program or "lib.exe", opt.pathes, opt.check or function (program) + + -- make an stub source file + local libraryfile = os.tmpfile() .. ".lib" + local objectfile = os.tmpfile() .. ".obj" + local sourcefile = os.tmpfile() .. ".c" + io.writefile(sourcefile, "int test(void)\n{return 0;}") + + -- check it + os.run("cl -c -Fo%s %s", objectfile, sourcefile) + os.run("link -lib -out:%s %s", libraryfile, objectfile) + verinfo = os.iorun("%s -list %s", program, libraryfile) + + -- remove files + os.rm(objectfile) + os.rm(sourcefile) + os.rm(libraryfile) + end) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, function () return verinfo end, + function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tools/find_link.lua b/xmake/modules/detect/tools/find_link.lua new file mode 100644 index 000000000..d30fe6fbe --- /dev/null +++ b/xmake/modules/detect/tools/find_link.lua @@ -0,0 +1,78 @@ +--!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 find_link.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find link +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local link = find_link() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local verinfo = nil + local program = find_program(opt.program or "link.exe", opt.pathes, opt.check or function (program) + + -- make an stub source file + local binaryfile = os.tmpfile() .. ".exe" + local objectfile = os.tmpfile() .. ".obj" + local sourcefile = os.tmpfile() .. ".c" + + -- main entry + io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + + -- check it + os.run("cl -c -Fo%s %s", objectfile, sourcefile) + verinfo = os.iorun("%s -out:%s %s", program, binaryfile, objectfile) + + -- remove files + os.rm(objectfile) + os.rm(sourcefile) + os.rm(binaryfile) + end) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, function () return verinfo end, + function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tool/find_lipo.lua b/xmake/modules/detect/tools/find_lipo.lua index 621bb80d5..27be94c1f 100644 --- a/xmake/modules/detect/tool/find_lipo.lua +++ b/xmake/modules/detect/tools/find_lipo.lua @@ -40,6 +40,9 @@ import("lib.detect.find_programver") -- function main(opt) + -- init options + opt = opt or {} + -- find program - return find_program("lipo", {}, function (program) os.run("%s -info %s", program, os.programfile()) end) + return find_program(opt.program or "lipo", opt.pathes, opt.check or function (program) os.run("%s -info %s", program, os.programfile()) end) end diff --git a/xmake/modules/detect/tool/find_lldb.lua b/xmake/modules/detect/tools/find_lldb.lua index 3c15c2fb1..8a6e86341 100644 --- a/xmake/modules/detect/tool/find_lldb.lua +++ b/xmake/modules/detect/tools/find_lldb.lua @@ -46,7 +46,7 @@ function main(opt) opt = opt or {} -- find program - local program = find_program(opt.program or "lldb") + local program = find_program(opt.program or "lldb", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_ml.lua b/xmake/modules/detect/tools/find_ml.lua new file mode 100644 index 000000000..da3f026ac --- /dev/null +++ b/xmake/modules/detect/tools/find_ml.lua @@ -0,0 +1,59 @@ +--!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 find_ml.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find ml +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local ml = find_ml() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "ml.exe", opt.pathes, opt.check or function (program) os.run(program) end) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, function () local _, info = os.iorun(program); return info end, + function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tools/find_ml64.lua b/xmake/modules/detect/tools/find_ml64.lua new file mode 100644 index 000000000..d2377c19e --- /dev/null +++ b/xmake/modules/detect/tools/find_ml64.lua @@ -0,0 +1,59 @@ +--!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 find_ml64.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find ml64 +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local ml64 = find_ml64() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "ml64.exe", opt.pathes, opt.check or function (program) os.run(program) end) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, function () local _, info = os.iorun(program); return info end, + function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tool/find_ollydbg.lua b/xmake/modules/detect/tools/find_ollydbg.lua index 636f52932..636f52932 100644 --- a/xmake/modules/detect/tool/find_ollydbg.lua +++ b/xmake/modules/detect/tools/find_ollydbg.lua diff --git a/xmake/modules/detect/tool/find_pkg_config.lua b/xmake/modules/detect/tools/find_pkg_config.lua index 8bbad9f3f..8bbad9f3f 100644 --- a/xmake/modules/detect/tool/find_pkg_config.lua +++ b/xmake/modules/detect/tools/find_pkg_config.lua diff --git a/xmake/modules/detect/tools/find_rc.lua b/xmake/modules/detect/tools/find_rc.lua new file mode 100644 index 000000000..cbd24e82a --- /dev/null +++ b/xmake/modules/detect/tools/find_rc.lua @@ -0,0 +1,58 @@ +--!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 find_rc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find rc +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local rc = find_rc() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "rc.exe", opt.pathes, "-?") + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, "-?", function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end) + end + + -- ok? + return program, version +end + diff --git a/xmake/tools/gccgo.lua b/xmake/modules/detect/tools/find_rustc.lua index 1254130d4..d01380d72 100644 --- a/xmake/tools/gccgo.lua +++ b/xmake/modules/detect/tools/find_rustc.lua @@ -19,34 +19,39 @@ -- Copyright (C) 2015 - 2017, TBOOX Open Source Group. -- -- @author ruki --- @file gccgo.lua +-- @file find_rustc.lua -- --- inherit gcc -inherit("gcc") +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") --- init it -function init(shellname, kind) - - -- init super - _super.init(shellname or "gccgo", kind) -end - --- check the given flags -function check(flags) - - -- make an stub source file - local objectfile = os.tmpfile() .. ".o" - local sourcefile = os.tmpfile() .. ".go" +-- find rustc +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local rustc = find_rustc() +-- +-- @endcode +-- +function main(opt) - -- make stub code - io.writefile(sourcefile, "package main\nfunc main() {\n}") + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "rustc", opt.pathes, opt.check) - -- check it - os.run("%s -c %s -o %s %s", _super._g.shellname, ifelse(flags, flags, ""), objectfile, sourcefile) + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end - -- remove files - os.rm(objectfile) - os.rm(sourcefile) + -- ok? + return program, version end - diff --git a/xmake/modules/detect/tool/find_sudo.lua b/xmake/modules/detect/tools/find_sudo.lua index 3d0082b17..3306f2fd3 100644 --- a/xmake/modules/detect/tool/find_sudo.lua +++ b/xmake/modules/detect/tools/find_sudo.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("sudo", {}, "-h") + local program = find_program(opt.program or "sudo", opt.pathes, opt.check or "-h") -- find program version local version = nil diff --git a/xmake/modules/detect/tools/find_swiftc.lua b/xmake/modules/detect/tools/find_swiftc.lua new file mode 100644 index 000000000..cf9373739 --- /dev/null +++ b/xmake/modules/detect/tools/find_swiftc.lua @@ -0,0 +1,58 @@ +--!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 find_swiftc.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find swiftc +-- +-- @param opt the argument options, .e.g {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local swiftc = find_swiftc() +-- local swiftc, version = find_swiftc({program = "xcrun -sdk macosx swiftc", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "swiftc", opt.pathes, opt.check) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tool/find_tar.lua b/xmake/modules/detect/tools/find_tar.lua index e091d3204..f37843171 100644 --- a/xmake/modules/detect/tool/find_tar.lua +++ b/xmake/modules/detect/tools/find_tar.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("tar") + local program = find_program(opt.program or "tar", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tool/find_unzip.lua b/xmake/modules/detect/tools/find_unzip.lua index 19c30f517..c3533cd54 100644 --- a/xmake/modules/detect/tool/find_unzip.lua +++ b/xmake/modules/detect/tools/find_unzip.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("unzip", {}, "-v") + local program = find_program(opt.program or "unzip", opt.pathes, opt.check or "-v") -- find program version local version = nil diff --git a/xmake/modules/detect/tool/find_vsjitdebugger.lua b/xmake/modules/detect/tools/find_vsjitdebugger.lua index 879fd0a5d..879fd0a5d 100644 --- a/xmake/modules/detect/tool/find_vsjitdebugger.lua +++ b/xmake/modules/detect/tools/find_vsjitdebugger.lua diff --git a/xmake/modules/detect/tool/find_wget.lua b/xmake/modules/detect/tools/find_wget.lua index 59a9c7d63..5f8dd7594 100644 --- a/xmake/modules/detect/tool/find_wget.lua +++ b/xmake/modules/detect/tools/find_wget.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("wget") + local program = find_program(opt.program or "wget", opt.pathes, opt.check) -- find program version local version = nil diff --git a/xmake/modules/detect/tool/find_windbg.lua b/xmake/modules/detect/tools/find_windbg.lua index 323855d79..323855d79 100644 --- a/xmake/modules/detect/tool/find_windbg.lua +++ b/xmake/modules/detect/tools/find_windbg.lua diff --git a/xmake/modules/detect/tool/find_x64dbg.lua b/xmake/modules/detect/tools/find_x64dbg.lua index 431fea112..431fea112 100644 --- a/xmake/modules/detect/tool/find_x64dbg.lua +++ b/xmake/modules/detect/tools/find_x64dbg.lua diff --git a/xmake/modules/detect/tool/find_zip.lua b/xmake/modules/detect/tools/find_zip.lua index b424d6e99..71405d3ff 100644 --- a/xmake/modules/detect/tool/find_zip.lua +++ b/xmake/modules/detect/tools/find_zip.lua @@ -40,9 +40,12 @@ import("lib.detect.find_programver") -- @endcode -- function main(opt) + + -- init options + opt = opt or {} -- find program - local program = find_program("zip", {}, "-v") + local program = find_program(opt.program or "zip", opt.pathes, opt.check or "-v") -- find program version local version = nil diff --git a/xmake/modules/detect/tools/gcc/has_flag.lua b/xmake/modules/detect/tools/gcc/has_flag.lua new file mode 100644 index 000000000..396c460e4 --- /dev/null +++ b/xmake/modules/detect/tools/gcc/has_flag.lua @@ -0,0 +1,119 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- is linker? +function _islinker(flag, opt) + + -- the flag is "-Wl,<arg>" or "-Xlinker <arg>"? + if flag:startswith("-Wl,") or flag: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 + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt, islinker) + + -- only for compiler + if islinker then + return + end + + -- make cache key + local key = "detect.tools.gcc.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = os.iorunv(opt.program, {"--help"}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + flags[arg] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag] +end + +-- try running to check flag +function _check_try_running(flag, opt, islinker) + + -- check flag for linker + if islinker then + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flag.c") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + end + + -- check it + return try { function () os.runv(opt.program, {flag, "-o", os.nuldev(), sourcefile}); return true end } + end + + -- check flag for compiler + return try { function () os.runv(opt.program, {flag, "-S", "-o", os.nuldev(), "-xc", os.nuldev()}); return true end } +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- is linker? + local islinker = _islinker(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt, islinker) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt, islinker) +end + diff --git a/xmake/modules/detect/tools/gccgo/has_flag.lua b/xmake/modules/detect/tools/gccgo/has_flag.lua new file mode 100644 index 000000000..0cb83600e --- /dev/null +++ b/xmake/modules/detect/tools/gccgo/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flag") + diff --git a/xmake/modules/detect/tools/gdc/has_flag.lua b/xmake/modules/detect/tools/gdc/has_flag.lua new file mode 100644 index 000000000..617355673 --- /dev/null +++ b/xmake/modules/detect/tools/gdc/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.dmd.has_flag") + diff --git a/xmake/modules/detect/tools/gxx/has_flag.lua b/xmake/modules/detect/tools/gxx/has_flag.lua new file mode 100644 index 000000000..0cb83600e --- /dev/null +++ b/xmake/modules/detect/tools/gxx/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.gcc.has_flag") + diff --git a/xmake/modules/detect/tools/ldc/has_flag.lua b/xmake/modules/detect/tools/ldc/has_flag.lua new file mode 100644 index 000000000..617355673 --- /dev/null +++ b/xmake/modules/detect/tools/ldc/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.dmd.has_flag") + diff --git a/xmake/modules/detect/tools/link/has_flag.lua b/xmake/modules/detect/tools/link/has_flag.lua new file mode 100644 index 000000000..008f28912 --- /dev/null +++ b/xmake/modules/detect/tools/link/has_flag.lua @@ -0,0 +1,116 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt) + + -- make cache key + local key = "detect.tools.link.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = nil + try + { + function () os.runv(opt.program, {"-?"}) end, + catch + { + function (errors) arglist = errors end + } + } + if arglist then + for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do + flags[arg:gsub("/", "-"):lower()] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag:gsub("/", "-"):lower()] +end + +-- try running to check flag +function _check_try_running(flag, opt) + + -- make an stub source file + local winmain = flag:lower():find("subsystem:windows") + local sourcefile = path.join(os.tmpdir(), "detect", ifelse(winmain, "winmain_", "") .. "link_has_flag.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;}") + else + io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + end + end + + -- compile the source file + local objectfile = os.tmpfile() .. ".obj" + local binaryfile = os.tmpfile() .. ".exe" + os.iorunv("cl", {"-c", "-nologo", "-Fo" .. objectfile, sourcefile}) + + -- try link it + local ok = try { function () os.execv(opt.program, {flag, "-nologo", "-out:" .. binaryfile, objectfile}); return true end } + + -- remove files + os.tryrm(objectfile) + os.tryrm(binaryfile) + + -- ok? + return ok +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt) +end + diff --git a/xmake/modules/detect/tools/ml/has_flag.lua b/xmake/modules/detect/tools/ml/has_flag.lua new file mode 100644 index 000000000..f41561953 --- /dev/null +++ b/xmake/modules/detect/tools/ml/has_flag.lua @@ -0,0 +1,98 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt) + + -- make cache key + local key = "detect.tools.ml.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = os.iorunv(opt.program, {"-?"}) + if arglist then + for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do + flags[arg:gsub("/", "-")] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag:gsub("/", "-")] +end + +-- try running to check flag +function _check_try_running(flag, opt) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "ml_has_flag.asm") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, ".code\nend") + end + + -- check it + return try { function () + local _, errors = os.iorunv(opt.program, {"-c", "-nologo", flag, "-Fo" .. os.nuldev(), sourcefile}) + if errors and #errors:trim() > 0 then + return false + end + return true + end + } +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt) +end + diff --git a/xmake/modules/detect/tools/ml64/has_flag.lua b/xmake/modules/detect/tools/ml64/has_flag.lua new file mode 100644 index 000000000..c0086f0e7 --- /dev/null +++ b/xmake/modules/detect/tools/ml64/has_flag.lua @@ -0,0 +1,27 @@ +--!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 has_flag.lua +-- + +-- imports +inherit("detect.tools.ml.has_flag") + diff --git a/xmake/modules/detect/tools/rustc/has_flag.lua b/xmake/modules/detect/tools/rustc/has_flag.lua new file mode 100644 index 000000000..e5766bba8 --- /dev/null +++ b/xmake/modules/detect/tools/rustc/has_flag.lua @@ -0,0 +1,98 @@ +--!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 has_flag.lua +-- + +-- imports +import("lib.detect.cache") + +-- attempt to check it from the argument list +function _check_from_arglist(flag, opt) + + -- make cache key + local key = "detect.tools.rustc.has_flag" + + -- make flags key + local flagskey = opt.program .. "_" .. (opt.programver or "") + + -- load cache + local cacheinfo = cache.load(key) + + -- get all flags from argument list + local flags = cacheinfo[flagskey] + if not flags then + + -- get argument list + flags = {} + local arglist = os.iorunv(opt.program, {"--help"}) + if arglist then + for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do + flags[arg] = true + end + end + + -- save cache + cacheinfo[flagskey] = flags + cache.save(key, cacheinfo) + end + + -- ok? + return flags[flag] +end + +-- try running to check flag +function _check_try_running(flag, opt) + + -- make an stub source file + local sourcefile = path.join(os.tmpdir(), "detect", "rustc_has_flag.rs") + if not os.isfile(sourcefile) then + io.writefile(sourcefile, "fn main() {\n}") + end + + -- check it + local objectfile = os.tmpfile() .. ".o" + local ok = try { function () os.runv(opt.program, {"--emit", "obj", flag, "-o", objectfile, sourcefile}); return true end } + + -- remove files + os.tryrm(objectfile) + + -- ok? + return ok +end + +-- has_flag(flag)? +-- +-- @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(flag, opt) + + -- attempt to check it from the argument list + if _check_from_arglist(flag, opt) then + return true + end + + -- try running to check it + return _check_try_running(flag, opt) +end + diff --git a/xmake/modules/devel/debugger/run.lua b/xmake/modules/devel/debugger/run.lua index a94f7852f..1b71caafe 100644 --- a/xmake/modules/devel/debugger/run.lua +++ b/xmake/modules/devel/debugger/run.lua @@ -25,12 +25,12 @@ -- imports import("core.base.option") import("core.project.config") -import("detect.tool.find_gdb") -import("detect.tool.find_lldb") -import("detect.tool.find_windbg") -import("detect.tool.find_x64dbg") -import("detect.tool.find_ollydbg") -import("detect.tool.find_vsjitdebugger") +import("detect.tools.find_gdb") +import("detect.tools.find_lldb") +import("detect.tools.find_windbg") +import("detect.tools.find_x64dbg") +import("detect.tools.find_ollydbg") +import("detect.tools.find_vsjitdebugger") -- run gdb function _run_gdb(program, argv) @@ -62,18 +62,18 @@ function _run_lldb(program, argv) return false end - -- attempt to split shellname, .e.g xcrun -sdk macosx lldb - local shellnames = lldb:split("%s") + -- attempt to split name, .e.g xcrun -sdk macosx lldb + local names = lldb:split("%s") -- patch arguments argv = argv or {} table.insert(argv, 1, program) - for i = #shellnames, 2, -1 do - table.insert(argv, 1, shellnames[i]) + for i = #names, 2, -1 do + table.insert(argv, 1, names[i]) end -- run it - os.execv(shellnames[1], argv) + os.execv(names[1], argv) -- ok return true diff --git a/xmake/modules/devel/git/checkout.lua b/xmake/modules/devel/git/checkout.lua index a69801711..02f6c657e 100644 --- a/xmake/modules/devel/git/checkout.lua +++ b/xmake/modules/devel/git/checkout.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_git") +import("detect.tools.find_git") -- checkout to given branch, tag or commit -- diff --git a/xmake/modules/devel/git/clean.lua b/xmake/modules/devel/git/clean.lua index dcc94c805..d6eff80bd 100644 --- a/xmake/modules/devel/git/clean.lua +++ b/xmake/modules/devel/git/clean.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_git") +import("detect.tools.find_git") -- clean files -- diff --git a/xmake/modules/devel/git/clone.lua b/xmake/modules/devel/git/clone.lua index c717065b8..9e17a69b0 100644 --- a/xmake/modules/devel/git/clone.lua +++ b/xmake/modules/devel/git/clone.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_git") +import("detect.tools.find_git") -- clone url -- diff --git a/xmake/modules/devel/git/ls_remote.lua b/xmake/modules/devel/git/ls_remote.lua index 6ffb77d10..1f41c6e84 100644 --- a/xmake/modules/devel/git/ls_remote.lua +++ b/xmake/modules/devel/git/ls_remote.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_git") +import("detect.tools.find_git") -- ls_remote to given branch, tag or commit -- diff --git a/xmake/modules/devel/git/pull.lua b/xmake/modules/devel/git/pull.lua index 5874ae460..504d64ebd 100644 --- a/xmake/modules/devel/git/pull.lua +++ b/xmake/modules/devel/git/pull.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_git") +import("detect.tools.find_git") -- pull remote commits -- diff --git a/xmake/modules/lib/detect/find_tool.lua b/xmake/modules/lib/detect/find_tool.lua new file mode 100644 index 000000000..3cc07b071 --- /dev/null +++ b/xmake/modules/lib/detect/find_tool.lua @@ -0,0 +1,94 @@ +--!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 find_tool.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") +import("lib.detect.find_toolname") + +-- find tool from modules +function _find_from_modules(name, opt) + + -- "detect.tools.find_xxx" exists? + if os.isfile(path.join(os.programdir(), "modules", "detect", "tools", "find_" .. name .. ".lua")) then + local find_tool = import("detect.tools.find_" .. name) + if find_tool then + local program, version = find_tool(opt) + return {name = name, program = program, version = version} + end + end +end + +-- find tool +-- +-- @param name the tool name +-- @param opt the options, .e.g {program = "xcrun -sdk macosx clang", pathes = {"/usr/bin"}, check = function (tool) os.run("%s -h", tool) end, version = true} +-- +-- @return {name = "", program = "", version = ""} +-- +-- @code +-- +-- local tool = find_tool("clang") +-- local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"}) +-- local tool = find_tool("clang", {pathes = {"/usr/bin", "/usr/local/bin"}}) +-- local tool = find_tool("clang", {check= "--help"}) -- simple check command: ccache --help +-- local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end}) +-- local tool = find_tool("clang", {pathes = {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}}) +-- local tool = find_tool("clang", {pathes = {"$(env PATH)", function () return "/usr/bin"end}}) +-- local tool = find_tool("ccache", {version = true}) +-- +-- @endcode +-- +function main(name, opt) + + -- init options + opt = opt or {} + + -- find tool name + local toolname = find_toolname(name or opt.program) + if not toolname then + return + end + + -- init program + opt.program = opt.program or name + + -- attempt to find tool from modules first + local tool = _find_from_modules(toolname, opt) + if tool then + return tool + end + + -- find tool + local program = find_program(opt.program, opt.pathes, opt.check) + + -- find tool version + local version = nil + if program and opt.version then + version = find_programver(program) + end + + -- ok? + return {name = toolname, program = program, version = version} +end diff --git a/xmake/modules/lib/detect/find_toolname.lua b/xmake/modules/lib/detect/find_toolname.lua new file mode 100644 index 000000000..ce3b4f1f1 --- /dev/null +++ b/xmake/modules/lib/detect/find_toolname.lua @@ -0,0 +1,107 @@ +--!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 find_toolname.lua +-- + +-- find tool name from the given program +function _find(program) + + -- get tool directory + local tooldir = path.join(os.programdir(), "modules", "detect", "tools") + + -- attempt to find it directly first + if os.isfile(path.join(tooldir, "find_" .. program .. ".lua")) then + return program + end + + -- get file name first + name = path.filename(program):lower() + + -- remove arguments: " -xxx" or " --xxx" + name = name:gsub("%s%-+%w+", " ") + + -- get the last name by ' ': xxx xxx toolname + local names = name:split("%s") + if #names > 0 then + name = names[#names] + end + + -- remove suffix: ".xxx" + name = name:gsub("%.%w+", "") + + -- find_toolname.lua exists? found + local toolname = name:gsub("[%+%-]", function (ch) return ifelse(ch == "+", "x", "_") end) + if os.isfile(path.join(tooldir, "find_" .. toolname .. ".lua")) then + return toolname + end + + -- get the last valid name: xxx-xxx-toolname-5 + local partnames = {} + for partname in name:gmatch("([%a%+]+)") do + table.insert(partnames, partname) + end + if #partnames > 0 then + name = partnames[#partnames] + end + + -- find_toolname.lua exists? found + toolname = name:gsub("%+", "x") + if os.isfile(path.join(tooldir, "find_" .. toolname .. ".lua")) then + return toolname + end +end + +-- find tool name +-- +-- .e.g +-- "xcrun -sdk macosx clang": clang +-- "/usr/bin/arm-linux-gcc": gcc +-- "link.exe -lib": link +-- "gcc-5": gcc +-- "arm-android-clang++": clangxx +-- "pkg-config": pkg_config +-- +-- @param program the program path or name +-- +-- @return the tool name +-- +function main(program) + + -- init cache + local toolnames = _g._TOOLNAMES or {} + + -- get it from the cache first + local toolname = toolnames[program] + if toolname ~= nil then + return ifelse(toolname, toolname, nil) + end + + -- find the tool name + toolname = _find(program) + + -- save result to cache + toolnames[program] = ifelse(toolname, toolname, false) + _g._TOOLNAMES = toolnames + + -- found? + return toolname +end diff --git a/xmake/modules/lib/detect/has_cxsnippets.lua b/xmake/modules/lib/detect/has_cxsnippets.lua new file mode 100644 index 000000000..59ef12872 --- /dev/null +++ b/xmake/modules/lib/detect/has_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 has_csnippets.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 + +-- has 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 = has_csnippets("void test() {}") +-- local ok = has_csnippets({"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 + diff --git a/xmake/modules/lib/detect/has_flags.lua b/xmake/modules/lib/detect/has_flags.lua new file mode 100644 index 000000000..f307fc40f --- /dev/null +++ b/xmake/modules/lib/detect/has_flags.lua @@ -0,0 +1,115 @@ +--!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 has_flags.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") + +-- has this flag? +function _has_flag(name, flag, opt) + + -- find tool program and version first + opt.version = true + local tool = find_tool(name, opt) + if not tool then + return false + end + + -- init tool + opt.toolname = tool.name + opt.program = tool.program + opt.programver = tool.version + + -- init cache and key + local key = tool.program .. "_" .. (tool.version or "") .. "_" .. (opt.toolkind or "") .. "_" .. flag + _g._RESULTS = _g._RESULTS or {} + local results = _g._RESULTS + + -- @note avoid detect the same program in the same time if running in the coroutine (.e.g ccache) + local coroutine_running = coroutine.running() + if coroutine_running then + while _g._checking ~= nil and _g._checking == key do + coroutine.yield() + end + end + + -- get result from the cache first + local result = results[key] + if result ~= nil then + return result + end + + -- detect.tools.xxx.has_flag(flag, opt)? + _g._checking = ifelse(coroutine_running, key, nil) + if os.isfile(path.join(os.programdir(), "modules", "detect", "tools", tool.name, "has_flag.lua")) then + local hasflag = import("detect.tools." .. tool.name .. ".has_flag") + if hasflag then + result = hasflag(flag, opt) + end + else + result = try { function () os.runv(tool.program, {flag}); return true end } + end + _g._checking = nil + + -- trace + if option.get("verbose") or opt.verbose then + cprint("checking for the flags(%s) %s ... %s", path.filename(tool.program), flag, ifelse(result, "${green}ok", "${red}no")) + end + + -- save result to cache + results[key] = ifelse(result, result, false) + + -- ok? + return result +end + +-- has the given flags for the current tool? +-- +-- @param name the tool name +-- @param flags the flags +-- @param opt the argument options, .e.g {verbose = false, program = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"} +-- +-- @return true or false +-- +-- @code +-- local ok = has_flags("clang", "-g") +-- local ok = has_flags("clang", {"-g", "-O0"}, {program = "xcrun -sdk macosx clang"}) +-- local ok = has_flags("clang", "-g", {toolkind = "cxx"}) +-- @endcode +-- +function main(name, flags, opt) + + -- init options + opt = opt or {} + + -- has all flags? + for _, flag in ipairs(flags) do + if not _has_flag(name, flag, opt) then + return false + end + end + + -- ok + return true +end diff --git a/xmake/modules/lib/detect/pkg_config.lua b/xmake/modules/lib/detect/pkg_config.lua new file mode 100644 index 000000000..322977dbd --- /dev/null +++ b/xmake/modules/lib/detect/pkg_config.lua @@ -0,0 +1,183 @@ +--!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 pkg_config.lua +-- + +-- imports +import("lib.detect.find_library") +import("detect.tools.find_brew") +import("detect.tools.find_pkg_config") + +-- get package info +-- +-- @param name the package name +-- @param opt the argument options, {version = true, configdirs = {"/xxxx/pkgconfig/"}} +-- +-- @return {links = {"ssl", "crypto", "z"}, linkdirs = {""}, includedirs = {""}, version = ""} +-- +-- @code +-- +-- local pkginfo = pkg_config.info("openssl") +-- +-- @endcode +-- +function info(name, opt) + + -- attempt to add search pathes from pkg-config + local pkg_config = find_pkg_config() + if not pkg_config then + return + end + + -- init options and cache + opt = opt or {} + _g._INFO = _g._INFO or {} + + -- get it from cache first + local result = _g._INFO[name] + if result then + return result + end + + -- get pkg-config path from brew + local brew = find_brew() + local configdirs = opt.configdirs or {} + if brew then + local prefix = try { function () return os.iorunv(brew, {"--prefix", name}) end } + if prefix then + prefix = path.join(prefix:trim(), "lib", "pkgconfig") + if os.isdir(prefix) then + table.insert(configdirs, prefix) + end + end + end + + -- add PKG_CONFIG_PATH + local configdirs_old = nil + if #configdirs > 0 then + configdirs_old = os.getenv("PKG_CONFIG_PATH") + os.addenv("PKG_CONFIG_PATH", unpack(configdirs)) + end + + -- get libs and cflags + local flags = try { function () return os.iorunv(pkg_config, {"--libs", "--cflags", name}) end } + if flags then + + -- init result + result = {} + for _, flag in ipairs(flags:split('%s*')) do + + -- get links + local link = flag:match("%-l(.*)") + if link then + result.links = result.links or {} + table.insert(result.links, link) + end + + -- get linkdirs + local linkdirs = nil + local linkdir = flag:match("%-L(.*)") + if linkdir and os.isdir(linkdir) then + result.linkdirs = result.linkdirs or {} + table.insert(result.linkdirs, linkdir) + end + + -- get includedirs + local includedirs = nil + local includedir = flag:match("%-I(.*)") + if includedir and os.isdir(includedir) then + result.includedirs = result.includedirs or {} + table.insert(result.includedirs, includedir) + end + end + end + + -- get version + if opt.version then + + -- get version + local version = try { function() return os.iorunv(pkg_config, {"--modversion", name}) end } + if version then + result = result or {} + result.version = version:trim() + end + end + + -- restore PKG_CONFIG_PATH + if configdirs_old then + os.setenv("PKG_CONFIG_PATH", configdirs_old) + end + + -- save result to cache + _g._INFO[name] = result + + -- ok? + return result +end + +-- find package +-- +-- @param name the package name +-- @param opt the argument options, {plat = "", arch = "", version = "1.0.1"} +-- +-- @return {links = {"ssl", "crypto", "z"}, linkdirs = {""}, includedirs = {""}} +-- +-- @code +-- +-- local pkginfo = pkg_config.find("openssl") +-- +-- @endcode +-- +function find(name, opt) + + -- get package info + local pkginfo = info(name, opt) + if not pkginfo then + return + end + + -- match version? + opt = opt or {} + if opt.version and pkginfo.version ~= opt.version then + return + end + + -- find library + local result = nil + for _, link in ipairs(table.wrap(pkginfo.links)) do + local libinfo = find_library(link, pkginfo.linkdirs) + if libinfo then + result = result or {} + result.links = table.join(result.links or {}, libinfo.link) + result.linkdirs = table.join(result.linkdirs or {}, libinfo.linkdir) + end + end + + -- found? + if result and result.links then + result.linkdirs = table.unique(result.linkdirs) + result.includedirs = table.join(result.includedirs or {}, pkginfo.includedirs) + end + + -- ok? + return result +end diff --git a/xmake/modules/net/http/download.lua b/xmake/modules/net/http/download.lua index 66e211578..e5cc6c14d 100644 --- a/xmake/modules/net/http/download.lua +++ b/xmake/modules/net/http/download.lua @@ -24,8 +24,8 @@ -- imports import("core.base.option") -import("detect.tool.find_curl") -import("detect.tool.find_wget") +import("detect.tools.find_curl") +import("detect.tools.find_wget") -- download url using curl function _curl_download(program, url, outputfile) diff --git a/xmake/modules/privilege/sudo.lua b/xmake/modules/privilege/sudo.lua index 4eb5f6538..0a8816098 100644 --- a/xmake/modules/privilege/sudo.lua +++ b/xmake/modules/privilege/sudo.lua @@ -24,9 +24,9 @@ -- imports import("core.base.option") -import("detect.tool.find_sudo") +import("detect.tools.find_sudo") --- sudo run shell with administrator permission +-- sudo run command with administrator permission -- -- .e.g -- _sudo(os.run, "echo", "hello xmake!") @@ -34,8 +34,8 @@ import("detect.tool.find_sudo") function _sudo(runner, cmd, ...) -- find sudo - local program = find_sudo() - assert(program, "sudo not found!") + local sudo = find_sudo() + assert(sudo, "sudo not found!") -- get current path environment local pathenv = os.getenv("PATH") @@ -45,26 +45,26 @@ function _sudo(runner, cmd, ...) pathenv = pathenv:gsub("\"", "\\\"") -- run it with administrator permission and preserve parent environment - runner(program .. " env PATH=\"" .. pathenv .. "\" " .. cmd, ...) + runner(sudo .. " env PATH=\"" .. pathenv .. "\" " .. cmd, ...) else -- run it with administrator permission - runner(program .. " " .. cmd, ...) + runner(sudo .. " " .. cmd, ...) end end --- sudo run shell with administrator permission and arguments list +-- sudo run command with administrator permission and arguments list -- -- .e.g -- _sudov(os.runv, {"echo", "hello xmake!"}) -- -function _sudov(runner, shellname, argv) +function _sudov(runner, program, argv) -- find sudo - local program = find_sudo() - assert(program, "sudo not found!") + local sudo = find_sudo() + assert(sudo, "sudo not found!") -- run it with administrator permission and preserve parent environment - runner(program, table.join("env", "PATH=" .. os.getenv("PATH"), shellname, argv)) + runner(sudo, table.join("env", "PATH=" .. os.getenv("PATH"), program, argv)) end -- sudo run lua script with administrator permission and arguments list @@ -94,44 +94,44 @@ function has() return find_sudo() ~= nil end --- sudo run shell +-- sudo run command function run(cmd, ...) return _sudo(os.run, cmd, ...) end --- sudo run shell with arguments list -function runv(shellname, argv) - return _sudov(os.run, shellname, argv) +-- sudo run command with arguments list +function runv(program, argv) + return _sudov(os.run, program, argv) end --- sudo quietly run shell and echo verbose info if [-v|--verbose] option is enabled +-- sudo quietly run command and echo verbose info if [-v|--verbose] option is enabled function vrun(cmd, ...) return _sudo(os.vrun, cmd, ...) end --- sudo quietly run shell with arguments list and echo verbose info if [-v|--verbose] option is enabled -function vrunv(shellname, argv) - return _sudov(os.vrunv, shellname, argv) +-- sudo quietly run command with arguments list and echo verbose info if [-v|--verbose] option is enabled +function vrunv(program, argv) + return _sudov(os.vrunv, program, argv) end --- sudo run shell and return output and error data +-- sudo run command and return output and error data function iorun(cmd, ...) return _sudo(os.iorun, cmd, ...) end --- sudo run shell and return output and error data -function iorunv(shellname, argv) - return _sudov(os.iorunv, shellname, argv) +-- sudo run command and return output and error data +function iorunv(program, argv) + return _sudov(os.iorunv, program, argv) end --- sudo execute shell +-- sudo execute command function exec(cmd, ...) return _sudo(os.exec, cmd, ...) end --- sudo execute shell with arguments list -function execv(shellname, argv) - return _sudov(os.execv, shellname, argv) +-- sudo execute command with arguments list +function execv(program, argv) + return _sudov(os.execv, program, argv) end -- sudo run lua script diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua index e350ff636..4672c2442 100644 --- a/xmake/modules/utils/archive/extract.lua +++ b/xmake/modules/utils/archive/extract.lua @@ -25,10 +25,10 @@ -- imports import("core.base.option") import("lib.detect.find_file") -import("detect.tool.find_7z") -import("detect.tool.find_tar") -import("detect.tool.find_gzip") -import("detect.tool.find_unzip") +import("detect.tools.find_7z") +import("detect.tools.find_tar") +import("detect.tools.find_gzip") +import("detect.tools.find_unzip") -- extract archivefile using tar function _extract_using_tar(archivefile, outputdir, extension) diff --git a/xmake/platforms/android/check.lua b/xmake/platforms/android/check.lua index cb8b15e21..4d70c5001 100644 --- a/xmake/platforms/android/check.lua +++ b/xmake/platforms/android/check.lua @@ -24,8 +24,8 @@ -- imports import(".checker") -import("detect.sdk.find_ndk_sdkvers") -import("detect.sdk.find_ndk_toolchains") +import("detect.sdks.find_ndk_sdkvers") +import("detect.sdks.find_ndk_toolchains") -- check the sdk version for ndk function _check_ndk_sdkver(config) diff --git a/xmake/platforms/checker.lua b/xmake/platforms/checker.lua index 870b51053..bf6e60b8c 100644 --- a/xmake/platforms/checker.lua +++ b/xmake/platforms/checker.lua @@ -23,92 +23,52 @@ -- -- imports -import("core.tool.tool") import("core.base.option") -import("detect.sdk.find_xcode_dir") -import("detect.sdk.find_xcode_sdkvers") +import("detect.sdks.find_xcode_dir") +import("detect.sdks.find_xcode_sdkvers") +import("lib.detect.find_tool") -- find the given tool function _toolchain_check(config, toolkind, toolinfo) - -- get the tool path - local toolpath = config.get(toolkind) - if not toolpath then + -- get the program + local program = config.get(toolkind) + if not program then - -- get name - local name = toolinfo.name - - -- get cross - local cross = config.get("cross") or toolinfo.cross - - -- get shell name from the env if not cross-compilation - if cross and cross:trim() == "" then - local shellname = os.getenv(toolkind:upper():split('-')[1]) - if shellname and shellname:trim() ~= "" then - toolpath = tool.check(shellname) - end + -- get name and attempt to get `$(env XX)` + local name = vformat(toolinfo.name) + if #name == 0 then + return end - -- check it using the custom script - if not toolpath and toolinfo.check then - - -- check it - try - { - function () - - -- check it - toolinfo.check(cross .. name) - - -- ok - toolpath = cross .. name - end - } - end + -- get cross + local cross = config.get("cross") or toolinfo.cross or "" - -- get toolchains - local toolchains = config.get("toolchains") - if not toolchains then - local sdkdir = config.get("sdk") - if sdkdir then - toolchains = path.join(sdkdir, "bin") + -- attempt to check it + if not program then + local tool = find_tool(name, {program = cross .. name, pathes = config.get("toolchains"), check = toolinfo.check}) + if tool then + program = tool.program end end - -- attempt to check it from the given cross toolchains - if not toolpath and toolchains then - toolpath = tool.check(cross .. name, toolchains) - end - - -- attempt to check it with cross prefix - if not toolpath then - toolpath = tool.check(cross .. name) - end - - -- attempt to check it without cross prefix - if not toolpath then - toolpath = tool.check(name) - end - -- check ok? - if toolpath then - - -- update config - config.set(toolkind, toolpath) + if program then + config.set(toolkind, program) end -- trace if option.get("verbose") then - if toolpath then - cprint("checking for %s (%s) ... ${green}%s", toolinfo.description, toolkind, path.filename(toolpath)) + if program then + cprint("checking for %s (%s) ... ${green}%s", toolinfo.description, toolkind, path.filename(program)) else cprint("checking for %s (%s: ${red}%s${clear}) ... ${red}no", toolinfo.description, toolkind, name) end end end - -- get tool path - return toolpath + -- ok? + return program end -- check all for the given config kind diff --git a/xmake/platforms/iphoneos/check.lua b/xmake/platforms/iphoneos/check.lua index b3fa9b728..a12a53801 100644 --- a/xmake/platforms/iphoneos/check.lua +++ b/xmake/platforms/iphoneos/check.lua @@ -25,20 +25,6 @@ -- imports import(".checker") --- check the as -function _check_as(shellname) - - -- make an empty tmp.S - local tmpfile = os.tmpfile() .. ".S" - io.writefile(tmpfile, "") - - -- check it - os.run("%s -arch armv7 -o %s -c %s", shellname, os.nuldev(), tmpfile) - - -- remove this tmp.S - os.rm(tmpfile) -end - -- get toolchains function _toolchains(config) @@ -82,7 +68,7 @@ function _toolchains(config) if simulator then checker.toolchain_insert(toolchains, "as", cross, "clang", "the assember") else - checker.toolchain_insert(toolchains, "as", path.join(os.toolsdir(), "utils/gas-preprocessor.pl " .. cross), "clang", "the assember", _check_as) + checker.toolchain_insert(toolchains, "as", path.join(os.programdir(), "scripts", "gas-preprocessor.pl " .. cross), "clang", "the assember") end -- save toolchains diff --git a/xmake/platforms/linux/check.lua b/xmake/platforms/linux/check.lua index 82e7737cc..c3751b644 100644 --- a/xmake/platforms/linux/check.lua +++ b/xmake/platforms/linux/check.lua @@ -23,7 +23,7 @@ -- -- imports -import("detect.sdk.find_cross_toolchains") +import("detect.sdks.find_cross_toolchains") import(".checker") -- check the architecture @@ -63,63 +63,87 @@ function _toolchains(config) -- init toolchains local toolchains = {} + -- inset tools from environment variables if not cross-compilation + if #cross == 0 then + checker.toolchain_insert(toolchains, "cc", "", "$(env CC)", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", "", "$(env CXX)", "the linker") + checker.toolchain_insert(toolchains, "ld", "", "$(env LD)", "the linker") + checker.toolchain_insert(toolchains, "ld", "", "$(env CXX)", "the linker") + checker.toolchain_insert(toolchains, "ar", "", "$(env AR)", "the static library archiver") + checker.toolchain_insert(toolchains, "sh", "", "$(env SH)", "the shared library linker") + checker.toolchain_insert(toolchains, "mm", "", "$(env MM)", "the objc compiler") + checker.toolchain_insert(toolchains, "mxx", "", "$(env MXX)", "the objc++ compiler") + checker.toolchain_insert(toolchains, "as", "", "$(env AS)", "the assember") + end + -- insert c/c++ tools to toolchains - checker.toolchain_insert(toolchains, "cc", cross, "gcc", "the c compiler") - checker.toolchain_insert(toolchains, "cc", cross, "clang", "the c compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "gcc", "the c++ compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "clang", "the c++ compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "g++", "the c++ compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "clang++", "the c++ compiler") - checker.toolchain_insert(toolchains, "ld", cross, "g++", "the linker") - checker.toolchain_insert(toolchains, "ld", cross, "gcc", "the linker") - checker.toolchain_insert(toolchains, "ld", cross, "clang++", "the linker") - checker.toolchain_insert(toolchains, "ld", cross, "clang", "the linker") - checker.toolchain_insert(toolchains, "ar", cross, "ar", "the static library archiver") - checker.toolchain_insert(toolchains, "ex", cross, "ar", "the static library extractor") - checker.toolchain_insert(toolchains, "sh", cross, "g++", "the shared library linker") - checker.toolchain_insert(toolchains, "sh", cross, "gcc", "the shared library linker") - checker.toolchain_insert(toolchains, "sh", cross, "clang++", "the shared library linker") - checker.toolchain_insert(toolchains, "sh", cross, "clang", "the shared library linker") + checker.toolchain_insert(toolchains, "cc", cross, "gcc", "the c compiler") + checker.toolchain_insert(toolchains, "cc", cross, "clang", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "gcc", "the c++ compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "clang", "the c++ compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "g++", "the c++ compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "clang++", "the c++ compiler") + checker.toolchain_insert(toolchains, "ld", cross, "g++", "the linker") + checker.toolchain_insert(toolchains, "ld", cross, "gcc", "the linker") + checker.toolchain_insert(toolchains, "ld", cross, "clang++", "the linker") + checker.toolchain_insert(toolchains, "ld", cross, "clang", "the linker") + checker.toolchain_insert(toolchains, "ar", cross, "ar", "the static library archiver") + checker.toolchain_insert(toolchains, "ex", cross, "ar", "the static library extractor") + checker.toolchain_insert(toolchains, "sh", cross, "g++", "the shared library linker") + checker.toolchain_insert(toolchains, "sh", cross, "gcc", "the shared library linker") + checker.toolchain_insert(toolchains, "sh", cross, "clang++", "the shared library linker") + checker.toolchain_insert(toolchains, "sh", cross, "clang", "the shared library linker") -- insert objc/c++ tools to toolchains - checker.toolchain_insert(toolchains, "mm", cross, "clang", "the objc compiler") - checker.toolchain_insert(toolchains, "mm", cross, "gcc", "the objc compiler") - checker.toolchain_insert(toolchains, "mxx", cross, "clang++", "the objc++ compiler") - checker.toolchain_insert(toolchains, "mxx", cross, "clang", "the objc++ compiler") - checker.toolchain_insert(toolchains, "mxx", cross, "g++", "the objc++ compiler") - checker.toolchain_insert(toolchains, "mxx", cross, "gcc", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mm", cross, "clang", "the objc compiler") + checker.toolchain_insert(toolchains, "mm", cross, "gcc", "the objc compiler") + checker.toolchain_insert(toolchains, "mxx", cross, "clang++", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mxx", cross, "clang", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mxx", cross, "g++", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mxx", cross, "gcc", "the objc++ compiler") -- insert asm tools to toolchains - checker.toolchain_insert(toolchains, "as", cross, "clang", "the assember") - checker.toolchain_insert(toolchains, "as", cross, "gcc", "the assember") + checker.toolchain_insert(toolchains, "as", cross, "clang", "the assember") + checker.toolchain_insert(toolchains, "as", cross, "gcc", "the assember") -- insert golang tools to toolchains - checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") - checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") - checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") - checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") + checker.toolchain_insert(toolchains, "gc", "", "$(env GC)", "the golang compiler") + checker.toolchain_insert(toolchains, "gc-ar", "", "$(env GC)", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ld", "", "$(env GC)", "the golang linker") + checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") + checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") + checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") + checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") -- insert dlang tools to toolchains - checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") + checker.toolchain_insert(toolchains, "dc", "", "$(env DC)", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc-ar", "", "$(env Dc)", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-sh", "", "$(env DC)", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "$(env DC)", "the dlang linker") + checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") -- insert rust tools to toolchains - checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") - checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") - checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") - checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") + checker.toolchain_insert(toolchains, "rc", "", "$(env RC)", "the rust compiler") + checker.toolchain_insert(toolchains, "rc-ar", "", "$(env RC)", "the rust static library archiver") + checker.toolchain_insert(toolchains, "rc-sh", "", "$(env RC)", "the rust shared library linker") + checker.toolchain_insert(toolchains, "rc-ld", "", "$(env RC)", "the rust linker") + checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") + checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") + checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") + checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") -- save toolchains _g.TOOLCHAINS = toolchains diff --git a/xmake/platforms/macosx/check.lua b/xmake/platforms/macosx/check.lua index 56d4e48c6..833087684 100644 --- a/xmake/platforms/macosx/check.lua +++ b/xmake/platforms/macosx/check.lua @@ -37,56 +37,79 @@ function _toolchains(config) local toolchains = {} -- insert c/c++ tools to toolchains - checker.toolchain_insert(toolchains, "cc", "xcrun -sdk macosx ", "clang", "the c compiler") - checker.toolchain_insert(toolchains, "cxx", "xcrun -sdk macosx ", "clang", "the c++ compiler") - checker.toolchain_insert(toolchains, "cxx", "xcrun -sdk macosx ", "clang++", "the c++ compiler") - checker.toolchain_insert(toolchains, "ld", "xcrun -sdk macosx ", "clang++", "the linker") - checker.toolchain_insert(toolchains, "ld", "xcrun -sdk macosx ", "clang", "the linker") - checker.toolchain_insert(toolchains, "ar", "xcrun -sdk macosx ", "ar", "the static library archiver") - checker.toolchain_insert(toolchains, "ex", "xcrun -sdk macosx ", "ar", "the static library extractor") - checker.toolchain_insert(toolchains, "sh", "xcrun -sdk macosx ", "clang++", "the shared library linker") - checker.toolchain_insert(toolchains, "sh", "xcrun -sdk macosx ", "clang", "the shared library linker") + checker.toolchain_insert(toolchains, "cc", "", "$(env CC)", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", "", "$(env CXX)", "the linker") + checker.toolchain_insert(toolchains, "ld", "", "$(env LD)", "the linker") + checker.toolchain_insert(toolchains, "ld", "", "$(env CXX)", "the linker") + checker.toolchain_insert(toolchains, "ar", "", "$(env AR)", "the static library archiver") + checker.toolchain_insert(toolchains, "sh", "", "$(env SH)", "the shared library linker") + checker.toolchain_insert(toolchains, "cc", "xcrun -sdk macosx ", "clang", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", "xcrun -sdk macosx ", "clang", "the c++ compiler") + checker.toolchain_insert(toolchains, "cxx", "xcrun -sdk macosx ", "clang++", "the c++ compiler") + checker.toolchain_insert(toolchains, "ld", "xcrun -sdk macosx ", "clang++", "the linker") + checker.toolchain_insert(toolchains, "ld", "xcrun -sdk macosx ", "clang", "the linker") + checker.toolchain_insert(toolchains, "ar", "xcrun -sdk macosx ", "ar", "the static library archiver") + checker.toolchain_insert(toolchains, "ex", "xcrun -sdk macosx ", "ar", "the static library extractor") + checker.toolchain_insert(toolchains, "sh", "xcrun -sdk macosx ", "clang++", "the shared library linker") + checker.toolchain_insert(toolchains, "sh", "xcrun -sdk macosx ", "clang", "the shared library linker") -- insert objc/c++ tools to toolchains - checker.toolchain_insert(toolchains, "mm", "xcrun -sdk macosx ", "clang", "the objc compiler") - checker.toolchain_insert(toolchains, "mxx", "xcrun -sdk macosx ", "clang++", "the objc++ compiler") - checker.toolchain_insert(toolchains, "mxx", "xcrun -sdk macosx ", "clang", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mm", "", "$(env MM)", "the objc compiler") + checker.toolchain_insert(toolchains, "mxx", "", "$(env MXX)", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mm", "xcrun -sdk macosx ", "clang", "the objc compiler") + checker.toolchain_insert(toolchains, "mxx", "xcrun -sdk macosx ", "clang++", "the objc++ compiler") + checker.toolchain_insert(toolchains, "mxx", "xcrun -sdk macosx ", "clang", "the objc++ compiler") -- insert asm tools to toolchains - checker.toolchain_insert(toolchains, "as", "xcrun -sdk macosx ", "clang", "the assember") + checker.toolchain_insert(toolchains, "as", "", "$(env AS)", "the assember") + checker.toolchain_insert(toolchains, "as", "xcrun -sdk macosx ", "clang", "the assember") -- insert swift tools to toolchains - checker.toolchain_insert(toolchains, "sc", "xcrun -sdk macosx ", "swiftc", "the swift compiler") - checker.toolchain_insert(toolchains, "sc-ld", "xcrun -sdk macosx ", "swiftc", "the swift linker") - checker.toolchain_insert(toolchains, "sc-sh", "xcrun -sdk macosx ", "swiftc", "the swift shared library linker") + checker.toolchain_insert(toolchains, "sc", "", "$(env SC)", "the swift compiler") + checker.toolchain_insert(toolchains, "sc-ld", "", "$(env SC)", "the swift linker") + checker.toolchain_insert(toolchains, "sc-sh", "", "$(env SC)", "the swift shared library linker") + checker.toolchain_insert(toolchains, "sc", "xcrun -sdk macosx ", "swiftc", "the swift compiler") + checker.toolchain_insert(toolchains, "sc-ld", "xcrun -sdk macosx ", "swiftc", "the swift linker") + checker.toolchain_insert(toolchains, "sc-sh", "xcrun -sdk macosx ", "swiftc", "the swift shared library linker") -- insert golang tools to toolchains - checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") - checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") - checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") - checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") + checker.toolchain_insert(toolchains, "gc", "", "$(env GC)", "the golang compiler") + checker.toolchain_insert(toolchains, "gc-ar", "", "$(env GC)", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ld", "", "$(env GC)", "the golang linker") + checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") + checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") + checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") + checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") -- insert dlang tools to toolchains - checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") + checker.toolchain_insert(toolchains, "dc", "", "$(env DC)", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc-ar", "", "$(env Dc)", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-sh", "", "$(env DC)", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "$(env DC)", "the dlang linker") + checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") -- insert rust tools to toolchains - checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") - checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") - checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") - checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") + checker.toolchain_insert(toolchains, "rc", "", "$(env RC)", "the rust compiler") + checker.toolchain_insert(toolchains, "rc-ar", "", "$(env RC)", "the rust static library archiver") + checker.toolchain_insert(toolchains, "rc-sh", "", "$(env RC)", "the rust shared library linker") + checker.toolchain_insert(toolchains, "rc-ld", "", "$(env RC)", "the rust linker") + checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") + checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") + checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") + checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") -- save toolchains _g.TOOLCHAINS = toolchains diff --git a/xmake/platforms/mingw/check.lua b/xmake/platforms/mingw/check.lua index 887aa43db..f3f8872db 100644 --- a/xmake/platforms/mingw/check.lua +++ b/xmake/platforms/mingw/check.lua @@ -23,7 +23,7 @@ -- -- imports -import("detect.sdk.find_cross_toolchains") +import("detect.sdks.find_cross_toolchains") import(".checker") -- get toolchains @@ -53,16 +53,16 @@ function _toolchains(config) -- make toolchains local toolchains = {} - checker.toolchain_insert(toolchains, "cc", cross, "gcc", "the c compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "g++", "the c++ compiler") - checker.toolchain_insert(toolchains, "cxx", cross, "gcc", "the c++ compiler") - checker.toolchain_insert(toolchains, "as", cross, "gcc", "the assember") - checker.toolchain_insert(toolchains, "ld", cross, "g++", "the linker") - checker.toolchain_insert(toolchains, "ld", cross, "gcc", "the linker") - checker.toolchain_insert(toolchains, "ar", cross, "ar", "the static library archiver") - checker.toolchain_insert(toolchains, "ex", cross, "ar", "the static library extractor") - checker.toolchain_insert(toolchains, "sh", cross, "g++", "the shared library linker") - checker.toolchain_insert(toolchains, "sh", cross, "gcc", "the shared library linker") + checker.toolchain_insert(toolchains, "cc", cross, "gcc", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "g++", "the c++ compiler") + checker.toolchain_insert(toolchains, "cxx", cross, "gcc", "the c++ compiler") + checker.toolchain_insert(toolchains, "as", cross, "gcc", "the assember") + checker.toolchain_insert(toolchains, "ld", cross, "g++", "the linker") + checker.toolchain_insert(toolchains, "ld", cross, "gcc", "the linker") + checker.toolchain_insert(toolchains, "ar", cross, "ar", "the static library archiver") + checker.toolchain_insert(toolchains, "ex", cross, "ar", "the static library extractor") + checker.toolchain_insert(toolchains, "sh", cross, "g++", "the shared library linker") + checker.toolchain_insert(toolchains, "sh", cross, "gcc", "the shared library linker") -- save toolchains _g.TOOLCHAINS = toolchains diff --git a/xmake/platforms/watchos/check.lua b/xmake/platforms/watchos/check.lua index c6ce73e21..60a923fa8 100644 --- a/xmake/platforms/watchos/check.lua +++ b/xmake/platforms/watchos/check.lua @@ -25,20 +25,6 @@ -- imports import(".checker") --- check the as -function _check_as(shellname) - - -- make an empty tmp.S - local tmpfile = os.tmpfile() .. ".S" - io.writefile(tmpfile, "") - - -- check it - os.run("%s -arch armv7 -o %s -c %s", shellname, os.nuldev(), tmpfile) - - -- remove this tmp.S - os.rm(tmpfile) -end - -- get toolchains function _toolchains(config) @@ -82,7 +68,7 @@ function _toolchains(config) if simulator then checker.toolchain_insert(toolchains, "as", cross, "clang", "the assember") else - checker.toolchain_insert(toolchains, "as", path.join(os.toolsdir(), "utils/gas-preprocessor.pl " .. cross), "clang", "the assember", _check_as) + checker.toolchain_insert(toolchains, "as", path.join(os.programdir(), "scripts", "gas-preprocessor.pl " .. cross), "clang", "the assember") end -- save toolchains diff --git a/xmake/platforms/windows/check.lua b/xmake/platforms/windows/check.lua index 8218ffd3a..7bcb96326 100644 --- a/xmake/platforms/windows/check.lua +++ b/xmake/platforms/windows/check.lua @@ -23,11 +23,11 @@ -- -- imports -import("core.tool.tool") -import("core.base.option") -import("platforms.checker", {rootdir = os.programdir()}) +import(".checker") import("environment") -import("detect.sdk.find_vstudio") +import("core.base.option") +import("detect.sdks.find_vstudio") +import("lib.detect.find_tool") -- attempt to check vs environment function _check_vsenv(config) @@ -65,11 +65,15 @@ function _check_vsenv(config) -- check compiler environment.enter("toolchains") - local toolpath = tool.check("cl.exe") + local program = nil + local tool = find_tool("cl.exe") + if tool then + program = tool.program + end environment.leave("toolchains") -- ok? - if toolpath then + if program then return vsver end end @@ -119,47 +123,47 @@ function _toolchains(config) local toolchains = {} -- insert c/c++ tools to toolchains - checker.toolchain_insert(toolchains, "cc", "", "cl.exe", "the c compiler") - checker.toolchain_insert(toolchains, "cxx", "", "cl.exe", "the c++ compiler") - checker.toolchain_insert(toolchains, "mrc", "", "rc.exe", "the resource compiler") - checker.toolchain_insert(toolchains, "ld", "", "link.exe", "the linker") - checker.toolchain_insert(toolchains, "ar", "", "link.exe -lib", "the static library archiver") - checker.toolchain_insert(toolchains, "sh", "", "link.exe -dll", "the shared library linker") - checker.toolchain_insert(toolchains, "ex", "", "lib.exe", "the static library extractor") + checker.toolchain_insert(toolchains, "cc", "", "cl.exe", "the c compiler") + checker.toolchain_insert(toolchains, "cxx", "", "cl.exe", "the c++ compiler") + checker.toolchain_insert(toolchains, "mrc", "", "rc.exe", "the resource compiler") + checker.toolchain_insert(toolchains, "ld", "", "link.exe", "the linker") + checker.toolchain_insert(toolchains, "ar", "", "link.exe -lib", "the static library archiver") + checker.toolchain_insert(toolchains, "sh", "", "link.exe -dll", "the shared library linker") + checker.toolchain_insert(toolchains, "ex", "", "lib.exe", "the static library extractor") -- insert golang tools to toolchains - checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") - checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") - checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") - checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") - checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") + checker.toolchain_insert(toolchains, "gc", "", "go", "the golang compiler") + checker.toolchain_insert(toolchains, "gc", "", "gccgo", "the golang compiler") + checker.toolchain_insert(toolchains, "gc-ar", "", "go", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ar", "", "gccgo", "the golang static library archiver") + checker.toolchain_insert(toolchains, "gc-ld", "", "go", "the golang linker") + checker.toolchain_insert(toolchains, "gc-ld", "", "gccgo", "the golang linker") -- insert dlang tools to toolchains - checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") - checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") - checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") - checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") + checker.toolchain_insert(toolchains, "dc", "", "dmd", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "ldc2", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc", "", "gdc", "the dlang compiler") + checker.toolchain_insert(toolchains, "dc-ar", "", "dmd", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "ldc2", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-ar", "", "gdc", "the dlang static library archiver") + checker.toolchain_insert(toolchains, "dc-sh", "", "dmd", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "ldc2", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-sh", "", "gdc", "the dlang shared library linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "dmd", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "ldc2", "the dlang linker") + checker.toolchain_insert(toolchains, "dc-ld", "", "gdc", "the dlang linker") -- insert rust tools to toolchains - checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") - checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") - checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") - checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") + checker.toolchain_insert(toolchains, "rc", "", "rustc", "the rust compiler") + checker.toolchain_insert(toolchains, "rc-ar", "", "rustc", "the rust static library archiver") + checker.toolchain_insert(toolchains, "rc-sh", "", "rustc", "the rust shared library linker") + checker.toolchain_insert(toolchains, "rc-ld", "", "rustc", "the rust linker") -- insert asm tools to toolchains if config.get("arch"):find("64") then - checker.toolchain_insert(toolchains, "as", "", "ml64.exe", "the assember") + checker.toolchain_insert(toolchains, "as", "", "ml64.exe", "the assember") else - checker.toolchain_insert(toolchains, "as", "", "ml.exe", "the assember") + checker.toolchain_insert(toolchains, "as", "", "ml.exe", "the assember") end -- save toolchains diff --git a/xmake/plugins/app2ipa/main.lua b/xmake/plugins/app2ipa/main.lua index 7fba742dc..f03657b70 100644 --- a/xmake/plugins/app2ipa/main.lua +++ b/xmake/plugins/app2ipa/main.lua @@ -24,7 +24,7 @@ -- imports import("core.base.option") -import("detect.tool.find_zip") +import("detect.tools.find_zip") -- main function main() diff --git a/xmake/plugins/doxygen/main.lua b/xmake/plugins/doxygen/main.lua index 7129c7306..c13327959 100644 --- a/xmake/plugins/doxygen/main.lua +++ b/xmake/plugins/doxygen/main.lua @@ -26,7 +26,7 @@ import("core.base.option") import("core.project.config") import("core.project.project") -import("detect.tool.find_doxygen") +import("detect.tools.find_doxygen") -- main function main() diff --git a/xmake/plugins/lua/scripts/lipo.lua b/xmake/plugins/lua/scripts/lipo.lua index 8b87eb9e0..5c0ce510d 100644 --- a/xmake/plugins/lua/scripts/lipo.lua +++ b/xmake/plugins/lua/scripts/lipo.lua @@ -23,7 +23,7 @@ -- -- imports -import("detect.tool.find_lipo") +import("detect.tools.find_lipo") -- main -- diff --git a/xmake/plugins/macro/main.lua b/xmake/plugins/macro/main.lua index 1fbd26207..59510fc89 100644 --- a/xmake/plugins/macro/main.lua +++ b/xmake/plugins/macro/main.lua @@ -24,9 +24,9 @@ -- imports import("core.base.option") -import("core.project.cache") +import("core.project.cache", {nocache = true}) import("core.project.config") -import("core.project.history") +import("core.project.history", {nocache = true}) -- the macro directories function _directories() diff --git a/xmake/plugins/project/makefile/makefile.lua b/xmake/plugins/project/makefile/makefile.lua index 2df00a4a9..e09b4edc1 100644 --- a/xmake/plugins/project/makefile/makefile.lua +++ b/xmake/plugins/project/makefile/makefile.lua @@ -23,11 +23,11 @@ -- -- imports -import("core.tool.tool") import("core.tool.compiler") import("core.project.config") import("core.project.project") import("core.language.language") +import("core.platform.platform") -- get log makefile function _logfile() @@ -99,14 +99,14 @@ function _make_object(makefile, target, sourcefile, objectfile) return _make_object_for_static(makefile, target, sourcefile, objectfile) end - -- get shellname name - local shellname = tool.shellname(sourcekind) + -- get program + local program = platform.tool(sourcekind) -- get complier flags - local compflags = compiler.compflags(sourcefile, target, sourcekind) + local compflags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind}) -- make command - local command = compiler.compcmd(sourcefile, objectfile, target) + local command = compiler.compcmd(sourcefile, objectfile, {target = target}) -- replace compflags to $(XX) local p, e = command:find(compflags, 1, true) @@ -114,8 +114,8 @@ function _make_object(makefile, target, sourcefile, objectfile) command = format("%s$(%s_%s)%s", command:sub(1, p - 1), target:name(), sourcekind:upper(), command:sub(e + 1)) end - -- replace shellname to $(XX) - p, e = command:find(shellname, 1, true) + -- replace program to $(XX) + p, e = command:find(program, 1, true) if p then command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) end @@ -160,14 +160,14 @@ function _make_single_object(makefile, target, sourcekind, sourcebatch) local objectfiles = sourcebatch.objectfiles local incdepfiles = sourcebatch.incdepfiles - -- get shellname name - local shellname = tool.shellname(sourcekind) + -- get program + local program = platform.tool(sourcekind) -- get complier flags - local compflags = compiler.compflags(sourcefiles, target, sourcekind) + local compflags = compiler.compflags(sourcefiles, {target = target, sourcekind = sourcekind}) -- make command - local command = compiler.compcmd(sourcefiles, objectfiles, target, sourcekind) + local command = compiler.compcmd(sourcefiles, objectfiles, {target = target, sourcekind = sourcekind}) -- replace compflags to $(XX) local p, e = command:find(compflags, 1, true) @@ -175,8 +175,8 @@ function _make_single_object(makefile, target, sourcekind, sourcebatch) command = format("%s$(%s_%s)%s", command:sub(1, p - 1), target:name(), sourcekind:upper(), command:sub(e + 1)) end - -- replace shellname to $(XX) - p, e = command:find(shellname, 1, true) + -- replace program to $(XX) + p, e = command:find(program, 1, true) if p then command = format("%s$(%s)%s", command:sub(1, p - 1), sourcekind:upper(), command:sub(e + 1)) end @@ -248,10 +248,10 @@ function _make_target(makefile, target) makefile:print("") -- get linker kind - local linkerkind = target:linker():get("kind") + local linkerkind = target:linker():kind() - -- get shellname - local shellname = tool.shellname(linkerkind) + -- get program + local program = platform.tool(linkerkind) -- get command local command = target:linkcmd() @@ -262,8 +262,8 @@ function _make_target(makefile, target) command = format("%s$(%s_%s)%s", command:sub(1, p - 1), target:name(), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) end - -- replace shellname to $(XX) - p, e = command:find(shellname, 1, true) + -- replace program to $(XX) + p, e = command:find(program, 1, true) if p then command = format("%s$(%s)%s", command:sub(1, p - 1), (linkerkind:upper():gsub('%-', '_')), command:sub(e + 1)) end @@ -322,9 +322,9 @@ function _make_all(makefile) -- make variables for source kinds for sourcekind, _ in pairs(language.sourcekinds()) do - local shellname = tool.shellname(sourcekind) - if shellname and shellname ~= "" then - makefile:print("%s=%s", sourcekind:upper(), shellname) + local program = platform.tool(sourcekind) + if program and program ~= "" then + makefile:print("%s=%s", sourcekind:upper(), program) end end makefile:print("") @@ -335,9 +335,9 @@ function _make_all(makefile) table.join2(linkerkinds, _linkerkinds) end for _, linkerkind in ipairs(table.unique(linkerkinds)) do - local shellname = tool.shellname(linkerkind) - if shellname and shellname ~= "" then - makefile:print("%s=%s", (linkerkind:upper():gsub('%-', '_')), shellname) + local program = platform.tool(linkerkind) + if program and program ~= "" then + makefile:print("%s=%s", (linkerkind:upper():gsub('%-', '_')), program) end end makefile:print("") @@ -346,9 +346,9 @@ function _make_all(makefile) for targetname, target in pairs(project.targets()) do if not target:isphony() then for sourcekind, sourcebatch in pairs(target:sourcebatches()) do - makefile:print("%s_%s=%s", targetname, sourcekind:upper(), compiler.compflags(sourcebatch.sourcefiles, target, sourcekind)) + makefile:print("%s_%s=%s", targetname, sourcekind:upper(), compiler.compflags(sourcebatch.sourcefiles, {target = target, sourcekind = sourcekind})) end - makefile:print("%s_%s=%s", targetname, target:linker():get("kind"):upper(), target:linkflags()) + makefile:print("%s_%s=%s", targetname, target:linker():kind():upper(), target:linkflags()) end end makefile:print("") diff --git a/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua b/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua index 094b7a166..3fe67bf45 100644 --- a/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs200x_vcproj.lua @@ -32,7 +32,7 @@ import("vsfile") function _make_compflags(sourcefile, target, vcprojdir) -- make the compiling flags - local _, compflags = compiler.compflags(sourcefile, target) + local _, compflags = compiler.compflags(sourcefile, {target = target}) -- replace -Idir or /Idir, -Fdsymbol.pdb or /Fdsymbol.pdb local flags = {} @@ -74,7 +74,7 @@ end function _make_linkflags(target, vcprojdir) -- make the linking flags - local _, linkflags = linker.linkflags(target) + local _, linkflags = linker.linkflags(target:get("kind"), target:sourcekinds(), {target = target}) -- replace -libpath:dir or /libpath:dir, -pdb:symbol.pdb or /pdb:symbol.pdb local flags = {} diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 29b004030..566c45470 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -32,6 +32,7 @@ import("core.tool.linker") import("vs201x_solution") import("vs201x_vcxproj") import("vs201x_vcxproj_filters") +import("actions.config.configheader", {rootdir = os.programdir()}) -- make target info function _make_targetinfo(mode, arch, target) @@ -39,30 +40,93 @@ function _make_targetinfo(mode, arch, target) -- init target info local targetinfo = { mode = mode, arch = ifelse(arch == "x86", "Win32", "x64") } + -- get sdk version + local vcvarsall = config.get("__vcvarsall") + if vcvarsall then + targetinfo.sdkver = (vcvarsall[arch] or {}).sdkver + end + -- save symbols targetinfo.symbols = target:get("symbols") -- save target kind targetinfo.targetkind = target:targetkind() + -- save target file + targetinfo.targetfile = target:targetfile() + + -- save symbol file + targetinfo.symbolfile = target:symbolfile() + -- save sourcebatches targetinfo.sourcebatches = target:sourcebatches() -- save compiler flags targetinfo.compflags = {} for _, sourcefile in ipairs(target:sourcefiles()) do - local _, compflags = compiler.compflags(sourcefile, target) + local _, compflags = compiler.compflags(sourcefile, {target = target}) targetinfo.compflags[sourcefile] = compflags end -- save linker flags - local _, linkflags = linker.linkflags(target) + local _, linkflags = linker.linkflags(target:get("kind"), target:sourcekinds(), {target = target}) targetinfo.linkflags = linkflags -- ok return targetinfo end +-- make target headers +function _make_targetheaders(mode, arch, target, last) + + -- only for static and shared target + local kind = target:get("kind") + if kind == "static" or kind == "shared" then + + -- make headers + local srcheaders, dstheaders = target:headerfiles() + if srcheaders and dstheaders then + local i = 1 + for _, srcheader in ipairs(srcheaders) do + local dstheader = dstheaders[i] + if dstheader then + os.cp(srcheader, dstheader) + end + i = i + 1 + end + end + + -- make config header + local configheader_raw = target:configheader() + if configheader_raw and os.isfile(configheader_raw) then + + -- init the config header path for each mode and arch + local configheader_mode_arch = path.join(path.directory(configheader_raw), mode .. "." .. arch .. "." .. path.filename(configheader_raw)) + + -- init the temporary config header path + local configheader_tmp = path.join(path.directory(configheader_raw), "tmp." .. path.filename(configheader_raw)) + + -- copy the original config header first + os.cp(configheader_raw, configheader_mode_arch) + + -- append the current config header + local file = io.open(configheader_tmp, "a+") + if file then + file:print("") + file:print("#if defined(__config_%s__) && defined(__config_%s__)", mode, arch) + file:print("# include \"%s.%s.%s\"", mode, arch, path.filename(configheader_raw)) + file:print("#endif") + file:close() + end + + -- override the raw config header at last + if last and os.isfile(configheader_tmp) then + os.mv(configheader_tmp, configheader_raw) + end + end + end +end + -- make vstudio project function make(outputdir, vsinfo) @@ -88,8 +152,11 @@ function make(outputdir, vsinfo) -- load targets local targets = {} - for _, mode in ipairs(vsinfo.modes) do - for _, arch in ipairs({"x86", "x64"}) do + for mode_idx, mode in ipairs(vsinfo.modes) do + for arch_idx, arch in ipairs({"x86", "x64"}) do + + -- trace + print("checking for the %s.%s ...", mode, arch) -- reload config, project and platform if mode ~= config.mode() or arch ~= config.arch() then @@ -106,6 +173,9 @@ function make(outputdir, vsinfo) -- reload project project.load() + + -- remake configheader + configheader.make() end -- ensure to enter project directory @@ -129,6 +199,9 @@ function make(outputdir, vsinfo) -- save all sourcefiles and headerfiles _target.sourcefiles = table.unique(table.join(_target.sourcefiles or {}, (target:sourcefiles()))) _target.headerfiles = table.unique(table.join(_target.headerfiles or {}, (target:headerfiles()))) + + -- make target headers + _make_targetheaders(mode, arch, target, mode_idx == #vsinfo.modes and arch_idx == 2) end end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index 320c4813c..2972e5562 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -55,6 +55,10 @@ function _make_compflags(sourcefile, targetinfo, vcxprojdir) table.insert(flags, flag) end + -- add -D__config_$(mode)__ and -D__config_$(arch)__ for the config header + table.insert(flags, "-D__config_" .. targetinfo.mode .. "__") + table.insert(flags, "-D__config_" .. targetinfo.arch .. "__") + -- ok? return flags end @@ -62,7 +66,7 @@ end -- make linking flags function _make_linkflags(targetinfo, vcxprojdir) - -- replace -libpath:dir or /libpath:dir, -pdb:symbol.pdb or /pdb:symbol.pdb + -- replace -libpath:dir or /libpath:dir local flags = {} for _, flag in ipairs(targetinfo.linkflags) do @@ -75,15 +79,6 @@ function _make_linkflags(targetinfo, vcxprojdir) return "/libpath:" .. dir end) - -- replace -pdb:symbol.pdb or /pdb:symbol.pdb - flag = flag:gsub("[%-|/]pdb:(.*)", function (dir) - dir = dir:trim() - if not path.is_absolute(dir) then - dir = path.relative(path.absolute(dir), vcxprojdir) - end - return "/pdb:" .. dir - end) - -- save flag table.insert(flags, flag) end @@ -142,13 +137,22 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) , vs2017 = "141" } - -- the sdk version + -- the default sdk version local sdk_versions = { vs2015 = "10.0.10240.0" , vs2017 = "10.0.14393.0" } + -- get sdk version + local sdkver = nil + for _, targetinfo in ipairs(target.info) do + sdkver = targetinfo.sdkver + if sdkver then + break + end + end + -- make ProjectConfigurations vcxprojfile:enter("<ItemGroup Label=\"ProjectConfigurations\">") for _, targetinfo in ipairs(target.info) do @@ -164,7 +168,7 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) vcxprojfile:print("<ProjectGuid>{%s}</ProjectGuid>", os.uuid(targetname)) vcxprojfile:print("<RootNamespace>%s</RootNamespace>", targetname) if vsinfo.vstudio_version >= "2015" then - vcxprojfile:print("<WindowsTargetPlatformVersion>%s</WindowsTargetPlatformVersion>", sdk_versions["vs" .. vsinfo.vstudio_version]) + vcxprojfile:print("<WindowsTargetPlatformVersion>%s</WindowsTargetPlatformVersion>", sdkver or sdk_versions["vs" .. vsinfo.vstudio_version]) end vcxprojfile:leave("</PropertyGroup>") @@ -202,6 +206,10 @@ function _make_configurations(vcxprojfile, vsinfo, target, vcxprojdir) vcxprojfile:enter("<PropertyGroup Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">", targetinfo.mode, targetinfo.arch) vcxprojfile:print("<OutDir>%s\\</OutDir>", path.relative(path.absolute(config.get("buildir")), vcxprojdir)) vcxprojfile:print("<IntDir>%$(Configuration)\\</IntDir>") + vcxprojfile:print("<TargetName>%s</TargetName>", path.basename(targetinfo.targetfile)) + vcxprojfile:print("<TargetExt>%s</TargetExt>", path.extension(targetinfo.targetfile)) + vcxprojfile:print("<TargetPath>%s</TargetPath>", path.relative(path.absolute(targetinfo.targetfile), vcxprojdir)) + if target.kind == "binary" then vcxprojfile:print("<LinkIncremental>true</LinkIncremental>") end @@ -298,17 +306,36 @@ function _make_common_item(vcxprojfile, vsinfo, targetinfo, vcxprojdir) -- enter ItemDefinitionGroup vcxprojfile:enter("<ItemDefinitionGroup Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">", targetinfo.mode, targetinfo.arch) + -- init the linker kinds + local linkerkinds = + { + binary = "Link" + , static = "Lib" + , shared = "Link" + } + -- for linker? - if targetinfo.targetkind == "binary" then - vcxprojfile:enter("<Link>") + vcxprojfile:enter("<%s>", linkerkinds[targetinfo.targetkind]) - -- make linker flags - local flags = table.concat(_make_linkflags(targetinfo, vcxprojdir), " "):trim() + -- make linker flags + local flags = table.concat(_make_linkflags(targetinfo, vcxprojdir), " "):trim() - -- make AdditionalOptions - vcxprojfile:print("<AdditionalOptions>%s %%(AdditionalOptions)</AdditionalOptions>", flags) + -- remove "-machine:[x86|x64]" + flags = flags:gsub("[%-/]machine:%w+", "") + + -- remove "-pdb:*.pdb" + flags = flags:gsub("[%-/]pdb:.+%.pdb", "") - -- generate debug infomation? + -- remove "-debug" + flags = flags:gsub("[%-/]debug", "") + + -- make AdditionalOptions + vcxprojfile:print("<AdditionalOptions>%s %%(AdditionalOptions)</AdditionalOptions>", flags) + + -- generate debug infomation? + if linkerkinds[targetinfo.targetkind] == "Link" then + + -- enable debug infomation? local debug = false for _, symbol in ipairs(targetinfo.symbols) do if symbol == "debug" then @@ -318,14 +345,25 @@ function _make_common_item(vcxprojfile, vsinfo, targetinfo, vcxprojdir) end vcxprojfile:print("<GenerateDebugInformation>%s</GenerateDebugInformation>", tostring(debug)) - -- make SubSystem + -- make *.pdb file path + local symbolfile = targetinfo.symbolfile + if symbolfile then + vcxprojfile:print("<ProgramDatabaseFile>%s</ProgramDatabaseFile>", path.relative(path.absolute(symbolfile), vcxprojdir)) + end + end + + -- make SubSystem + if targetinfo.targetkind == "binary" then vcxprojfile:print("<SubSystem>Console</SubSystem>") - - -- make TargetMachine - vcxprojfile:print("<TargetMachine>%s</TargetMachine>", ifelse(targetinfo.arch == "x64", "MachineX64", "MachineX86")) + end + + -- make TargetMachine + vcxprojfile:print("<TargetMachine>%s</TargetMachine>", ifelse(targetinfo.arch == "x64", "MachineX64", "MachineX86")) - vcxprojfile:leave("</Link>") - end + -- make OutputFile + vcxprojfile:print("<OutputFile>%s</OutputFile>", path.relative(path.absolute(targetinfo.targetfile), vcxprojdir)) + + vcxprojfile:leave("</%s>", linkerkinds[targetinfo.targetkind]) -- for compiler? vcxprojfile:enter("<ClCompile>") @@ -333,8 +371,11 @@ function _make_common_item(vcxprojfile, vsinfo, targetinfo, vcxprojdir) -- make source options _make_source_options(vcxprojfile, targetinfo.commonflags) - -- make ProgramDataBaseFileName (default: empty) - vcxprojfile:print("<ProgramDataBaseFileName></ProgramDataBaseFileName>") + -- make *.pdb file path + local symbolfile = targetinfo.symbolfile + if symbolfile then + vcxprojfile:print("<ProgramDatabaseFile>%s</ProgramDatabaseFile>", path.relative(path.absolute(symbolfile), vcxprojdir)) + end vcxprojfile:leave("</ClCompile>") diff --git a/xmake/tools/utils/gas-preprocessor.pl b/xmake/scripts/gas-preprocessor.pl index 98dfe4ad9..7e0857a66 100755 --- a/xmake/tools/utils/gas-preprocessor.pl +++ b/xmake/scripts/gas-preprocessor.pl @@ -86,7 +86,7 @@ if (grep /\.c$/, @gcc_cmd) { } elsif (grep /\.[sS]$/, @gcc_cmd) { # asm file, just do C preprocessor @preprocess_c_cmd = (@gcc_cmd, "-E"); -} elsif (grep /-(v|-version|dumpversion)/, @gcc_cmd) { +} elsif (grep /-(v|-help|-version|dumpversion)/, @gcc_cmd) { # pass -v/--version along, used during probing. Matching '-v' might have # uninteded results but it doesn't matter much if gas-preprocessor or # the compiler fails. |
