summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/modules_support
diff options
context:
space:
mode:
authorruki <[email protected]>2024-02-11 12:45:31 +0800
committerGitHub <[email protected]>2024-02-11 12:45:31 +0800
commita7396842b55fb3d9747b5da199d6d5ec1afb8aa9 (patch)
tree52722618a91ecbb537534f75874949a68b02a5e3 /xmake/rules/c++/modules/modules_support
parentc68dad9c520093e74de0659d8723bfe5b14aae9a (diff)
parentb6983ac3373a704f0f63c514655221473383e46d (diff)
Merge pull request #4707 from Arthapz/support-moduleonly-libraries
Support moduleonly libraries
Diffstat (limited to 'xmake/rules/c++/modules/modules_support')
-rw-r--r--xmake/rules/c++/modules/modules_support/builder.lua66
-rw-r--r--xmake/rules/c++/modules/modules_support/clang/builder.lua19
-rw-r--r--xmake/rules/c++/modules/modules_support/compiler_support.lua22
-rw-r--r--xmake/rules/c++/modules/modules_support/dependency_scanner.lua15
-rw-r--r--xmake/rules/c++/modules/modules_support/gcc/builder.lua35
-rw-r--r--xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua1
-rw-r--r--xmake/rules/c++/modules/modules_support/msvc/builder.lua22
-rw-r--r--xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua1
8 files changed, 90 insertions, 91 deletions
diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua
index 4ceb67b0b..936f90414 100644
--- a/xmake/rules/c++/modules/modules_support/builder.lua
+++ b/xmake/rules/c++/modules/modules_support/builder.lua
@@ -21,6 +21,7 @@
-- imports
import("core.base.json")
import("core.base.option")
+import("async.runjobs")
import("private.async.buildjobs")
import("core.tool.compiler")
import("core.project.config")
@@ -31,8 +32,7 @@ import("dependency_scanner")
-- build target modules
function _build_modules(target, sourcebatch, modules, opt)
- local objectfiles = dependency_scanner.sort_modules_by_dependencies(sourcebatch.objectfiles, modules)
-
+ local objectfiles = sourcebatch.objectfiles
_builder(target).populate_module_map(target, modules)
-- build modules
@@ -42,22 +42,15 @@ function _build_modules(target, sourcebatch, modules, opt)
goto CONTINUE
end
- local name, provide, cppfile = compiler_support.get_provided_module(module)
+ local name, _, cppfile = compiler_support.get_provided_module(module)
cppfile = cppfile or module.cppfile
- local fileconfig = target:fileconfig(cppfile)
- local bmifile = provide and compiler_support.get_bmi_path(provide.bmi)
- -- add objectfile if module is not from external dep
- if not (fileconfig and fileconfig.external) then
- target:add("objectfiles", objectfile)
- end
-
local deps = {}
for _, dep in ipairs(table.keys(module.requires or {})) do
table.insert(deps, opt.batchjobs and target:name() .. dep or dep)
end
- opt.build_module(deps, module, name, provide, objectfile, cppfile, fileconfig)
+ opt.build_module(deps, module, name, objectfile, cppfile)
::CONTINUE::
end
@@ -198,21 +191,10 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op
local modulesjobs = {}
_build_modules(target, sourcebatch, modules, table.join(opt, {
- build_module = function(deps, module, name, provide, objectfile, cppfile, fileconfig)
+ build_module = function(deps, module, name, objectfile, cppfile)
local job_name = name and target:name() .. name or cppfile
modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {module = module, objectfile = objectfile, cppfile = cppfile})
-
- if provide and fileconfig and fileconfig.public then
- batchjobs:addjob(name .. "_metafile", function(index, total)
- local metafilepath = compiler_support.get_metafile(target, cppfile)
- depend.on_changed(function()
- progress.show((index * 100) / total, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name)
- local metadata = _generate_meta_module_info(target, name, cppfile, module.requires)
- json.savefile(metafilepath, metadata)
- end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()})
- end, {rootjob = opt.rootjob})
- end
end
}))
@@ -228,17 +210,8 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op
-- build modules
_build_modules(target, sourcebatch, modules, table.join(opt, {
- build_module = function(_, module, name, provide, objectfile, cppfile, fileconfig)
+ build_module = function(_, module, _, objectfile, cppfile)
depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress}))
-
- if provide and fileconfig and fileconfig.public then
- local metafilepath = compiler_support.get_metafile(target, cppfile)
- depend.on_changed(function()
- progress.show(opt.progress, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name)
- local metadata = _generate_meta_module_info(target, name, cppfile, module.requires)
- json.savefile(metafilepath, metadata)
- end, {dependfile = target:dependfile(metafilepath), files = {cppfile}, changed = target:is_rebuilt()})
- end
end
}))
@@ -312,6 +285,33 @@ function build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules
end
end
+function generate_metadata(target, modules)
+ local public_modules
+ for _, module in table.orderpairs(modules) do
+ local _, _, cppfile = compiler_support.get_provided_module(module)
+ local fileconfig = target:fileconfig(cppfile)
+ local public = fileconfig and fileconfig.public
+ if public then
+ public_modules = public_modules or {}
+ table.insert(public_modules, module)
+ end
+ end
+
+ if not public_modules then
+ return
+ end
+
+ local jobs = option.get("jobs") or os.default_njob()
+ runjobs(target:name() .. "_install_modules", function(index)
+ local module = public_modules[index]
+ local name, _, cppfile = compiler_support.get_provided_module(module)
+ local metafilepath = compiler_support.get_metafile(target, cppfile)
+ progress.show((index * 100) / #public_modules, "${color.build.target}<%s> generating.module.metadata %s", target:name(), name)
+ local metadata = _generate_meta_module_info(target, name, cppfile, module.requires)
+ json.savefile(metafilepath, metadata)
+ end, {comax = jobs, total = #public_modules})
+end
+
-- flush target module mapper keys
function flush_target_module_mapper_keys(target)
local memcache = compiler_support.memcache()
diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua
index 15a53c00b..0e5f0b5bd 100644
--- a/xmake/rules/c++/modules/modules_support/clang/builder.lua
+++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua
@@ -38,12 +38,12 @@ function _make_modulebuildflags(target, provide, bmifile, opt)
local flags
local precompile = false
- if module_outputflag and provide and not opt.external then -- one step compilation of named module, clang >= 16
+ if module_outputflag and provide and opt.build_objectfile then -- one step compilation of named module, clang >= 16
flags = {{"-x", "c++-module", module_outputflag .. bmifile}}
elseif provide then -- two step compilation of named module
precompile = true
flags = {{"-x", "c++-module", "--precompile"}}
- if not opt.external then
+ if opt.build_objectfile then
table.insert(flags, {})
end
else -- internal module, no bmi needed
@@ -199,7 +199,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt)
return {
name = job_name,
deps = deps,
- sourcefile = cppfile,
+ sourcefile = opt.cppfile,
job = batchjobs:newjob(name or opt.cppfile, function(index, total)
local compinst = compiler.load("cxx", {target = target})
@@ -242,10 +242,12 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt)
end
end
- local fileconfig = target:fileconfig(opt.cppfile)
- local external = fileconfig and fileconfig.external
+ local fileconfig = target:fileconfig(opt.cppfile)
+ local public = fileconfig and fileconfig.public
+ local external = fileconfig and fileconfig.external
+ local build_objectfile = target:kind() == "binary" or (not public and not external)
- local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, external = external, name = name})
+ local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name})
_compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile)
@@ -289,6 +291,7 @@ function make_module_buildcmds(target, batchcmds, opt)
build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires})
end
+ local build_objectfile = target:kind() == "binary"
if build then
-- compile if it's a named module
if provide or compiler_support.has_module_extension(opt.cppfile) then
@@ -296,9 +299,11 @@ function make_module_buildcmds(target, batchcmds, opt)
batchcmds:mkdir(path.directory(opt.objectfile))
local fileconfig = target:fileconfig(opt.cppfile)
+ local public = fileconfig and fileconfig.public
local external = fileconfig and fileconfig.external
+ local build_objectfile = target:kind() == "binary" or (not public and not external)
- local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name})
+ local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, build_objectfile = build_objectfile, name = name})
_batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile)
if second_step then
diff --git a/xmake/rules/c++/modules/modules_support/compiler_support.lua b/xmake/rules/c++/modules/modules_support/compiler_support.lua
index 52ee86a57..d11e833fd 100644
--- a/xmake/rules/c++/modules/modules_support/compiler_support.lua
+++ b/xmake/rules/c++/modules/modules_support/compiler_support.lua
@@ -64,14 +64,26 @@ function patch_sourcebatch(target, sourcebatch)
end
-- cull sourcebatch objectfiles
-function cull_objectfiles(target, sourcebatch)
+function cull_objectfiles(target, modules, sourcebatch)
+
+ -- don't cull for executables
+ if target:is_binary() then
+ return
+ end
- sourcebatch.sourcekind = "cxx"
sourcebatch.objectfiles = {}
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
- local fileconfig = target:fileconfig(sourcefile)
- if not (fileconfig and fileconfig.external) then
- local objectfile = target:objectfile(sourcefile)
+ local objectfile = target:objectfile(sourcefile)
+ local module = modules[objectfile]
+ local _, provide, _ = get_provided_module(module)
+ if provide then
+ local fileconfig = target:fileconfig(sourcefile)
+ local public = fileconfig and fileconfig.public
+ local external = fileconfig and fileconfig.external
+ if not public and not external then
+ table.insert(sourcebatch.objectfiles, objectfile)
+ end
+ else
table.insert(sourcebatch.objectfiles, objectfile)
end
end
diff --git a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua
index 7ad344750..0b02292ef 100644
--- a/xmake/rules/c++/modules/modules_support/dependency_scanner.lua
+++ b/xmake/rules/c++/modules/modules_support/dependency_scanner.lua
@@ -182,7 +182,7 @@ function _get_edges(nodes, modules)
for _, required_node in ipairs(nodes) do
local name, _, _ = compiler_support.get_provided_module(modules[required_node])
if name and name == required_name then
- table.insert(edges, {node, required_node})
+ table.insert(edges, {required_node, node})
break
end
end
@@ -396,9 +396,9 @@ function get_all_packages_modules(target, opt)
end
-- topological sort
-function sort_modules_by_dependencies(objectfiles, modules)
+function sort_modules_by_dependencies(target, objectfiles, modules)
local result = {}
- local edges, nodeps_nodes = _get_edges(objectfiles, modules)
+ local edges = _get_edges(objectfiles, modules)
local dag = graph.new(true)
for _, e in ipairs(edges) do
dag:add_edge(e[1], e[2])
@@ -418,10 +418,17 @@ function sort_modules_by_dependencies(objectfiles, modules)
for _, objectfile in ipairs(objectfiles_sorted) do
table.insert(result, objectfile)
end
+
local objectfiles_sorted_set = hashset.from(objectfiles_sorted)
for _, objectfile in ipairs(objectfiles) do
if not objectfiles_sorted_set:has(objectfile) then
- table.insert(result, objectfile)
+ -- cull unreferenced non-public named module but add non-module files and implementation modules
+ local _, provide, cppfile = compiler_support.get_provided_module(modules[objectfile])
+ local fileconfig = target:fileconfig(cppfile)
+ local public = fileconfig and fileconfig.public
+ if not provide or public then
+ table.insert(result, objectfile)
+ end
end
end
return result
diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua
index 7e96c3fcc..c4c9871e2 100644
--- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua
+++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua
@@ -99,31 +99,14 @@ end
function _get_maplines(target, module)
local maplines = {}
- local m_name, m = compiler_support.get_provided_module(module)
+ local m_name, m, cppfile = compiler_support.get_provided_module(module)
if m then
table.insert(maplines, m_name .. " " .. compiler_support.get_bmi_path(m.bmi))
end
for required, _ in table.orderpairs(module.requires) do
- local dep_module
- local dep_target
- for _, dep in ipairs(target:orderdeps()) do
- dep_module = get_from_target_mapper(dep, required)
- if dep_module then
- dep_target = dep
- break
- end
- end
-
- -- if not in target dep
- if not dep_module then
- dep_module = get_from_target_mapper(target, required)
- if dep_module then
- dep_target = target
- end
- end
-
- assert(dep_module, "module dependency %s required for %s not found", required, m_name)
+ local dep_module = get_from_target_mapper(target, required)
+ assert(dep_module, "module dependency %s required for %s not found", required, m_name or module.cppfile)
local bmifile = dep_module.bmi
local mapline
@@ -143,7 +126,7 @@ function _get_maplines(target, module)
-- append deps
if dep_module.opt and dep_module.opt.deps then
- local deps = _get_maplines(dep_target, { name = dep_module.name, bmi = bmifile, requires = dep_module.opt.deps })
+ local deps = _get_maplines(target, {name = dep_module.name, bmi = bmifile, requires = dep_module.opt.deps})
table.join2(maplines, deps)
end
end
@@ -173,16 +156,6 @@ end
-- populate module map
function populate_module_map(target, modules)
-
- -- append all modules
- for _, module in pairs(modules) do
- local name, provide = compiler_support.get_provided_module(module)
- if provide then
- add_module_to_target_mapper(target, name, provide.sourcefile, compiler_support.get_bmi_path(provide.bmi))
- end
- end
-
- -- then update their deps
for _, module in pairs(modules) do
local name, provide = compiler_support.get_provided_module(module)
if provide then
diff --git a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua
index a598f39f5..c365a107a 100644
--- a/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua
+++ b/xmake/rules/c++/modules/modules_support/gcc/compiler_support.lua
@@ -99,7 +99,6 @@ end
-- not supported atm
function get_stdmodules(target)
- return {}
end
function get_bmi_extension()
diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua
index 10a0ad409..3fc86b369 100644
--- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua
+++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua
@@ -37,11 +37,11 @@ function _make_modulebuildflags(target, provide, bmifile, opt)
local ifconlyflag = compiler_support.get_ifconlyflag(target)
local interfaceflag = compiler_support.get_interfaceflag(target)
local internalpartitionflag = compiler_support.get_internalpartitionflag(target)
- local ifconly = (opt.external and ifconlyflag)
+ local ifconly = (not opt.build_objectfile and ifconlyflag)
local flags
if provide then -- named module
- flags = table.join({"-TP", ifcoutputflag, bmifile, provide.interface and interfaceflag or internalpartitionflag}, ifconly or {})
+ flags = table.join({"-TP", ifcoutputflag, path(bmifile), provide.interface and interfaceflag or internalpartitionflag}, ifconly or {})
else
flags = {"-TP"}
end
@@ -102,8 +102,8 @@ function _batchcmds_compile(batchcmds, target, flags, sourcefile, outputfile)
opt = opt or {}
local compinst = target:compiler("cxx")
local compflags = compinst:compflags({sourcefile = sourcefile, target = target})
- flags = table.join("-c", compflags or {}, flags, {"/Fo", outputfile, sourcefile})
- batchcmds:compilev(flags, {compiler = compinst, sourcekind = "cxx"})
+ flags = table.join(compflags or {}, flags)
+ batchcmds:compile(sourcefile, outputfile, {sourcekind = "cxx", compflags = flags})
end
-- get module requires flags
@@ -260,8 +260,10 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt)
end
local fileconfig = target:fileconfig(opt.cppfile)
+ local public = fileconfig and fileconfig.public
local external = fileconfig and fileconfig.external
- local flags = _make_modulebuildflags(target, provide, bmifile, {external = external})
+ local build_objectfile = target:kind() == "binary" or (not public and not external)
+ local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile})
_compile(target, flags, opt.cppfile, opt.objectfile)
else
@@ -276,7 +278,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt)
end
-- build module file for batchcmds
-function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt)
+function make_module_buildcmds(target, batchcmds, opt)
local name, provide, _ = compiler_support.get_provided_module(opt.module)
local bmifile = provide and compiler_support.get_bmi_path(provide.bmi)
@@ -308,9 +310,11 @@ function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt)
batchcmds:mkdir(path.directory(opt.objectfile))
local fileconfig = target:fileconfig(opt.cppfile)
- local external = fileconfig and fileconfig.external
- local flags = _make_modulebuildflags(target, provide, bmifile, opt.cppfile, opt.objectfile, {batchcmds = true, external = external})
- _batchcmds_compile(batchcmds, target, flags, opt.cppfile, objectfile)
+ local public = fileconfig and fileconfig.public
+ local external = fileconfig and fileconfig.external
+ local build_objectfile = target:kind() == "binary" or (not public and not external)
+ local flags = _make_modulebuildflags(target, provide, bmifile, {build_objectfile = build_objectfile})
+ _batchcmds_compile(batchcmds, target, flags, opt.cppfile, opt.objectfile)
else
batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files
end
diff --git a/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua b/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua
index 662fd603e..e65effa11 100644
--- a/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua
+++ b/xmake/rules/c++/modules/modules_support/msvc/compiler_support.lua
@@ -88,7 +88,6 @@ function get_stdmodules(target)
end
end
end
- return {}
end
function get_bmi_extension()