diff options
| author | ruki <[email protected]> | 2021-01-08 11:35:04 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-01-08 11:35:04 +0800 |
| commit | b5a414be7af97fd058abb5dc5c37a7564da1c1ce (patch) | |
| tree | 6bfcb618892a7ad818eea1b9f642367599078e58 | |
| parent | 8a9dad0bbb9932cf5f5aa5cab10043a784028d53 (diff) | |
| parent | 0ff70c2c239a0857798583650dcd349c24292aa3 (diff) | |
Merge pull request #1175 from xmake-io/deps
Improve package deps
28 files changed, 624 insertions, 267 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 3d89a3303..88c22d90c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,7 +1,6 @@ #version: v2.1.8.{build} image: - Visual Studio 2013 - - Visual Studio 2015 - Visual Studio 2017 platform: diff --git a/.github/workflows/msys2_mingw.yml b/.github/workflows/msys2_mingw.yml index 0f41834aa..3964d5c2f 100644 --- a/.github/workflows/msys2_mingw.yml +++ b/.github/workflows/msys2_mingw.yml @@ -25,7 +25,7 @@ jobs: - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} - install: git base-devel mingw-w64-${{ matrix.arch }}-toolchain + install: git base-devel unzip mingw-w64-${{ matrix.arch }}-toolchain update: true - name: Move Checkout diff --git a/tests/projects/package/basic/test.lua b/tests/projects/package/basic/test.lua index a4b905689..8644a2af9 100644 --- a/tests/projects/package/basic/test.lua +++ b/tests/projects/package/basic/test.lua @@ -1,7 +1,6 @@ --- main entry function main(t) - - -- TODO - -- build project --- t:build() + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end end diff --git a/tests/projects/package/basic/xmake.lua b/tests/projects/package/basic/xmake.lua index b71a22c1d..f06d2a199 100644 --- a/tests/projects/package/basic/xmake.lua +++ b/tests/projects/package/basic/xmake.lua @@ -1,11 +1,11 @@ add_requires("tbox master", {debug = true}) add_requires("zlib >=1.2.11") -add_requires("pcre2", "luajit", {system = false, optional = true}) +add_requires("pcre2", {system = false, optional = true}) add_rules("mode.debug", "mode.release") target("console") set_kind("binary") add_files("src/*.c") - add_packages("tbox", "zlib", "pcre2", "luajit") + add_packages("tbox", "zlib", "pcre2") diff --git a/tests/projects/package/depconfigs/src/main.c b/tests/projects/package/depconfigs/src/main.c new file mode 100755 index 000000000..9ae580511 --- /dev/null +++ b/tests/projects/package/depconfigs/src/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char** argv) +{ + printf("hello world!\n"); + return 0; +} diff --git a/tests/projects/package/depconfigs/test.lua b/tests/projects/package/depconfigs/test.lua new file mode 100644 index 000000000..8644a2af9 --- /dev/null +++ b/tests/projects/package/depconfigs/test.lua @@ -0,0 +1,6 @@ +function main(t) + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end +end diff --git a/tests/projects/package/depconfigs/xmake.lua b/tests/projects/package/depconfigs/xmake.lua new file mode 100644 index 000000000..c76e92df5 --- /dev/null +++ b/tests/projects/package/depconfigs/xmake.lua @@ -0,0 +1,55 @@ +add_requires("libpng", "libtiff", {system = false, configs = {vs_runtime = "MD"}}) +add_requires("libwebp") + +add_requireconfs("libwebp", {system = false, configs = {shared = true, vs_runtime = "MD"}}) +add_requireconfs("libpng.zlib", {system = false, override = true, configs = {cxflags = "-DTEST1"}, version = "1.2.10"}) +add_requireconfs("libtiff.*|cmake", {system = false, configs = {cxflags = "-DTEST2"}}) +add_requireconfs("libwebp.**|cmake", {system = false, configs = {cxflags = "-DTEST3"}}) + +target("test") + set_kind("binary") + add_files("src/*.c") + add_packages("libpng") + before_build(function (target) + if target:pkg("libpng") then + local found + for _, linkdir in ipairs(target:pkg("libpng"):get("linkdirs")) do + if linkdir:find("zlib[/\\]1%.2%.10") then + found = true + end + end + assert(found, "package(zlib 1.2.10) not found!") + end + end) + +target("test2") + set_kind("binary") + add_files("src/*.c") + add_packages("libtiff") + before_build(function (target) + if target:pkg("libtiff") then + local found + for _, linkdir in ipairs(target:pkg("libtiff"):get("linkdirs")) do + if linkdir:find("zlib", 1, true) then + found = true + end + end + assert(found, "package(zlib) not found!") + end + end) + +target("test3") + set_kind("binary") + add_files("src/*.c") + add_packages("libwebp") + before_build(function (target) + if target:pkg("libwebp") then + local found + for _, linkdir in ipairs(target:pkg("libwebp"):get("linkdirs")) do + if linkdir:find("zlib", 1, true) then + found = true + end + end + assert(found, "package(zlib) not found!") + end + end) diff --git a/tests/projects/package/multiconfig/test.lua b/tests/projects/package/multiconfig/test.lua index a4b905689..8644a2af9 100644 --- a/tests/projects/package/multiconfig/test.lua +++ b/tests/projects/package/multiconfig/test.lua @@ -1,7 +1,6 @@ --- main entry function main(t) - - -- TODO - -- build project --- t:build() + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end end diff --git a/tests/projects/package/multiconfig/xmake.lua b/tests/projects/package/multiconfig/xmake.lua index 48d64da13..09121e8d2 100644 --- a/tests/projects/package/multiconfig/xmake.lua +++ b/tests/projects/package/multiconfig/xmake.lua @@ -11,7 +11,7 @@ target("test1") target("test2") set_kind("binary") add_files("src/*.c") - add_packages("zlib#debug") + add_packages("zlib~debug") target("test3") set_kind("binary") diff --git a/tests/projects/package/rootconfigs/src/main.c b/tests/projects/package/rootconfigs/src/main.c new file mode 100755 index 000000000..9ae580511 --- /dev/null +++ b/tests/projects/package/rootconfigs/src/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char** argv) +{ + printf("hello world!\n"); + return 0; +} diff --git a/tests/projects/package/rootconfigs/test.lua b/tests/projects/package/rootconfigs/test.lua new file mode 100644 index 000000000..8644a2af9 --- /dev/null +++ b/tests/projects/package/rootconfigs/test.lua @@ -0,0 +1,6 @@ +function main(t) + -- only for x86/x64, because it will take too long time on ci with arm/mips + if os.subarch():startswith("x") or os.subarch() == "i386" then + t:build() + end +end diff --git a/tests/projects/package/rootconfigs/xmake.lua b/tests/projects/package/rootconfigs/xmake.lua new file mode 100644 index 000000000..3e395ab7b --- /dev/null +++ b/tests/projects/package/rootconfigs/xmake.lua @@ -0,0 +1,7 @@ +add_requireconfs("*", {system = false, configs = {debug = false}}) +add_requires("zlib", {system = false, debug = true}) + +target("test") + set_kind("binary") + add_files("src/*.c") + add_packages("zlib") diff --git a/tests/test_utils/test_build.lua b/tests/test_utils/test_build.lua index 44026200b..2a42e67d8 100644 --- a/tests/test_utils/test_build.lua +++ b/tests/test_utils/test_build.lua @@ -9,7 +9,7 @@ function test_build:build(argv) os.exec("xmake g -c") -- generic? - os.exec("xmake f -c") + os.exec("xmake f -c -D -y") os.exec("xmake") os.exec("xmake p -D") if not is_host("windows") then @@ -17,7 +17,7 @@ function test_build:build(argv) os.exec("xmake uninstall --installdir=$(tmpdir) -D") end os.exec("xmake c -D") - os.exec("xmake f --mode=debug -D") + os.exec("xmake f --mode=debug -D -y") os.exec("xmake m -b") os.exec("xmake -r -a -D") os.exec("xmake m -e buildtest") diff --git a/xmake/actions/require/impl/actions/download.lua b/xmake/actions/require/impl/actions/download.lua index 3db3e2da9..25243eaa9 100644 --- a/xmake/actions/require/impl/actions/download.lua +++ b/xmake/actions/require/impl/actions/download.lua @@ -1,4 +1,4 @@ ---!The Make-like download Utility based on Lua +--!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. @@ -40,7 +40,7 @@ function _checkout(package, url, sourcedir, url_alias) not (option.get("force") and package:branch()) then -- we need disable cache if we force to clone from the given branch -- clean the previous build files - git.clean({repodir = packagedir, force = true}) + git.clean({repodir = packagedir, force = true, all = true}) -- reset the previous modified files git.reset({repodir = packagedir, hard = true}) tty.erase_line_to_start().cr() @@ -50,7 +50,7 @@ function _checkout(package, url, sourcedir, url_alias) -- 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}) + git.clean({repodir = localdir, force = true, all = true}) tty.erase_line_to_start().cr() return end diff --git a/xmake/actions/require/impl/actions/install.lua b/xmake/actions/require/impl/actions/install.lua index 2410e8edb..69d01c6be 100644 --- a/xmake/actions/require/impl/actions/install.lua +++ b/xmake/actions/require/impl/actions/install.lua @@ -1,4 +1,4 @@ ---!The Make-like install Utility based on Lua +--!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. @@ -211,7 +211,7 @@ function main(package) -- trace tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:name(), package:version_str() or "") + cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:displayname(), package:version_str() or "") end, catch @@ -230,7 +230,7 @@ function main(package) -- trace tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:name(), package:version_str() or "") + cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:displayname(), package:version_str() or "") -- leave the package environments package:envs_leave() diff --git a/xmake/actions/require/impl/package.lua b/xmake/actions/require/impl/package.lua index a63c948dc..755d0312a 100644 --- a/xmake/actions/require/impl/package.lua +++ b/xmake/actions/require/impl/package.lua @@ -74,20 +74,17 @@ end -- - add_requires("zlib~debug", {debug = true}) -- - add_requires("zlib~shared", {configs = {shared = true}, alias = "zlib_shared"}) -- +-- pass configs to all dependent packages +-- - add_requires("libpng", {deps = {system = false, configs = {shared = true, cxflags = "-DTEST"}}}) +-- -- {system = nil/true/false}: -- nil: get local or system packages -- true: only get system package -- false: only get local packages -- +-- function _parse_require(require_str, requires_extra, parentinfo) - -- get it from cache first - local requires = _memcache():get("requires") or {} - local required = requires[require_str] - if required then - return required.packagename, required.requireinfo - end - -- split package and version info local splitinfo = require_str:split('%s+') assert(splitinfo and #splitinfo > 0, "require(\"%s\"): invalid!", require_str) @@ -172,17 +169,12 @@ function _parse_require(require_str, requires_extra, parentinfo) system = require_extra.system, -- default: true, we can set it to disable system package manually option = require_extra.option, -- set and attach option configs = require_build_configs, -- the required building configurations + deps = require_extra.deps, -- the configuration passed to dependent packages default = require_extra.default, -- default: true, we can set it to disable package manually optional = parentinfo.optional or require_extra.optional, -- default: false, inherit parentinfo.optional verify = require_extra.verify, -- default: true, we can set false to ignore sha256sum and select any version - external = require_extra.external -- default: true, we use sysincludedirs/-isystem instead of -I/xxx + external = require_extra.external, -- default: true, we use sysincludedirs/-isystem instead of -I/xxx } - - -- save this required item to cache - requires[require_str] = required - _memcache():set("requires", requires) - - -- ok return required.packagename, required.requireinfo end @@ -244,6 +236,7 @@ function _add_package_configurations(package) package:add("configs", "cxflags", {builtin = true, description = "Set the C/C++ compiler flags."}) package:add("configs", "cxxflags", {builtin = true, description = "Set the C++ compiler flags."}) package:add("configs", "asflags", {builtin = true, description = "Set the assembler flags."}) + package:add("configs", "pic", {builtin = true, description = "Enable the position independent code.", default = true, type = "boolean"}) package:add("configs", "vs_runtime", {builtin = true, description = "Set vs compiler runtime.", default = vs_runtime, values = {"MT", "MTd", "MD", "MDd"}}) end @@ -278,7 +271,7 @@ function _select_package_version(package, requireinfo) elseif has_giturl then -- select branch? version, source = require_version ~= "latest" and require_version or "master", "branches" else - raise("package(%s %s): not found!", package:name(), require_version) + raise("package(%s %s): not found!", package:displayname(), require_version) end return version, source end @@ -301,7 +294,7 @@ function _check_package_configurations(package) if conf then local config_type = conf.type if config_type ~= nil and type(value) ~= config_type then - raise("package(%s %s): invalid type(%s) for config(%s), need type(%s)!", package:name(), package:version_str(), type(value), name, config_type) + raise("package(%s %s): invalid type(%s) for config(%s), need type(%s)!", package:displayname(), package:version_str(), type(value), name, config_type) end if conf.values then local found = false @@ -312,38 +305,177 @@ function _check_package_configurations(package) end end if not found then - raise("package(%s %s): invalid value(%s) for config(%s), please run `xmake require --info %s` to get all valid values!", package:name(), package:version_str(), value, name, package:name()) + raise("package(%s %s): invalid value(%s) for config(%s), please run `xmake require --info %s` to get all valid values!", package:displayname(), package:version_str(), value, name, package:name()) end end if conf.restrict then if not conf.restrict(value) then - raise("package(%s %s): invalid value(%s) for config(%s)!", package:name(), package:version_str(), value, name) + raise("package(%s %s): invalid value(%s) for config(%s)!", package:displayname(), package:version_str(), value, name) end end else - raise("package(%s %s): invalid config(%s), please run `xmake require --info %s` to get all configurations!", package:name(), package:version_str(), name, package:name()) + raise("package(%s %s): invalid config(%s), please run `xmake require --info %s` to get all configurations!", package:displayname(), package:version_str(), name, package:name()) end end end --- load required packages -function _load_package(packagename, requireinfo, opt) +-- match require path +function _match_requirepath(requirepath, requireconf) - -- attempt to get it from cache first - opt = opt or {} - local packages = _memcache():get("packages") or {} - local package = packages[packagename] - if package then + -- get pattern + local function _get_pattern(pattern) + pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1") + pattern = pattern:gsub("%*%*", "\001") + pattern = pattern:gsub("%*", "\002") + pattern = pattern:gsub("\001", ".*") + pattern = pattern:gsub("\002", "[^.]*") + pattern = string.ipattern(pattern, true) + return pattern + end + + -- get the excludes + local excludes = requireconf:match("|.*$") + if excludes then excludes = excludes:split("|", {plain = true}) end + + -- do match + local pattern = requireconf:gsub("|.*$", "") + pattern = _get_pattern(pattern) + if (requirepath:match('^' .. pattern .. '$')) then + -- exclude sub-deps, e.g. "libwebp.**|cmake|autoconf" + local splitinfo = requirepath:split(".", {plain = true}) + if #splitinfo > 0 then + local name = splitinfo[#splitinfo] + for _, exclude in ipairs(excludes) do + pattern = _get_pattern(exclude) + if (name:match('^' .. pattern .. '$')) then + return false + end + end + end + return true + end +end + +-- merge requireinfo from `add_requireconfs()` +-- +-- add_requireconfs("*", {system = false, configs = {vs_runtime = "MD"}}) +-- add_requireconfs("lib*", {system = false, configs = {vs_runtime = "MD"}}) +-- add_requireconfs("libwebp", {system = false, configs = {vs_runtime = "MD"}}) +-- add_requireconfs("libpng.zlib", {system = false, override = true, configs = {cxflags = "-DTEST1"}, version = "1.2.10"}) +-- add_requireconfs("libtiff.*", {system = false, configs = {cxflags = "-DTEST2"}}) +-- add_requireconfs("libwebp.**|cmake|autoconf", {system = false, configs = {cxflags = "-DTEST3"}}) -- recursive deps +-- +function _merge_requireinfo(requireinfo, requirepath) + + -- find requireconf from the given requirepath + local requireconf_result = {} + local requireconfs, requireconfs_extra = project.requireconfs_str() + if requireconfs then + for _, requireconf in ipairs(requireconfs) do + if _match_requirepath(requirepath, requireconf) then + local requireconf_extra = requireconfs_extra[requireconf] + table.insert(requireconf_result, {requireconf = requireconf, requireconf_extra = requireconf_extra}) + end + end + end - -- satisfy required version? - local version_required = _select_package_version(package, requireinfo) - if version_required and version_required ~= package:version_str() then - raise("package(%s): version conflict, '%s' does not satisfy '%s'!", packagename, package:version_str(), requireinfo.version) + -- append requireconf_extra into requireinfo + -- and the configs of add_requires have a higher priority than add_requireconfs. + -- + -- e.g. + -- add_requireconfs("*", {configs = {debug = false}}) + -- add_requires("foo", "bar", {configs = {debug = true}}) + -- + -- foo and bar will be debug mode + -- + -- we can also override the configs of add_requires + -- + -- e.g. + -- add_requires("zlib 1.2.11") + -- add_requireconfs("zlib", {override = true, version = "1.2.10"}) + -- + -- we override the version of zlib to 1.2.10 + -- + if #requireconf_result == 1 then + local requireconf_extra = requireconf_result[1].requireconf_extra + if requireconf_extra then + -- preprocess requireconf_extra, (debug, override ..) + local override = requireconf_extra.override + requireconf_extra.override = nil + if requireconf_extra.debug then + requireconf_extra.configs = requireconf_extra.configs or {} + requireconf_extra.configs.debug = true + requireconf_extra.debug = nil + end + -- append or override configs and extra options + for k, v in pairs(requireconf_extra.configs) do + requireinfo.configs = requireinfo.configs or {} + if override or requireinfo.configs[k] == nil then + requireinfo.configs[k] = v + end + end + for k, v in pairs(requireconf_extra) do + if k ~= "configs" then + if override or requireinfo[k] == nil then + requireinfo[k] = v + end + end + end + end + elseif #requireconf_result > 1 then + local confs = {} + for _, item in ipairs(requireconf_result) do + table.insert(confs, item.requireconf) + end + raise("package(%s) will match multiple add_requireconfs(%s)!", requirepath, table.concat(confs, " ")) + end +end + +-- get package key +function _get_packagekey(packagename, requireinfo, version) + local key = packagename .. "/" .. (version or requireinfo.version) + local configs = requireinfo.configs + if configs then + local configs_order = {} + for k, v in pairs(configs) do + table.insert(configs_order, k .. "=" .. tostring(v)) end - return package + table.sort(configs_order) + key = key .. ":" .. string.serialize(configs_order, true) + end + return key +end + +-- inherit some builtin configs of parent package if these config values are not default value +-- e.g. add_requires("libpng", {configs = {vs_runtime = "MD", pic = false}}) +-- +function _inherit_parent_configs(requireinfo, parentinfo) + local requireinfo_configs = requireinfo.configs or {} + local parentinfo_configs = parentinfo.configs or {} + if not requireinfo_configs.shared then + if requireinfo_configs.vs_runtime == nil then + requireinfo_configs.vs_runtime = parentinfo_configs.vs_runtime + end + if requireinfo_configs.pic == nil then + requireinfo_configs.pic = parentinfo_configs.pic + end + end + requireinfo.configs = requireinfo_configs +end + +-- load required packages +function _load_package(packagename, requireinfo, opt) + + -- strip trailng ~tag, e.g. zlib~debug + local displayname + if packagename:find('~', 1, true) then + displayname = packagename + packagename = packagename:gsub("~.+$", "") + requireinfo.alias = requireinfo.alias or displayname end -- load package from project first + local package if os.isfile(os.projectfile()) then package = _load_package_from_project(packagename) end @@ -361,22 +493,78 @@ function _load_package(packagename, requireinfo, opt) -- check assert(package, "package(%s) not found!", packagename) + -- merge requireinfo from `add_requireconfs()` + _merge_requireinfo(requireinfo, opt.requirepath) + + -- inherit some builtin configs of parent package, e.g. vs_runtime, pic + if opt.parentinfo and package:kind() ~= "binary" then + _inherit_parent_configs(requireinfo, opt.parentinfo) + end + -- select package version local version, source = _select_package_version(package, requireinfo) if version then package:version_set(version, source) end - -- save require info to package + -- get package key + local packagekey = _get_packagekey(packagename, requireinfo, version) + + -- It exists conflict for dependent packages for each root packages? resolve it first + -- e.g. + -- add_requires("foo") -> bar -> zlib 1.2.10 + -- -> xyz -> zlib 1.2.11 or other configs + -- + -- add_requires("ddd") -> zlib + -- + -- We assume that there is no conflict between `foo` and `ddd`. + -- + -- Of course, conflicts caused by `add_packages("foo", "ddd")` + -- cannot be detected at present and can only be resolved by the user + -- + local rootkey = opt.rootkey + local packagekey_prev = _memcache():get3("packages_root", rootkey, packagename) + if packagekey_prev then + if packagekey_prev and packagekey_prev ~= packagekey then + raise("package(%s): conflict dependences with package(%s)!", packagekey, packagekey_prev) + end + end + _memcache():set3("packages_root", rootkey, packagename, packagekey) + + -- get package from cache first + local package_cached = _memcache():get2("packages", packagekey) + if package_cached then + return package_cached + end + + -- save require info package:requireinfo_set(requireinfo) + -- save display name + if not displayname then + local packageid = _memcache():get2("packageids", packagename) + displayname = packagename + if packageid then + displayname = displayname .. "#" .. tostring(packageid) + end + _memcache():set2("packageids", packagename, (packageid or 0) + 1) + end + package:displayname_set(displayname) + + -- disable parallelize if the package cache directory conflicts + local cachedirs = _memcache():get2("cachedirs", package:cachedir()) + if cachedirs then + package:set("parallelize", false) + end + _memcache():set2("cachedirs", package:cachedir(), true) + -- add some builtin configurations to package _add_package_configurations(package) -- check package configurations _check_package_configurations(package) - -- do load for package + -- do load local on_load = package:script("load") if on_load then on_load(package) @@ -386,8 +574,7 @@ function _load_package(packagename, requireinfo, opt) package:envs_load() -- save this package package to cache - packages[packagename] = package - _memcache():set("packages", packages) + _memcache():set2("packages", packagekey, package) return package end @@ -401,10 +588,13 @@ function _load_packages(requires, opt) -- load packages local packages = {} - for _, requireinfo in ipairs(load_requires(requires, opt.requires_extra, opt.parentinfo)) do + for _, requireitem in ipairs(load_requires(requires, opt.requires_extra, opt)) do -- load package - local package = _load_package(requireinfo.name, requireinfo.info, opt) + local rootkey = opt.rootkey or requireitem.name + local requireinfo = requireitem.info + local requirepath = opt.requirepath and (opt.requirepath .. "." .. requireitem.name) or requireitem.name + local package = _load_package(requireitem.name, requireinfo, table.join(opt, {rootkey = rootkey, requirepath = requirepath})) -- maybe package not found and optional if package then @@ -414,25 +604,14 @@ function _load_packages(requires, opt) local deps = package:get("deps") if deps and opt.nodeps ~= true then - -- get the extra configs dependent packages and inherit some builtin configs - local extraconfs = package:extraconf("deps") or {} - if not package:config("shared") then - for _, depstr in ipairs(deps) do - local depconf = extraconfs[depstr] - if not depconf then - depconf = {} - extraconfs[depstr] = depconf - end - depconf.configs = depconf.configs or {} - if depconf.configs.vs_runtime == nil then - depconf.configs.vs_runtime = package:config("vs_runtime") - end - end - end - - -- load dependent packages and do not load system packages for package/deps() + -- load dependent packages and do not load system/3rd packages for package/deps() local packagedeps = {} - for _, dep in ipairs(_load_packages(deps, {requires_extra = extraconfs, parentinfo = requireinfo.info, nodeps = opt.nodeps, system = false})) do + for _, dep in ipairs(_load_packages(deps, {rootkey = rootkey, + requirepath = requirepath, + requires_extra = package:extraconf("deps") or {}, + parentinfo = requireinfo, + nodeps = opt.nodeps, + system = false})) do dep:parents_add(package) table.insert(packages, dep) packagedeps[dep:name()] = dep @@ -463,16 +642,47 @@ function _sort_packages_urls(packages) end end --- get package status string -function _get_package_status_str(package) - local status = {} - if package:debug() then - table.insert(status, "debug") +-- get package parents string +function _get_package_parents_str(package) + local parents = package:parents() + if parents then + local parentnames = {} + for _, parent in pairs(parents) do + table.insert(parentnames, parent:displayname()) + end + if #parentnames == 0 then + return + end + return table.concat(parentnames, ",") end +end + +-- get package configs string +function _get_package_configs_str(package) + local configs = {} if package:optional() then - table.insert(status, "optional") + table.insert(configs, "optional") + end + local requireinfo = package:requireinfo() + if requireinfo then + for k, v in pairs(requireinfo.configs) do + if type(v) == "boolean" then + table.insert(configs, k .. ":" .. (v and "y" or "n")) + else + table.insert(configs, k .. ":" .. v) + end + end end - return #status > 0 and "(" .. table.concat(status, ", ") .. ")" or "" + local parents_str = _get_package_parents_str(package) + if parents_str then + table.insert(configs, "from:" .. parents_str) + end + local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or "" + local limitwidth = os.getwinsize().width * 2 / 3 + if #configs_str > limitwidth then + configs_str = configs_str:sub(1, limitwidth) .. " ..)" + end + return configs_str end -- get user confirm @@ -518,12 +728,12 @@ function _get_confirm(packages) local group = package:group() if group and packages_group[group] and #packages_group[group] > 1 then for idx, package_in_group in ipairs(packages_group[group]) do - cprint(" ${yellow}%s${clear} %s %s %s", idx == 1 and "->" or " or", package_in_group:name(), package_in_group:version_str() or "", _get_package_status_str(package_in_group)) + cprint(" ${yellow}%s${clear} %s %s ${dim}%s", idx == 1 and "->" or " or", package_in_group:displayname(), package_in_group:version_str() or "", _get_package_configs_str(package_in_group)) packages_showed[tostring(package_in_group)] = true end packages_group[group] = nil else - cprint(" ${yellow}->${clear} %s %s %s", package:name(), package:version_str() or "", _get_package_status_str(package)) + cprint(" ${yellow}->${clear} %s %s ${dim}%s", package:displayname(), package:version_str() or "", _get_package_configs_str(package)) packages_showed[tostring(package)] = true end end @@ -533,36 +743,6 @@ function _get_confirm(packages) return confirm end --- patch some builtin dependent packages -function _patch_packages(packages_install, packages_download) - - -- @NOTE use git.apply instead of patch - -- we can add some builtin packages like this - --[[ - -- add package(patch) - local patched_package = nil - for _, package in ipairs(packages_install) do - if package:patches() then - patched_package = package - break - end - end - if patched_package then - local packages = load_packages("patch") - if packages and #packages > 0 then - -- install patch package - local package = packages[1] - if not package:fetch() then - packages_download[tostring(package)] = package - table.insert(packages_install, 1, package) - end - -- add dependences to ensure to be installed first - patched_package:deps_add(package) - end - end - ]] -end - -- install packages function _install_packages(packages_install, packages_download) @@ -678,11 +858,11 @@ function _install_packages(packages_install, packages_download) for _, index in ipairs(running_jobs_indices) do local package = packages_installing[index] if package then - table.insert(installing, package:name()) + table.insert(installing, package:displayname()) end local package = packages_downloading[index] if package then - table.insert(downloading, package:name()) + table.insert(downloading, package:displayname()) end end @@ -736,13 +916,14 @@ function cachedir() end -- load requires -function load_requires(requires, requires_extra, parentinfo) - local requireinfos = {} +function load_requires(requires, requires_extra, opt) + opt = opt or {} + local requireitems = {} for _, require_str in ipairs(requires) do - local packagename, requireinfo = _parse_require(require_str, requires_extra, parentinfo) - table.insert(requireinfos, {name = packagename, info = requireinfo}) + local packagename, requireinfo = _parse_require(require_str, requires_extra, opt.parentinfo) + table.insert(requireitems, {name = packagename, info = requireinfo}) end - return requireinfos + return requireitems end -- load all required packages @@ -751,8 +932,7 @@ function load_packages(requires, opt) local unique = {} local packages = {} for _, package in ipairs(_load_packages(requires, opt)) do - -- remove repeat packages with same the package name and version - local key = package:name() .. (package:version_str() or "") + local key = _get_packagekey(package:name(), package:requireinfo()) if not unique[key] then table.insert(packages, package) unique[key] = true @@ -802,20 +982,17 @@ function install_packages(requires, opt) -- show tips cprint("${bright color.warning}note: ${clear}the following packages are unsupported for $(plat)/$(arch)!") for _, package in ipairs(packages_unsupported) do - print(" -> %s %s", package:name(), package:version_str() or "") + print(" -> %s %s", package:displayname(), package:version_str() or "") end raise() end - -- patch some dependent builtin packages - _patch_packages(packages_install, packages_download) - -- get user confirm if not _get_confirm(packages_install) then local packages_must = {} for _, package in ipairs(packages_install) do if not package:optional() then - table.insert(packages_must, package:name()) + table.insert(packages_must, package:displayname()) end end if #packages_must > 0 then diff --git a/xmake/actions/require/install.lua b/xmake/actions/require/install.lua index cedc3e434..90366b1b6 100644 --- a/xmake/actions/require/install.lua +++ b/xmake/actions/require/install.lua @@ -115,9 +115,9 @@ function _register_required_packages(packages) local registered_in_group = {} for _, instance in ipairs(packages) do - -- only register the first package in same group + -- only register the first package in same group and root packages local group = instance:group() - if not group or not registered_in_group[group] then + if not instance:parents() and (not group or not registered_in_group[group]) then -- do not register binary package local requireinfo = project.require(instance:alias() or instance:name()) diff --git a/xmake/core/base/scopeinfo.lua b/xmake/core/base/scopeinfo.lua index 45a7761f2..70755e14a 100644 --- a/xmake/core/base/scopeinfo.lua +++ b/xmake/core/base/scopeinfo.lua @@ -519,7 +519,7 @@ end -- function (target) -- _instance:extraconf("includedirs", "inc", "public") -> true -- _instance:extraconf("includedirs", "inc") -> {public = true} --- _instance:extraconf("includedirs") -> {["inc"] = {public = true}} +-- _instance:extraconf("includedirs") -> {inc = {public = true}} -- end -- function _instance:extraconf(name, item, key) @@ -549,6 +549,33 @@ function _instance:extraconf(name, item, key) return value end +-- set the extra configuration +-- +-- e.g. +-- +-- add_includedirs("inc", {public = true}) +-- +-- function (target) +-- _instance:extraconf_set("includedirs", "inc", "public", true) +-- _instance:extraconf_set("includedirs", "inc", {public = true}) +-- _instance:extraconf_set("includedirs", {inc = {public = true}}) +-- end +-- +function _instance:extraconf_set(name, item, key, value) + if key ~= nil then + local extraconf = self:get("__extra_" .. name) or {} + if value ~= nil then + extraconf[item] = extraconf[item] or {} + extraconf[item][key] = value + else + extraconf[item] = key + end + self:set("__extra_" .. name, extraconf) + else + self:set("__extra_" .. name, item) + end +end + -- clone a new instance from the current function _instance:clone() return _instance.new(self:kind(), self:info(), {interpreter = self:interpreter(), remove_repeat = self._REMOVE_REPEAT, enable_filter = self._ENABLE_FILTER}) diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 52c9a0c7c..6c730aebd 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -83,6 +83,11 @@ function _instance:extraconf(name, item, key) return self._INFO:extraconf(name, item, key) end +-- set the extra configuration +function _instance:extraconf_set(name, item, key, value) + return self._INFO:extraconf_set(name, item, key, value) +end + -- get the package license function _instance:license() return self:get("license") @@ -219,17 +224,6 @@ function _instance:orderdeps() return self._ORDERDEPS end --- add deps -function _instance:deps_add(...) - for _, dep in ipairs({...}) do - self:add("deps", dep:name()) - self._DEPS = self._DEPS or {} - self._DEPS[dep:name()] = dep - self._ORDERDEPS = self._ORDERDEPS or {} - table.insert(self._ORDERDEPS, dep) - end -end - -- get parents function _instance:parents() return self._PARENTS @@ -302,8 +296,8 @@ end function _instance:lock(opt) if self:filelock():trylock(opt) then return true - elseif option.get("diagnosis") then - utils.warning("the current package is being accessed by other processes, please waiting!") + else + utils.cprint("${color.warning}package(%s) is being accessed by other processes, please waiting!", self:name()) end local ok, errors = self:filelock():lock(opt) if not ok then @@ -677,6 +671,16 @@ function _instance:requireinfo_set(requireinfo) self._REQUIREINFO = requireinfo end +-- get the display name +function _instance:displayname() + return self._DISPLAYNAME +end + +-- set the display name +function _instance:displayname_set(displayname) + self._DISPLAYNAME = displayname +end + -- get the given configuration value of package function _instance:config(name) local configs = self:configs() @@ -685,6 +689,14 @@ function _instance:config(name) end end +-- set configuration value +function _instance:config_set(name, value) + local configs = self:configs() + if configs then + configs[name] = value + end +end + -- get the configurations of package function _instance:configs() local configs = self._CONFIGS @@ -713,23 +725,46 @@ end function _instance:buildhash() local buildhash = self._BUILDHASH if buildhash == nil then - local str = self:plat() .. self:arch() - local configs = self:configs() - if configs then - -- since luajit v2.1, the key order of the table is random and undefined. - -- We cannot directly deserialize the table, so the result may be different each time - local configs_order = {} - for k, v in pairs(table.wrap(configs)) do - table.insert(configs_order, k .. "=" .. tostring(v)) + local function _get_buildhash(configs) + local str = self:plat() .. self:arch() + if configs then + -- since luajit v2.1, the key order of the table is random and undefined. + -- We cannot directly deserialize the table, so the result may be different each time + local configs_order = {} + for k, v in pairs(table.wrap(configs)) do + table.insert(configs_order, k .. "=" .. tostring(v)) + end + table.sort(configs_order) + + -- we need to be compatible with the hash value string for the previous luajit version + local configs_str = string.serialize(configs_order, true) + configs_str = configs_str:gsub("\"", "") + str = str .. configs_str end - table.sort(configs_order) + return hash.uuid4(str):gsub('-', ''):lower() + end + local function _get_installdir(...) + local name = self:name():lower():gsub("::", "_") + local dir = path.join(package.installdir(), name:sub(1, 1):lower(), name) + if self:version_str() then + dir = path.join(dir, self:version_str()) + end + return path.join(dir, ...) + end - -- We need to be compatible with the hash value string for the previous luajit version - local configs_str = string.serialize(configs_order, true) - configs_str = configs_str:gsub("\"", "") - str = str .. configs_str + -- we need to be compatible with the hash value string for the previous xmake version + -- without builtin pic configuration (< 2.5.1). + if self:config("pic") then + local configs = table.copy(self:configs()) + configs.pic = nil + buildhash = _get_buildhash(configs) + if not os.isdir(_get_installdir(buildhash)) then + buildhash = nil + end + end + if not buildhash then + buildhash = _get_buildhash(self:configs()) end - buildhash = hash.uuid4(str):gsub('-', ''):lower() self._BUILDHASH = buildhash end return buildhash @@ -922,6 +957,7 @@ function _instance:fetch(opt) -- fetch it from the system directories if not fetchinfo and system ~= false then fetchinfo = self._find_tool(self:name(), {cachekey = "fetch_package_system", + require_version = require_ver, force = opt.force}) if fetchinfo then isSys = true @@ -982,6 +1018,7 @@ function _instance:fetchdeps() if not fetchinfo then return end + fetchinfo = table.copy(fetchinfo) -- avoid the cached fetchinfo be modified local orderdeps = self:orderdeps() if orderdeps then local total = #orderdeps @@ -990,8 +1027,10 @@ function _instance:fetchdeps() local depinfo = dep:fetch() if depinfo then for name, values in pairs(depinfo) do - fetchinfo[name] = table.wrap(fetchinfo[name]) - table.join2(fetchinfo[name], values) + if name ~= "license" and name ~= "version" then + fetchinfo[name] = table.wrap(fetchinfo[name]) + table.join2(fetchinfo[name], values) + end end end end diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua index db00493ea..60ba7a0ea 100644 --- a/xmake/core/project/project.lua +++ b/xmake/core/project/project.lua @@ -614,29 +614,18 @@ function project._load_requires() -- load it from cache first (@note will discard scripts in extrainfo) local instance = requireinfo.load(alias or packagename) if not instance then - - -- init a require info instance instance = table.inherit(requireinfo) - - -- save name and info instance._NAME = alias or packagename instance._INFO = { __requirestr = requirestr, __extrainfo = extrainfo } end - -- move scripts of extrainfo (e.g. on_load ..) + -- @deprecated discard scripts in extrainfo, we need not it now (e.g. on_load ..) if extrainfo then for k, v in pairs(extrainfo) do if type(v) == "function" then - instance._SCRIPTS = instance._SCRIPTS or {} - instance._SCRIPTS[k] = v extrainfo[k] = nil end end - - -- TODO exists deprecated option? show tips - if extrainfo.option then - os.raise("`option = {}` is no longger supported in add_requires(), please update xmake.lua") - end end -- add require info @@ -704,6 +693,7 @@ function project.apis() , "set_description" -- add_xxx , "add_requires" + , "add_requireconfs" , "add_repositories" } , paths = @@ -1013,10 +1003,23 @@ function project.requires_str() requires_str, requires_extra = project.get("requires"), project.get("__extra_requires") project._memcache():set("requires_str", requires_str or false) project._memcache():set("requires_extra", requires_extra) + + -- get raw requireconfs + local requireconfs_str, requireconfs_extra = project.get("requireconfs"), project.get("__extra_requireconfs") + project._memcache():set("requireconfs_str", requireconfs_str or false) + project._memcache():set("requireconfs_extra", requireconfs_extra) end return requires_str or nil, requires_extra end +-- get string requireconfs +function project.requireconfs_str() + project.requires_str() + local requireconfs_str = project._memcache():get("requireconfs_str") + local requireconfs_extra = project._memcache():get("requireconfs_extra") + return requireconfs_str, requireconfs_extra +end + -- get the given rule function project.rule(name) return project.rules()[name] diff --git a/xmake/core/project/requireinfo.lua b/xmake/core/project/requireinfo.lua index 205b7f6e9..0c90e6fb5 100644 --- a/xmake/core/project/requireinfo.lua +++ b/xmake/core/project/requireinfo.lua @@ -39,20 +39,6 @@ end -- save the requires info to the cache function requireinfo:save() - - -- To ensure that the full information (version, ..) is obtained, delay loading it - if not self._LOADED then - local on_load = self:script("on_load") - if on_load then - local ok, errors = sandbox.load(on_load, self) - if not ok then - os.raise(errors) - end - end - self._LOADED = true - end - - -- save it requireinfo._cache():set(self:name(), self._INFO) requireinfo._cache():save() end @@ -84,11 +70,6 @@ function requireinfo:name() return self._NAME end --- get the given script -function requireinfo:script(name) - return self._SCRIPTS and self._SCRIPTS[name] or nil -end - -- get the package version function requireinfo:version() diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua index 1e5faa2a9..11bbb3a19 100644 --- a/xmake/core/sandbox/modules/import/core/project/project.lua +++ b/xmake/core/sandbox/modules/import/core/project/project.lua @@ -36,31 +36,32 @@ local package = require("package/package") local import = require("sandbox/modules/import") -- export some readonly interfaces -sandbox_core_project.get = project.get -sandbox_core_project.rule = project.rule -sandbox_core_project.rules = project.rules -sandbox_core_project.toolchain = project.toolchain -sandbox_core_project.toolchains = project.toolchains -sandbox_core_project.target = project.target -sandbox_core_project.targets = project.targets -sandbox_core_project.ordertargets = project.ordertargets -sandbox_core_project.option = project.option -sandbox_core_project.options = project.options -sandbox_core_project.rootfile = project.rootfile -sandbox_core_project.allfiles = project.allfiles -sandbox_core_project.rcfile = project.rcfile -sandbox_core_project.directory = project.directory -sandbox_core_project.name = project.name -sandbox_core_project.modes = project.modes -sandbox_core_project.mtimes = project.mtimes -sandbox_core_project.version = project.version -sandbox_core_project.require = project.require -sandbox_core_project.requires = project.requires -sandbox_core_project.requires_str = project.requires_str -sandbox_core_project.policy = project.policy -sandbox_core_project.tmpdir = project.tmpdir -sandbox_core_project.tmpfile = project.tmpfile -sandbox_core_project.is_loaded = project.is_loaded +sandbox_core_project.get = project.get +sandbox_core_project.rule = project.rule +sandbox_core_project.rules = project.rules +sandbox_core_project.toolchain = project.toolchain +sandbox_core_project.toolchains = project.toolchains +sandbox_core_project.target = project.target +sandbox_core_project.targets = project.targets +sandbox_core_project.ordertargets = project.ordertargets +sandbox_core_project.option = project.option +sandbox_core_project.options = project.options +sandbox_core_project.rootfile = project.rootfile +sandbox_core_project.allfiles = project.allfiles +sandbox_core_project.rcfile = project.rcfile +sandbox_core_project.directory = project.directory +sandbox_core_project.name = project.name +sandbox_core_project.modes = project.modes +sandbox_core_project.mtimes = project.mtimes +sandbox_core_project.version = project.version +sandbox_core_project.require = project.require +sandbox_core_project.requires = project.requires +sandbox_core_project.requires_str = project.requires_str +sandbox_core_project.requireconfs_str = project.requireconfs_str +sandbox_core_project.policy = project.policy +sandbox_core_project.tmpdir = project.tmpdir +sandbox_core_project.tmpfile = project.tmpfile +sandbox_core_project.is_loaded = project.is_loaded -- check project options function sandbox_core_project.check() @@ -133,7 +134,7 @@ function sandbox_core_project.lock(opt) if sandbox_core_project.trylock(opt) then return true elseif baseoption.get("diagnosis") then - utils.warning("the current project is being accessed by other processes, please waiting!") + utils.cprint("${color.warning}the current project is being accessed by other processes, please waiting!") end local ok, errors = sandbox_core_project.filelock():lock(opt) if not ok then diff --git a/xmake/modules/devel/git/clean.lua b/xmake/modules/devel/git/clean.lua index 0f6c57e3f..ae21c3d88 100644 --- a/xmake/modules/devel/git/clean.lua +++ b/xmake/modules/devel/git/clean.lua @@ -56,6 +56,11 @@ function main(opt) table.insert(argv, "-f") end + -- remove all files and does not use the standard ignore rules + if opt.all then + table.insert(argv, "-x") + end + -- enter repository directory local oldir = nil if opt.repodir then diff --git a/xmake/modules/lib/detect/find_package.lua b/xmake/modules/lib/detect/find_package.lua index 5e50c2345..7b7ba7032 100644 --- a/xmake/modules/lib/detect/find_package.lua +++ b/xmake/modules/lib/detect/find_package.lua @@ -56,23 +56,28 @@ function main(name, opt) opt.mode = opt.mode or config.mode() or "release" -- init cache key - local key = "find_package_" .. opt.plat .. "_" .. opt.arch - if opt.require_version then - key = key .. "_" .. opt.require_version - end + local cachekey = "find_package_" .. opt.plat .. "_" .. opt.arch if opt.cachekey then - key = key .. "_" .. opt.cachekey + cachekey = cachekey .. "_" .. opt.cachekey + end + + -- init package key + local packagekey = name + if opt.buildhash then + packagekey = packagekey .. "_" .. opt.buildhash end if opt.mode then - key = key .. "_" .. opt.mode + packagekey = packagekey .. "_" .. opt.mode + end + if opt.require_version then + packagekey = packagekey .. "_" .. opt.require_version end if opt.external then - key = key .. "_external" + packagekey = packagekey .. "_external" end -- attempt to get result from cache first - local cacheinfo = detectcache:get(key) or {} - local result = cacheinfo[name] + local result = detectcache:get2(cachekey, packagekey) if result == nil or opt.force then -- find package @@ -86,8 +91,7 @@ function main(name, opt) end -- cache result - cacheinfo[name] = result and result or false - detectcache:set(key, cacheinfo) + detectcache:set2(cachekey, packagekey, result and result or false) detectcache:save() -- trace diff --git a/xmake/modules/lib/detect/find_tool.lua b/xmake/modules/lib/detect/find_tool.lua index 9d494d68f..02c9c03d1 100644 --- a/xmake/modules/lib/detect/find_tool.lua +++ b/xmake/modules/lib/detect/find_tool.lua @@ -22,6 +22,7 @@ import("lib.detect.find_program") import("lib.detect.find_programver") import("lib.detect.find_toolname") +import("core.base.semver") -- find tool from modules function _find_from_modules(name, opt) @@ -37,31 +38,7 @@ function _find_from_modules(name, opt) end -- find tool --- --- @param name the tool name --- @param opt the options, e.g. {program = "xcrun -sdk macosx clang", paths = {"/usr/bin"}, --- check = function (tool) os.run("%s -h", tool) end, version = true --- force = true, cachekey = "xxx", envs = {PATH = "xxx"}} --- --- @return {name = "", program = "", version = ""} or nil --- --- @code --- --- local tool = find_tool("clang") --- local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"}) --- local tool = find_tool("clang", {paths = {"/usr/bin", "/usr/local/bin"}}) --- local tool = find_tool("clang", {check = "--help"}) -- simple check command: ccache --help --- local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end}) --- local tool = find_tool("clang", {paths = {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}}) --- local tool = find_tool("clang", {paths = {"$(env PATH)", function () return "/usr/bin"end}}) --- local tool = find_tool("ccache", {version = true}) --- --- @endcode --- -function main(name, opt) - - -- init options - opt = opt or {} +function _find_tool(name, opt) -- find tool name local toolname = find_toolname(name or opt.program) @@ -90,3 +67,43 @@ function main(name, opt) end return {name = toolname, program = program, version = version} end + +-- find tool +-- +-- @param name the tool name +-- @param opt the options, e.g. {program = "xcrun -sdk macosx clang", paths = {"/usr/bin"}, +-- check = function (tool) os.run("%s -h", tool) end, version = true +-- force = true, cachekey = "xxx", envs = {PATH = "xxx"}} +-- +-- @return {name = "", program = "", version = ""} or nil +-- +-- @code +-- +-- local tool = find_tool("clang") +-- local tool = find_tool("clang", {program = "xcrun -sdk macosx clang"}) +-- local tool = find_tool("clang", {paths = {"/usr/bin", "/usr/local/bin"}}) +-- local tool = find_tool("clang", {check = "--help"}) -- simple check command: ccache --help +-- local tool = find_tool("clang", {check = function (tool) os.run("%s -h", tool) end}) +-- local tool = find_tool("clang", {paths = {"$(env PATH)", "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger)"}}) +-- local tool = find_tool("clang", {paths = {"$(env PATH)", function () return "/usr/bin"end}}) +-- local tool = find_tool("ccache", {version = true}) +-- +-- @endcode +-- +function main(name, opt) + + -- do find + opt = opt or {} + if opt.require_version then + opt.version = true + end + local result = _find_tool(name, opt) + + -- match version? + if opt.require_version and opt.require_version:find('.', 1, true) and result then + if not (result.version and (result.version == opt.require_version or semver.satisfies(result.version, opt.require_version))) then + result = nil + end + end + return result +end diff --git a/xmake/modules/net/ping.lua b/xmake/modules/net/ping.lua index 1f361a5d6..86472ce94 100644 --- a/xmake/modules/net/ping.lua +++ b/xmake/modules/net/ping.lua @@ -114,8 +114,6 @@ function main(hosts, opt) detectcache:set("net.ping", cacheinfo) detectcache:save() end - - -- ok? return results end diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua index a126fe514..ac8c87a73 100644 --- a/xmake/modules/package/tools/cmake.lua +++ b/xmake/modules/package/tools/cmake.lua @@ -28,6 +28,22 @@ import("lib.detect.find_file") import("lib.detect.find_tool") import("package.tools.ninja") +-- translate paths +function _translate_paths(paths) + if is_host("windows") then + if type(paths) == "string" then + return (paths:gsub("\\", "/")) + elseif type(paths) == "table" then + local result = {} + for _, p in ipairs(paths) do + table.insert(result, (p:gsub("\\", "/"))) + end + return result + end + end + return paths +end + -- translate windows bin path function _translate_windows_bin_path(bin_path) if bin_path then @@ -44,8 +60,8 @@ function _get_cflags_from_packagedeps(package, opt) local fetchinfo = dep:fetch({external = false}) if fetchinfo then table.join2(result, compiler.map_flags("cxx", "define", fetchinfo.defines)) - table.join2(result, compiler.map_flags("cxx", "includedir", fetchinfo.includedirs)) - table.join2(result, compiler.map_flags("cxx", "sysincludedir", fetchinfo.sysincludedirs)) + table.join2(result, _translate_paths(compiler.map_flags("cxx", "includedir", fetchinfo.includedirs))) + table.join2(result, _translate_paths(compiler.map_flags("cxx", "sysincludedir", fetchinfo.sysincludedirs))) end end end @@ -60,9 +76,9 @@ function _get_ldflags_from_packagedeps(package, opt) if dep then local fetchinfo = dep:fetch({external = false}) if fetchinfo then - table.join2(result, linker.map_flags("binary", {"cxx"}, "linkdir", fetchinfo.linkdirs)) + table.join2(result, _translate_paths(linker.map_flags("binary", {"cxx"}, "linkdir", fetchinfo.linkdirs))) table.join2(result, linker.map_flags("binary", {"cxx"}, "link", fetchinfo.links)) - table.join2(result, linker.map_flags("binary", {"cxx"}, "syslink", fetchinfo.syslinks)) + table.join2(result, _translate_paths(linker.map_flags("binary", {"cxx"}, "syslink", fetchinfo.syslinks))) end end end diff --git a/xmake/modules/private/async/runjobs.lua b/xmake/modules/private/async/runjobs.lua index 69991578a..307adfa55 100644 --- a/xmake/modules/private/async/runjobs.lua +++ b/xmake/modules/private/async/runjobs.lua @@ -75,13 +75,17 @@ function main(name, jobs, opt) -- run timer local stop = false - local running_jobs_indices + local running_jobs_indices = {} if opt.on_timer then scheduler.co_start_named(name .. "/timer", function () while not stop do os.sleep(timeout) if not stop then - opt.on_timer(running_jobs_indices) + local indices + if running_jobs_indices then + indices = table.keys(running_jobs_indices) + end + opt.on_timer(indices) end end end) @@ -137,7 +141,6 @@ function main(name, jobs, opt) local priority_curr = 0 local job_pending = nil while index < total do - running_jobs_indices = {} scheduler.co_group_begin(group_name, function (co_group) local freemax = comax - #co_group local max = math.min(index + freemax, total) @@ -178,11 +181,11 @@ function main(name, jobs, opt) -- start this job index = index + 1 - table.insert(running_jobs_indices, index) scheduler.co_start_named(name .. '/' .. jobname, function(i) try { function() + running_jobs_indices[i] = i if jobfunc then if opt.curdir then os.cd(opt.curdir) @@ -190,6 +193,7 @@ function main(name, jobs, opt) jobfunc(count_as_index and count or i, total) count = count + 1 end + running_jobs_indices[i] = nil end, catch { @@ -218,7 +222,7 @@ function main(name, jobs, opt) end end) - -- need only one jobs exited if be same priority + -- need only one job exited if be same priority if priority_curr == priority_prev then scheduler.co_group_wait(group_name, {limit = 1}) else |
