diff options
| author | Arthur LAURENT <[email protected]> | 2023-01-22 19:26:23 +0100 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2023-01-22 19:26:23 +0100 |
| commit | ae76b2aaf0c8ee2bbc1452999e57284a08ddba7c (patch) | |
| tree | 0e01f564cf9d51af5444780ad8bc73b3f663d35a /xmake/rules/c++/modules/modules_support | |
| parent | 409105b9e5a7267001d0fe77fb83904758de7393 (diff) | |
improve module compilation on msvc
Diffstat (limited to 'xmake/rules/c++/modules/modules_support')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/common.lua | 71 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 39 |
2 files changed, 57 insertions, 53 deletions
diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 32c1b7be8..98eae7be9 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -20,6 +20,7 @@ -- imports import("core.base.json") +import("core.base.bytes") import("core.base.hashset") import("core.project.config") import("core.tool.compiler") @@ -43,7 +44,7 @@ end -- get stl modules cache directory function stlmodules_cachedir(target, opt) opt = opt or {} - local stlcachedir = path.join(config.buildir(), "stlmodules", "cache") + local stlcachedir = path.join(config.buildir(), "stlmodules", "cache", config.mode() or "release") if opt.mkdir and not os.isdir(stlcachedir) then os.mkdir(stlcachedir) os.mkdir(path.join(stlcachedir, "experimental")) @@ -287,7 +288,6 @@ end }]] function _parse_dependencies_data(target, moduleinfos) local modules - local cachedir = modules_cachedir(target) for _, moduleinfo in ipairs(moduleinfos) do assert(moduleinfo.version <= 1) for _, rule in ipairs(moduleinfo.rules) do @@ -297,24 +297,27 @@ function _parse_dependencies_data(target, moduleinfos) for _, provide in ipairs(rule.provides) do m.provides = m.provides or {} assert(provide["logical-name"]) - if provide["compiled-module-path"] then - if not path.is_absolute(provide["compiled-module-path"]) then - m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) - else - m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) + local bmifile = provide["compiled-module-path"] + -- try to find the compiled module path in outputs filed (MSVC doesn't generate compiled-module-path) + if not bmifile then + for _, output in ipairs(rule.outputs) do + if output:endswith(".ifc") or output:endswith(".pcm") or output:endswith(".bmi") then + bmifile = output + break + end + end + + -- we didn't found the compiled module path, so we assume it + if not bmifile then + local name = provide["logical-name"] .. bmi_extension(target) + bmifile = path.join(get_outputdir(target, name), name) end - else - -- assume path with name - local name = provide["logical-name"] .. bmi_extension(target) - -- partition ":" character is invalid path character on windows - -- @see https://github.com/xmake-io/xmake/issues/2954 - name = name:replace(":", "-") - m.provides[provide["logical-name"]] = { - bmi = path.join(cachedir, name), - sourcefile = moduleinfo.sourcefile, - interface = provide["is-interface"] - } end + m.provides[provide["logical-name"]] = { + bmi = bmifile, + sourcefile = moduleinfo.sourcefile, + interface = provide["is-interface"] + } end else m.cppfile = moduleinfo.sourcefile @@ -516,7 +519,7 @@ end ] }]] function fallback_generate_dependencies(target, jsonfile, sourcefile, preprocess_file) - local output = {version = 0, revision = 0, rules = {}} + local output = {version = 1, revision = 0, rules = {}} local rule = {outputs = {jsonfile}} rule["primary-output"] = target:objectfile(sourcefile) @@ -550,6 +553,7 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile, preprocess if module_depname:startswith(":") then local module_name = (module_name_export or module_name_private or "") module_name = module_name:split(":")[1] + module_dep["unique-on-source-path"] = true module_depname = module_name .. module_depname elseif module_depname:startswith("\"") then module_depname = module_depname:sub(2, -2) @@ -569,12 +573,13 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile, preprocess end if module_name_export or internal then - table.insert(rule.outputs, (module_name_export or module_name_private) .. bmi_extension(target)) + local outputdir = get_outputdir(target, sourcefile) local provide = {} provide["logical-name"] = module_name_export or module_name_private - provide["source-path"] = path.absolute(sourcefile, project.directory()) + provide["source-path"] = sourcefile provide["is-interface"] = not internal + provide["compiled-module-path"] = path.join(outputdir, (module_name_export or module_name_private) .. bmi_extension(target)) rule.provides = {} table.insert(rule.provides, provide) @@ -693,7 +698,6 @@ 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()) @@ -704,7 +708,8 @@ function install_module_target(target) 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") + local outputdir = get_outputdir(target,sourcefile) + local metafile = path.join(outputdir, path.filename(sourcefile) .. ".meta-info") if os.exists(metafile) then target:add("installfiles", metafile, {prefixdir = prefixdir}) end @@ -712,3 +717,23 @@ function install_module_target(target) end end end + +function get_outputdir(target, module) + local cachedir = modules_cachedir(target) + local modulepath = module.path or module + local cached = localcache():get2("modules_paths", modulepath) + if cached then + if not os.exists(cached) then + os.mkdir(cached) + end + return cached + else + local hashed = hash.sha1(bytes(path.directory(modulepath) .. target:name())):sub(1, 6) + local moduledir = path.join(cachedir, hashed) + localcache():set2("modules_paths", modulepath, moduledir) + if not os.exists(moduledir) then + os.mkdir(moduledir) + end + return moduledir + end +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 3d4e03db2..e849c24b8 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -25,7 +25,6 @@ import("core.tool.compiler") import("core.project.project") import("core.project.depend") import("core.project.config") -import("core.base.hashset") import("core.base.semver") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) @@ -182,8 +181,8 @@ end function generate_dependencies(target, sourcebatch, opt) local msvc = target:toolchain("msvc") local scandependenciesflag = get_scandependenciesflag(target) + local ifcoutputflag = get_ifcoutputflag(target) local common_flags = {"-TP", scandependenciesflag} - local cachedir = common.modules_cachedir(target) local changed = false for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) @@ -191,14 +190,11 @@ function generate_dependencies(target, sourcebatch, opt) if opt.progress then progress.show(opt.progress, "${color.build.object}generating.module.deps %s", sourcefile) end - local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, projectdir))) - if not os.isdir(outputdir) then - os.mkdir(outputdir) - end + local outputdir = common.get_outputdir(target, sourcefile) - local jsonfile = path.join(outputdir, path.filename(sourcefile) .. ".json") + local jsonfile = path.join(outputdir, path.filename(sourcefile) .. ".module.json") if scandependenciesflag and not target:policy("build.c++.msvc.fallbackscanner") then - local flags = {jsonfile, sourcefile, "-Fo" .. target:objectfile(sourcefile)} + local flags = {jsonfile, sourcefile, ifcoutputflag, outputdir, "-Fo" .. target:objectfile(sourcefile)} _compile(target, table.join(common_flags, flags), sourcefile) else common.fallback_generate_dependencies(target, jsonfile, sourcefile, function(file) @@ -311,8 +307,6 @@ end -- generate target user header units for batchcmds function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) - local cachedir = common.modules_cachedir(target) - -- get flags local exportheaderflag = get_exportheaderflag(target) local headerunitflag = get_headerunitflag(target) @@ -326,17 +320,10 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {rootjob = opt.rootjob}) -- build headerunits - local projectdir = os.projectdir() for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) - local outputdir - if headerunit.type == ":quote" then - outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - -- if path is relative then its a subtarget path - outputdir = path.join(cachedir, path.is_absolute(headerunit.path) and path.directory(headerunit.path):sub(3) or headerunit.path) - end + local outputdir = common.get_outputdir(target, headerunit) local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = path.join(outputdir, bmifilename) batchjobs:addjob(headerunit.name, function (index, total) @@ -368,7 +355,6 @@ end -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) - local cachedir = common.modules_cachedir(target) local exportheaderflag = get_exportheaderflag(target) local headerunitflag = get_headerunitflag(target) local headernameflag = get_headernameflag(target) @@ -376,18 +362,11 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") -- build headerunits - local projectdir = os.projectdir() local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) - local outputdir - if headerunit.type == ":quote" then - outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) - else - -- if path is relative then its a subtarget path - outputdir = path.join(cachedir, path.is_absolute(headerunit.path) and path.directory(headerunit.path):sub(3) or headerunit.path) - end + local outputdir = common.get_outputdir(target, headerunit) batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() @@ -466,10 +445,10 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local fileconfig = target:fileconfig(cppfile) if fileconfig and fileconfig.install then batchjobs:addjob(name .. "_metafile", function(index, total) - local cachedir = common.modules_cachedir(target) - local metafilepath = path.join(cachedir, path.filename(cppfile) .. ".meta-info") + local outputdir = common.get_outputdir(target, cppfile) + local metafilepath = path.join(outputdir, path.filename(cppfile) .. ".meta-info") depend.on_changed(function() - progress.show(opt.progress, "${color.build.object}generating.module.metadata %s", name) + progress.show((index * 100) / total, "${color.build.object}generating.module.metadata %s", name) local metadata = common.generate_meta_module_info(target, name, cppfile, module.requires) json.savefile(metafilepath, metadata) |
