diff options
| author | ruki <[email protected]> | 2020-06-23 22:37:44 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-06-23 22:37:44 +0800 |
| commit | c18d15eb89116a0f3ce96bd56f3ccf861849f6ec (patch) | |
| tree | 52b63db3274349f9a41872414208c7c30058cfd7 | |
| parent | 53df324acd9c7432336a5894ceef578daa1ce38d (diff) | |
| parent | 18bded45c229f5580c13fc8b4afc5edb6f18819a (diff) | |
Merge pull request #857 from xmake-io/toolchain
Improve toolchain to support host and cross toolchains at same time
104 files changed, 1173 insertions, 444 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a326bd965..8e9c9e954 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## master (unreleased) +### New features + +* Add `xmake show -l envs` to show all builtin envirnoment variables +* [#861](https://github.com/xmake-io/xmake/issues/861): Support search local package file to install remote package +* [#854](https://github.com/xmake-io/xmake/issues/854): Support global proxy settings for curl, wget and git + ### Change * [#828](https://github.com/xmake-io/xmake/issues/828): Support to import sub-directory files for protobuf rules @@ -9,6 +15,8 @@ * [#828](https://github.com/xmake-io/xmake/issues/828): Support multi-level directories for protobuf/import * [#838](https://github.com/xmake-io/xmake/issues/838#issuecomment-643570920): Support to override builtin-rules for `add_files("src/*.c", {rules = {"xx", override = true}})` * [#847](https://github.com/xmake-io/xmake/issues/847): Support to parse include deps for rc file +* Improve msvc tool chain, remove the dependence of global environment variables +* [#857](https://github.com/xmake-io/xmake/pull/857): Improved `set_toolchains()` when cross-compilation is supported, specific target can be switched to host toolchain and compiled at the same time ### Bugs fixed @@ -761,6 +769,12 @@ ## master (开发中) +### 新特性 + +* 添加`xmake show -l envs`去显示xmake内置的环境变量列表 +* [#861](https://github.com/xmake-io/xmake/issues/861): 支持从指定目录搜索本地包去直接安装远程依赖包 +* [#854](https://github.com/xmake-io/xmake/issues/854): 针对wget, curl和git支持全局代理设置 + ### 改进 * [#828](https://github.com/xmake-io/xmake/issues/828): 针对protobuf规则增加导入子目录proto文件支持 @@ -768,6 +782,8 @@ * [#828](https://github.com/xmake-io/xmake/issues/828): protobuf规则支持import多级子目录 * [#838](https://github.com/xmake-io/xmake/issues/838#issuecomment-643570920): 支持完全重写内置的构建规则,`add_files("src/*.c", {rules = {"xx", override = true}})` * [#847](https://github.com/xmake-io/xmake/issues/847): 支持rc文件的头文件依赖解析 +* 改进msvc工具链,去除全局环境变量的依赖 +* [#857](https://github.com/xmake-io/xmake/pull/857): 改进`set_toolchains()`支持交叉编译的时候,特定target可以切换到host工具链同时编译 ### Bugs修复 diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox -Subproject 015ae373ddefaad1762567575034aa3ca9d459b +Subproject 3c88337d6c4a80a3890a9a92f8d84cba4d2878f diff --git a/tests/modules/math/test.lua b/tests/modules/math/test.lua index 3d05adb61..bcbd11fd3 100644 --- a/tests/modules/math/test.lua +++ b/tests/modules/math/test.lua @@ -4,8 +4,8 @@ function test_isinf(t) t:require_not(math.isinf(0)) t:require_not(math.isinf(math.nan)) - t:are_same(math.isinf(math.huge), 1) - t:are_same(math.isinf(-math.huge), -1) + t:are_same(math.isinf(math.inf), 1) + t:are_same(math.isinf(-math.inf), -1) end function test_isnan(t) diff --git a/tests/plugins/project/test.lua b/tests/plugins/project/test.lua index e3295d68d..5cc1e7e0e 100644 --- a/tests/plugins/project/test.lua +++ b/tests/plugins/project/test.lua @@ -1,7 +1,7 @@ -import("detect.sdks.find_vstudio") import("core.project.config") import("core.platform.platform") -import("core.platform.environment") +import("core.tool.toolchain") +import("lib.detect.find_tool") function test_vsxmake(t) @@ -34,9 +34,9 @@ function test_vsxmake(t) try { function () - environment.enter("toolchains") - os.exec("msbuild /P:XmakeDiagnosis=true /P:XmakeVerbose=true") - environment.leave("toolchains") + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.execv(msbuild.program, {"/P:XmakeDiagnosis=true", "/P:XmakeVerbose=true"}, {envs = runenvs}) end, catch { diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index ae68fd1a3..9dbd93a8f 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -22,7 +22,6 @@ import("core.base.option") import("core.project.config") import("core.project.project") -import("core.platform.environment") import("private.async.jobpool") import("private.async.runjobs") import("core.base.hashset") @@ -219,14 +218,12 @@ function main(targetname) -- build all jobs local batchjobs = get_batchjobs(targetname) if batchjobs and batchjobs:size() > 0 then - environment.enter("toolchains") runjobs("build", batchjobs, {comax = option.get("jobs") or 1, on_exit = function (errors) import("private.utils.progress") if errors and progress.showing_without_scroll() then print("") end end}) - environment.leave("toolchains") end end diff --git a/xmake/actions/build/build_files.lua b/xmake/actions/build/build_files.lua index 76bf64f4c..3bd4804df 100644 --- a/xmake/actions/build/build_files.lua +++ b/xmake/actions/build/build_files.lua @@ -23,7 +23,6 @@ import("core.base.option") import("core.base.hashset") import("core.project.config") import("core.project.project") -import("core.platform.environment") import("private.async.jobpool") import("private.async.runjobs") import("kinds.object") @@ -206,9 +205,7 @@ function main(targetname, sourcefiles) -- build all jobs local batchjobs = _get_batchjobs(targetname, filepatterns) if batchjobs and batchjobs:size() > 0 then - environment.enter("toolchains") runjobs("build_files", batchjobs, {comax = option.get("jobs") or 1}) - environment.leave("toolchains") end end diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua index d1c39911d..2ce139f54 100644 --- a/xmake/actions/build/main.lua +++ b/xmake/actions/build/main.lua @@ -73,9 +73,7 @@ function _try_build() if not trybuild then task.run("config", {target = targetname, trybuild = trybuild_detected}) end - environment.enter("toolchains") tool.build() - environment.leave("toolchains") return true end end diff --git a/xmake/actions/clean/main.lua b/xmake/actions/clean/main.lua index 02f0d804a..359ed0a25 100644 --- a/xmake/actions/clean/main.lua +++ b/xmake/actions/clean/main.lua @@ -226,9 +226,7 @@ function _try_clean() -- try cleaning it if configfile and tool and trybuild then - environment.enter("toolchains") tool.clean() - environment.leave("toolchains") end end diff --git a/xmake/actions/config/main.lua b/xmake/actions/config/main.lua index f6b9e4b5b..5af867f5a 100644 --- a/xmake/actions/config/main.lua +++ b/xmake/actions/config/main.lua @@ -85,6 +85,14 @@ function _need_check(changed) end end + -- xmake has been updated? force to check config again + -- we need clean the dirty config cache of the old version + if not changed then + if os.mtime(path.join(os.programdir(), "core", "main.lua")) > os.mtime(config.filepath()) then + changed = true + end + end + -- update mtimes configcache:set("mtimes", mtimes) @@ -241,7 +249,9 @@ force to build in current directory via run `xmake -P .`]], os.projectdir()) config.check() -- check project options - project.check() + if not trybuild then + project.check() + end end -- load platform diff --git a/xmake/actions/config/xmake.lua b/xmake/actions/config/xmake.lua index 28c6ebb50..c53844e5c 100644 --- a/xmake/actions/config/xmake.lua +++ b/xmake/actions/config/xmake.lua @@ -43,14 +43,6 @@ task("config") { {'c', "clean", "k", nil , "Clean the cached configure and configure all again." } , {nil, "menu", "k", nil , "Configure project with a menu-driven user interface." } - , {nil, "require", "kv", nil , "Require all dependent packages?" - , values = function (complete) - if complete then - return {"yes", "no"} - else - return {"y: force to enable", "n: disable" } - end - end } , {category = "."} , {'p', "plat", "kv", "$(subhost)" , "Compile for the given platform." , values = function (complete, opt) @@ -128,6 +120,20 @@ task("config") , values = {"static", "shared", "binary"} } , {nil, "host", "kv", "$(host)" , "The Current Host Environment." } + -- package configuration + , {category = "Package Configuration"} + , {nil, "require", "kv", nil , "Require all dependent packages?" + , values = function (complete) + if complete then + return {"yes", "no"} + else + return {"y: force to enable", "n: disable" } + end + end } + , {nil, "pkg_searchdirs", "kv", nil , "The search directories of the remote package." + , " e.g." + , " - xmake f --pkg_searchdirs=/dir1" .. path.envsep() .. "/dir2"} + -- show project menu options , function () diff --git a/xmake/actions/global/xmake.lua b/xmake/actions/global/xmake.lua index f294d2804..c70571dd2 100644 --- a/xmake/actions/global/xmake.lua +++ b/xmake/actions/global/xmake.lua @@ -41,15 +41,33 @@ task("global") -- options , options = { - {'c', "clean", "k" , nil , "Clean the cached configure and configure all again." } - , {nil, "menu", "k" , nil , "Configure with a menu-driven user interface." } - + {'c', "clean", "k" , nil , "Clean the cached configure and configure all again." } + , {nil, "menu", "k" , nil , "Configure with a menu-driven user interface." } , {category = "."} - , {nil, "theme", "kv", "default" , "The theme name." - , values = function () + , {nil, "theme", "kv", "default" , "The theme name." + , values = function () return import("core.theme.theme.names")() - end } - , {nil, "debugger", "kv", "auto" , "The Debugger Program Path." } + end} + , {nil, "debugger", "kv", "auto" , "The debugger program path." } + + -- proxy configuration + , {category = "Proxy Configuration"} + , {'x', "proxy", "kv", nil , "Use proxy on given port. [protocol://]host[:port]" + , " e.g." + , " - xmake g --proxy='http://host:port'" + , " - xmake g --proxy='https://host:port'" + , " - xmake g --proxy='socks5://host:port'" } + , {nil, "proxy_hosts", "kv", nil , "Only enable proxy for the given hosts list, it will enable all if be unset," + , "and we can pass match pattern to list:" + , " e.g." + , " - xmake g --proxy_hosts='github.com,gitlab.*,*.xmake.io'"} + + -- package configuration + , {category = "Package Configuration"} + , {nil, "pkg_searchdirs", "kv", nil , "The search directories of the remote package." + , " e.g." + , " - xmake g --pkg_searchdirs=/dir1" .. path.envsep() .. "/dir2"} + , {nil, "pkg_installdir", "kv", nil , "The install root directory of the remote package." } -- show platform menu options , {category = "Platform Configuration"} diff --git a/xmake/actions/require/impl/action/download.lua b/xmake/actions/require/impl/action/download.lua index b09e77011..cb973ba3b 100644 --- a/xmake/actions/require/impl/action/download.lua +++ b/xmake/actions/require/impl/action/download.lua @@ -21,6 +21,11 @@ -- imports import("core.base.option") import("core.base.tty") +import("core.base.hashset") +import("core.project.config") +import("core.package.package", {alias = "core_package"}) +import("lib.detect.find_file") +import("lib.detect.find_directory") import(".utils.filter") import("net.http") import("devel.git") @@ -40,6 +45,14 @@ function _checkout(package, url, sourcedir, url_alias) return end + -- we can use local package from the search directories directly if network is too slow + local localdir = find_directory(package:name() .. archive.extension(url), core_package.searchdirs()) + if localdir and os.isdir(localdir) then + git.clean({repodir = localdir, force = true}) + tty.erase_line_to_start().cr() + return + end + -- remove temporary directory os.rm(sourcedir .. ".tmp") @@ -90,8 +103,12 @@ function _download(package, url, sourcedir, url_alias, url_excludes) os.tryrm(packagefile) -- download or copy package file + local localfile = find_file(path.filename(packagefile), core_package.searchdirs()) if os.isfile(url) then os.cp(url, packagefile) + elseif localfile and os.isfile(localfile) then + -- we can use local package from the search directories directly if network is too slow + os.cp(localfile, packagefile) else http.download(url, packagefile) end @@ -164,6 +181,7 @@ function main(package) -- download package from urls local ok = false + local urls_failed = {} for idx, url in ipairs(urls) do -- get url alias @@ -207,9 +225,26 @@ function main(package) else cprint("${yellow} => ${clear}download %s .. ${color.failure}${text.failure}", url) end + table.insert(urls_failed, url) -- failed? break it if idx == #urls and not package:optional() then + if #urls_failed > 0 then + print("") + print("we can also download these packages manually:") + local searchnames = hashset.new() + for _, url_failed in ipairs(urls_failed) do + cprint(" ${yellow}- %s", url_failed) + if git.checkurl(url_failed) then + searchnames:insert(package:name() .. archive.extension(url_failed)) + else + searchnames:insert(package:name() .. "-" .. package:version_str() .. archive.extension(url_failed)) + end + end + cprint("to the local search directories: ${bright}%s", table.concat(table.wrap(core_package.searchdirs()), path.envsep())) + cprint(" ${bright}- %s", table.concat(searchnames:to_array(), ", ")) + cprint("and we can run `xmake g --pkg_searchdirs=/xxx` to set the search directories.") + end raise("download failed!") end end diff --git a/xmake/actions/require/impl/action/download_resources.lua b/xmake/actions/require/impl/action/download_resources.lua index 7371f270f..df560b3d3 100644 --- a/xmake/actions/require/impl/action/download_resources.lua +++ b/xmake/actions/require/impl/action/download_resources.lua @@ -20,6 +20,8 @@ -- imports import("core.base.option") +import("core.package.package", {alias = "core_package"}) +import("lib.detect.find_file") import("net.http") import("utils.archive") @@ -42,8 +44,12 @@ function _download(package, resource_name, resource_url, resource_hash) -- attempt to remove the previous file first os.tryrm(resource_file) - -- download the resource file - if resource_url:find(string.ipattern("https-://")) or resource_url:find(string.ipattern("ftps-://")) then + -- download or copy the resource file + local localfile = find_file(path.filename(resource_file), core_package.searchdirs()) + if localfile and os.isfile(localfile) then + -- we can use local resource from the search directories directly if network is too slow + os.cp(localfile, resource_file) + elseif resource_url:find(string.ipattern("https-://")) or resource_url:find(string.ipattern("ftps-://")) then http.download(resource_url, resource_file) else raise("invalid resource url(%s)", resource_url) @@ -70,7 +76,6 @@ end -- download all resources of the given package function main(package) - -- no resources? local resources = package:resources() if not resources then diff --git a/xmake/actions/require/impl/package.lua b/xmake/actions/require/impl/package.lua index 9bc25e3a4..c0f7f7d0e 100644 --- a/xmake/actions/require/impl/package.lua +++ b/xmake/actions/require/impl/package.lua @@ -139,6 +139,7 @@ function _parse_require(require_str, requires_extra, parentinfo) version = version, plat = require_extra.plat, -- require package in the given platform arch = require_extra.arch, -- require package in the given architecture + kind = require_extra.kind, -- default: library, set package kind, e.g. binary, library, we can set `kind = "binary"` to only detect binary program and ignore library. alias = require_extra.alias, -- set package alias name group = require_extra.group, -- only uses the first package in same group system = require_extra.system, -- default: true, we can set it to disable system package manually diff --git a/xmake/actions/require/info.lua b/xmake/actions/require/info.lua index c6b3f6995..f0a7ba939 100644 --- a/xmake/actions/require/info.lua +++ b/xmake/actions/require/info.lua @@ -21,7 +21,11 @@ -- imports import("core.base.task") import("core.base.option") +import("core.base.hashset") import("core.project.project") +import("core.package.package", {alias = "core_package"}) +import("devel.git") +import("utils.archive") import("impl.utils.filter") import("impl.package") import("impl.repository") @@ -133,6 +137,18 @@ function main(requires_raw) -- show install directory cprint(" -> ${magenta}installdir${clear}: %s", instance:installdir()) + -- show search directories and search names + cprint(" -> ${magenta}searchdirs${clear}: %s", table.concat(table.wrap(core_package.searchdirs()), path.envsep())) + local searchnames = hashset.new() + for _, url in ipairs(instance:urls()) do + if git.checkurl(url) then + searchnames:insert(instance:name() .. archive.extension(url)) + else + searchnames:insert(instance:name() .. "-" .. instance:version_str() .. archive.extension(url)) + end + end + cprint(" -> ${magenta}searchnames${clear}: %s", table.concat(searchnames:to_array(), ", ")) + -- show fetch info cprint(" -> ${magenta}fetchinfo${clear}: %s", _info(instance)) local fetchinfo = instance:fetch() diff --git a/xmake/core/base/math.lua b/xmake/core/base/math.lua index 2cd53a21f..c46982328 100644 --- a/xmake/core/base/math.lua +++ b/xmake/core/base/math.lua @@ -24,16 +24,14 @@ local math = math or {} -- init constants math.nan = math.log(-1) math.e = math.exp(1) +math.inf = 1/0 -- @see http://lua-users.org/wiki/InfAndNanComparisons -- check a number is int -- -- @returns true for int, otherwise false -- function math:isint() - - -- check assert(type(self) == "number", "number expacted") - return self == math.floor(self) and self ~= math.huge and self ~= -math.huge end @@ -42,13 +40,10 @@ end -- @returns 1 for inf, -1 for -inf, otherwise false -- function math:isinf() - - -- check assert(type(self) == "number", "number expacted") - - if self == math.huge then + if self == math.inf then return 1 - elseif self == -math.huge then + elseif self == -math.inf then return -1 else return false @@ -60,10 +55,7 @@ end -- @returns true for nan, otherwise false -- function math:isnan() - - -- check assert(type(self) == "number", "number expacted") - return self ~= self end diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 269ed22eb..ed4dbe1a6 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -690,6 +690,10 @@ function os.execv(program, argv, opt) if opt.envs then local envars = os.getenvs() for k, v in pairs(opt.envs) do + -- TODO + if type(v) == "table" then + v = path.joinenv(v) + end envars[k] = v end envs = {} diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index d47f0fc4e..f31abcc6e 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -244,9 +244,16 @@ function _instance:revision(url_alias) return self:sourcehash(url_alias) end --- get the package kind, binary or nil(static, shared) +-- get the package kind, binary or nil(library) function _instance:kind() - return self:get("kind") + local kind = self:get("kind") + if not kind then + local requireinfo = self:requireinfo() + if requireinfo then + kind = requireinfo.kind + end + end + return kind end -- get the filelock of the whole package directory @@ -1156,7 +1163,15 @@ end -- the install directory function package.installdir() - return path.join(global.directory(), "packages") + return global.get("pkg_installdir") or path.join(global.directory(), "packages") +end + +-- the search directories +function package.searchdirs() + local searchdirs = global.get("pkg_searchdirs") + if searchdirs then + return path.splitenv(searchdirs) + end end -- load the package from the system directories diff --git a/xmake/core/package/repository.lua b/xmake/core/package/repository.lua index 2b3e5a7b5..2b72123b8 100644 --- a/xmake/core/package/repository.lua +++ b/xmake/core/package/repository.lua @@ -185,6 +185,11 @@ end -- load the repository function repository.load(name, url, branch, is_global) + -- check url + if not url then + return nil, string.format("invalid repo(%s): url not found!", name) + end + -- get it directly from cache first repository._REPOS = repository._REPOS or {} if repository._REPOS[name] then diff --git a/xmake/core/platform/environment.lua b/xmake/core/platform/environment.lua index d3ff0a0fd..888fe2148 100644 --- a/xmake/core/platform/environment.lua +++ b/xmake/core/platform/environment.lua @@ -45,14 +45,6 @@ function environment._enter_toolchains() if os.host() == "windows" then os.addenv("PATH", path.join(os.programdir(), "winenv", "bin")) end - - -- add the runenvs of toolchains - for name, values in pairs(platform:runenvs()) do - if not oldenvs[name] then - oldenvs[name] = os.getenv(name) - end - os.addenv(name, table.unpack(table.wrap(values))) - end environment._OLDENVS_TOOLCHAINS = oldenvs return true end diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua index e9a66d0dc..5f75a7588 100644 --- a/xmake/core/platform/platform.lua +++ b/xmake/core/platform/platform.lua @@ -34,9 +34,10 @@ local config = require("project/config") local global = require("base/global") -- new an instance -function _instance.new(name, info) +function _instance.new(name, arch, info) local instance = table.inherit(_instance) instance._NAME = name + instance._ARCH = arch instance._INFO = info return instance end @@ -46,6 +47,11 @@ function _instance:name() return self._NAME end +-- get platform architecture +function _instance:arch() + return self._ARCH or config.get("arch") +end + -- set the value to the platform configuration function _instance:set(name, ...) self._INFO:apival_set(name, ...) @@ -129,13 +135,13 @@ function _instance:toolchains(opt) local names = nil toolchains = {} if not (opt and opt.all) then - names = config.get("__toolchains") + names = config.get("__toolchains_" .. self:name() .. "_" .. self:arch()) end if not names then -- get the given toolchain local toolchain_given = config.get("toolchain") if toolchain_given then - local toolchain_inst, errors = toolchain.load(toolchain_given) + local toolchain_inst, errors = toolchain.load(toolchain_given, {plat = self:name(), arch = self:arch()}) -- attempt to load toolchain from project if not toolchain_inst and platform._project() then toolchain_inst = platform._project().toolchain(toolchain_given) @@ -154,7 +160,7 @@ function _instance:toolchains(opt) end if names then for _, name in ipairs(names) do - local toolchain_inst, errors = toolchain.load(name) + local toolchain_inst, errors = toolchain.load(name, {plat = self:name(), arch = self:arch()}) -- attempt to load toolchain from project if not toolchain_inst and platform._project() then toolchain_inst = platform._project().toolchain(name) @@ -181,7 +187,7 @@ function _instance:tool(toolkind) end -- get tool program - local program, toolname + local program, toolname, toolchain_info local toolinfo = tools[toolkind] if toolinfo == nil then toolinfo = {} @@ -189,17 +195,20 @@ function _instance:tool(toolkind) for idx, toolchain_inst in ipairs(toolchains) do program, toolname = toolchain_inst:tool(toolkind) if program then + toolchain_info = {name = toolchain_inst:name(), plat = toolchain_inst:plat(), arch = toolchain_inst:arch()} toolinfo[1] = program toolinfo[2] = toolname + toolinfo[3] = toolchain_info break end end tools[toolkind] = toolinfo else - program = toolinfo[1] - toolname = toolinfo[2] + program = toolinfo[1] + toolname = toolinfo[2] + toolchain_info = toolinfo[3] end - return program, toolname + return program, toolname, toolchain_info end -- get tool configuration from the toolchains @@ -291,7 +300,7 @@ function _instance:check() end -- save valid toolchains - config.set("__toolchains", toolchains_valid) + config.set("__toolchains_" .. self:name() .. "_" .. self:arch(), toolchains_valid) return true end @@ -415,16 +424,14 @@ function platform.add_directories(...) end -- load the given platform -function platform.load(plat) +function platform.load(plat, arch) -- get platform name plat = plat or config.get("plat") or os.host() - if not plat then - return nil, string.format("unknown platform!") - end + arch = arch or config.get("arch") or os.arch() -- get cache key - local cachekey = plat .. "_" .. (config.get("arch") or os.arch()) + local cachekey = plat .. "_" .. arch -- get it directly from cache dirst platform._PLATFORMS = platform._PLATFORMS or {} @@ -479,14 +486,14 @@ function platform.load(plat) end -- save instance to the cache - local instance = _instance.new(plat, result) + local instance = _instance.new(plat, arch, result) platform._PLATFORMS[cachekey] = instance return instance end -- get the given platform configuration -function platform.get(name, plat) - local instance, errors = platform.load(plat) +function platform.get(name, plat, arch) + local instance, errors = platform.load(plat, arch) if instance then return instance:get(name) else @@ -498,24 +505,29 @@ end -- -- e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. -- -function platform.tool(toolkind, plat) +function platform.tool(toolkind, plat, arch) -- attempt to get program from config first - local program = config.get(toolkind) - local toolname = config.get("__toolname_" .. toolkind) + plat = plat or config.get("plat") or os.host() + arch = arch or config.get("arch") or os.arch() + local key = toolkind .. "_" .. plat .. "_" .. arch + local program = config.get(toolkind) or config.get("__tool_" .. key) + local toolname = config.get("__toolname_" .. key) + local toolchain_info = config.get("__toolchain_info_" .. key) if program == nil then -- get the current platform - local instance, errors = platform.load(plat) + local instance, errors = platform.load(plat, arch) if not instance then os.raise(errors) end -- get it from the platform toolchains - program, toolname = instance:tool(toolkind) + program, toolname, toolchain_info = instance:tool(toolkind) if program then - config.set(toolkind, program, {force = true, readonly = true}) - config.set("__toolname_" .. toolkind, toolname) + config.set("__tool_" .. key, program, {force = true, readonly = true}) + config.set("__toolname_" .. key, toolname) + config.set("__toolchain_info_" .. key, toolchain_info) config.save() end end @@ -528,12 +540,12 @@ function platform.tool(toolkind, plat) program = program:sub(pos + 1) end end - return program, toolname + return program, toolname, toolchain_info end -- get the given tool configuration -function platform.toolconfig(name, plat) - local instance, errors = platform.load(plat) +function platform.toolconfig(name, plat, arch) + local instance, errors = platform.load(plat, arch) if instance then return instance:toolconfig(name) else @@ -592,20 +604,20 @@ function platform.toolchains() end -- get the platform os -function platform.os(plat) - return platform.get("os", plat) +function platform.os(plat, arch) + return platform.get("os", plat, arch) end -- get the platform archs -function platform.archs(plat) - return platform.get("archs", plat) +function platform.archs(plat, arch) + return platform.get("archs", plat, arch) end -- get the format of the given target kind for platform -function platform.format(targetkind) +function platform.format(targetkind, plat, arch) -- get platform instance - local instance, errors = platform.load(plat) + local instance, errors = platform.load(plat, arch) if not instance then os.raise(errors) end diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index 96d4256ef..9ec7bc0bf 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -41,7 +41,6 @@ local requireinfo = require("project/requireinfo") local deprecated_project = require("project/deprecated/project") local package = require("package/package") local platform = require("platform/platform") -local environment = require("platform/environment") local toolchain = require("tool/toolchain") local language = require("language/language") local sandbox_os = require("sandbox/modules/os") @@ -433,7 +432,7 @@ function project._load_targets() if toolchains then t._TOOLCHAINS = {} for _, name in ipairs(table.wrap(toolchains)) do - local toolchain_inst, errors = toolchain.load(name) + local toolchain_inst, errors = toolchain.load(name, t:extraconf("toolchains", name)) -- attempt to load toolchain from project if not toolchain_inst then toolchain_inst = project.toolchain(name) @@ -446,9 +445,6 @@ function project._load_targets() end end - -- enter toolchains environment - environment.enter("toolchains") - -- do load for each target local ok = false for _, t in pairs(targets) do @@ -458,9 +454,6 @@ function project._load_targets() end end - -- leave toolchains environment - environment.leave("toolchains") - -- do load failed? if not ok then return nil, errors diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index 3df4128c5..14409fec4 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -444,6 +444,29 @@ function _instance:name() return self._NAME end +-- get the platform of this target +function _instance:plat() + return self:get("plat") or config.get("plat") or os.host() +end + +-- get the architecture of this target +function _instance:arch() + return self:get("arch") or config.get("arch") or os.arch() +end + +-- get the platform instance +function _instance:platform() + local platform_inst = self._PLATFORM + if platform_inst == nil then + platform_inst, errors = platform.load(self:plat(), self:arch()) + if not platform_inst then + os.raise(errors) + end + self._PLATFORM = platform_inst + end + return platform_inst +end + -- get the cache key function _instance:cachekey() return string.format("%s_%d", tostring(self), self._CACHEID) @@ -718,13 +741,13 @@ function _instance:objectdir(opt) end -- append plat sub-directory - local plat = config.get("plat") + local plat = self:plat() if plat then objectdir = path.join(objectdir, plat) end -- append arch sub-directory - local arch = config.get("arch") + local arch = self:arch() if arch then objectdir = path.join(objectdir, arch) end @@ -753,13 +776,13 @@ function _instance:dependir(opt) end -- append plat sub-directory - local plat = config.get("plat") + local plat = self:plat() if plat then dependir = path.join(dependir, plat) end -- append arch sub-directory - local arch = config.get("arch") + local arch = self:arch() if arch then dependir = path.join(dependir, arch) end @@ -784,13 +807,13 @@ function _instance:autogendir(opt) end -- append plat sub-directory - local plat = config.get("plat") + local plat = self:plat() if plat then autogendir = path.join(autogendir, plat) end -- append arch sub-directory - local arch = config.get("arch") + local arch = self:arch() if arch then autogendir = path.join(autogendir, arch) end @@ -856,13 +879,13 @@ function _instance:targetdir() targetdir = config.buildir() -- append plat sub-directory - local plat = config.get("plat") + local plat = self:plat() if plat then targetdir = path.join(targetdir, plat) end -- append arch sub-directory - local arch = config.get("arch") + local arch = self:arch() if arch then targetdir = path.join(targetdir, arch) end @@ -893,7 +916,7 @@ function _instance:targetfile() end -- make the target file name and attempt to use the format of linker first - local filename = self:get("filename") or target.filename(self:basename(), targetkind, self:linker():format(targetkind)) + local filename = self:get("filename") or target.filename(self:basename(), targetkind, {plat = self:plat(), arch = self:arch(), format = self:linker():format(targetkind)}) assert(filename) -- make the target file path @@ -908,7 +931,7 @@ function _instance:symbolfile() assert(targetdir and type(targetdir) == "string") -- the symbol file name - local filename = target.filename(self:basename(), "symbol") + local filename = target.filename(self:basename(), "symbol", {plat = self:plat(), arch = self:arch()}) assert(filename) -- make the symbol file path @@ -1075,6 +1098,7 @@ function _instance:sourcefiles() local count = 0 local sourcefiles = {} local sourcefiles_deleted = {} + local sourcefiles_inserted = {} local deleted_count = 0 for _, file in ipairs(table.wrap(files)) do @@ -1110,8 +1134,9 @@ function _instance:sourcefiles() if deleted then deleted_count = deleted_count + 1 sourcefiles_deleted[sourcefile] = true - else + elseif not sourcefiles_inserted[sourcefile] then table.insert(sourcefiles, sourcefile) + sourcefiles_inserted[sourcefile] = true end end end @@ -1133,7 +1158,7 @@ end -- get object file from source file function _instance:objectfile(sourcefile) - return self:autogenfile(sourcefile, {rootdir = self:objectdir(), filename = target.filename(path.filename(sourcefile), "object")}) + return self:autogenfile(sourcefile, {rootdir = self:objectdir(), filename = target.filename(path.filename(sourcefile), "object", {plat = self:plat(), arch = self:arch()})}) end -- get the object files @@ -1497,8 +1522,8 @@ function _instance:script(name, generic) elseif type(script) == "table" then -- get plat and arch - local plat = config.get("plat") or "" - local arch = config.get("arch") or "" + local plat = self:plat() + local arch = self:arch() -- match pattern -- @@ -1672,11 +1697,7 @@ end function _instance:toolchains() local toolchains = self._TOOLCHAINS if toolchains == nil then - local instance, errors = platform.load() - if not instance then - os.raise(errors) - end - toolchains = instance:toolchains() + toolchains = self:platform():toolchains() self._TOOLCHAINS = toolchains end return toolchains @@ -1693,8 +1714,9 @@ function _instance:tool(toolkind) end -- get tool program - local program, toolname - local toolinfo = tools[toolkind] + local key = toolkind .. "_" .. self:plat() .. "_" .. self:arch() + local program, toolname, toolchain_info + local toolinfo = tools[key] if toolinfo == nil then toolinfo = {} @@ -1707,23 +1729,23 @@ function _instance:tool(toolkind) end end - -- attempt to get program from config first - if not program then - program = config.get(toolkind) - toolname = config.get("__toolname_" .. toolkind) + -- attempt to get program from config first if no the given toolchains in target + if not program and not self:get("toolchains") then + program = config.get(toolkind) or config.get("__tool_" .. key) + toolname = config.get("__toolname_" .. key) + toolchain_info = config.get("__toolchain_info_" .. key) end -- get program from target/toolchains if not program then local toolchains = self:toolchains() - environment.enter("toolchains") for idx, toolchain_inst in ipairs(toolchains) do program, toolname = toolchain_inst:tool(toolkind) if program then + toolchain_info = {name = toolchain_inst:name(), plat = toolchain_inst:plat(), arch = toolchain_inst:arch()} break end end - environment.leave("toolchains") end -- contain toolname? parse it, e.g. '[email protected]' @@ -1738,13 +1760,15 @@ function _instance:tool(toolkind) if program then toolinfo[1] = program toolinfo[2] = toolname + toolinfo[3] = toolchain_info end - tools[toolkind] = toolinfo + tools[key] = toolinfo else program = toolinfo[1] toolname = toolinfo[2] + toolchain_info = toolinfo[3] end - return program, toolname + return program, toolname, toolchain_info end -- get tool configuration from the toolchains @@ -1786,6 +1810,8 @@ function target.apis() { -- target.set_xxx "target.set_kind" + , "target.set_plat" + , "target.set_arch" , "target.set_strip" , "target.set_rules" , "target.set_version" @@ -1882,13 +1908,14 @@ function target.apis() end -- get the filename from the given target name and kind -function target.filename(targetname, targetkind, targetformat) +function target.filename(targetname, targetkind, opt) -- check + opt = opt or {} assert(targetname and targetkind) -- make filename by format - local format = targetformat or platform.format(targetkind) + local format = opt.format or platform.format(targetkind, opt.plat, opt.arch) return format and (format:gsub("%$%(name%)", targetname)) or targetname end @@ -1901,9 +1928,9 @@ function target.linkname(filename) if count == 0 and config.is_plat("mingw") then -- for the mingw platform, it is compatible with the libxxx.a and xxx.lib local formats = {static = "lib$(name).a", shared = "lib$(name).so"} - linkname, count = filename:gsub(target.filename("__pattern__", "static", formats["static"]):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") + linkname, count = filename:gsub(target.filename("__pattern__", "static", {format = formats["static"]}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") if count == 0 then - linkname, count = filename:gsub(target.filename("__pattern__", "shared", formats["shared"]):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") + linkname, count = filename:gsub(target.filename("__pattern__", "shared", {format = formats["shared"]}):gsub("%.", "%%."):gsub("__pattern__", "(.+)") .. "$", "%1") end end return count > 0 and linkname or nil diff --git a/xmake/core/sandbox/modules/import/core/package/package.lua b/xmake/core/sandbox/modules/import/core/package/package.lua index 5d37554da..13bc1a900 100644 --- a/xmake/core/sandbox/modules/import/core/package/package.lua +++ b/xmake/core/sandbox/modules/import/core/package/package.lua @@ -36,6 +36,11 @@ function sandbox_core_package_package.installdir() return package.installdir() end +-- the search directories +function sandbox_core_package_package.searchdirs() + return package.searchdirs() +end + -- load the package from the project file function sandbox_core_package_package.load_from_project(packagename) diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua index 14cb0fcac..ff398ff1b 100644 --- a/xmake/core/sandbox/modules/import/core/package/repository.lua +++ b/xmake/core/sandbox/modules/import/core/package/repository.lua @@ -91,7 +91,6 @@ function sandbox_core_package_repository.repositories(is_global) end end - -- load repositories from repository cache for name, repoinfo in pairs(table.wrap(repository.repositories(is_global))) do local url = repoinfo diff --git a/xmake/core/sandbox/modules/import/core/platform/platform.lua b/xmake/core/sandbox/modules/import/core/platform/platform.lua index d9730f830..627e4c02c 100644 --- a/xmake/core/sandbox/modules/import/core/platform/platform.lua +++ b/xmake/core/sandbox/modules/import/core/platform/platform.lua @@ -26,18 +26,18 @@ local platform = require("platform/platform") local raise = require("sandbox/modules/raise") -- load the current platform -function sandbox_core_platform.load(plat) +function sandbox_core_platform.load(plat, arch) -- load the platform configure - local ok, errors = platform.load(plat) + local ok, errors = platform.load(plat, arch) if not ok then raise(errors) end end -- get the platform os -function sandbox_core_platform.os() - return platform.os() +function sandbox_core_platform.os(plat, arch) + return platform.os(plat, arch) end -- get the all platforms @@ -51,26 +51,26 @@ function sandbox_core_platform.toolchains() end -- get the all architectures for the given platform -function sandbox_core_platform.archs(plat) - return platform.archs(plat) +function sandbox_core_platform.archs(plat, arch) + return platform.archs(plat, arch) end -- get the current platform configuration -function sandbox_core_platform.get(name, plat) - return platform.get(name, plat) +function sandbox_core_platform.get(name, plat, arch) + return platform.get(name, plat, arch) 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) +function sandbox_core_platform.tool(toolkind, plat, arch) + return platform.tool(toolkind, plat, arch) end -- get the current platform tool configuration -function sandbox_core_platform.toolconfig(name, plat) - return platform.toolconfig(name, plat) +function sandbox_core_platform.toolconfig(name, plat, arch) + return platform.toolconfig(name, plat, arch) end -- return module diff --git a/xmake/core/sandbox/modules/import/core/project/config.lua b/xmake/core/sandbox/modules/import/core/project/config.lua index 3ea6d3a30..73dd71daf 100644 --- a/xmake/core/sandbox/modules/import/core/project/config.lua +++ b/xmake/core/sandbox/modules/import/core/project/config.lua @@ -23,6 +23,7 @@ local sandbox_core_project_config = sandbox_core_project_config or {} -- load modules local config = require("project/config") +local project = require("project/project") local platform = require("platform/platform") local raise = require("sandbox/modules/raise") @@ -113,7 +114,7 @@ end -- check the configuration function sandbox_core_project_config.check() - -- get the current platform + -- check configuration for the current platform local instance, errors = platform.load() if instance then local ok, errors = instance:check() diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index cb7465fcd..1ea9c96b5 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -83,9 +83,6 @@ function sandbox_core_project.check() raise(errors) end - -- enter toolchains environment - environment.enter("toolchains") - -- init check task local checked = {} local checktask = function (index) @@ -114,12 +111,30 @@ function sandbox_core_project.check() local jobs = baseoption.get("jobs") or math.ceil(os.cpuinfo().ncpu * 3 / 2) import("private.async.runjobs", {anonymous = true})("check_options", instance:fork(checktask):script(), {total = #options, comax = jobs}) - -- leave toolchains environment - environment.leave("toolchains") - -- save all options to the cache file option.save() + -- check toolchains configuration for all target in the current project + -- @note we must check targets after loading options + for _, target in pairs(table.wrap(targets)) do + if target:get("enabled") ~= false and (target:get("toolchains") or target:plat() ~= config.get("plat")) then + for _, toolchain_inst in pairs(target:toolchains()) do + -- check toolchains for `target/set_toolchains()` + if target:get("toolchains") then + if not toolchain_inst:check() then + raise("toolchain(\"%s\"): not found!", toolchain_inst:name()) + end + else + -- check platform toolchains for `target/set_plat()` + local ok, errors = target:platform():check() + if not ok then + raise(errors) + end + end + end + end + end + -- leave the project directory local ok, errors = os.cd(oldir) if not ok then diff --git a/xmake/core/sandbox/modules/import/core/tool/compiler.lua b/xmake/core/sandbox/modules/import/core/tool/compiler.lua index 0fdeb3124..9cab2b54d 100644 --- a/xmake/core/sandbox/modules/import/core/tool/compiler.lua +++ b/xmake/core/sandbox/modules/import/core/tool/compiler.lua @@ -194,7 +194,7 @@ function sandbox_core_tool_compiler.features(langkind, opt) local flags = instance:compflags(opt) -- get features - local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._features, instance:name(), {flags = flags, program = instance:program()}) + local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._features, instance:name(), {flags = flags, program = instance:program(), envs = instance:runenvs()}) if not ok then raise(results_or_errors) end @@ -257,7 +257,7 @@ function sandbox_core_tool_compiler.has_features(features, opt) local flags = instance:compflags(opt) -- has features? - local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._has_features, instance:name(), features, {flags = flags, program = instance:program()}) + local ok, results_or_errors = sandbox.load(sandbox_core_tool_compiler._has_features, instance:name(), features, {flags = flags, program = instance:program(), envs = instance:runenvs()}) if not ok then raise(results_or_errors) end diff --git a/xmake/core/sandbox/modules/import/core/tool/toolchain.lua b/xmake/core/sandbox/modules/import/core/tool/toolchain.lua index 8f4202f2b..26af1f141 100644 --- a/xmake/core/sandbox/modules/import/core/tool/toolchain.lua +++ b/xmake/core/sandbox/modules/import/core/tool/toolchain.lua @@ -39,8 +39,8 @@ function sandbox_core_tool_toolchain.list() end -- load the toolchain from the given name -function sandbox_core_tool_toolchain.load(name) - local instance, errors = toolchain.load(name) +function sandbox_core_tool_toolchain.load(name, opt) + local instance, errors = toolchain.load(name, opt) if not instance then raise(errors) end 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 c277364bb..2b4f9996a 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_library.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_library.lua @@ -67,7 +67,7 @@ function sandbox_lib_detect_find_library.main(names, pathes, opt) if not filepath and config.is_plat("mingw") then -- for the mingw platform, it is compatible with the libxxx.a and xxx.lib local formats = {static = "lib$(name).a", shared = "lib$(name).so"} - filepath = find_file(target.filename(name, kind, formats[kind]), pathes, opt) + filepath = find_file(target.filename(name, kind, {format = formats[kind]}), pathes, opt) end if filepath then local filename = path.filename(filepath) 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 120125687..85d4d733b 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua @@ -55,14 +55,14 @@ function sandbox_lib_detect_find_program._check(program, opt) -- no check script? attempt to run it directly if not opt.check then - return 0 == os.execv(program, {"--version"}, {stdout = os.nuldev(), stderr = os.nuldev()}) + return 0 == os.execv(program, {"--version"}, {stdout = os.nuldev(), stderr = os.nuldev(), envs = opt.envs}) end -- check it local ok = false local errors = nil if type(opt.check) == "string" then - ok, errors = os.runv(program, {opt.check}) + ok, errors = os.runv(program, {opt.check}, {envs = opt.envs}) else ok, errors = sandbox.load(opt.check, program) end @@ -71,8 +71,6 @@ function sandbox_lib_detect_find_program._check(program, opt) if not ok and option.get("diagnosis") then utils.cprint("${color.warning}checkinfo: ${clear dim}" .. errors) end - - -- ok? return ok end @@ -233,6 +231,7 @@ end -- local program = find_program("ccache", {pathes = {"/usr/bin", "/usr/local/bin"}, check = function (program) os.run("%s -h", program) end}) -- local program = find_program("ccache", {pathes = {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}}) -- local program = find_program("ccache", {pathes = {"$(env PATH)", function () return "/usr/local/bin" end}}) +-- local program = find_program("ccache", {envs = {PATH = "xxx"}}) -- -- @endcode -- @@ -259,16 +258,27 @@ function sandbox_lib_detect_find_program.main(name, opt) local cacheinfo = cache.load(cachekey) local result = cacheinfo[name] if result ~= nil and not opt.force then - return utils.ifelse(result, result, nil) + return result and result or nil + end + + -- get pathes from the opt.envs.PATH + local envs = opt.envs + local pathes = opt.pathes + if envs and (envs.PATH or envs.path) then + local pathenv = envs.PATH or envs.path + if type(pathenv) == "string" then + pathenv = path.splitenv(pathenv) + end + pathes = table.join(table.wrap(opt.pathes), pathenv) end -- find executable program - checking = utils.ifelse(coroutine_running, name, nil) - result = sandbox_lib_detect_find_program._find(name, opt.pathes, opt) + checking = coroutine_running and name or nil + result = sandbox_lib_detect_find_program._find(name, pathes, opt) checking = nil -- cache result - cacheinfo[name] = utils.ifelse(result, result, false) + cacheinfo[name] = result and result or false -- save cache info cache.save(cachekey, cacheinfo) @@ -276,13 +286,11 @@ function sandbox_lib_detect_find_program.main(name, opt) -- trace if option.get("verbose") or opt.verbose then if result then - utils.cprint("checking for the %s ... ${color.success}%s", name, utils.ifelse(name == result, "${text.success}", result)) + utils.cprint("checking for the %s ... ${color.success}%s", name, (name == result and "${text.success}" or result)) else utils.cprint("checking for the %s ... ${color.nothing}${text.nothing}", name) end end - - -- ok? return result end 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 e48fb6d9e..b51f6a8ba 100644 --- a/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua +++ b/xmake/core/sandbox/modules/import/lib/detect/find_programver.lua @@ -65,7 +65,7 @@ function sandbox_lib_detect_find_programver.main(program, opt) local cacheinfo = cache.load(cachekey) local result = cacheinfo[program] if result ~= nil and not opt.force then - return utils.ifelse(result, result, nil) + return result and result or nil end -- attempt to get version output info @@ -78,7 +78,7 @@ function sandbox_lib_detect_find_programver.main(program, opt) utils.cprint("${color.warning}checkinfo: ${clear dim}" .. outdata) end else - ok, outdata = os.iorunv(program, {command or "--version"}) + ok, outdata = os.iorunv(program, {command or "--version"}, {envs = opt.envs}) end -- find version info @@ -98,13 +98,9 @@ function sandbox_lib_detect_find_programver.main(program, opt) end end - -- cache result - cacheinfo[program] = utils.ifelse(result, result, false) - - -- save cache info + -- save result + cacheinfo[program] = result and result or false cache.save(cachekey, cacheinfo) - - -- ok? return result end diff --git a/xmake/core/sandbox/modules/string.lua b/xmake/core/sandbox/modules/string.lua index 36f2f7b58..755b12fba 100644 --- a/xmake/core/sandbox/modules/string.lua +++ b/xmake/core/sandbox/modules/string.lua @@ -48,7 +48,7 @@ function sandbox_string.vformat(format, ...) if #{...} > 0 then -- escape "%$", "%(", "%)", "%%" to '$', '(', ')', '%%' - format = format:gsub("%%([%$%(%)%%])", function (ch) return utils.ifelse(ch ~= "%", "%%" .. ch, "%%%%") end) + format = format:gsub("%%([%$%(%)%%])", function (ch) return ch ~= "%" and ("%%" .. ch) or "%%%%" end) -- try to format it result = string.format(format, ...) diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua index 03a9f34ed..d8a01ba2a 100644 --- a/xmake/core/tool/builder.lua +++ b/xmake/core/tool/builder.lua @@ -383,6 +383,16 @@ function builder:program() return self:_tool():program() end +-- get toolchain of this tool +function builder:toolchain() + return self:_tool():toolchain() +end + +-- get the run environments +function builder:runenvs() + return self:_tool():runenvs() +end + -- get properties of the tool function builder:get(name) return self:_tool():get(name) diff --git a/xmake/core/tool/compiler.lua b/xmake/core/tool/compiler.lua index e56f2d300..c47ffb9e1 100644 --- a/xmake/core/tool/compiler.lua +++ b/xmake/core/tool/compiler.lua @@ -78,13 +78,13 @@ end function compiler._load_tool(sourcekind, target) -- get program from target - local program, toolname + local program, toolname, toolchain_info if target and target:type() == "target" then - program, toolname = target:tool(sourcekind) + program, toolname, toolchain_info = target:tool(sourcekind) end -- load the compiler tool from the source kind - local result, errors = tool.load(sourcekind, program, toolname) + local result, errors = tool.load(sourcekind, {program = program, toolname = toolname, toolchain_info = toolchain_info}) if not result then return nil, errors end @@ -236,7 +236,7 @@ function compiler:compile(sourcefiles, objectfile, opt) end -- compile it - return sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags) + return sandbox.load(self:_tool().compile, self:_tool(), sourcefiles, objectfile, opt.dependinfo, compflags, opt) end -- get the compile arguments list diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua index baafde7ae..06ae051cb 100644 --- a/xmake/core/tool/linker.lua +++ b/xmake/core/tool/linker.lua @@ -85,13 +85,13 @@ function linker._load_tool(targetkind, sourcekinds, target) for _, _linkerinfo in ipairs(linkerinfos) do -- get program from target - local program, toolname + local program, toolname, toolchain_info if target and target:type() == "target" then - program, toolname = target:tool(_linkerinfo.linkerkind) + program, toolname, toolchain_info = target:tool(_linkerinfo.linkerkind) end -- load the linker tool from the linker kind (with cache) - linkertool, errors = tool.load(_linkerinfo.linkerkind, program, toolname) + linkertool, errors = tool.load(_linkerinfo.linkerkind, {program = program, toolname = toolname, toolchain_info = toolchain_info}) if linkertool then linkerinfo = _linkerinfo linkerinfo.program = program diff --git a/xmake/core/tool/tool.lua b/xmake/core/tool/tool.lua index 9e6dec6d4..b8eb29ddd 100644 --- a/xmake/core/tool/tool.lua +++ b/xmake/core/tool/tool.lua @@ -30,16 +30,17 @@ local table = require("base/table") local string = require("base/string") local config = require("project/config") local sandbox = require("sandbox/sandbox") +local toolchain = require("tool/toolchain") local platform = require("platform/platform") local import = require("sandbox/modules/import") -- new an instance -function _instance.new(kind, name, program) +function _instance.new(kind, name, program, plat, arch, toolchain_inst) -- 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) + toolclass = import("core.tools." .. name, {nocache = true}) -- @note we need create a tool instance with unique toolclass context (_g) end -- not found? @@ -51,10 +52,13 @@ function _instance.new(kind, name, program) local instance = table.inherit(_instance, toolclass) -- save name, kind and program - instance._NAME = name - instance._KIND = kind - instance._PROGRAM = program - instance._INFO = {} + instance._NAME = name + instance._KIND = kind + instance._PROGRAM = program + instance._PLAT = plat + instance._ARCH = arch + instance._TOOLCHAIN = toolchain_inst + instance._INFO = {} -- init instance if instance.init then @@ -78,11 +82,31 @@ function _instance:kind() return self._KIND end +-- get the tool platform +function _instance:plat() + return self._PLAT +end + +-- get the tool architecture +function _instance:arch() + return self._ARCH +end + -- get the tool program function _instance:program() return self._PROGRAM end +-- get the toolchain of this tool +function _instance:toolchain() + return self._TOOLCHAIN +end + +-- get run environments +function _instance:runenvs() + return self:toolchain() and self:toolchain():runenvs() +end + -- set the value to the platform info function _instance:set(name, ...) self._INFO[name] = table.unwrap({...}) @@ -123,25 +147,39 @@ function _instance:has_flags(flags, flagkind, opt) -- import has_flags() self._has_flags = self._has_flags or import("lib.detect.has_flags", {anonymous = true}) + -- bind the run environments + opt.envs = self:runenvs() + -- has flags? return self._has_flags(self:name(), flags, opt) end -- load the given tool from the given kind -- --- @param kind the tool kind e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. --- @param program the tool program, e.g. /xxx/arm-linux-gcc, [email protected], (optional) --- @param toolname gcc, clang, .. (optional) +-- @param kind the tool kind e.g. cc, cxx, mm, mxx, as, ar, ld, sh, .. +-- @param opt.program the tool program, e.g. /xxx/arm-linux-gcc, [email protected], (optional) +-- @param opt.toolname gcc, clang, .. (optional) +-- @param opt.toolchain_info the toolchain info (optional) -- -function tool.load(kind, program, toolname) +function tool.load(kind, opt) + + -- get tool information + opt = opt or {} + local program = opt.program + local toolname = opt.toolname + local toolchain_info = opt.toolchain_info or {} + + -- get platform and architecture + local plat = toolchain_info.plat or config.get("plat") or os.host() + local arch = toolchain_info.arch or config.get("arch") or os.arch() - -- init key - local key = kind .. (program or "") .. (config.get("arch") or os.arch()) + -- init cachekey + local cachekey = kind .. (program or "") .. plat .. arch -- get it directly from cache dirst tool._TOOLS = tool._TOOLS or {} - if tool._TOOLS[key] then - return tool._TOOLS[key] + if tool._TOOLS[cachekey] then + return tool._TOOLS[cachekey] end -- contain toolname? parse it, e.g. '[email protected]' @@ -155,7 +193,11 @@ function tool.load(kind, program, toolname) -- get the tool program and name if not program then - program, toolname = platform.tool(kind) + program, toolname, toolchain_info = platform.tool(kind, plat, arch) + if toolchain_info then + assert(toolchain_info.plat == plat) + assert(toolchain_info.arch == arch) + end end if not program then return nil, string.format("cannot get program for %s", kind) @@ -176,14 +218,20 @@ function tool.load(kind, program, toolname) return nil, string.format("cannot find known tool script for %s", toolname or program) end + -- load toolchain instance + local toolchain_inst + if toolchain_info and toolchain_info.name then + toolchain_inst = toolchain.load(toolchain_info.name, {plat = plat, arch = arch}) + end + -- new an instance - local instance, errors = _instance.new(kind, name, program) + local instance, errors = _instance.new(kind, name, program, plat, arch, toolchain_inst) if not instance then return nil, errors end -- save instance to the cache - tool._TOOLS[key] = instance + tool._TOOLS[cachekey] = instance -- ok return instance diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 6e48ef836..f6eafa94b 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -36,9 +36,11 @@ local sandbox = require("sandbox/sandbox") local sandbox_module = require("sandbox/modules/import/core/sandbox/module") -- new an instance -function _instance.new(name, info) +function _instance.new(name, plat, arch, info) local instance = table.inherit(_instance) instance._NAME = name + instance._PLAT = plat + instance._ARCH = arch instance._INFO = info return instance end @@ -50,12 +52,32 @@ end -- get toolchain platform function _instance:plat() - return config.get("plat") or os.host() + return self._PLAT end -- get toolchain architecture function _instance:arch() - return config.get("arch") or os.arch() + return self._ARCH +end + +-- the current platform is belong to the given platforms? +function _instance:is_plat(...) + local plat = self:plat() + for _, v in ipairs(table.join(...)) do + if v and plat == v then + return true + end + end +end + +-- the current architecture is belong to the given architectures? +function _instance:is_arch(...) + local arch = self:arch() + for _, v in ipairs(table.join(...)) do + if v and arch:find("^" .. v:gsub("%-", "%%-") .. "$") then + return true + end + end end -- get toolchain info @@ -111,6 +133,26 @@ function _instance:standalone() return self:kind() == "standalone" end +-- get the run environments +function _instance:runenvs() + local runenvs = self._RUNENVS + if runenvs == nil then + local toolchain_runenvs = self:get("runenvs") + if toolchain_runenvs then + runenvs = {} + for name, values in pairs(toolchain_runenvs) do + if type(values) == "table" then + values = path.joinenv(values) + end + runenvs[name] = values + end + end + runenvs = runenvs or false + self._RUNENVS = runenvs + end + return runenvs or nil +end + -- get the program and name of the given tool kind function _instance:tool(toolkind) local toolpathes = self:get("toolset." .. toolkind) @@ -139,23 +181,6 @@ function _instance:sdkdir() return config.get("sdk") or self:get("sdkdir") end --- do load, @note we need load it repeatly for each architectures -function _instance:_load() - local info = self:info() - if not info:get("__loaded") and not info:get("__loading") then - local on_load = info:get("load") - if on_load then - info:set("__loading", true) - local ok, errors = sandbox.load(on_load, self) - info:set("__loading", false) - if not ok then - os.raise(errors) - end - end - info:set("__loaded", true) - end -end - -- do check, we only check it once for all architectures function _instance:check() local checkok = true @@ -174,6 +199,23 @@ function _instance:check() return checkok end +-- do load, @note we need load it repeatly for each architectures +function _instance:_load() + local info = self:info() + if not info:get("__loaded") and not info:get("__loading") then + local on_load = info:get("load") + if on_load then + info:set("__loading", true) + local ok, errors = sandbox.load(on_load, self) + info:set("__loading", false) + if not ok then + os.raise(errors) + end + end + info:set("__loaded", true) + end +end + -- get the tool description from the tool kind function _instance:_description(toolkind) local descriptions = self._DESCRIPTIONS @@ -240,7 +282,7 @@ function _instance:_checktool(toolkind, toolpath) -- find tool program local program, toolname - local tool = find_tool(toolpath, {program = toolpath, pathes = self:bindir()}) + local tool = find_tool(toolpath, {program = toolpath, pathes = self:bindir(), envs = self:get("runenvs")}) if tool then program = tool.program toolname = tool.name @@ -318,24 +360,26 @@ end -- get toolchain directories function toolchain.directories() - - -- init directories local dirs = toolchain._DIRS or { path.join(global.directory(), "toolchains") , path.join(os.programdir(), "toolchains") } - - -- save directories to cache toolchain._DIRS = dirs return dirs end -- load the given toolchain -function toolchain.load(name) +function toolchain.load(name, opt) + + -- init cache key + opt = opt or {} + local plat = opt.plat or config.get("plat") or os.host() + local arch = opt.arch or config.get("arch") or os.arch() + local cachekey = name .. plat .. arch -- get it directly from cache dirst toolchain._TOOLCHAINS = toolchain._TOOLCHAINS or {} - if toolchain._TOOLCHAINS[name] then - return toolchain._TOOLCHAINS[name] + if toolchain._TOOLCHAINS[cachekey] then + return toolchain._TOOLCHAINS[cachekey] end -- find the toolchain script path @@ -372,8 +416,8 @@ function toolchain.load(name) end -- save instance to the cache - local instance = _instance.new(name, result) - toolchain._TOOLCHAINS[name] = instance + local instance = _instance.new(name, plat, arch, result) + toolchain._TOOLCHAINS[cachekey] = instance return instance end diff --git a/xmake/includes/check_syslinks.lua b/xmake/includes/check_syslinks.lua new file mode 100644 index 000000000..2764e7ebd --- /dev/null +++ b/xmake/includes/check_syslinks.lua @@ -0,0 +1,54 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file check_syslinks.lua +-- + +-- check links and add macro definition +-- +-- e.g. +-- +-- check_syslinks("HAS_PTHREAD", "pthread") +-- check_syslinks("HAS_PTHREAD", {"pthread", "m", "dl"}) +-- +function check_syslinks(definition, links, opt) + opt = opt or {} + local optname = "__" .. (opt.name or definition) + option(optname) + add_syslinks(links) + add_defines(definition) + option_end() + add_options(optname) +end + +-- check links and add macro definition to the configuration files +-- +-- e.g. +-- +-- configvar_check_syslinks("HAS_PTHREAD", "pthread") +-- configvar_check_syslinks("HAS_PTHREAD", {"pthread", "m", "dl"}) +-- +function configvar_check_syslinks(definition, links, opt) + opt = opt or {} + local optname = "__" .. (opt.name or definition) + local defname, defval = unpack(definition:split('=')) + option(optname) + add_syslinks(links) + set_configvar(defname, defval or 1) + option_end() + add_options(optname) +end diff --git a/xmake/modules/core/tools/ar.lua b/xmake/modules/core/tools/ar.lua index 576d40695..3e520f887 100644 --- a/xmake/modules/core/tools/ar.lua +++ b/xmake/modules/core/tools/ar.lua @@ -71,7 +71,8 @@ function link(self, objectfiles, targetkind, targetfile, flags) os.tryrm(targetfile) -- link it - os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) + local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags) + os.runv(program, argv, {envs = self:runenvs()}) end -- extract the static library to object directory diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 9f6421c21..3dfa0bb0f 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -353,7 +353,8 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) end -- use vstool to compile and enable vs_unicode_output @see https://github.com/xmake-io/xmake/issues/528 - return vstool.iorunv(compargv(self, sourcefile, objectfile, compflags, opt)) + local program, argv = compargv(self, sourcefile, objectfile, compflags, opt) + return vstool.iorunv(program, argv, {envs = self:runenvs()}) end, catch { diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index 04839ceaf..7896deab6 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -330,7 +330,8 @@ function link(self, objectfiles, targetkind, targetfile, flags) os.mkdir(path.directory(targetfile)) -- link it - os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags)) + local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags) + os.runv(program, argv, {envs = self:runenvs()}) end -- has color diagnostics? @@ -424,7 +425,8 @@ function compile(self, sourcefile, objectfile, dependinfo, flags) end -- do compile - return os.iorunv(compargv(self, sourcefile, objectfile, compflags)) + local program, argv = compargv(self, sourcefile, objectfile, compflags) + return os.iorunv(program, argv, {envs = self:runenvs()}) end, catch { diff --git a/xmake/modules/core/tools/lib.lua b/xmake/modules/core/tools/lib.lua index 704fe406c..6c07e9d1f 100644 --- a/xmake/modules/core/tools/lib.lua +++ b/xmake/modules/core/tools/lib.lua @@ -28,7 +28,7 @@ function extract(self, libraryfile, objectdir) os.mkdir(objectdir) -- list object files - local objectfiles = vstool.iorunv(self:program(), {"-nologo", "-list", libraryfile}) + local objectfiles = vstool.iorunv(self:program(), {"-nologo", "-list", libraryfile}, {envs = self:runenvs()}) -- extrace all object files for _, objectfile in ipairs(objectfiles:split('\n')) do @@ -50,7 +50,7 @@ function extract(self, libraryfile, objectdir) end -- extract it - vstool.runv(self:program(), {"-nologo", "-extract:" .. objectfile, "-out:" .. outputfile, libraryfile}) + vstool.runv(self:program(), {"-nologo", "-extract:" .. objectfile, "-out:" .. outputfile, libraryfile}, {envs = self:runenvs()}) end end end diff --git a/xmake/modules/core/tools/link.lua b/xmake/modules/core/tools/link.lua index 3bcbb238d..10a242e6d 100644 --- a/xmake/modules/core/tools/link.lua +++ b/xmake/modules/core/tools/link.lua @@ -52,7 +52,7 @@ function get(self, name) local values = self._INFO[name] if name == "ldflags" or name == "arflags" or name == "shflags" then -- switch architecture, @note does cache it in init() for generating vs201x project - values = table.join(values, "-machine:" .. (config.arch() or "x86")) + values = table.join(values, "-machine:" .. (self:arch() or "x86")) end return values end @@ -94,7 +94,16 @@ end function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) opt = opt or {} local argv = table.join(flags, "-out:" .. targetfile, objectfiles) - return self:program(), opt.rawargs and argv or winos.cmdargv(argv) + if not opt.rawargs then + argv = winos.cmdargv(argv) + end + -- @note we cannot put -lib/-dll to @args.txt + if targetkind == "static" then + table.insert(argv, 1, "-lib") + elseif targetkind == "shared" then + table.insert(argv, 1, "-dll") + end + return self:program(), argv end -- link the target file @@ -108,7 +117,8 @@ function link(self, objectfiles, targetkind, targetfile, flags, opt) function () -- use vstool to link and enable vs_unicode_output @see https://github.com/xmake-io/xmake/issues/528 - vstool.runv(linkargv(self, objectfiles, targetkind, targetfile, flags, opt)) + local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags, opt) + vstool.runv(program, argv, {envs = self:runenvs()}) end, catch { diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua index 4899b46c6..3d6fb7c18 100644 --- a/xmake/modules/core/tools/ml.lua +++ b/xmake/modules/core/tools/ml.lua @@ -91,12 +91,12 @@ function nf_includedir(self, dir) end -- make the compile arguments list -function _compargv1(self, sourcefile, objectfile, flags) +function compargv(self, sourcefile, objectfile, flags) return self:program(), table.join("-c", flags, "-Fo" .. os.args(objectfile), sourcefile) end -- compile the source file -function _compile1(self, sourcefile, objectfile, dependinfo, flags) +function compile(self, sourcefile, objectfile, dependinfo, flags) -- ensure the object directory os.mkdir(path.directory(objectfile)) @@ -105,7 +105,8 @@ function _compile1(self, sourcefile, objectfile, dependinfo, flags) { function () -- @note we need not uses vstool.runv to enable unicode output for ml.exe - os.runv(_compargv1(self, sourcefile, objectfile, flags)) + local program, argv = compargv(self, sourcefile, objectfile, flags) + os.runv(program, argv, {envs = self:runenvs()}) end, catch { @@ -125,23 +126,3 @@ function _compile1(self, sourcefile, objectfile, dependinfo, flags) } end --- make the compile arguments list -function compargv(self, sourcefiles, objectfile, flags) - - -- only support single source file now - assert(type(sourcefiles) ~= "table", "'object:sources' not support!") - - -- for only single source file - return _compargv1(self, sourcefiles, objectfile, flags) -end - --- compile the source file -function compile(self, sourcefiles, objectfile, dependinfo, flags) - - -- only support single source file now - assert(type(sourcefiles) ~= "table", "'object:sources' not support!") - - -- for only single source file - _compile1(self, sourcefiles, objectfile, dependinfo, flags) -end - diff --git a/xmake/modules/core/tools/rc.lua b/xmake/modules/core/tools/rc.lua index cdaaa6b49..a0379ca57 100644 --- a/xmake/modules/core/tools/rc.lua +++ b/xmake/modules/core/tools/rc.lua @@ -59,7 +59,8 @@ function compile(self, sourcefile, objectfile, dependinfo, flags) { function () -- @note we need not uses vstool.iorunv to enable unicode output for rc.exe - local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, flags)) + local program, argv = compargv(self, sourcefile, objectfile, flags) + local outdata, errdata = os.iorunv(program, argv, {envs = self:runenvs()}) return (outdata or "") .. (errdata or "") end, catch diff --git a/xmake/modules/detect/sdks/find_xcode.lua b/xmake/modules/detect/sdks/find_xcode.lua index d7eb2ddd7..a1ab709df 100644 --- a/xmake/modules/detect/sdks/find_xcode.lua +++ b/xmake/modules/detect/sdks/find_xcode.lua @@ -147,13 +147,19 @@ function main(sdkdir, opt) local plat = opt.plat or config.get("plat") or "macosx" local arch = opt.arch or config.get("arch") or "x86_64" + -- get xcode sdk version + local xcode_sdkver = (plat == config.plat()) and config.get("xcode_sdkver") + if not xcode_sdkver then + xcode_sdkver = config.get("xcode_sdkver_" .. plat) + end + -- find xcode - local xcode = _find_xcode(sdkdir or config.get("xcode") or global.get("xcode") or config.get("sdk"), opt.sdkver or config.get("xcode_sdkver"), plat, arch) + local xcode = _find_xcode(sdkdir or config.get("xcode") or global.get("xcode"), opt.sdkver or xcode_sdkver, plat, arch) if xcode and xcode.sdkdir then -- save to config config.set("xcode", xcode.sdkdir, {force = true, readonly = true}) - config.set("xcode_sdkver", xcode.sdkver, {force = true, readonly = true}) + config.set("xcode_sdkver_" .. plat, xcode.sdkver, {force = true, readonly = true}) config.set("xcode_codesign_identity", xcode.codesign_identity, {force = true, readonly = true}) config.set("xcode_mobile_provision", xcode.mobile_provision, {force = true, readonly = true}) @@ -166,7 +172,7 @@ function main(sdkdir, opt) else cprint("checking for the Codesign Identity of Xcode ... ${color.nothing}${text.nothing}") end - if is_plat("iphoneos") then + if plat == "iphoneos" then if xcode.mobile_provision then cprint("checking for the Mobile Provision of Xcode ... ${color.success}%s", xcode.mobile_provision) else diff --git a/xmake/modules/detect/tools/cl/features.lua b/xmake/modules/detect/tools/cl/features.lua index 976085659..fb4c98cca 100644 --- a/xmake/modules/detect/tools/cl/features.lua +++ b/xmake/modules/detect/tools/cl/features.lua @@ -36,8 +36,8 @@ function _get_macro_defines(snippets, extension, opt) local defines = try { function () - os.runv(opt.program, table.join(opt.flags or {}, {"-nologo", "-Fo" .. objectfile, sourcefile, "-link", "-out:" .. binaryfile})) - return os.iorunv(binaryfile) + os.runv(opt.program, table.join(opt.flags or {}, {"-nologo", "-Fo" .. objectfile, sourcefile, "-link", "-out:" .. binaryfile}), {envs = opt.envs}) + return os.iorunv(binaryfile, {}, {envs = opt.envs}) end } if defines then @@ -50,8 +50,6 @@ function _get_macro_defines(snippets, extension, opt) os.tryrm(sourcefile) os.tryrm(objectfile) os.tryrm(binaryfile) - - -- ok? return results end @@ -97,6 +95,7 @@ end function check_features(opt) -- check features with all extensions + opt = opt or {} local results = {} for extension, features in pairs(_g.features) do diff --git a/xmake/modules/detect/tools/cl/has_flags.lua b/xmake/modules/detect/tools/cl/has_flags.lua index 1d9deff3f..b5dabc737 100644 --- a/xmake/modules/detect/tools/cl/has_flags.lua +++ b/xmake/modules/detect/tools/cl/has_flags.lua @@ -44,7 +44,7 @@ function _check_from_arglist(flags, opt) -- get argument list allflags = {} - local arglist = os.iorunv(opt.program, {"-?"}) + local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs}) if arglist then for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do allflags[arg:gsub("/", "-")] = true @@ -72,7 +72,7 @@ function _check_try_running(flags, opt) -- check it local errors = nil return try { function () - local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile)) + local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile), {envs = opt.envs}) if errs and #errs:trim() > 0 then return false, errs end diff --git a/xmake/modules/detect/tools/find_cl.lua b/xmake/modules/detect/tools/find_cl.lua index 48289cfbc..a6f5d2fa6 100644 --- a/xmake/modules/detect/tools/find_cl.lua +++ b/xmake/modules/detect/tools/find_cl.lua @@ -38,7 +38,7 @@ function main(opt) -- init options opt = opt or {} - opt.check = opt.check or function (program) os.run(program) end + opt.check = opt.check or function (program) os.runv(program, {}, {envs = opt.envs}) end -- find program local program = find_program(opt.program or "cl.exe", opt) diff --git a/xmake/modules/detect/tools/find_lib.lua b/xmake/modules/detect/tools/find_lib.lua index 9c5b4be74..653dca5bb 100644 --- a/xmake/modules/detect/tools/find_lib.lua +++ b/xmake/modules/detect/tools/find_lib.lua @@ -21,6 +21,7 @@ -- imports import("lib.detect.find_program") import("lib.detect.find_programver") +import("lib.detect.find_tool") -- find lib -- @@ -50,9 +51,11 @@ function main(opt) 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) + local cl = assert(find_tool("cl")) + local link = assert(find_tool("link")) + os.runv(cl.program, {"-c", "-Fo" .. objectfile, sourcefile}, {envs = opt.envs}) + os.runv(link.program, {"-lib", "-out:" .. libraryfile, objectfile}, {envs = opt.envs}) + verinfo = os.iorunv(program, {"-list", libraryfile}, {envs = opt.envs}) -- remove files os.rm(objectfile) diff --git a/xmake/modules/detect/tools/find_link.lua b/xmake/modules/detect/tools/find_link.lua index 71fba5323..5814cba09 100644 --- a/xmake/modules/detect/tools/find_link.lua +++ b/xmake/modules/detect/tools/find_link.lua @@ -21,6 +21,7 @@ -- imports import("lib.detect.find_program") import("lib.detect.find_programver") +import("lib.detect.find_tool") -- find link -- @@ -43,17 +44,20 @@ function main(opt) opt = opt or {} opt.check = opt.check or function (program) + -- find cl + local cl = assert(find_tool("cl", {envs = opt.envs})) + -- make an stub source file local binaryfile = os.tmpfile() .. ".exe" local objectfile = os.tmpfile() .. ".obj" local sourcefile = os.tmpfile() .. ".c" - -- main entry + -- compile sourcefile first io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + os.runv(cl.program, {"-c", "-Fo" .. objectfile, sourcefile}, {envs = opt.envs}) - -- check it - os.run("cl -c -Fo%s %s", objectfile, sourcefile) - verinfo = os.iorun("%s -out:%s %s", program, binaryfile, objectfile) + -- do link + verinfo = os.iorunv(program, {"-lib", "-out:" .. binaryfile, objectfile}, {envs = opt.envs}) -- remove files os.rm(objectfile) diff --git a/xmake/modules/detect/tools/find_ml.lua b/xmake/modules/detect/tools/find_ml.lua index dda0da3e1..c5da1eaee 100644 --- a/xmake/modules/detect/tools/find_ml.lua +++ b/xmake/modules/detect/tools/find_ml.lua @@ -38,7 +38,7 @@ function main(opt) -- init options opt = opt or {} - opt.check = opt.check or function (program) os.run(program) end + opt.check = opt.check or function (program) os.runv(program, {}, {envs = opt.envs}) end -- find program local program = find_program(opt.program or "ml.exe", opt) @@ -46,7 +46,7 @@ function main(opt) -- find program version local version = nil if program and opt and opt.version then - opt.command = opt.command or function () local _, info = os.iorun(program); return info end + opt.command = opt.command or function () local _, info = os.iorunv(program, {}, {envs = opt.envs}); return info end opt.parse = opt.parse or function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end version = find_programver(program, opt) end diff --git a/xmake/modules/detect/tools/find_ml64.lua b/xmake/modules/detect/tools/find_ml64.lua index bb2083ae7..f446fbeeb 100644 --- a/xmake/modules/detect/tools/find_ml64.lua +++ b/xmake/modules/detect/tools/find_ml64.lua @@ -38,7 +38,7 @@ function main(opt) -- init options opt = opt or {} - opt.check = opt.check or function (program) os.run(program) end + opt.check = opt.check or function (program) os.runv(program, {}, {envs = opt.envs}) end -- find program local program = find_program(opt.program or "ml64.exe", opt) @@ -46,7 +46,7 @@ function main(opt) -- find program version local version = nil if program and opt and opt.version then - opt.command = opt.command or function () local _, info = os.iorun(program); return info end + opt.command = opt.command or function () local _, info = os.iorunv(program, {}, {envs = opt.envs}); return info end opt.parse = opt.parse or function (output) return output:match("Version (%d+%.?%d*%.?%d*.-)%s") end version = find_programver(program, opt) end diff --git a/xmake/modules/detect/tools/find_msbuild.lua b/xmake/modules/detect/tools/find_msbuild.lua new file mode 100644 index 000000000..38d83c5ab --- /dev/null +++ b/xmake/modules/detect/tools/find_msbuild.lua @@ -0,0 +1,55 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_msbuild.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find msbuild +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local msbuild = find_msbuild() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "/version" + + -- find program + local program = find_program(opt.program or "msbuild.exe", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tools/find_nmake.lua b/xmake/modules/detect/tools/find_nmake.lua new file mode 100644 index 000000000..dcb65f63c --- /dev/null +++ b/xmake/modules/detect/tools/find_nmake.lua @@ -0,0 +1,55 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file find_nmake.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nmake +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nmake = find_nmake() +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + opt.check = "/?" + + -- find program + local program = find_program(opt.program or "nmake.exe", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end + diff --git a/xmake/modules/detect/tools/gcc/features.lua b/xmake/modules/detect/tools/gcc/features.lua index 6f339f664..ad4cb3214 100644 --- a/xmake/modules/detect/tools/gcc/features.lua +++ b/xmake/modules/detect/tools/gcc/features.lua @@ -32,7 +32,7 @@ function _get_macro_defines(snippets, extension, opt) -- get defines local results = {} - local defines = try { function () return os.iorunv(opt.program, table.join(opt.flags or {}, {"-dM", "-E", sourcefile})) end } + local defines = try { function () return os.iorunv(opt.program, table.join(opt.flags or {}, {"-dM", "-E", sourcefile}), {envs = opt.envs}) end } if defines then for _, define in ipairs(defines:split("\n")) do local name = define:match("#define%s+(.-)%s+") diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua index 28b4cd254..04956998b 100644 --- a/xmake/modules/detect/tools/gcc/has_flags.lua +++ b/xmake/modules/detect/tools/gcc/has_flags.lua @@ -37,11 +37,9 @@ function _islinker(flags, opt) end -- try running -function _try_running(...) - - local argv = {...} +function _try_running(program, argv, opt) local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list @@ -67,7 +65,7 @@ function _check_from_arglist(flags, opt, islinker) -- get argument list allflags = {} - local arglist = os.iorunv(opt.program, {"--help"}) + local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs}) if arglist then for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do allflags[arg] = true @@ -98,12 +96,12 @@ function _check_try_running(flags, opt, islinker) -- check flags for linker if islinker then - return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile)) + return _try_running(opt.program, table.join(flags, "-o", os.tmpfile(), sourcefile), opt) end -- check flags for compiler -- @note we cannot use os.nuldev() as the output file, maybe run failed for some flags, e.g. --coverage - return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile)) + return _try_running(opt.program, table.join(flags, "-S", "-o", os.tmpfile(), sourcefile), opt) end -- has_flags(flags)? diff --git a/xmake/modules/detect/tools/link/has_flags.lua b/xmake/modules/detect/tools/link/has_flags.lua index db93ba195..188d22976 100644 --- a/xmake/modules/detect/tools/link/has_flags.lua +++ b/xmake/modules/detect/tools/link/has_flags.lua @@ -20,13 +20,12 @@ -- imports import("lib.detect.cache") +import("lib.detect.find_tool") -- try running -function _try_running(...) - - local argv = {...} +function _try_running(program, argv, opt) local errors = nil - return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors + return try { function () os.runv(program, argv, opt); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors end -- attempt to check it from the argument list @@ -55,7 +54,7 @@ function _check_from_arglist(flags, opt) local arglist = nil try { - function () os.runv(opt.program, {"-?"}) end, + function () os.runv(opt.program, {"-?"}, {envs = opt.envs}) end, catch { function (errors) arglist = errors end @@ -71,8 +70,6 @@ function _check_from_arglist(flags, opt) cacheinfo[flagskey] = allflags cache.save(key, cacheinfo) end - - -- ok? return allflags[flags[1]:gsub("/", "-"):lower()] end @@ -94,16 +91,15 @@ function _check_try_running(flags, opt) -- compile the source file local objectfile = os.tmpfile() .. ".obj" local binaryfile = os.tmpfile() .. ".exe" - os.runv("cl", {"-c", "-nologo", "-Fo" .. objectfile, sourcefile}) + local cl = find_tool("cl") + if cl then + os.runv(cl.program, {"-c", "-nologo", "-Fo" .. objectfile, sourcefile}, {envs = envs}) + end -- try link it - local ok, errors = _try_running(opt.program, table.join(flags, "-nologo", "-out:" .. binaryfile, objectfile)) - - -- remove files + local ok, errors = _try_running(opt.program, table.join(flags, "-nologo", "-out:" .. binaryfile, objectfile), {envs = opt.envs}) os.tryrm(objectfile) os.tryrm(binaryfile) - - -- ok? return ok, errors end diff --git a/xmake/modules/detect/tools/ml/has_flags.lua b/xmake/modules/detect/tools/ml/has_flags.lua index 98bbb2775..21641d91d 100644 --- a/xmake/modules/detect/tools/ml/has_flags.lua +++ b/xmake/modules/detect/tools/ml/has_flags.lua @@ -44,7 +44,7 @@ function _check_from_arglist(flags, opt) -- get argument list allflags = {} - local arglist = os.iorunv(opt.program, {"-?"}) + local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs}) if arglist then for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do allflags[arg:gsub("/", "-")] = true @@ -72,7 +72,7 @@ function _check_try_running(flags, opt) -- check it local errors = nil return try { function () - local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile)) + local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile), {envs = opt.envs}) if errs and #errs:trim() > 0 then return false, errs end diff --git a/xmake/modules/devel/git/clone.lua b/xmake/modules/devel/git/clone.lua index 4285b392d..ef3aa769b 100644 --- a/xmake/modules/devel/git/clone.lua +++ b/xmake/modules/devel/git/clone.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("lib.detect.find_tool") +import("net.proxy") -- clone url -- @@ -75,6 +76,13 @@ function main(url, opt) table.insert(argv, path.translate(opt.outputdir)) end + -- use proxy? + local envs + local proxy_conf = proxy.get(url) + if proxy_conf then + envs = {ALL_PROXY = proxy_conf} + end + -- clone it - os.vrunv(git.program, argv) + os.vrunv(git.program, argv, {envs = envs}) end diff --git a/xmake/modules/devel/git/ls_remote.lua b/xmake/modules/devel/git/ls_remote.lua index a52e0d68d..1775567db 100644 --- a/xmake/modules/devel/git/ls_remote.lua +++ b/xmake/modules/devel/git/ls_remote.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("lib.detect.find_tool") +import("net.proxy") -- ls_remote to given branch, tag or commit -- @@ -55,8 +56,15 @@ function main(reftype, url) print("%s %s", git.program, os.args(argv)) end + -- use proxy? + local envs + local proxy_conf = proxy.get(url) + if proxy_conf then + envs = {ALL_PROXY = proxy_conf} + end + -- get refs - local data = os.iorunv(git.program, argv) + local data = os.iorunv(git.program, argv, {envs = envs}) -- get commmits and tags local refs = {} diff --git a/xmake/modules/devel/git/pull.lua b/xmake/modules/devel/git/pull.lua index 7eba74114..2320c51bd 100644 --- a/xmake/modules/devel/git/pull.lua +++ b/xmake/modules/devel/git/pull.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("lib.detect.find_tool") +import("net.proxy") -- pull remote commits -- @@ -63,8 +64,29 @@ function main(opt) oldir = os.cd(opt.repodir) end + -- use proxy? + local envs + local proxy_conf = proxy.get() + if proxy_conf then + -- get proxy configuration from the current remote url + local remoteinfo = try { function() return os.iorunv(git.program, {"remote", "-v"}) end } + if remoteinfo then + for _, line in ipairs(remoteinfo:split('\n', {plain = true})) do + local splitinfo = line:split("%s+") + if #splitinfo > 1 and splitinfo[1] == (opt.remote or "origin") then + local url = splitinfo[2] + if url then + proxy_conf = proxy.get(url) + end + break + end + end + end + envs = {ALL_PROXY = proxy_conf} + end + -- pull it - os.vrunv(git.program, argv) + os.vrunv(git.program, argv, {envs = envs}) -- leave repository directory if oldir then diff --git a/xmake/modules/lib/detect/features.lua b/xmake/modules/lib/detect/features.lua index 048ee85a6..9146e5da6 100644 --- a/xmake/modules/lib/detect/features.lua +++ b/xmake/modules/lib/detect/features.lua @@ -32,7 +32,7 @@ import("core.base.scheduler") -- @code -- local features = features("clang") -- local features = features("clang", {flags = "-O0", program = "xcrun -sdk macosx clang"}) --- local features = features("clang", {flags = {"-g", "-O0"}}) +-- local features = features("clang", {flags = {"-g", "-O0"}, envs = {PATH = ""}}) -- @endcode -- function main(name, opt) diff --git a/xmake/modules/lib/detect/find_tool.lua b/xmake/modules/lib/detect/find_tool.lua index 7e40c0b0e..83f543ebf 100644 --- a/xmake/modules/lib/detect/find_tool.lua +++ b/xmake/modules/lib/detect/find_tool.lua @@ -41,7 +41,7 @@ end -- @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 --- force = true, cachekey = "xxx"} +-- force = true, cachekey = "xxx", envs = {PATH = "xxx"}} -- -- @return {name = "", program = "", version = ""} or nil -- diff --git a/xmake/modules/lib/detect/has_flags.lua b/xmake/modules/lib/detect/has_flags.lua index 833bbcf65..4e4f3535a 100644 --- a/xmake/modules/lib/detect/has_flags.lua +++ b/xmake/modules/lib/detect/has_flags.lua @@ -62,14 +62,14 @@ function main(name, flags, opt) opt.programver = tool.version -- get tool platform - local plat = config.get("plat") or os.host() + local plat = opt.plat or config.get("plat") or os.host() -- get tool architecture -- -- some tools select arch by path environment, not be flags, e.g. cl.exe of msvc) -- so, it will affect the cache result -- - local arch = config.get("arch") or os.arch() + local arch = opt.arch or config.get("arch") or os.arch() -- init cache key local key = plat .. "_" .. arch .. "_" .. tool.program .. "_" .. (tool.version or "") .. "_" .. (opt.toolkind or "") .. "_" .. (opt.flagkind or "") .. "_" .. table.concat(opt.sysflags, " ") .. "_" .. opt.flagskey @@ -113,7 +113,7 @@ function main(name, flags, opt) if hasflags then result, errors = hasflags(checkflags, opt) else - result = try { function () os.runv(tool.program, checkflags); return true end, catch { function (errs) errors = errs end }} + result = try { function () os.runv(tool.program, checkflags, {envs = opt.envs}); return true end, catch { function (errs) errors = errs end }} end _g._checking = nil result = result or false diff --git a/xmake/modules/net/http/download.lua b/xmake/modules/net/http/download.lua index 6a292c20e..1267e24b8 100644 --- a/xmake/modules/net/http/download.lua +++ b/xmake/modules/net/http/download.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("lib.detect.find_tool") +import("net.proxy") -- get user agent function _get_user_agent() @@ -62,6 +63,13 @@ function _curl_download(tool, url, outputfile) table.insert(argv, "-fsSL") end + -- use proxy? + local proxy_conf = proxy.get(url) + if proxy_conf then + table.insert(argv, "-x") + table.insert(argv, proxy_conf) + end + -- set user-agent local user_agent = _get_user_agent() if user_agent then @@ -99,6 +107,23 @@ function _wget_download(tool, url, outputfile) os.mkdir(outputdir) end + -- use proxy? + local proxy_conf = proxy.get(url) + if proxy_conf then + table.insert(argv, "-e") + table.insert(argv, "use_proxy=yes") + table.insert(argv, "-e") + if url:startswith("http://") then + table.insert(argv, "http_proxy=" .. proxy_conf) + elseif url:startswith("https://") then + table.insert(argv, "https_proxy=" .. proxy_conf) + elseif url:startswith("ftp://") then + table.insert(argv, "ftp_proxy=" .. proxy_conf) + else + table.insert(argv, "http_proxy=" .. proxy_conf) + end + end + -- set user-agent local user_agent = _get_user_agent() if user_agent then diff --git a/xmake/modules/net/proxy.lua b/xmake/modules/net/proxy.lua new file mode 100644 index 000000000..0c7d308cb --- /dev/null +++ b/xmake/modules/net/proxy.lua @@ -0,0 +1,62 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file proxy.lua +-- + +-- imports +import("core.base.global") + +-- get proxy hosts +function _proxy_hosts() + local proxy_hosts = _g._PROXY_HOSTS + if proxy_hosts == nil then + proxy_hosts = global.get("proxy_hosts") + if proxy_hosts then + proxy_hosts = proxy_hosts:split(',', {plain = true}) + end + _g._PROXY_HOSTS = proxy_hosts or false + end + return proxy_hosts or nil +end + +-- convert host pattern to a lua pattern +function _host_pattern(pattern) + pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1") + pattern = pattern:gsub("%*", "\001") + pattern = pattern:gsub("\001", ".*") + return pattern +end + +-- get proxy configuration from the given url, [protocol://]host[:port] +function get(url) + if url then + local host = url:match("://(.-)/") or url:match("@(.-):") + local proxy_hosts = _proxy_hosts() + if host and proxy_hosts then + host = host:lower() + for _, proxy_host in ipairs(proxy_hosts) do + proxy_host = proxy_host:lower() + if host == proxy_hosts or host:match(_host_pattern(proxy_host)) then + return global.get("proxy") + end + end + end + return + end + return global.get("proxy") +end diff --git a/xmake/modules/package/manager/conan/install_package.lua b/xmake/modules/package/manager/conan/install_package.lua index 201c50841..e1ad06df4 100644 --- a/xmake/modules/package/manager/conan/install_package.lua +++ b/xmake/modules/package/manager/conan/install_package.lua @@ -219,7 +219,7 @@ function main(name, opt) table.insert(argv, "compiler.runtime=" .. opt.vs_runtime) end elseif opt.plat == "iphoneos" then - local target_minver = config.get("target_minver") + local target_minver = config.get("target_minver_iphoneos") if target_minver and tonumber(target_minver) > 10 and (arch == "armv7" or arch == "armv7s" or arch == "x86") then target_minver = "10" -- iOS 10 is the maximum deployment target for 32-bit targets end diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index 7299f20b4..f35b489b4 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -20,7 +20,9 @@ -- imports import("core.base.option") +import("core.tool.toolchain") import("lib.detect.find_file") +import("lib.detect.find_tool") -- get configs function _get_configs(package, configs) @@ -118,10 +120,12 @@ function install(package, configs, opt) -- do build and install if package:is_plat("windows") then local slnfile = assert(find_file("*.sln", os.curdir()), "*.sln file not found!") - os.vrun("msbuild \"%s\" -nologo -t:Rebuild -p:Configuration=%s -p:Platform=%s", slnfile, package:debug() and "Debug" or "Release", package:is_arch("x64") and "x64" or "Win32") + local runenvs = toolchain.load("msvc", {plat = package:plat(), arch = package:arch()}):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.vrunv(msbuild.program, {slnfile, "-nologo", "-t:Rebuild", "-p:Configuration=" .. (package:debug() and "Debug" or "Release"), "-p:Platform=" .. (package:is_arch("x64") and "x64" or "Win32")}, {envs = runenvs}) local projfile = os.isfile("INSTALL.vcxproj") and "INSTALL.vcxproj" or "INSTALL.vcproj" if os.isfile(projfile) then - os.vrun("msbuild \"%s\" /property:configuration=%s", projfile, package:debug() and "Debug" or "Release") + os.vrunv(msbuild.program, {projfile, "/property:configuration=" .. (package:debug() and "Debug" or "Release")}, {envs = runenvs}) os.trycp("install/lib", package:installdir()) -- perhaps only headers library os.cp("install/include", package:installdir()) else diff --git a/xmake/modules/package/tools/msbuild.lua b/xmake/modules/package/tools/msbuild.lua new file mode 100644 index 000000000..98263d5bf --- /dev/null +++ b/xmake/modules/package/tools/msbuild.lua @@ -0,0 +1,49 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file msbuild.lua +-- + +-- imports +import("core.base.option") +import("core.tool.toolchain") +import("lib.detect.find_tool") + +-- build package +function build(package, configs, opt) + + -- init options + opt = opt or {} + + -- pass configurations + local argv = {} + for name, value in pairs(configs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end + + -- do build + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.vrunv(msbuild.program, argv, {envs = runenvs}) +end diff --git a/xmake/modules/package/tools/nmake.lua b/xmake/modules/package/tools/nmake.lua new file mode 100644 index 000000000..d948df039 --- /dev/null +++ b/xmake/modules/package/tools/nmake.lua @@ -0,0 +1,78 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file nmake.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.tool.toolchain") +import("lib.detect.find_tool") + +-- build package +function build(package, configs, opt) + + -- init options + opt = opt or {} + + -- pass configurations + local argv = {} + if option.get("verbose") then + table.insert(argv, "VERBOSE=1") + end + for name, value in pairs(configs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end + + -- do build + local runenvs = toolchain.load("msvc"):runenvs() + local nmake = find_tool("nmake", {envs = runenvs}) + os.vrunv(nmake.program, argv, {envs = runenvs}) +end + +-- install package +function install(package, configs) + + -- pass configurations + local argv = {"install"} + if option.get("verbose") then + table.insert(argv, "VERBOSE=1") + end + for name, value in pairs(configs) do + value = tostring(value):trim() + if value ~= "" then + if type(name) == "number" then + table.insert(argv, value) + else + table.insert(argv, name .. "=" .. value) + end + end + end + + -- do install + local runenvs = toolchain.load("msvc"):runenvs() + local nmake = find_tool("nmake", {envs = runenvs}) + os.vrunv(nmake.program, argv, {envs = runenvs}) +end diff --git a/xmake/modules/private/action/trybuild/cmake.lua b/xmake/modules/private/action/trybuild/cmake.lua index d5e0cbce2..684941c39 100644 --- a/xmake/modules/private/action/trybuild/cmake.lua +++ b/xmake/modules/private/action/trybuild/cmake.lua @@ -22,6 +22,7 @@ import("core.base.cli") import("core.base.option") import("core.project.config") +import("core.tool.toolchain") import("lib.detect.find_file") import("lib.detect.find_tool") @@ -76,7 +77,9 @@ function clean() if configfile then local oldir = os.cd(buildir) if is_plat("windows") then - os.vexec("msbuild \"%s\" -nologo -t:Clean -p:Configuration=%s -p:Platform=%s", configfile, is_mode("debug") and "Debug" or "Release", is_arch("x64") and "x64" or "Win32") + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.vexecv(msbuild.program, {configfile, "-nologo", "-t:Clean", "-p:Configuration=" .. (is_mode("debug") and "Debug" or "Release"), "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs}) else os.vexec("make clean") end @@ -107,11 +110,13 @@ function build() -- do build if is_plat("windows") then + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) local slnfile = assert(find_file("*.sln", os.curdir()), "*.sln file not found!") - os.vexec("msbuild \"%s\" -nologo -t:Build -p:Configuration=%s -p:Platform=%s", slnfile, is_mode("debug") and "Debug" or "Release", is_arch("x64") and "x64" or "Win32") + os.vexecv(msbuild.program, {slnfile, "-nologo", "-t:Build", "-p:Configuration=" .. (is_mode("debug") and "Debug" or "Release"), "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs}) local projfile = os.isfile("INSTALL.vcxproj") and "INSTALL.vcxproj" or "INSTALL.vcproj" if os.isfile(projfile) then - os.vexec("msbuild \"%s\" /property:configuration=%s", projfile, is_mode("debug") and "Debug" or "Release") + os.vexecv(msbuild.program, {projfile, "/property:configuration=" .. (is_mode("debug") and "Debug" or "Release")}, {envs = runenvs}) end else local argv = {"-j" .. option.get("jobs")} diff --git a/xmake/modules/private/action/trybuild/msbuild.lua b/xmake/modules/private/action/trybuild/msbuild.lua index 0cd00fef9..e86830900 100644 --- a/xmake/modules/private/action/trybuild/msbuild.lua +++ b/xmake/modules/private/action/trybuild/msbuild.lua @@ -21,7 +21,9 @@ -- imports import("core.base.option") import("core.project.config") +import("core.tool.toolchain") import("lib.detect.find_file") +import("lib.detect.find_tool") -- detect build-system and configuration file function detect() @@ -32,7 +34,9 @@ end -- do clean function clean() - os.vexec("msbuild \"%s\" -nologo -t:Clean -p:Configuration=Release -p:Platform=%s", configfile, is_arch("x64") and "x64" or "Win32") + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.vexecv(msbuild.program, {configfile, "-nologo", "-t:Clean", "-p:Configuration=Release", "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs}) end -- do build @@ -42,6 +46,9 @@ function build() assert(is_subhost(config.plat()), "msbuild: %s not supported!", config.plat()) -- do build - os.vexec("msbuild \"%s\" -nologo -t:Build -p:Configuration=Release -p:Platform=%s", configfile, is_arch("x64") and "x64" or "Win32") + local configfile = find_file("*.sln", os.curdir()) + local runenvs = toolchain.load("msvc"):runenvs() + local msbuild = find_tool("msbuild", {envs = runenvs}) + os.vexecv(msbuild.program, {configfile, "-nologo", "-t:Build", "-p:Configuration=Release", "-p:Platform=" .. (is_arch("x64") and "x64" or "Win32")}, {envs = runenvs}) cprint("${color.success}build ok!") end diff --git a/xmake/modules/private/tools/vstool.lua b/xmake/modules/private/tools/vstool.lua index e632ed00f..b53758838 100644 --- a/xmake/modules/private/tools/vstool.lua +++ b/xmake/modules/private/tools/vstool.lua @@ -31,10 +31,10 @@ function runv(program, argv, opt) -- enable unicode output for vs toolchains, e.g. cl.exe, link.exe and etc. -- @see https://github.com/xmake-io/xmake/issues/528 - local envs = {VS_UNICODE_OUTPUT = outfile:rawfd()} + opt.envs = table.join(opt.envs or {}, {VS_UNICODE_OUTPUT = outfile:rawfd()}) -- execute it - local ok, syserrors = os.execv(program, argv, table.join(opt, {try = true, stdout = outfile, stderr = errpath, envs = envs})) + local ok, syserrors = os.execv(program, argv, table.join(opt, {try = true, stdout = outfile, stderr = errpath})) -- close outfile first outfile:close() @@ -93,10 +93,10 @@ function iorunv(program, argv, opt) -- enable unicode output for vs toolchains, e.g. cl.exe, link.exe and etc. -- @see https://github.com/xmake-io/xmake/issues/528 - local envs = {VS_UNICODE_OUTPUT = outfile:rawfd()} + opt.envs = table.join(opt.envs or {}, {VS_UNICODE_OUTPUT = outfile:rawfd()}) -- run command - local ok, syserrors = os.execv(program, argv, table.join(opt, {try = true, stdout = outfile, stderr = errpath, envs = envs})) + local ok, syserrors = os.execv(program, argv, table.join(opt, {try = true, stdout = outfile, stderr = errpath})) -- get output and error data outfile:close() @@ -132,7 +132,7 @@ function iorunv(program, argv, opt) errors = string.format("vstool.iorunv(%s), %s", cmd, syserrors and syserrors or "unknown reason") end end - + -- raise errors os.raise({errors = errors, stderr = errdata, stdout = outdata}) end diff --git a/xmake/platforms/windows/xmake.lua b/xmake/platforms/windows/xmake.lua index 5c29b0e0b..9dd8fecbd 100644 --- a/xmake/platforms/windows/xmake.lua +++ b/xmake/platforms/windows/xmake.lua @@ -48,7 +48,7 @@ platform("windows") end) -- set toolchains - set_toolchains("vs", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go") + set_toolchains("msvc", "clang", "yasm", "nasm", "cuda", "dlang", "rust", "go") -- set menu set_menu { diff --git a/xmake/plugins/project/main.lua b/xmake/plugins/project/main.lua index 0cb8d0d0e..7090413ed 100755 --- a/xmake/plugins/project/main.lua +++ b/xmake/plugins/project/main.lua @@ -22,7 +22,6 @@ import("core.base.option") import("core.base.task") import("core.project.config") -import("core.platform.environment") import("make.makefile") import("make.xmakefile") import("cmake.cmakelists") @@ -82,15 +81,9 @@ function main() -- config it first task.run("config") - -- enter toolchains environment - environment.enter("toolchains") - -- make project _make(option.get("kind")) - -- leave toolchains environment - environment.leave("toolchains") - -- trace cprint("${color.success}create ok!") end diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua index 1168ae3e7..01a38e670 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x.lua @@ -23,7 +23,6 @@ import("core.base.option") import("core.project.config") import("core.project.project") import("core.platform.platform") -import("core.platform.environment") import("core.tool.compiler") import("core.tool.linker") import("vs201x_solution") @@ -234,6 +233,9 @@ function make(outputdir, vsinfo) -- clear project to reload and recheck it project.clear() + -- check configure + config.check() + -- check project options project.check() @@ -247,9 +249,6 @@ function make(outputdir, vsinfo) -- ensure to enter project directory os.cd(project.directory()) - -- enter environment (maybe check flags by calling tools) - environment.enter("toolchains") - -- save targets for targetname, target in pairs(project.targets()) do if not target:isphony() then @@ -277,9 +276,6 @@ function make(outputdir, vsinfo) _make_targetheaders(mode, arch, target, mode_idx == #vsinfo.modes and arch_idx == 2) end end - - -- leave environment - environment.leave("toolchains") end end diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua index b69651f5f..3e9de321f 100644 --- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua +++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua @@ -36,16 +36,6 @@ function _get_toolset_ver(targetinfo, vsinfo) if not toolset_ver then toolset_ver = vsinfo.toolset_version end - - -- for xp? - for _, flag in ipairs(targetinfo.linkflags) do - if flag:lower():find("^[%-/]subsystem:.-,5%.%d+$") then - toolset_ver = toolset_ver .. "_xp" - break - end - end - - -- done return toolset_ver end diff --git a/xmake/plugins/project/vsxmake/getinfo.lua b/xmake/plugins/project/vsxmake/getinfo.lua index cbfbf13d9..1cd51035b 100644 --- a/xmake/plugins/project/vsxmake/getinfo.lua +++ b/xmake/plugins/project/vsxmake/getinfo.lua @@ -26,7 +26,6 @@ import("core.project.config") import("core.project.cache") import("core.project.project") import("core.platform.platform") -import("core.platform.environment") import("core.tool.compiler") import("core.tool.linker") import("lib.detect.find_tool") @@ -285,6 +284,9 @@ function main(outputdir, vsinfo) -- clear project to reload and recheck it project.clear() + -- check configure + config.check() + -- check project options project.check() @@ -300,9 +302,6 @@ function main(outputdir, vsinfo) -- ensure to enter project directory os.cd(project.directory()) - -- enter environment (maybe check flags by calling tools) - environment.enter("toolchains") - -- save targets for targetname, target in pairs(project.targets()) do if not target:isphony() then @@ -333,9 +332,6 @@ function main(outputdir, vsinfo) _target.deps = table.unique(table.join(_target.deps or {}, table.keys(target:deps()), nil)) end end - - -- leave environment - environment.leave("toolchains") end end diff --git a/xmake/plugins/show/lists/envs.lua b/xmake/plugins/show/lists/envs.lua new file mode 100644 index 000000000..18fbed14b --- /dev/null +++ b/xmake/plugins/show/lists/envs.lua @@ -0,0 +1,42 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file envs.lua +-- + +-- imports +import("core.base.text") +import("core.base.global") +import("core.project.config") + +-- show all toolchains +function main() + + local envs = { XMAKE_PROGRAM_DIR = {"Set the program scripts directory of xmake.", os.programdir()}, + XMAKE_CONFIGDIR = {"Set the local config directory of project.", config.directory()}, + XMAKE_GLOBALDIR = {"Set the global config directory of xmake.", global.directory()}, + XMAKE_COLORTERM = {"Set the color terminal environment.", os.getenv("XMAKE_COLORTERM") or os.getenv("COLORTERM")}, + XMAKE_LOGFILE = {"Set the log output file path.", os.getenv("XMAKE_LOGFILE")}, + XMAKE_ROOT = {"Allow xmake to run under root.", os.getenv("XMAKE_ROOT")}, + XMAKE_RAMDIR = {"Set the ramdisk directory.", os.getenv("XMAKE_RAMDIR")}, + XMAKE_TMPDIR = {"Set the temporary directory.", os.tmpdir()}} + local width = 24 + for name, env in pairs(envs) do + cprint("${color.dump.string}%s${clear}%s%s", name, (" "):rep(width - #name), env[1]) + cprint("%s${bright}%s", (" "):rep(width), env[2] or "<empty>") + end +end diff --git a/xmake/rules/qt/deploy/macosx.lua b/xmake/rules/qt/deploy/macosx.lua index bbefe38ee..6b3549ec2 100644 --- a/xmake/rules/qt/deploy/macosx.lua +++ b/xmake/rules/qt/deploy/macosx.lua @@ -59,7 +59,7 @@ function _save_info_plist(target, info_plist_file) <key>NSPrincipalClass</key> <string>NSApplication</string> </dict> -</plist>]], name, name, name, name, get_config("target_minver") or (macos.version():major() .. "." .. macos.version():minor()))) +</plist>]], name, name, name, name, get_config("target_minver_macosx") or (macos.version():major() .. "." .. macos.version():minor()))) end -- deploy application package for macosx diff --git a/xmake/rules/xcode/info_plist/xmake.lua b/xmake/rules/xcode/info_plist/xmake.lua index 611969e0c..6f1899f8e 100644 --- a/xmake/rules/xcode/info_plist/xmake.lua +++ b/xmake/rules/xcode/info_plist/xmake.lua @@ -60,7 +60,7 @@ rule("xcode.info_plist") PRODUCT_NAME = target:name(), PRODUCT_DISPLAY_NAME = target:name(), CURRENT_PROJECT_VERSION = target:version() and tostring(target:version()) or "1.0", - MACOSX_DEPLOYMENT_TARGET = get_config("target_minver") + MACOSX_DEPLOYMENT_TARGET = get_config("target_minver_macosx") } if target:rule("xcode.bundle") then maps.PRODUCT_BUNDLE_PACKAGE_TYPE = "BNDL" diff --git a/xmake/rules/xcode/storyboard/xmake.lua b/xmake/rules/xcode/storyboard/xmake.lua index bc9444d38..264525b61 100644 --- a/xmake/rules/xcode/storyboard/xmake.lua +++ b/xmake/rules/xcode/storyboard/xmake.lua @@ -57,11 +57,14 @@ rule("xcode.storyboard") os.tryrm(base_lproj) -- do compile + local target_minver local argv = {"--errors", "--warnings", "--notices", "--auto-activate-custom-fonts", "--output-format", "human-readable-text"} if is_plat("macosx") then + target_minver = get_config("target_minver_macosx") table.insert(argv, "--target-device") table.insert(argv, "mac") elseif is_plat("iphoneos") then + target_minver = get_config("target_minver_iphoneos") table.insert(argv, "--target-device") table.insert(argv, "iphone") table.insert(argv, "--target-device") @@ -69,8 +72,10 @@ rule("xcode.storyboard") else assert("unknown device!") end - table.insert(argv, "--minimum-deployment-target") - table.insert(argv, get_config("target_minver")) + if target_minver then + table.insert(argv, "--minimum-deployment-target") + table.insert(argv, target_minver) + end table.insert(argv, "--compilation-directory") table.insert(argv, base_lproj) table.insert(argv, sourcefile) @@ -82,8 +87,10 @@ rule("xcode.storyboard") table.insert(argv, "--target-device") table.insert(argv, "mac") end - table.insert(argv, "--minimum-deployment-target") - table.insert(argv, get_config("target_minver")) + if target_minver then + table.insert(argv, "--minimum-deployment-target") + table.insert(argv, target_minver) + end table.insert(argv, "--link") table.insert(argv, resourcesdir) table.insert(argv, path.join(base_lproj, path.filename(sourcefile) .. "c")) diff --git a/xmake/rules/xcode/xcassets/xmake.lua b/xmake/rules/xcode/xcassets/xmake.lua index df25794e5..6803a2999 100644 --- a/xmake/rules/xcode/xcassets/xmake.lua +++ b/xmake/rules/xcode/xcassets/xmake.lua @@ -60,13 +60,16 @@ rule("xcode.xcassets") io.writefile(assetcatalog_generated_info_plist, "") -- do compile + local target_minver local argv = {"--warnings", "--notices", "--output-format", "human-readable-text"} if is_plat("macosx") then + target_minver = get_config("target_minver_macosx") table.insert(argv, "--target-device") table.insert(argv, "mac") table.insert(argv, "--platform") table.insert(argv, "macosx") elseif is_plat("iphoneos") then + target_minver = get_config("target_minver_iphoneos") table.insert(argv, "--target-device") table.insert(argv, "iphone") table.insert(argv, "--target-device") @@ -76,8 +79,10 @@ rule("xcode.xcassets") else assert("unknown device!") end - table.insert(argv, "--minimum-deployment-target") - table.insert(argv, get_config("target_minver")) + if target_minver then + table.insert(argv, "--minimum-deployment-target") + table.insert(argv, target_minver) + end table.insert(argv, "--app-icon") table.insert(argv, "AppIcon") if is_plat("iphoneos") then diff --git a/xmake/toolchains/clang/xmake.lua b/xmake/toolchains/clang/xmake.lua index 1319d9899..c616a4023 100644 --- a/xmake/toolchains/clang/xmake.lua +++ b/xmake/toolchains/clang/xmake.lua @@ -50,9 +50,9 @@ toolchain("clang") -- add march flags local march - if is_arch("x86_64", "x64") then + if toolchain:is_arch("x86_64", "x64") then march = "-m64" - elseif is_arch("i386", "x86") then + elseif toolchain:is_arch("i386", "x86") then march = "-m32" end if march then @@ -64,7 +64,7 @@ toolchain("clang") end -- add includedirs and linkdirs - if not is_plat("windows") and os.isdir("/usr") then + if not toolchain:is_plat("windows") and os.isdir("/usr") then for _, includedir in ipairs({"/usr/local/include", "/usr/include"}) do if os.isdir(includedir) then toolchain:add("includedirs", includedir) diff --git a/xmake/toolchains/dlang/xmake.lua b/xmake/toolchains/dlang/xmake.lua index 0c87d8505..e258e9af8 100644 --- a/xmake/toolchains/dlang/xmake.lua +++ b/xmake/toolchains/dlang/xmake.lua @@ -33,7 +33,7 @@ toolchain("dlang") -- on load on_load(function (toolchain) - local march = is_arch("x86_64", "x64") and "-m64" or "-m32" + local march = toolchain:is_arch("x86_64", "x64") and "-m64" or "-m32" toolchain:add("dcflags", march) toolchain:add("dcshflags", march) toolchain:add("dcldflags", march) diff --git a/xmake/toolchains/gcc/xmake.lua b/xmake/toolchains/gcc/xmake.lua index ab12fd13a..8a4a53bb5 100644 --- a/xmake/toolchains/gcc/xmake.lua +++ b/xmake/toolchains/gcc/xmake.lua @@ -50,9 +50,9 @@ toolchain("gcc") -- add march flags local march - if is_arch("x86_64", "x64") then + if toolchain:is_arch("x86_64", "x64") then march = "-m64" - elseif is_arch("i386", "x86") then + elseif toolchain:is_arch("i386", "x86") then march = "-m32" end if march then @@ -64,7 +64,7 @@ toolchain("gcc") end -- add includedirs and linkdirs - if not is_plat("windows") and os.isdir("/usr") then + if not toolchain:is_plat("windows") and os.isdir("/usr") then for _, includedir in ipairs({"/usr/local/include", "/usr/include"}) do if os.isdir(includedir) then toolchain:add("includedirs", includedir) diff --git a/xmake/toolchains/llvm/check.lua b/xmake/toolchains/llvm/check.lua index 04d4d6dec..d590b4381 100644 --- a/xmake/toolchains/llvm/check.lua +++ b/xmake/toolchains/llvm/check.lua @@ -29,7 +29,7 @@ function main(toolchain) local sdkdir = config.get("sdk") local bindir = config.get("bin") if not sdkdir and not bindir then - if is_plat("linux") and os.isfile("/usr/bin/llvm-ar") then + if toolchain:is_plat("linux") and os.isfile("/usr/bin/llvm-ar") then sdkdir = "/usr" end end diff --git a/xmake/toolchains/llvm/xmake.lua b/xmake/toolchains/llvm/xmake.lua index d4371682c..3912ab8d7 100644 --- a/xmake/toolchains/llvm/xmake.lua +++ b/xmake/toolchains/llvm/xmake.lua @@ -48,9 +48,9 @@ toolchain("llvm") -- add march flags local march - if is_arch("x86_64", "x64") then + if toolchain:is_arch("x86_64", "x64") then march = "-m64" - elseif is_arch("i386", "x86") then + elseif toolchain:is_arch("i386", "x86") then march = "-m32" end if march then diff --git a/xmake/toolchains/mingw/xmake.lua b/xmake/toolchains/mingw/xmake.lua index 2d246553a..e5603527f 100644 --- a/xmake/toolchains/mingw/xmake.lua +++ b/xmake/toolchains/mingw/xmake.lua @@ -39,9 +39,9 @@ toolchain("mingw") -- get cross local cross - if is_arch("x86_64") then + if toolchain:is_arch("x86_64") then cross = "x86_64-w64-mingw32-" - elseif is_arch("i386") then + elseif toolchain:is_arch("i386") then cross = "i686-w64-mingw32-" else cross = config.get("cross") or "" @@ -75,7 +75,7 @@ toolchain("mingw") -- init flags for architecture local archflags = nil - local arch = config.get("arch") + local arch = toolchain:arch() if arch then if arch == "x86_64" then archflags = "-m64" elseif arch == "i386" then archflags = "-m32" diff --git a/xmake/toolchains/vs/check.lua b/xmake/toolchains/msvc/check.lua index 12fac2aa0..d4861e16d 100644 --- a/xmake/toolchains/vs/check.lua +++ b/xmake/toolchains/msvc/check.lua @@ -25,7 +25,7 @@ import("detect.sdks.find_vstudio") import("lib.detect.find_tool") -- attempt to check vs environment -function _check_vsenv() +function _check_vsenv(toolchain) -- have been checked? local vs = config.get("vs") @@ -52,28 +52,18 @@ function _check_vsenv() -- get vcvarsall for _, vsver in ipairs(vsvers) do local vcvarsall = (vstudio[vsver] or {}).vcvarsall or {} - local vsenv = vcvarsall[config.get("arch") or ""] + local vsenv = vcvarsall[toolchain:arch()] if vsenv and vsenv.path and vsenv.include and vsenv.lib then -- save vsenv config.set("__vcvarsall", vcvarsall) -- check compiler - local oldenvs = {} - oldenvs.PATH = os.getenv("PATH") - oldenvs.LIB = os.getenv("LIB") - os.setenv("PATH", vsenv.path .. ';' .. (oldenvs.PATH or "")) - os.setenv("LIB", vsenv.lib .. ';' .. (oldenvs.LIB or "")) local program = nil - local tool = find_tool("cl.exe", {force = true}) + local tool = find_tool("cl.exe", {force = true, envs = vsenv}) if tool then program = tool.program end - for name, values in pairs(oldenvs) do - os.setenv(name, values) - end - - -- ok? if program then return vsver end @@ -83,13 +73,13 @@ function _check_vsenv() end -- check the visual studio -function _check_vstudio() - local vs = _check_vsenv() +function _check_vstudio(toolchain) + local vs = _check_vsenv(toolchain) if vs then config.set("vs", vs, {readonly = true, force = true}) - cprint("checking for the Microsoft Visual Studio (%s) version ... ${color.success}%s", config.get("arch"), vs) + cprint("checking for the Microsoft Visual Studio (%s) version ... ${color.success}%s", toolchain:arch(), vs) else - cprint("checking for the Microsoft Visual Studio (%s) version ... ${color.nothing}${text.nothing}", config.get("arch")) + cprint("checking for the Microsoft Visual Studio (%s) version ... ${color.nothing}${text.nothing}", toolchain:arch()) if not (opt and opt.try) then print("please run:") print(" - xmake config --vs=xxx [--vs_toolset=xxx]") @@ -101,13 +91,13 @@ function _check_vstudio() end -- main entry -function main() +function main(toolchain) -- @see https://github.com/xmake-io/xmake/pull/679 local cc = path.basename(config.get("cc") or "cl"):lower() local cxx = path.basename(config.get("cxx") or "cl"):lower() local mrc = path.basename(config.get("mrc") or "rc"):lower() if cc == "cl" or cxx == "cl" or mrc == "rc" then - return _check_vstudio(config) + return _check_vstudio(toolchain) end end diff --git a/xmake/toolchains/vs/load.lua b/xmake/toolchains/msvc/load.lua index af32ca092..3b25a298f 100644 --- a/xmake/toolchains/vs/load.lua +++ b/xmake/toolchains/msvc/load.lua @@ -32,10 +32,8 @@ function _add_vsenv(toolchain, name) return end - -- get arch - local arch = config.get("arch") or "" - -- get vs environment for the current arch + local arch = toolchain:arch() local vsenv = vcvarsall[arch] or {} -- switch vstudio environment if vs_sdkver has been changed @@ -71,14 +69,14 @@ function main(toolchain) toolchain:set("toolset", "cc", "cl.exe") toolchain:set("toolset", "cxx", "cl.exe") toolchain:set("toolset", "mrc", "rc.exe") - if is_arch("x64") then + if toolchain:is_arch("x64") then toolchain:set("toolset", "as", "ml64.exe") else toolchain:set("toolset", "as", "ml.exe") end toolchain:set("toolset", "ld", "link.exe") - toolchain:set("toolset", "sh", "link.exe -dll") - toolchain:set("toolset", "ar", "link.exe -lib") + toolchain:set("toolset", "sh", "link.exe") + toolchain:set("toolset", "ar", "link.exe") toolchain:set("toolset", "ex", "lib.exe") -- add vs environments diff --git a/xmake/toolchains/vs/xmake.lua b/xmake/toolchains/msvc/xmake.lua index 4bbc5798c..b9f80cdc1 100644 --- a/xmake/toolchains/vs/xmake.lua +++ b/xmake/toolchains/msvc/xmake.lua @@ -19,11 +19,11 @@ -- -- define toolchain -toolchain("vs") +toolchain("msvc") -- set homepage set_homepage("https://visualstudio.microsoft.com") - set_description("VisualStudio IDE") + set_description("Microsoft Visual C/C++ Compiler") -- mark as standalone toolchain set_kind("standalone") diff --git a/xmake/toolchains/nasm/xmake.lua b/xmake/toolchains/nasm/xmake.lua index 164eaedd8..3d31a1e93 100644 --- a/xmake/toolchains/nasm/xmake.lua +++ b/xmake/toolchains/nasm/xmake.lua @@ -30,11 +30,11 @@ toolchain("nasm") -- on load on_load(function (toolchain) - if is_plat("macosx") then - toolchain:add("nasm.asflags", "-f", is_arch("x86_64") and "macho64" or "macho32") - elseif is_plat("linux", "bsd") then - toolchain:add("nasm.asflags", "-f", is_arch("x86_64") and "elf64" or "elf32") - elseif is_plat("windows", "mingw", "msys", "cygwin") then - toolchain:add("nasm.asflags", "-f", is_arch("x64") and "win64" or "win32") + if toolchain:is_plat("macosx") then + toolchain:add("nasm.asflags", "-f", toolchain:is_arch("x86_64") and "macho64" or "macho32") + elseif toolchain:is_plat("linux", "bsd") then + toolchain:add("nasm.asflags", "-f", toolchain:is_arch("x86_64") and "elf64" or "elf32") + elseif toolchain:is_plat("windows", "mingw", "msys", "cygwin") then + toolchain:add("nasm.asflags", "-f", toolchain:is_arch("x64") and "win64" or "win32") end end) diff --git a/xmake/toolchains/ndk/load.lua b/xmake/toolchains/ndk/load.lua index 153a93f9b..cbc2ab4a2 100644 --- a/xmake/toolchains/ndk/load.lua +++ b/xmake/toolchains/ndk/load.lua @@ -48,7 +48,7 @@ function main(toolchain) -- init flags local arm32 = false - local arch = config.get("arch") + local arch = toolchain:arch() toolchain:add("ldflags", "-llog") toolchain:add("shflags", "-llog") if arch and (arch == "armeabi" or arch == "armeabi-v7a" or arch == "armv5te" or arch == "armv7-a") then -- armv5te/armv7-a are deprecated diff --git a/xmake/toolchains/sdcc/xmake.lua b/xmake/toolchains/sdcc/xmake.lua index ce4862822..c76723c2a 100644 --- a/xmake/toolchains/sdcc/xmake.lua +++ b/xmake/toolchains/sdcc/xmake.lua @@ -67,7 +67,7 @@ toolchain("sdcc") end -- add port flags for arch - local arch = get_config("arch") + local arch = toolchain:arch() if arch then toolchain:add("cxflags", "-m" .. arch) toolchain:add("ldflags", "-m" .. arch) diff --git a/xmake/toolchains/xcode/check.lua b/xmake/toolchains/xcode/check.lua index 925db3870..e49957b17 100644 --- a/xmake/toolchains/xcode/check.lua +++ b/xmake/toolchains/xcode/check.lua @@ -27,7 +27,7 @@ import("detect.sdks.find_xcode") function main(toolchain) -- find xcode - local xcode = find_xcode(config.get("xcode"), {force = not optional, verbose = true, plat = config.get("plat"), arch = config.get("arch")}) + local xcode = find_xcode(config.get("xcode"), {force = not optional, verbose = true, plat = toolchain:plat(), arch = toolchain:arch()}) if xcode then config.set("xcode", xcode.sdkdir, {force = true, readonly = true}) else @@ -35,17 +35,32 @@ function main(toolchain) end -- save target minver - local xcode_sdkver = config.get("xcode_sdkver") - local target_minver = config.get("target_minver") + -- + -- @note we need to differentiate the version for the system, + -- because the xcode toolchain of iphoneos/macosx may need to be used at the same time. + -- + -- e.g. + -- + -- target("test") + -- set_toolchains("xcode", {plat = os.host(), arch = os.arch()}) + -- + local xcode_sdkver = toolchain:is_plat(config.plat()) and config.get("xcode_sdkver") + if not xcode_sdkver then + xcode_sdkver = config.get("xcode_sdkver_" .. toolchain:plat()) + end + local target_minver = toolchain:is_plat(config.plat()) and config.get("target_minver") + if not target_minver then + target_minver = config.get("target_minver_" .. toolchain:plat()) + end if xcode_sdkver and not target_minver then target_minver = xcode_sdkver - if is_plat("macosx") then + if toolchain:is_plat("macosx") then local macos_ver = macos.version() if macos_ver then target_minver = macos_ver:major() .. "." .. macos_ver:minor() end end - config.set("target_minver", target_minver) + config.set("target_minver_" .. toolchain:plat(), target_minver) end return true end diff --git a/xmake/toolchains/xcode/load_iphoneos.lua b/xmake/toolchains/xcode/load_iphoneos.lua index 3aeb78672..1d495a5cb 100644 --- a/xmake/toolchains/xcode/load_iphoneos.lua +++ b/xmake/toolchains/xcode/load_iphoneos.lua @@ -25,14 +25,14 @@ import("core.project.config") function main(toolchain) -- init architecture - local arch = config.get("arch") or "arm64" + local arch = toolchain:arch() local simulator = (arch == "i386" or arch == "x86_64") -- init platform name local platname = simulator and "iPhoneSimulator" or "iPhoneOS" -- init target minimal version - local target_minver = config.get("target_minver") + local target_minver = config.get("target_minver_iphoneos") if target_minver and tonumber(target_minver) > 10 and (arch == "armv7" or arch == "armv7s" or arch == "i386") then target_minver = "10" -- iOS 10 is the maximum deployment target for 32-bit targets end @@ -40,7 +40,7 @@ function main(toolchain) -- init the xcode sdk directory local xcode_dir = config.get("xcode") - local xcode_sdkver = config.get("xcode_sdkver") + local xcode_sdkver = config.get("xcode_sdkver_iphoneos") local xcode_sdkdir = format("%s/Contents/Developer/Platforms/%s.platform/Developer/SDKs/%s%s.sdk", xcode_dir, platname, platname, xcode_sdkver) -- init flags for c/c++ diff --git a/xmake/toolchains/xcode/load_macosx.lua b/xmake/toolchains/xcode/load_macosx.lua index de7dddb1e..c16fd6665 100644 --- a/xmake/toolchains/xcode/load_macosx.lua +++ b/xmake/toolchains/xcode/load_macosx.lua @@ -25,12 +25,12 @@ import("core.project.config") function main(toolchain) -- init flags for architecture - local arch = config.get("arch") or os.arch() - local target_minver = config.get("target_minver") + local arch = toolchain:arch() + local target_minver = config.get("target_minver_macosx") -- init flags for the xcode sdk directory local xcode_dir = config.get("xcode") - local xcode_sdkver = config.get("xcode_sdkver") + local xcode_sdkver = config.get("xcode_sdkver_macosx") local xcode_sdkdir = nil if xcode_dir and xcode_sdkver then xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" .. xcode_sdkver .. ".sdk" diff --git a/xmake/toolchains/xcode/load_watchos.lua b/xmake/toolchains/xcode/load_watchos.lua index 5048f4bb7..cae0b40d4 100644 --- a/xmake/toolchains/xcode/load_watchos.lua +++ b/xmake/toolchains/xcode/load_watchos.lua @@ -25,19 +25,19 @@ import("core.project.config") function main(toolchain) -- init architecture - local arch = config.get("arch") + local arch = toolchain:arch() local simulator = arch == "i386" -- init platform name local platname = simulator and "WatchSimulator" or "WatchOS" -- init target minimal version - local target_minver = config.get("target_minver") + local target_minver = config.get("target_minver_watchos") local target_minver_flags = (simulator and "-mwatchos-simulator-version-min=" or "-mwatchos-version-min=") .. target_minver -- init the xcode sdk directory local xcode_dir = config.get("xcode") - local xcode_sdkver = config.get("xcode_sdkver") + local xcode_sdkver = config.get("xcode_sdkver_watchos") local xcode_sdkdir = format("%s/Contents/Developer/Platforms/%s.platform/Developer/SDKs/%s%s.sdk", xcode_dir, platname, platname, xcode_sdkver) -- init flags for c/c++ diff --git a/xmake/toolchains/xcode/xmake.lua b/xmake/toolchains/xcode/xmake.lua index 776c142af..7394c8a13 100644 --- a/xmake/toolchains/xcode/xmake.lua +++ b/xmake/toolchains/xcode/xmake.lua @@ -36,14 +36,14 @@ toolchain("xcode") -- get cross local cross, arch, simulator - if is_plat("macosx") then + if toolchain:is_plat("macosx") then cross = "xcrun -sdk macosx " - elseif is_plat("iphoneos") then - arch = get_config("arch") or os.arch() + elseif toolchain:is_plat("iphoneos") then + arch = toolchain:arch() simulator = (arch == "i386" or arch == "x86_64") cross = simulator and "xcrun -sdk iphonesimulator " or "xcrun -sdk iphoneos " - elseif is_plat("watchos") then - arch = get_config("arch") or os.arch() + elseif toolchain:is_plat("watchos") then + arch = toolchain:arch() simulator = (arch == "i386") cross = simulator and "xcrun -sdk watchsimulator " or "xcrun -sdk watchos " else @@ -67,7 +67,7 @@ toolchain("xcode") if arch then toolchain:set("toolset", "cpp", cross .. "clang -arch " .. arch .. " -E") end - if is_plat("macosx") then + if toolchain:is_plat("macosx") then toolchain:set("toolset", "as", cross .. "clang") elseif simulator then toolchain:set("toolset", "as", cross .. "clang") @@ -76,5 +76,5 @@ toolchain("xcode") end -- load configurations - import("load_" .. get_config("plat"))(toolchain) + import("load_" .. toolchain:plat())(toolchain) end) diff --git a/xmake/toolchains/yasm/xmake.lua b/xmake/toolchains/yasm/xmake.lua index 7811219b5..b28fe7cc0 100644 --- a/xmake/toolchains/yasm/xmake.lua +++ b/xmake/toolchains/yasm/xmake.lua @@ -30,11 +30,11 @@ toolchain("yasm") -- on load on_load(function (toolchain) - if is_plat("macosx") then - toolchain:add("yasm.asflags", "-f", is_arch("x86_64") and "macho64" or "macho32") - elseif is_plat("linux", "bsd") then - toolchain:add("yasm.asflags", "-f", is_arch("x86_64") and "elf64" or "elf32") - elseif is_plat("windows", "mingw", "msys", "cygwin") then - toolchain:add("yasm.asflags", "-f", is_arch("x86_64", "x64") and "win64" or "win32") + if toolchain:is_plat("macosx") then + toolchain:add("yasm.asflags", "-f", toolchain:is_arch("x86_64") and "macho64" or "macho32") + elseif toolchain:is_plat("linux", "bsd") then + toolchain:add("yasm.asflags", "-f", toolchain:is_arch("x86_64") and "elf64" or "elf32") + elseif toolchain:is_plat("windows", "mingw", "msys", "cygwin") then + toolchain:add("yasm.asflags", "-f", toolchain:is_arch("x86_64", "x64") and "win64" or "win32") end end) |
