summaryrefslogtreecommitdiff
path: root/xmake/rules/c++
diff options
context:
space:
mode:
authorArthur LAURENT <[email protected]>2022-08-04 23:27:42 +0200
committerArthur LAURENT <[email protected]>2022-08-05 00:12:53 +0200
commitd2d7292907f6aecbcb0b52aca4897bc7fbaf94cd (patch)
treededbff6c706f5ae911bbf333671734128962d78e /xmake/rules/c++
parent6c27288e6156c41ad754c7a195faaf40dcce0c18 (diff)
Improve header unit support
Diffstat (limited to 'xmake/rules/c++')
-rw-r--r--xmake/rules/c++/modules/modules_support/clang.lua114
-rw-r--r--xmake/rules/c++/modules/modules_support/gcc.lua112
-rw-r--r--xmake/rules/c++/modules/modules_support/msvc.lua110
-rw-r--r--xmake/rules/c++/modules/xmake.lua26
4 files changed, 214 insertions, 148 deletions
diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua
index fd71b298f..e023acccb 100644
--- a/xmake/rules/c++/modules/modules_support/clang.lua
+++ b/xmake/rules/c++/modules/modules_support/clang.lua
@@ -127,79 +127,97 @@ function generate_dependencies(target, sourcebatch, opt)
end
end
--- generate target header units
-function generate_headerunits(target, batchcmds, headerunits, opt)
+-- generate target stl header units
+function generate_stl_headerunits(target, batchcmds, headerunits, opt)
local compinst = target:compiler("cxx")
- local cachedir = common.modules_cachedir(target)
+
+ -- get cachedirs
local stlcachedir = common.stlmodules_cachedir(target)
- assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!")
-- get headerunits flags
local modulecachepathflag = get_modulecachepathflag(target)
- local emitmoduleflag = get_emitmoduleflag(target)
local modulefileflag = get_modulefileflag(target)
-- build headerunits
- local objectfiles = {}
- local public_flags = {}
- local private_flags = {}
local projectdir = os.projectdir()
- for _, headerunit in ipairs(headerunits) do
- if not headerunit.stl then
- local file = path.relative(headerunit.path, target:scriptdir())
- local objectfile = target:objectfile(file)
+ local flags = {}
+ for i, headerunit in ipairs(headerunits) do
+ local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
+ if not os.isfile(bmifile) then
+ 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
- local outdir
- if headerunit.type == ":quote" then
- outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir)))
- else
- outdir = path.join(cachedir, path.directory(headerunit.path))
- end
- if not os.isdir(outdir) then
- os.mkdir(outdir)
- end
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
- local bmifilename = path.basename(objectfile) .. get_bmi_extension()
- local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename)
- if not os.isdir(path.directory(objectfile)) then
- os.mkdir(path.directory(objectfile))
- end
+ table.insert(flags, modulefileflag .. bmifile)
+ end
+ return flags
+end
- local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile}
- if headerunit.type == ":quote" then
- table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path})
- elseif headerunit.type == ":angle" then
- table.join2(args, {"-x", "c++-system-header", headerunit.name})
- end
+-- generate target user header units
+function generate_user_headerunits(target, batchcmds, headerunits, opt)
+ local compinst = target:compiler("cxx")
+ assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!")
- 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))
+ -- get cachedirs
+ local cachedir = common.modules_cachedir(target)
+
+ -- get headerunits flags
+ local modulecachepathflag = get_modulecachepathflag(target)
+ local emitmoduleflag = get_emitmoduleflag(target)
+ local modulefileflag = get_modulefileflag(target)
- batchcmds:add_depfiles(headerunit.path)
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
+ -- build headerunits
+ local objectfiles = {}
+ local flags = {}
+ local projectdir = os.projectdir()
+ for _, headerunit in ipairs(headerunits) do
+ local file = path.relative(headerunit.path, target:scriptdir())
+ local objectfile = target:objectfile(file)
- table.insert(public_flags, modulefileflag .. bmifile)
+ local outdir
+ if headerunit.type == ":quote" then
+ outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir)))
else
- local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
- if not os.isfile(bmifile) then
- 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
+ outdir = path.join(cachedir, path.directory(headerunit.path))
+ end
+ if not os.isdir(outdir) then
+ os.mkdir(outdir)
+ end
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
+ local bmifilename = path.basename(objectfile) .. get_bmi_extension()
+ local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename)
+ if not os.isdir(path.directory(objectfile)) then
+ os.mkdir(path.directory(objectfile))
+ end
- table.insert(private_flags, modulefileflag .. bmifile)
+ local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile}
+ if headerunit.type == ":quote" then
+ table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path})
+ elseif headerunit.type == ":angle" then
+ table.join2(args, {"-x", "c++-system-header", headerunit.name})
end
+
+ 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)
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
+
+ table.insert(flags, modulefileflag .. bmifile)
end
- return public_flags, private_flags
+ return flags
end
-- build module files
function build_modules(target, batchcmds, objectfiles, modules, opt)
local compinst = target:compiler("cxx")
+
+ -- get cachedirs
local cachedir = common.modules_cachedir(target)
-- get modules flags
diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua
index dba8b7e79..23e89a30b 100644
--- a/xmake/rules/c++/modules/modules_support/gcc.lua
+++ b/xmake/rules/c++/modules/modules_support/gcc.lua
@@ -149,77 +149,91 @@ function generate_dependencies(target, sourcebatch, opt)
end
end
--- generate target header units
-function generate_headerunits(target, batchcmds, headerunits, opt)
+-- generate target stl header units
+function generate_stl_headerunits(target, batchcmds, headerunits, opt)
local compinst = target:compiler("cxx")
- local cachedir = common.modules_cachedir(target)
- local stlcachedir = common.stlmodules_cachedir(target)
local mapper_file = _get_module_mapper()
+ -- get cachedirs
+ local stlcachedir = common.stlmodules_cachedir(target)
+
-- build headerunits
- local objectfiles = {}
local projectdir = os.projectdir()
- for _, headerunit in ipairs(headerunits) do
- if not headerunit.stl then
- local file = path.relative(headerunit.path, target:scriptdir())
- local objectfile = target:objectfile(file)
+ for i, headerunit in ipairs(headerunits) do
+ local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
+ if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then
+ local args = { "-c", "-x", "c++-system-header", headerunit.name }
- local outdir
- if headerunit.type == ":quote" then
- outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir)))
- else
- outdir = path.join(cachedir, path.directory(headerunit.path))
- end
- if not os.isdir(outdir) then
- os.mkdir(outdir)
- end
+ 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))
- local bmifilename = path.basename(objectfile) .. get_bmi_extension()
- local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename)
- if not os.isdir(path.directory(objectfile)) then
- os.mkdir(path.directory(objectfile))
- end
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
+ end
+ end
+end
- if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then
- local args = { "-c" }
- if headerunit.type == ":quote" then
- table.join2(args, { "-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.name })
- _add_module_to_mapper(mapper_file, path.join(".", path.relative(headerunit.path, projectdir)), path.absolute(bmifile, projectdir))
- elseif headerunit.type == ":angle" then
- table.join2(args, { "-x", "c++-system-header", headerunit.name })
- _add_module_to_mapper(mapper_file, headerunit.name, path.absolute(bmifile, projectdir))
- end
+-- generate target user header units
+function generate_user_headerunits(target, batchcmds, headerunits, opt)
+ local compinst = target:compiler("cxx")
+ local mapper_file = _get_module_mapper()
- 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))
+ -- get cachedirs
+ local cachedir = common.modules_cachedir(target)
- batchcmds:add_depfiles(headerunit.path)
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
- end
+ -- build headerunits
+ local projectdir = os.projectdir()
+ for _, headerunit in ipairs(headerunits) do
+ local file = path.relative(headerunit.path, projectdir)
+ local objectfile = target:objectfile(file)
+
+ local outdir
+ if headerunit.type == ":quote" then
+ outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir)))
else
- local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
- if _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) then
- if not os.isfile(bmifile) then
- local args = { "-c", "-x", "c++-system-header", headerunit.name }
+ outdir = path.join(cachedir, path.directory(headerunit.path))
+ end
+ if not os.isdir(outdir) then
+ os.mkdir(outdir)
+ end
- 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))
+ local bmifilename = path.basename(objectfile) .. get_bmi_extension()
+ local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename)
+ if not os.isdir(path.directory(objectfile)) then
+ os.mkdir(path.directory(objectfile))
+ end
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
- end
- end
+ local args = { "-c" }
+ local headerunit_path
+ if headerunit.type == ":quote" then
+ table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name })
+ headerunit_path = path.join(".", path.relative(headerunit.path, projectdir))
+ elseif headerunit.type == ":angle" then
+ table.join2(args, { "-x", "c++-system-header", headerunit.name })
+ -- if path is relative then its a subtarget path
+ headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path)
+ end
+
+ if _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) then
+ 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)
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
end
end
end
-- build module files
function build_modules(target, batchcmds, objectfiles, modules, opt)
- local cachedir = common.modules_cachedir(target)
local compinst = target:compiler("cxx")
local mapper_file = _get_module_mapper()
local common_args = {"-x", "c++"}
+
+ -- get cachedirs
+ local cachedir = common.modules_cachedir(target)
+
local projectdir = os.projectdir()
for _, objectfile in ipairs(objectfiles) do
local m = modules[objectfile]
diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua
index fa5741676..5006b4d9f 100644
--- a/xmake/rules/c++/modules/modules_support/msvc.lua
+++ b/xmake/rules/c++/modules/modules_support/msvc.lua
@@ -109,8 +109,8 @@ function generate_dependencies(target, sourcebatch, opt)
end
end
--- generate target header units
-function generate_headerunits(target, batchcmds, headerunits, opt)
+-- generate target stl header units
+function generate_stl_headerunits(target, batchcmds, headerunits, opt)
local compinst = target:compiler("cxx")
local toolchain = target:toolchain("msvc")
local vcvars = toolchain:config("vcvars")
@@ -123,62 +123,84 @@ function generate_headerunits(target, batchcmds, headerunits, opt)
assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!")
-- get cachedirs
- local cachedir = common.modules_cachedir(target)
local stlcachedir = common.stlmodules_cachedir(target)
-- build headerunits
local common_args = {"/TP", exportheaderflag, "/c"}
local objectfiles = {}
- local public_flags = {}
- local private_flags = {}
- local projectdir = os.projectdir()
+ local flags = {}
for _, headerunit in ipairs(headerunits) do
- if not headerunit.stl then
- 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
- outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3))
- end
- if not os.isdir(outputdir) then
- os.mkdir(outputdir)
- end
+ local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
+ if not os.isfile(bmifile) then
+ local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir}
+ 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), {envs = vcvars})
+ end
- local bmifilename = path.basename(objectfile) .. get_bmi_extension()
- local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename)
- if not os.isdir(path.directory(objectfile)) then
- os.mkdir(path.directory(objectfile))
- end
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
- local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile}
- 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}), common_args, args), {envs = vcvars})
+ local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()}
+ table.join2(flags, flag)
+ end
+ return flags
+end
- batchcmds:add_depfiles(headerunit.path)
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
- batchcmds:set_depmtime(os.mtime(objectfile))
- batchcmds:set_depcache(target:dependfile(objectfile))
+-- generate target user header units
+function generate_user_headerunits(target, batchcmds, headerunits, opt)
+ local compinst = target:compiler("cxx")
+ local toolchain = target:toolchain("msvc")
+ local vcvars = toolchain:config("vcvars")
- local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)}
- table.join2(public_flags, flag)
- target:add("objectfiles", objectfile)
- else
- local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension())
- local args = {exportheaderflag, headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir}
- 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), {envs = vcvars})
+ -- get flags
+ local exportheaderflag = get_exportheaderflag(target)
+ local headerunitflag = get_headerunitflag(target)
+ local headernameflag = get_headernameflag(target)
+ local ifcoutputflag = get_ifcoutputflag(target)
+ assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!")
- batchcmds:set_depmtime(os.mtime(bmifile))
- batchcmds:set_depcache(target:dependfile(bmifile))
+ -- get cachedirs
+ local cachedir = common.modules_cachedir(target)
- local flag = {headerunitflag .. ":angle", headerunit.name .. "=" .. headerunit.name .. get_bmi_extension()}
- table.join2(private_flags, flag)
+ -- build headerunits
+ local common_args = {"/TP", exportheaderflag, "/c"}
+ local objectfiles = {}
+ local flags = {}
+ 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
+ outputdir = path.join(cachedir, path.directory(headerunit.path):sub(3))
+ end
+ if not os.isdir(outputdir) then
+ os.mkdir(outputdir)
end
+
+ local bmifilename = path.basename(objectfile) .. get_bmi_extension()
+ local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename)
+ if not os.isdir(path.directory(objectfile)) then
+ os.mkdir(path.directory(objectfile))
+ end
+
+ local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile}
+ 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}), common_args, args), {envs = vcvars})
+
+ batchcmds:add_depfiles(headerunit.path)
+ batchcmds:set_depmtime(os.mtime(bmifile))
+ batchcmds:set_depcache(target:dependfile(bmifile))
+ batchcmds:set_depmtime(os.mtime(objectfile))
+ batchcmds:set_depcache(target:dependfile(objectfile))
+
+ local flag = {headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)}
+ table.join2(flags, flag)
+ target:add("objectfiles", objectfile)
end
- return public_flags, private_flags
+ return flags
end
-- build module files
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index a1d6fdca4..7c68f25e0 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -91,15 +91,22 @@ rule("c++.build.modules.builder")
-- get headerunits info
local headerunits
+ local stl_headerunits
local modules = target:data("cxx.modules")
for _, objectfile in ipairs(sourcebatch.objectfiles) do
local m = modules[objectfile]
if m then
for name, r in pairs(m.requires) do
if r.method ~= "by-name" then
- headerunits = headerunits or {}
local unittype = r.method == "include-angle" and ":angle" or ":quote"
- table.insert(headerunits, {name = name, path = r.path, type = unittype, stl = stl_headers.is_stl_header(name)})
+
+ if stl_headers.is_stl_header(name) then
+ stl_headerunits = stl_headerunits or {}
+ table.insert(stl_headerunits, {name = name, path = r.path, type = unittype})
+ else
+ headerunits = headerunits or {}
+ table.insert(headerunits, {name = name, path = r.path, type = unittype,})
+ end
end
end
end
@@ -107,17 +114,22 @@ rule("c++.build.modules.builder")
-- generate headerunits
local headerunits_flags
- local private_headerunits_flags
local modules_support = common.modules_support(target)
+ -- build stl header units as other headerunits may need them
+ if stl_headerunits then
+ headerunits_flags = headerunits_flags or {}
+ table.join2(headerunits_flags, modules_support.generate_stl_headerunits(target, batchcmds, stl_headerunits, opt))
+
+ -- force STL header unit generation
+ batchcmds:runcmds(opt)
+ end
if headerunits then
- headerunits_flags, private_headerunits_flags = modules_support.generate_headerunits(target, batchcmds, headerunits, opt)
+ headerunits_flags = headerunits_flags or {}
+ table.join2(headerunits_flags, modules_support.generate_user_headerunits(target, batchcmds, headerunits, opt))
end
if headerunits_flags then
target:add("cxxflags", headerunits_flags, {force = true, expand = false})
end
- if private_headerunits_flags then
- target:add("cxxflags", private_headerunits_flags, {force = true, expand = false})
- end
-- topological sort
local objectfiles = common.sort_modules_by_dependencies(sourcebatch.objectfiles, modules)