summaryrefslogtreecommitdiff
path: root/xmake/core
diff options
context:
space:
mode:
authorruki <[email protected]>2024-01-26 23:01:44 +0800
committerGitHub <[email protected]>2024-01-26 23:01:44 +0800
commitfd85ae0a81de712ca3837b262e936fd67b8f483f (patch)
tree97894c8d36a17ca6437aedd10400b8f24574d783 /xmake/core
parent042362f4c3f1dab8b6b5a32fcbbae20e66e224de (diff)
parent2a43a89241ff5044661fa7449d6455386cd3a449 (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.lua115
-rw-r--r--xmake/core/platform/platform.lua6
-rw-r--r--xmake/core/project/target.lua84
-rw-r--r--xmake/core/tool/toolchain.lua2
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"
}