diff options
| author | ruki <[email protected]> | 2024-01-26 23:01:44 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-01-26 23:01:44 +0800 |
| commit | fd85ae0a81de712ca3837b262e936fd67b8f483f (patch) | |
| tree | 97894c8d36a17ca6437aedd10400b8f24574d783 /xmake/core | |
| parent | 042362f4c3f1dab8b6b5a32fcbbae20e66e224de (diff) | |
| parent | 2a43a89241ff5044661fa7449d6455386cd3a449 (diff) | |
Merge pull request #4630 from xmake-io/runtimes
Improve runtimes to support libc++/libstdc++
Diffstat (limited to 'xmake/core')
| -rw-r--r-- | xmake/core/package/package.lua | 115 | ||||
| -rw-r--r-- | xmake/core/platform/platform.lua | 6 | ||||
| -rw-r--r-- | xmake/core/project/target.lua | 84 | ||||
| -rw-r--r-- | xmake/core/tool/toolchain.lua | 2 |
4 files changed, 192 insertions, 15 deletions
diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index d5e82b13f..5f9524019 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1130,9 +1130,38 @@ function _instance:build_envs(lazy_loading) return build_envs end +-- get runtimes +function _instance:runtimes() + local runtimes = self:_memcache():get("runtimes") + if runtimes == nil then + runtimes = self:config("runtimes") + if runtimes then + local runtimes_current = runtimes:split(",", {plain = true}) + runtimes = table.unwrap(runtimes_current) + end + runtimes = runtimes or false + self:_memcache():set("runtimes", runtimes) + end + return runtimes or nil +end + +-- has the given runtime for the current toolchains? +function _instance:has_runtime(...) + local runtimes_set = self:_memcache():get("runtimes_set") + if runtimes_set == nil then + runtimes_set = hashset.from(table.wrap(self:runtimes())) + self:_memcache():set("runtimes_set", runtimes_set) + end + for _, v in ipairs(table.pack(...)) do + if runtimes_set:has(v) then + return true + end + end +end + -- get the given toolchain function _instance:toolchain(name) - local toolchains_map = self._TOOLCHAINS_MAP + local toolchains_map = self:_memcache():get("toolchains_map") if toolchains_map == nil then toolchains_map = {} local toolchains = self:toolchains() @@ -1141,7 +1170,7 @@ function _instance:toolchain(name) toolchains_map[toolchain_inst:name()] = toolchain_inst end end - self._TOOLCHAINS_MAP = toolchains_map + self:_memcache():set("toolchains_map", toolchains_map) end return toolchains_map[name] end @@ -1391,6 +1420,19 @@ function _instance:config(name) local configs = self:configs() if configs then value = configs[name] + -- vs_runtime is deprecated now + if name == "vs_runtime" then + local runtimes = configs.runtimes + if runtimes then + for _, item in ipairs(runtimes:split(",")) do + if item:startswith("MT") or item:startswith("MD") then + value = item + break + end + end + end + utils.warning("please use package:runtimes() or package:has_runtime() instead of package:config(\"vs_runtime\")") + end end return value end @@ -1416,6 +1458,10 @@ function _instance:configs() local value = configs_required[name] if value == nil then value = self:extraconf("configs", name, "default") + -- support for the deprecated vs_runtime in add_configs + if name == "runtimes" and value == nil then + value = self:extraconf("configs", "vs_runtime", "default") + end end configs[name] = value end @@ -1453,6 +1499,10 @@ function _instance:_configs_for_buildhash() local value = configs_required[name] if value == nil then value = self:extraconf("configs", name, "default") + -- support for the deprecated vs_runtime in add_configs + if name == "runtimes" and value == nil then + value = self:extraconf("configs", "vs_runtime", "default") + end end configs[name] = value end @@ -1465,10 +1515,19 @@ function _instance:_configs_for_buildhash() return configs and configs or nil end +-- compute the build hash +function _instance:_compute_buildhash() + self._BUILDHASH_PREPRARED = true + self:buildhash() +end + -- get the build hash function _instance:buildhash() local buildhash = self._BUILDHASH if buildhash == nil then + if not self._BUILDHASH_PREPRARED then + os.raise("package:buildhash() must be called after loading package") + end local function _get_buildhash(configs, opt) opt = opt or {} local str = self:plat() .. self:arch() @@ -1477,6 +1536,15 @@ function _instance:buildhash() str = str .. label end if configs then + + -- with old vs_runtime configs + -- https://github.com/xmake-io/xmake/issues/4477 + if opt.vs_runtime then + configs = table.clone(configs) + configs.vs_runtime = configs.runtimes + configs.runtimes = nil + end + -- 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 = {} @@ -1554,6 +1622,16 @@ function _instance:buildhash() end end + -- we need to be compatible with the previous xmake version + -- with deprecated vs_runtime (< 2.8.7) + -- @see https://github.com/xmake-io/xmake/issues/4477 + if not buildhash then + buildhash = _get_buildhash(self:_configs_for_buildhash(), {vs_runtime = true}) + if not os.isdir(_get_installdir(buildhash)) then + buildhash = nil + end + end + -- get build hash for current version if not buildhash then buildhash = _get_buildhash(self:_configs_for_buildhash()) @@ -1775,6 +1853,13 @@ function _instance:find_package(name, opt) if system == nil and not name:startswith("xmake::") then system = true -- find system package by default end + local configs = table.clone(self:configs()) or {} + if opt.configs then + table.join2(configs, opt.configs) + end + if configs.runtimes then + configs.runtimes = self:runtimes() + end return self._find_package(name, { force = opt.force, installdir = self:installdir({readonly = true}), @@ -1783,7 +1868,7 @@ function _instance:find_package(name, opt) mode = self:mode(), plat = self:plat(), arch = self:arch(), - configs = table.join(self:configs(), opt.configs), + configs = configs, components = self:components_orderlist(), components_extsources = opt.components_extsources, buildhash = self:buildhash(), -- for xmake package or 3rd package manager, e.g. go:: .. @@ -2212,21 +2297,21 @@ function _instance:_generate_build_configs(configs, opt) configs = table.join(self:fetch_librarydeps(), configs) if self:is_plat("windows") then local ld = self:build_getenv("ld") - local vs_runtime = self:config("vs_runtime") - -- since we are ignoring the vs_runtime of the headeronly library, - -- we can only get the vs_runtime from the dependency library to detect the link. - if self:is_headeronly() and not vs_runtime and self:librarydeps() then + local runtimes = self:runtimes() + -- since we are ignoring the runtimes of the headeronly library, + -- we can only get the runtimes from the dependency library to detect the link. + if self:is_headeronly() and not runtimes and self:librarydeps() then for _, dep in ipairs(self:librarydeps()) do - if dep:is_plat("windows") and dep:config("vs_runtime") then - vs_runtime = dep:config("vs_runtime") + if dep:is_plat("windows") and dep:runtimes() then + runtimes = dep:runtimes() break end end end - if vs_runtime and ld and path.basename(ld:lower()) == "link" then -- for msvc? + if runtimes and ld and path.basename(ld:lower()) == "link" then -- for msvc? configs.cxflags = table.wrap(configs.cxflags) - table.insert(configs.cxflags, "/" .. vs_runtime) - if vs_runtime:startswith("MT") then + table.insert(configs.cxflags, "/" .. runtimes) + if runtimes:startswith("MT") then configs.ldflags = table.wrap(configs.ldflags) table.insert(configs.ldflags, "-nodefaultlib:msvcrt.lib") end @@ -2665,7 +2750,8 @@ function package.load_from_system(packagename) -- on install script local on_install = function (pkg) local opt = {} - opt.configs = pkg:configs() + local configs = table.clone(pkg:configs()) or {} + opt.configs = configs opt.mode = pkg:is_debug() and "debug" or "release" opt.plat = pkg:plat() opt.arch = pkg:arch() @@ -2673,6 +2759,9 @@ function package.load_from_system(packagename) opt.buildhash = pkg:buildhash() opt.cachedir = pkg:cachedir() opt.installdir = pkg:installdir() + if configs.runtimes then + configs.runtimes = pkg:runtimes() + end import("package.manager.install_package")(pkg:name(), opt) end diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua index 8a56a816e..f9a8fba77 100644 --- a/xmake/core/platform/platform.lua +++ b/xmake/core/platform/platform.lua @@ -162,7 +162,8 @@ function _instance:toolchains(opt) -- get the given toolchain local toolchain_given = config.get("toolchain") if toolchain_given then - local toolchain_inst, errors = toolchain.load(toolchain_given, {plat = self:name(), arch = self:arch()}) + 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) @@ -181,7 +182,8 @@ function _instance:toolchains(opt) end if names then for _, name in ipairs(table.wrap(names)) do - local toolchain_inst, errors = toolchain.load(name, {plat = self:name(), arch = self:arch()}) + 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) diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua index f4cdafb0e..8cc2ff824 100644 --- a/xmake/core/project/target.lua +++ b/xmake/core/project/target.lua @@ -272,16 +272,55 @@ function _instance:_visibility(opt) return visibility end +-- update file rules +-- +-- if we add files in on_load() dynamically, we need to update file rules, +-- otherwise it will cause: unknown source file: ... +-- +function _instance:_update_filerules() + local rulenames = {} + local extensions = {} + for _, sourcefile in ipairs(table.wrap(self:get("files"))) do + local extension = path.extension((sourcefile:gsub("|.*$", ""))) + if not extensions[extension] then + local lang = language.load_ex(extension) + if lang and lang:rules() then + table.join2(rulenames, lang:rules()) + end + extensions[extension] = true + end + end + rulenames = table.unique(rulenames) + for _, rulename in ipairs(rulenames) do + local r = target._project() and target._project().rule(rulename) or rule.rule(rulename) + if r then + -- only add target rules + if r:kind() == "target" then + if not self:rule(rulename) then + self:rule_add(r) + for _, deprule in ipairs(r:orderdeps()) do + if not self:rule(deprule:name()) then + self:rule_add(deprule) + end + end + end + end + end + end +end + -- invalidate the previous cache function _instance:_invalidate(name) self._CACHEID = self._CACHEID + 1 self._POLICIES = nil + self:_memcache():clear() -- we need to flush the source files cache if target/files are modified, e.g. `target:add("files", "xxx.c")` if name == "files" then self._SOURCEFILES = nil self._FILESCONFIG = nil self._OBJECTFILES = nil self._SOURCEBATCHES = nil + self:_update_filerules() elseif name == "deps" then self._DEPS = nil self._ORDERDEPS = nil @@ -2380,6 +2419,51 @@ function _instance:pcoutputfile(langkind) end end +-- get runtimes +function _instance:runtimes() + local runtimes = self:_memcache():get("runtimes") + if runtimes == nil then + runtimes = self:get("runtimes") + if runtimes then + local runtimes_supported = hashset.new() + local toolchains = self:toolchains() or platform.load(self:plat(), self:arch()):toolchains() + if toolchains then + for _, toolchain_inst in ipairs(toolchains) do + if toolchain_inst:is_standalone() and toolchain_inst:get("runtimes") then + for _, runtime in ipairs(table.wrap(toolchain_inst:get("runtimes"))) do + runtimes_supported:insert(runtime) + end + end + end + end + local runtimes_current = {} + for _, runtime in ipairs(table.wrap(runtimes)) do + if runtimes_supported:has(runtime) then + table.insert(runtimes_current, runtime) + end + end + runtimes = table.unwrap(runtimes_current) + end + runtimes = runtimes or false + self:_memcache():set("runtimes", runtimes) + end + return runtimes or nil +end + +-- has the given runtime for the current toolchains? +function _instance:has_runtime(...) + local runtimes_set = self:_memcache():get("runtimes_set") + if runtimes_set == nil then + runtimes_set = hashset.from(table.wrap(self:runtimes())) + self:_memcache():set("runtimes_set", runtimes_set) + end + for _, v in ipairs(table.pack(...)) do + if runtimes_set:has(v) then + return true + end + end +end + -- get the given toolchain function _instance:toolchain(name) local toolchains_map = self:_memcache():get("toolchains_map") diff --git a/xmake/core/tool/toolchain.lua b/xmake/core/tool/toolchain.lua index 4831bce5c..620b862d5 100644 --- a/xmake/core/tool/toolchain.lua +++ b/xmake/core/tool/toolchain.lua @@ -29,6 +29,7 @@ local utils = require("base/utils") local table = require("base/table") local global = require("base/global") local option = require("base/option") +local hashset = require("base/hashset") local scopeinfo = require("base/scopeinfo") local interpreter = require("base/interpreter") local config = require("project/config") @@ -567,6 +568,7 @@ function toolchain.apis() , "toolchain.set_bindir" , "toolchain.set_sdkdir" , "toolchain.set_archs" + , "toolchain.set_runtimes" , "toolchain.set_homepage" , "toolchain.set_description" } |
