diff options
| author | Arthur LAURENT <[email protected]> | 2022-08-07 04:10:32 +0200 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2022-08-07 04:10:32 +0200 |
| commit | f079c8e059ead5aeef0400ef360b6201150e1478 (patch) | |
| tree | 3635c64808f2abf8707dbf1a22e18c37a5f3ab17 /xmake/rules/c++/modules | |
| parent | 823ea42a24ad71abc284c118e1534b5d229c5a5b (diff) | |
Implement module mapper for clang
Diffstat (limited to 'xmake/rules/c++/modules')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/clang.lua | 128 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 8 |
2 files changed, 95 insertions, 41 deletions
diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 18243fadf..b50fd4bf2 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -27,31 +27,56 @@ import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") +-- get and create the path of module mapper +function _get_module_mapper() + local mapper_file = path.join(config.buildir(), "mapper.txt") + if not os.isfile(mapper_file) then + io.writefile(mapper_file, "") + end + return mapper_file +end + +-- add a module or header unit into the mapper +-- +-- e.g +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.ifc +-- +function _add_module_to_mapper(target, file, module, bmi) + local modulefileflag = get_modulefileflag(target) + for line in io.lines(file) do + if line:startswith(modulefileflag .. module) then + return + end + end + local f = io.open(file, "a") + f:print("%s%s=%s", modulefileflag, module, bmi) + f:close() +end + + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) local stlcachedir = common.stlmodules_cachedir(target) + local mapper_file = _get_module_mapper() -- get module and module cache flags local modulesflag = get_modulesflag(target) + local builtinmodulemapflag = get_builtinmodulemapflag(target) local implicitmodulesflag = get_implicitmodulesflag(target) - local implicitmodulemapsflag = get_implicitmodulemapsflag(target) - local prebuiltmodulepathflag = get_prebuiltmodulepathflag(target) + local noimplicitmodulemapsflag = get_noimplicitmodulemapsflag(target) -- add module flags target:add("cxxflags", modulesflag) -- add the module cache directory + target:add("cxxflags", builtinmodulemapflag, {force = true}) target:add("cxxflags", implicitmodulesflag, {force = true}) - target:add("cxxflags", implicitmodulemapsflag, {force = true}) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) + target:add("cxxflags", noimplicitmodulemapsflag, {force = true}) + -- target:add("cxxflags", prebuiltmodulepathflag .. cachedir, prebuiltmodulepathflag .. stlcachedir, {force = true}) - -- add module cachedirs of all dependent targets with modules - -- this target maybe does not contain module files, @see https://github.com/xmake-io/xmake/issues/1858 - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.modules_cachedir(dep) - target:add("cxxflags", prebuiltmodulepathflag .. cachedir, {force = true}) - end + target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++")) end -- get includedirs for stl headers @@ -135,6 +160,7 @@ end -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) @@ -145,7 +171,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- build headerunits local projectdir = os.projectdir() - local flags = {} local depmtime = 0 for i, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) @@ -153,19 +178,22 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.path} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - end - table.insert(flags, modulefileflag .. bmifile) + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) + end + end depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -205,19 +233,18 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - batchcmds:add_depfiles(headerunit.path) + _add_module_to_mapper(target, mapper_file, headerunit.name, bmifile) - table.insert(flags, modulefileflag .. bmifile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - return flags end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() -- get cachedirs local cachedir = common.modules_cachedir(target) @@ -225,14 +252,10 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - local modulefileflag = get_modulefileflag(target) - -- append deps modules - for _, dep in ipairs(target:orderdeps()) do - local flags = dep:data("cxx.modules.flags") - if flags then - target:add("cxxflags", flags, {force = true, expand = false}) - end + -- append module mapper flags + for line in io.lines(mapper_file) do + target:add("cxxflags", line, {force = true}) end -- build modules @@ -261,10 +284,9 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - local bmiflags = modulefileflag .. bmifile - target:add("cxxflags", bmiflags, {public = true, force = true}) + _add_module_to_mapper(target, mapper_file, name, bmifile) + target:add("objectfiles", objectfile) - target:data_add("cxx.modules.flags", bmiflags) depmtime = math.max(depmtime, os.mtime(bmifile)) end end @@ -293,6 +315,34 @@ function get_modulesflag(target) return modulesflag or nil end +function get_builtinmodulemapflag(target) + local builtinmodulemapflag = _g.builtinmodulemapflag + if builtinmodulemapflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-fbuiltin-module-map", "cxxflags", {flagskey = "clang_builtin_module_map"}) then + builtinmodulemapflag = "-fbuiltin-module-map" + end + assert(builtinmodulemapflag, "compiler(clang): does not support c++ module!") + _g.builtinmodulemapflag = builtinmodulemapflag or false + end + return builtinmodulemapflag or nil +end + +function get_modulemapfileflag(target) + local modulemapfileflag = _g.modulemapfileflag + if modulemapfileflag == nil then + local compinst = target:compiler("cxx") + local mapper_file = path.join(os.tmpdir(), "mapper.txt") + os.touch(mapper_file) + if compinst:has_flags("-fmodule-map-file=" .. mapper_file, "cxxflags", {flagskey = "clang_module_map_file"}) then + modulemapfileflag = "-fmodule-map-file=" + end + assert(modulemapfileflag, "compiler(clang): does not support c++ module!") + _g.modulemapfileflag = modulemapfileflag or false + end + return modulemapfileflag or nil +end + function get_implicitmodulesflag(target) local implicitmodulesflag = _g.implicitmodulesflag if implicitmodulesflag == nil then @@ -306,17 +356,17 @@ function get_implicitmodulesflag(target) return implicitmodulesflag or nil end -function get_implicitmodulemapsflag(target) - local implicitmodulemapsflag = _g.implicitmodulemapsflag - if implicitmodulemapsflag == nil then +function get_noimplicitmodulemapsflag(target) + local noimplicitmodulemapsflag = _g.noimplicitmodulemapsflag + if noimplicitmodulemapsflag == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-fimplicit-module-maps", "cxxflags", {flagskey = "clang_implicit_module_maps"}) then - implicitmodulemapsflag = "-fimplicit-module-maps" + if compinst:has_flags("-fno-implicit-module-maps", "cxxflags", {flagskey = "clang_no_implicit_module_maps"}) then + noimplicitmodulemapsflag = "-fno-implicit-module-maps" end - assert(implicitmodulemapsflag, "compiler(clang): does not support c++ module!") - _g.implicitmodulemapsflag = implicitmodulemapsflag or false + assert(noimplicitmodulemapsflag, "compiler(clang): does not support c++ module!") + _g.noimplicitmodulemapsflag = noimplicitmodulemapsflag or false end - return implicitmodulemapsflag or nil + return noimplicitmodulemapsflag or nil end function get_prebuiltmodulepathflag(target) @@ -388,11 +438,15 @@ function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then local compinst = target:compiler("cxx") - if compinst:has_flags("-x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags("-x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then + if compinst:has_flags(get_modulesflag(target) .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags(get_modulesflag(target) .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false end return support_headerunits or nil end + +-- no .o generated by header units on Clang +function append_headerunits_objectfiles(target) +end
\ No newline at end of file diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index e61beb6f2..1728d59f1 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -261,17 +261,17 @@ end -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) - local cachedir = common.modules_cachedir(target) - local mapper_file = _get_module_mapper() - local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + -- get cachedirs + local cachedir = common.modules_cachedir(target) + -- get flags local ifcoutputflag = get_ifcoutputflag(target) local interfaceflag = get_interfaceflag(target) - local referenceflag = get_referenceflag(target) -- append module mapper flags for line in io.lines(mapper_file) do |
