diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 741009af545..4ceb67b0baa 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -47,24 +47,17 @@ function _build_modules(target, sourcebatch, modules, opt) local fileconfig = target:fileconfig(cppfile) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) - local build = _should_build(target, cppfile, bmifile, {objectfile = objectfile, requires = module.requires}) - -- add objectfile if module is not from external dep if not (fileconfig and fileconfig.external) then target:add("objectfiles", objectfile) end - -- needed to detect rebuild of dependencies - if provide and build then - _mark_build(target, name) - 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, build, module, name, provide, objectfile, cppfile, fileconfig) + opt.build_module(deps, module, name, provide, objectfile, cppfile, fileconfig) ::CONTINUE:: end @@ -85,10 +78,10 @@ function _build_headerunits(target, headerunits, opt) end local bmifile = path.join(outputdir, path.filename(headerunit.name) .. compiler_support.get_bmi_extension(target)) local key = path.normalize(headerunit.path) - local build = _should_build(target, headerunit.path, bmifile, {key = key, headerunit = true}) + local build = should_build(target, headerunit.path, bmifile, {key = key, headerunit = true}) if build then - _mark_build(target, key) + mark_build(target, key) end opt.build_headerunit(headerunit, key, bmifile, outputdir, build) @@ -96,7 +89,7 @@ function _build_headerunits(target, headerunits, opt) end -- should we build this module or headerunit ? -function _should_build(target, sourcefile, bmifile, opt) +function should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt local requires = opt.requires @@ -112,23 +105,21 @@ function _should_build(target, sourcefile, bmifile, opt) end end - -- or rebuild it if the file changed for headerunit and namedmodules + -- or rebuild it if the file changed local objectfile = opt.objectfile - if compiler_support.has_module_extension(sourcefile) or (opt and opt.headerunit) then - local dryrun = option.get("dry-run") - local compinst = compiler.load("cxx", {target = target}) - local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) + local dryrun = option.get("dry-run") + local compinst = compiler.load("cxx", {target = target}) + local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) - local dependfile = target:dependfile(bmifile or objectfile) - local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) + local dependfile = target:dependfile(bmifile or objectfile) + local dependinfo = target:is_rebuilt() and {} or (depend.load(dependfile) or {}) - -- need build this object? - local depvalues = {compinst:program(), compflags} - local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 + -- need build this object? + local depvalues = {compinst:program(), compflags} + local lastmtime = os.isfile(bmifile or objectfile) and os.mtime(dependfile) or 0 - if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then - return true - end + if dryrun or depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then + return true end return false @@ -190,7 +181,7 @@ function _builder(target) return builder end -function _mark_build(target, name) +function mark_build(target, name) compiler_support.memcache():set2("should_build_in" .. target:name(), name, true) end @@ -207,10 +198,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, build, module, name, provide, objectfile, cppfile, fileconfig) + build_module = function(deps, module, name, provide, objectfile, cppfile, fileconfig) local job_name = name and target:name() .. name or cppfile - modulesjobs[job_name] = _builder(target).make_module_buildjobs(target, batchjobs, job_name, deps, {build = build, module = module, objectfile = objectfile, cppfile = 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) @@ -237,8 +228,8 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { - build_module = function(_, build, module, name, provide, objectfile, cppfile, fileconfig) - depmtime = math.max(depmtime, _builder(target).make_module_buildcmds(target, batchcmds, {build = build, module = module, cppfile = cppfile, objectfile = objectfile, progress = opt.progress})) + build_module = function(_, module, name, provide, objectfile, cppfile, fileconfig) + 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) diff --git a/xmake/rules/c++/modules/modules_support/clang/builder.lua b/xmake/rules/c++/modules/modules_support/clang/builder.lua index 86b3d1a37de..15a53c00ba5 100644 --- a/xmake/rules/c++/modules/modules_support/clang/builder.lua +++ b/xmake/rules/c++/modules/modules_support/clang/builder.lua @@ -205,36 +205,55 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) + local build + if provide or compiler_support.has_module_extension(opt.cppfile) then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + end + -- append requires flags if opt.module.requires then _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end + -- for cpp file we need to check after appendings the flags + if build == nil then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + end + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} local depvalues = {compinst:program(), compflags} - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then - local objectdir = path.directory(opt.objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) + if not dryrun then + local objectdir = path.directory(opt.objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end end - end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.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, external = external, name = name}) - _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) + _compile(target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - if second_step then - _compile(target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + if second_step then + _compile(target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + end + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files end end @@ -250,24 +269,43 @@ 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) + local build + if provide or compiler_support.has_module_extension(opt.cppfile) then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + end + -- append requires flags if opt.module.requires then _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - batchcmds:mkdir(path.directory(opt.objectfile)) + -- for cpp file we need to check after appendings the flags + if build == nil then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + end + + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + batchcmds:mkdir(path.directory(opt.objectfile)) - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.external - local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) - _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) + local precompile, first_step, second_step = _make_modulebuildflags(target, provide, bmifile, {batchcmds = true, sourcefile = opt.cppfile, external = external, name = name}) + _batchcmds_compile(batchcmds, target, first_step, opt.cppfile, precompile and bmifile or opt.objectfile) - if second_step then - _batchcmds_compile(batchcmds, target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + if second_step then + _batchcmds_compile(batchcmds, target, second_step, opt.cppfile, opt.objectfile, {bmifile = bmifile}) + end + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile) diff --git a/xmake/rules/c++/modules/modules_support/gcc/builder.lua b/xmake/rules/c++/modules/modules_support/gcc/builder.lua index 2f763744ac0..7e96c3fcc59 100644 --- a/xmake/rules/c++/modules/modules_support/gcc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/gcc/builder.lua @@ -222,6 +222,13 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + -- generate and append module mapper file local module_mapper if provide or opt.module.requires then @@ -234,7 +241,7 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) dependinfo.files = {} local depvalues = {compinst:program(), compflags} - if opt.build then + if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) @@ -245,6 +252,8 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local flags = _make_modulebuildflags(target, opt) _compile(target, flags, opt.cppfile, opt.objectfile) os.tryrm(module_mapper) + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files end end table.insert(dependinfo.files, opt.cppfile) @@ -257,8 +266,16 @@ end 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) local module_mapperflag = compiler_support.get_modulemapperflag(target) + local build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + -- generate and append module mapper file local module_mapper if provide or opt.module.requires then @@ -266,7 +283,7 @@ function make_module_buildcmds(target, batchcmds, opt) target:fileconfig_add(opt.cppfile, {force = {cxxflags = {module_mapperflag .. module_mapper}}}) end - if opt.build then + if build then -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) @@ -275,6 +292,8 @@ function make_module_buildcmds(target, batchcmds, opt) end batchcmds:mkdir(path.directory(opt.objectfile)) _batchcmds_compile(batchcmds, target, _make_modulebuildflags(target, {batchcmds = true, sourcefile = opt.cppfile}), opt.cppfile, opt.objectfile) + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile) diff --git a/xmake/rules/c++/modules/modules_support/msvc/builder.lua b/xmake/rules/c++/modules/modules_support/msvc/builder.lua index 019235837b0..10a0ad409c7 100644 --- a/xmake/rules/c++/modules/modules_support/msvc/builder.lua +++ b/xmake/rules/c++/modules/modules_support/msvc/builder.lua @@ -222,32 +222,51 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) local compinst = compiler.load("cxx", {target = target}) local compflags = compinst:compflags({sourcefile = opt.cppfile, target = target}) + local build + if provide or compiler_support.has_module_extension(opt.cppfile) then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + end + -- append requires flags if opt.module.requires then _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end + -- for cpp file we need to check after appendings the flags + if build == nil then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + end + local dependfile = target:dependfile(bmifile or opt.objectfile) local dependinfo = depend.load(dependfile) or {} dependinfo.files = {} local depvalues = {compinst:program(), compflags} - -- compile if it's a named module - if opt.build and (provide or compiler_support.has_module_extension(opt.cppfile)) then - progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) + if build then + -- compile if it's a named module + if provide or compiler_support.has_module_extension(opt.cppfile) then + progress.show((index * 100) / total, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) - if not dryrun then - local objectdir = path.directory(opt.objectfile) - if not os.isdir(objectdir) then - os.mkdir(objectdir) + if not dryrun then + local objectdir = path.directory(opt.objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end end - end - local fileconfig = target:fileconfig(opt.cppfile) - local external = fileconfig and fileconfig.external - local flags = _make_modulebuildflags(target, provide, bmifile, {external = external}) + local fileconfig = target:fileconfig(opt.cppfile) + local external = fileconfig and fileconfig.external + local flags = _make_modulebuildflags(target, provide, bmifile, {external = external}) - _compile(target, flags, opt.cppfile, opt.objectfile) + _compile(target, flags, opt.cppfile, opt.objectfile) + else + os.tryrm(opt.objectfile) -- force rebuild for .cpp files + end end table.insert(dependinfo.files, opt.cppfile) @@ -257,17 +276,33 @@ function make_module_buildjobs(target, batchjobs, job_name, deps, opt) end -- build module file for batchcmds -function make_module_buildcmds(target, batchcmds, opt) +function make_module_buildcmds(target, batchcmds, should_build, mark_build, opt) local name, provide, _ = compiler_support.get_provided_module(opt.module) local bmifile = provide and compiler_support.get_bmi_path(provide.bmi) + local build + if provide or compiler_support.has_module_extension(opt.cppfile) then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + + -- needed to detect rebuild of dependencies + if provide and build then + mark_build(target, name) + end + end + -- append requires flags if opt.module.requires then _append_requires_flags(target, opt.module, name, opt.cppfile, bmifile, opt) end - if opt.build then + -- for cpp file we need to check after appendings the flags + if build == nil then + build = should_build(target, opt.cppfile, bmifile, {objectfile = opt.objectfile, requires = opt.module.requires}) + end + + if build then + -- compile if it's a named module if provide or compiler_support.has_module_extension(opt.cppfile) then batchcmds:show_progress(opt.progress, "${color.build.target}<%s> ${clear}${color.build.object}compiling.module.$(mode) %s", target:name(), name or opt.cppfile) batchcmds:mkdir(path.directory(opt.objectfile)) @@ -276,6 +311,8 @@ function make_module_buildcmds(target, batchcmds, opt) 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) + else + batchcmds:rm(opt.objectfile) -- force rebuild for .cpp files end end batchcmds:add_depfiles(opt.cppfile)