summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/modules_support/common.lua
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/rules/c++/modules/modules_support/common.lua')
-rw-r--r--xmake/rules/c++/modules/modules_support/common.lua149
1 files changed, 145 insertions, 4 deletions
diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua
index 1c3b2f0b1..ace8f2c56 100644
--- a/xmake/rules/c++/modules/modules_support/common.lua
+++ b/xmake/rules/c++/modules/modules_support/common.lua
@@ -102,6 +102,87 @@ function patch_sourcebatch(target, sourcebatch)
end
end
+function parse_meta_info(target, metafile)
+ local metadata = json.loadfile(metafile)
+ if metadata._VENDOR_extension.xmake then
+ return metadata._VENDOR_extension.xmake.file, metadata._VENDOR_extension.xmake.name, metadata
+ end
+
+ local filename = path.basename(metafile)
+ local metadir = path.directory(metafile)
+ for _, ext in ipairs({".mpp", ".mxx", ".cppm", ".ixx"}) do
+ if os.isfile(path.join(metadir, filename .. ext)) then
+ filename = filename .. ext
+ break
+ end
+ end
+
+ local sourcecode = io.readfile(path.join(path.directory(metafile), filename))
+ sourcecode = sourcecode:gsub("//.-\n", "\n")
+ sourcecode = sourcecode:gsub("/%*.-%*/", "")
+
+ local name
+ for _, line in ipairs(sourcecode:split("\n", {plain = true})) do
+ name = line:match("export%s+module%s+(.+)%s*;") or line:match("export%s+__preprocessed_module%s+(.+)%s*;")
+ if name then
+ break
+ end
+ end
+
+ return filename, name, metadata
+end
+
+-- extract packages modules dependencies
+function get_all_package_modules(target, modules, opt)
+ local package_modules
+
+ -- parse all meta-info and append their informations to the package store
+ for name, package in pairs(target:pkgs()) do
+ package_modules = package_modules or {}
+ local modules_dir = path.join(package:installdir(), "modules", name)
+ local metafiles = os.files(path.join(modules_dir, "**.meta-info"))
+ for _, metafile in ipairs(metafiles) do
+ local modulefile, name, metadata = parse_meta_info(target, metafile)
+ package_modules[name] = {
+ file = path.join(modules_dir, modulefile),
+ metadata = metadata
+ }
+ end
+ end
+
+ return package_modules
+end
+
+-- cull unused modules
+function cull_unused_modules(target, modules, package_modules_data)
+ local needed_modules = {}
+ -- append all target dependencies
+ for _, module in pairs(modules) do
+ if module.requires then
+ for required, _ in pairs(module.requires) do
+ table.insert(needed_modules, required)
+ end
+ end
+ end
+
+ -- append all package dependencies
+ local module_names = table.keys(package_modules_data) or {}
+ local culled
+ for _, name in ipairs(module_names) do
+ culled = culled or {}
+ if table.find(needed_modules, name) and package_modules_data[name] and not culled[name] then
+ culled[name] = package_modules_data[name]
+
+ if culled[name].metadata.imports then
+ table.join2(needed_modules, culled[name].metadata.imports)
+ table.join2(module_names, culled[name].metadata.imports)
+ end
+ end
+ end
+
+ return culled
+end
+
-- get modules support
function modules_support(target)
local cachekey = tostring(target)
@@ -510,7 +591,7 @@ end
function get_module_dependencies(target, sourcebatch, opt)
local cachekey = target:name() .. "/" .. sourcebatch.rulename
local modules = memcache():get2("modules", cachekey)
- if modules == nil then
+ if modules == nil or opt.regenerate then
modules = localcache():get2("modules", cachekey)
opt.progress = opt.progress or 0
local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt)
@@ -564,11 +645,71 @@ function append_dependency_objectfiles(target)
local cache = localcache():get(cachekey)
if cache then
if target:is_binary() then
- target:add("ldflags", cache, {force = true})
+ target:add("ldflags", cache, {force = true, expand = false})
elseif target:is_static() then
- target:add("arflags", cache, {force = true})
+ target:add("arflags", cache, {force = true, expand = false})
elseif target:is_shared() then
- target:add("shflags", cache, {force = true})
+ target:add("shflags", cache, {force = true, expand = false})
+ end
+ end
+end
+
+-- generate meta module informations for package / other buildsystems import
+-- based on https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2473r1.pdf
+--
+-- e.g
+-- {
+-- "include_paths": ["foo/", "bar/"]
+-- "definitions": ["FOO=BAR"]
+-- "imports": ["std", "bar"]
+-- "_VENDOR_extension": {}
+-- }
+function generate_meta_module_info(target, name, sourcefile, requires)
+ local module_metadata = {}
+
+ -- add include paths
+ module_metadata.include_paths = table.wrap(target:get("includedirs")) or {}
+ for _, deps in ipairs(target:orderdeps()) do
+ table.join2(module_metadata.include_paths, deps:get("includedirs") or {})
+ end
+
+ -- add definitions
+ module_metadata.definitions = table.wrap(target:get("defines")) or {}
+ for _, deps in ipairs(target:orderdeps()) do
+ table.join2(module_metadata.definitions, deps:get("defines") or {})
+ end
+
+ -- add imports
+ if requires then
+ for name, _ in pairs(requires) do
+ module_metadata.imports = module_metadata.imports or {}
+ table.append(module_metadata.imports, name)
+ end
+ end
+
+ module_metadata._VENDOR_extension = { xmake = { name = name, file = path.filename(sourcefile) }}
+
+ return module_metadata
+end
+
+function install_module_target(target)
+ local sourcebatch = target:sourcebatches()["c++.build.modules.install"]
+ local cachedir = modules_cachedir(target)
+ if sourcebatch and sourcebatch.sourcefiles then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local prefixdir = path.join("modules", target:name())
+ local fileconfig = target:fileconfig(sourcefile)
+ if fileconfig and fileconfig.prefixdir then
+ prefixdir = fileconfig.prefixdir
+ end
+ local install = (fileconfig and not fileconfig.install) and false or true
+ if install then
+ target:add("installfiles", sourcefile, {prefixdir = prefixdir})
+ local metafile = path.join(cachedir, path.filename(sourcefile) .. ".meta-info")
+ if os.exists(metafile) then
+ target:add("installfiles", metafile, {prefixdir = prefixdir})
+ end
+ end
end
end
end