summaryrefslogtreecommitdiff
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
parentc68dad9c520093e74de0659d8723bfe5b14aae9a (diff)
parentb6983ac3373a704f0f63c514655221473383e46d (diff)
Merge pull request #4707 from Arthapz/support-moduleonly-libraries
Support moduleonly libraries
-rw-r--r--tests/projects/c++/modules/link_order/xmake.lua10
-rw-r--r--tests/projects/c++/modules/moduleonly/src/mod.mpp (renamed from tests/projects/c++/modules/staticlib_without_cpp/src/mod.mpp)0
-rw-r--r--tests/projects/c++/modules/moduleonly/test.lua (renamed from tests/projects/c++/modules/staticlib_without_cpp/test.lua)0
-rw-r--r--tests/projects/c++/modules/moduleonly/xmake.lua (renamed from tests/projects/c++/modules/staticlib_without_cpp/xmake.lua)2
-rw-r--r--tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/bar.mpp8
-rw-r--r--tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/xmake.lua6
-rw-r--r--tests/projects/c++/modules/packages/my-repo/packages/b/bar2/xmake.lua7
-rw-r--r--tests/projects/c++/modules/packages/src/main.cpp2
-rw-r--r--tests/projects/c++/modules/packages/xmake.lua4
-rw-r--r--tests/projects/c++/modules/staticlib/xmake.lua3
-rw-r--r--tests/projects/c++/modules/user_headerunit2/a/xmake.lua5
-rw-r--r--tests/projects/c++/modules/user_headerunit2/b/xmake.lua4
-rw-r--r--xmake/actions/build/build.lua2
-rw-r--r--xmake/actions/build/kinds/moduleonly.lua22
-rw-r--r--xmake/actions/package/local/main.lua100
-rw-r--r--xmake/core/project/target.lua9
-rw-r--r--xmake/modules/private/check/checkers/api/target/kind.lua2
-rw-r--r--xmake/modules/target/action/uninstall/main.lua9
-rw-r--r--xmake/plugins/project/cmake/cmakelists.lua13
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x.lua27
-rw-r--r--xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua49
-rw-r--r--xmake/plugins/project/vsxmake/getinfo.lua2
-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
-rw-r--r--xmake/rules/c++/modules/xmake.lua80
-rw-r--r--xmake/scripts/vsxmake/vsproj/Xmake.props5
32 files changed, 406 insertions, 146 deletions
diff --git a/tests/projects/c++/modules/link_order/xmake.lua b/tests/projects/c++/modules/link_order/xmake.lua
index b062dbe66..4cb2af87f 100644
--- a/tests/projects/c++/modules/link_order/xmake.lua
+++ b/tests/projects/c++/modules/link_order/xmake.lua
@@ -2,14 +2,12 @@ add_rules("mode.release", "mode.debug")
set_languages("c++20")
target("foo")
- add_rules("c++")
- set_kind("static")
- add_files("src/foo.mpp", {public = true})
+ set_kind("moduleonly")
+ add_files("src/foo.mpp")
target("bar")
- add_rules("c++")
- set_kind("static")
- add_files("src/bar.mpp", {public = true})
+ set_kind("moduleonly")
+ add_files("src/bar.mpp")
target("link_order_1")
set_kind("binary")
diff --git a/tests/projects/c++/modules/staticlib_without_cpp/src/mod.mpp b/tests/projects/c++/modules/moduleonly/src/mod.mpp
index b7dd3883c..b7dd3883c 100644
--- a/tests/projects/c++/modules/staticlib_without_cpp/src/mod.mpp
+++ b/tests/projects/c++/modules/moduleonly/src/mod.mpp
diff --git a/tests/projects/c++/modules/staticlib_without_cpp/test.lua b/tests/projects/c++/modules/moduleonly/test.lua
index 7717f8049..7717f8049 100644
--- a/tests/projects/c++/modules/staticlib_without_cpp/test.lua
+++ b/tests/projects/c++/modules/moduleonly/test.lua
diff --git a/tests/projects/c++/modules/staticlib_without_cpp/xmake.lua b/tests/projects/c++/modules/moduleonly/xmake.lua
index a06091414..54c681cc8 100644
--- a/tests/projects/c++/modules/staticlib_without_cpp/xmake.lua
+++ b/tests/projects/c++/modules/moduleonly/xmake.lua
@@ -2,5 +2,5 @@ add_rules("mode.release", "mode.debug")
set_languages("c++20")
target("mod")
- set_kind("static")
+ set_kind("moduleonly")
add_files("src/mod.mpp")
diff --git a/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/bar.mpp b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/bar.mpp
new file mode 100644
index 000000000..ee9fb2c78
--- /dev/null
+++ b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/bar.mpp
@@ -0,0 +1,8 @@
+export module bar2;
+
+export namespace bar {
+ const char *hello2() {
+ return "Hello world";
+ }
+}
+
diff --git a/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/xmake.lua b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/xmake.lua
new file mode 100644
index 000000000..0324fa931
--- /dev/null
+++ b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/src/xmake.lua
@@ -0,0 +1,6 @@
+add_rules("mode.release", "mode.debug")
+set_languages("c++20")
+
+target("bar2")
+ set_kind("moduleonly")
+ add_files("*.mpp")
diff --git a/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/xmake.lua b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/xmake.lua
new file mode 100644
index 000000000..ffa208234
--- /dev/null
+++ b/tests/projects/c++/modules/packages/my-repo/packages/b/bar2/xmake.lua
@@ -0,0 +1,7 @@
+package("bar2")
+ set_kind("library")
+ set_sourcedir(path.join(os.scriptdir(), "src"))
+
+ on_install(function(package)
+ import("package.tools.xmake").install(package, {})
+ end)
diff --git a/tests/projects/c++/modules/packages/src/main.cpp b/tests/projects/c++/modules/packages/src/main.cpp
index d12361c45..d6f2218c0 100644
--- a/tests/projects/c++/modules/packages/src/main.cpp
+++ b/tests/projects/c++/modules/packages/src/main.cpp
@@ -1,7 +1,9 @@
import foo;
import bar;
+import bar2;
int main() {
foo::say(bar::hello());
+ foo::say(bar::hello2());
return 0;
}
diff --git a/tests/projects/c++/modules/packages/xmake.lua b/tests/projects/c++/modules/packages/xmake.lua
index f772d6668..62dba119b 100644
--- a/tests/projects/c++/modules/packages/xmake.lua
+++ b/tests/projects/c++/modules/packages/xmake.lua
@@ -2,10 +2,10 @@ add_rules("mode.release", "mode.debug")
set_languages("c++2b")
add_repositories("my-repo my-repo")
-add_requires("foo", "bar")
+add_requires("foo", "bar", "bar2")
target("packages")
set_kind("binary")
add_files("src/*.cpp")
- add_packages("foo", "bar")
+ add_packages("foo", "bar", "bar2")
set_policy("build.c++.modules", true)
diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua
index d353774e4..9e1cf4221 100644
--- a/tests/projects/c++/modules/staticlib/xmake.lua
+++ b/tests/projects/c++/modules/staticlib/xmake.lua
@@ -3,7 +3,8 @@ set_languages("c++20")
target("mod")
set_kind("static")
- add_files("src/mod.mpp", "src/mod.cpp", {public = true})
+ add_files("src/mod.mpp", {public = true})
+ add_files("src/mod.cpp")
target("hello")
set_kind("binary")
diff --git a/tests/projects/c++/modules/user_headerunit2/a/xmake.lua b/tests/projects/c++/modules/user_headerunit2/a/xmake.lua
index 3225b2814..a3c5906fc 100644
--- a/tests/projects/c++/modules/user_headerunit2/a/xmake.lua
+++ b/tests/projects/c++/modules/user_headerunit2/a/xmake.lua
@@ -1,4 +1,5 @@
target("a")
+ set_kind("moduleonly")
+ add_headerfiles("*.hpp")
+ add_files("a.mpp")
set_languages("cxxlatest")
- set_kind("object")
- add_files("a.mpp", {public = true})
diff --git a/tests/projects/c++/modules/user_headerunit2/b/xmake.lua b/tests/projects/c++/modules/user_headerunit2/b/xmake.lua
index 24f9c9b1f..7a353ec26 100644
--- a/tests/projects/c++/modules/user_headerunit2/b/xmake.lua
+++ b/tests/projects/c++/modules/user_headerunit2/b/xmake.lua
@@ -1,5 +1,5 @@
target("b")
add_deps("a")
+ set_kind("moduleonly")
+ add_files("b.mpp")
set_languages("cxxlatest")
- set_kind("object")
- add_files("b.mpp", {public = true})
diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua
index bb0b61cc1..1db197cd6 100644
--- a/xmake/actions/build/build.lua
+++ b/xmake/actions/build/build.lua
@@ -65,7 +65,7 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target)
end
-- uses the builtin target script
- if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object()) then
+ if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object() or target:is_moduleonly()) then
job, job_leaf = import("kinds." .. target:kind(), {anonymous = true})(batchjobs, rootjob, target)
end
job = job or rootjob
diff --git a/xmake/actions/build/kinds/moduleonly.lua b/xmake/actions/build/kinds/moduleonly.lua
new file mode 100644
index 000000000..d177b8b97
--- /dev/null
+++ b/xmake/actions/build/kinds/moduleonly.lua
@@ -0,0 +1,22 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki, Arthapz
+-- @file moduleonly.lua
+--
+
+-- imports
+inherit("object")
diff --git a/xmake/actions/package/local/main.lua b/xmake/actions/package/local/main.lua
index 90495dae4..f27cbd091 100644
--- a/xmake/actions/package/local/main.lua
+++ b/xmake/actions/package/local/main.lua
@@ -25,6 +25,8 @@ import("core.project.rule")
import("core.project.config")
import("core.project.project")
import("core.base.bit")
+import("rules.c++.modules.modules_support.compiler_support", {alias = "module_compiler_support", rootdir = os.programdir()})
+import("rules.c++.modules.modules_support.builder", {alias = "module_builder", rootdir = os.programdir()})
-- get library deps
function _get_librarydeps(target)
@@ -95,6 +97,7 @@ function _package_library(target)
local binarydir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "bin")
local librarydir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "lib")
local headerdir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "include")
+ local modulesdir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "modules")
-- copy the library file to the output directory
local targetfile = target:targetfile()
@@ -142,6 +145,30 @@ function _package_library(target)
end
end
+ -- copy modules
+ if target:data("cxx.has_modules") then
+
+ local modules = module_compiler_support.localcache():get2(target:name(), "c++.modules")
+ module_builder.generate_metadata(target, modules)
+
+ local sourcebatch = target:sourcebatches()["c++.build.modules.install"]
+ if sourcebatch and sourcebatch.sourcefiles then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local fileconfig = target:fileconfig(sourcefile)
+ local install = fileconfig and fileconfig.public or false
+ if install then
+ local modulehash = module_compiler_support.get_modulehash(target, sourcefile)
+ local prefixdir = path.join(modulesdir, modulehash)
+ os.vcp(sourcefile, path.join(prefixdir, path.filename(sourcefile)))
+ local metafile = module_compiler_support.get_metafile(target, sourcefile)
+ if os.exists(metafile) then
+ os.vcp(metafile, path.join(prefixdir, path.filename(metafile)))
+ end
+ end
+ end
+ end
+ end
+
-- generate xmake.lua
local file = io.open(path.join(packagedir, "xmake.lua"), "w")
if file then
@@ -261,6 +288,78 @@ function _package_headeronly(target)
print("package(%s): %s generated", packagename, packagedir)
end
+function _package_moduleonly(target)
+
+ -- get the output directory
+ local packagedir = target:packagedir()
+ local packagename = target:name():lower()
+ local headerdir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "include")
+ local modulesdir = path.join(packagedir, target:plat(), target:arch(), config.mode(), "modules")
+
+ local modules = module_compiler_support.localcache():get2(target:name(), "c++.modules")
+ module_builder.generate_metadata(target, modules)
+
+ -- copy headers
+ local srcheaders, dstheaders = target:headerfiles(headerdir)
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ os.vcp(srcheader, dstheader)
+ end
+ i = i + 1
+ end
+ end
+
+ -- copy modules
+ local sourcebatch = target:sourcebatches()["c++.build.modules.install"]
+ if sourcebatch and sourcebatch.sourcefiles then
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local modulehash = module_compiler_support.get_modulehash(target, sourcefile)
+ local prefixdir = path.join(modulesdir, modulehash)
+ os.vcp(sourcefile, path.join(prefixdir, path.filename(sourcefile)))
+ local metafile = module_compiler_support.get_metafile(target, sourcefile)
+ if os.exists(metafile) then
+ os.vcp(metafile, path.join(prefixdir, path.filename(metafile)))
+ end
+ end
+ end
+
+ -- generate xmake.lua
+ local file = io.open(path.join(packagedir, "xmake.lua"), "w")
+ if file then
+ local deps = _get_librarydeps(target)
+ file:print("package(\"%s\")", packagename)
+ local homepage = option.get("homepage")
+ if homepage then
+ file:print(" set_homepage(\"%s\")", homepage)
+ end
+ local description = option.get("description") or ("The " .. packagename .. " package")
+ file:print(" set_description(\"%s\")", description)
+ if target:license() then
+ file:print(" set_license(\"%s\")", target:license())
+ end
+ if #deps > 0 then
+ file:print(" add_deps(\"%s\")", table.concat(deps, "\", \""))
+ end
+ file:print("")
+ file:print([[
+ on_load(function (package)
+ package:set("installdir", path.join(os.scriptdir(), package:plat(), package:arch(), package:mode()))
+ end)
+
+ on_fetch(function (package)
+ local result = {}
+ result.includedirs = package:installdir("include")
+ return result
+ end)]])
+ file:close()
+ end
+
+ -- show tips
+ print("package(%s): %s generated", packagename, packagedir)
+end
-- do package target
function _do_package_target(target)
if not target:is_phony() then
@@ -269,6 +368,7 @@ function _do_package_target(target)
binary = _package_binary
, static = _package_library
, shared = _package_library
+ , moduleonly = _package_moduleonly
, headeronly = _package_headeronly
}
local kind = target:kind()
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index 8cc2ff824..b6835a277 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -1201,9 +1201,14 @@ function _instance:is_headeronly()
return self:kind() == "headeronly"
end
+-- is moduleonly target?
+function _instance:is_moduleonly()
+ return self:kind() == "moduleonly"
+end
+
-- is library target?
function _instance:is_library()
- return self:is_static() or self:is_shared() or self:is_headeronly()
+ return self:is_static() or self:is_shared() or self:is_headeronly() or self:is_moduleonly()
end
-- is default target?
@@ -1555,7 +1560,7 @@ end
function _instance:filename()
-- no target file?
- if self:is_object() or self:is_phony() or self:is_headeronly() then
+ if self:is_object() or self:is_phony() or self:is_headeronly() or self:is_moduleonly() then
return
end
diff --git a/xmake/modules/private/check/checkers/api/target/kind.lua b/xmake/modules/private/check/checkers/api/target/kind.lua
index 127f78ad5..5d716b129 100644
--- a/xmake/modules/private/check/checkers/api/target/kind.lua
+++ b/xmake/modules/private/check/checkers/api/target/kind.lua
@@ -23,5 +23,5 @@ import(".api_checker")
function main(opt)
opt = opt or {}
- api_checker.check_targets("kind", table.join(opt, {values = {"object", "binary", "static", "shared", "headeronly", "phony"}}))
+ api_checker.check_targets("kind", table.join(opt, {values = {"object", "binary", "static", "shared", "headeronly", "moduleonly", "phony"}}))
end
diff --git a/xmake/modules/target/action/uninstall/main.lua b/xmake/modules/target/action/uninstall/main.lua
index cc5feb3ac..daa23917c 100644
--- a/xmake/modules/target/action/uninstall/main.lua
+++ b/xmake/modules/target/action/uninstall/main.lua
@@ -26,6 +26,12 @@ function _uninstall_files(target)
end
end
+-- uninstall modules
+function _uninstall_modules(target, opt)
+ local moduledir = path.join(target:installdir(), opt and opt.moduledir or "modules")
+ os.vrm(moduledir)
+end
+
-- the builtin uninstall main entry
function main(target, opt)
@@ -47,6 +53,9 @@ function main(target, opt)
end
end
+ -- remove modules
+ _uninstall_modules(target, opt)
+
-- uninstall the other files
_uninstall_files(target)
end
diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua
index 6fcf38313..4402f080f 100644
--- a/xmake/plugins/project/cmake/cmakelists.lua
+++ b/xmake/plugins/project/cmake/cmakelists.lua
@@ -68,6 +68,7 @@ end
function _escape_path(filepath)
if is_host("windows") then
filepath = filepath:gsub('\\', '/')
+ filepath = filepath:gsub(' ', '\\ ')
end
return filepath
end
@@ -323,6 +324,11 @@ function _add_target_headeronly(cmakelists, target)
cmakelists:print("add_library(%s INTERFACE)", target:name())
end
+-- add target: headeronly
+function _add_target_moduleonly(cmakelists, target)
+ cmakelists:print("add_custom_target(%s)", target:name())
+end
+
-- add target dependencies
function _add_target_dependencies(cmakelists, target)
local deps = target:get("deps")
@@ -340,8 +346,8 @@ function _add_target_sources(cmakelists, target, outputdir)
local has_cuda = false
cmakelists:print("target_sources(%s PRIVATE", target:name())
local sourcebatches = target:sourcebatches()
- for _, sourcebatch in table.orderpairs(sourcebatches) do
- if _sourcebatch_is_built(sourcebatch) then
+ for name, sourcebatch in table.orderpairs(sourcebatches) do
+ if _sourcebatch_is_built(sourcebatch) and not name:startswith("c++.build.modules") then
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
cmakelists:print(" " .. _get_relative_unix_path(sourcefile, outputdir))
end
@@ -1003,6 +1009,9 @@ function _add_target(cmakelists, target, outputdir)
_add_target_headeronly(cmakelists, target)
_add_target_include_directories(cmakelists, target, outputdir)
return
+ elseif targetkind == 'moduleonly' then
+ _add_target_moduleonly(cmakelists, target)
+ return
else
raise("unknown target kind %s", target:kind())
end
diff --git a/xmake/plugins/project/vstudio/impl/vs201x.lua b/xmake/plugins/project/vstudio/impl/vs201x.lua
index a8b48dada..b3c6f84c2 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x.lua
@@ -185,7 +185,6 @@ function _make_custom_commands_for_objectrules(commands, target, sourcebatch, vc
scriptname = "buildcmd_file" .. (suffix and ("_" .. suffix) or "")
script = ruleinst:script(scriptname)
if script then
- local sourcekind = sourcebatch.sourcekind
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
local batchcmds_ = batchcmds.new({target = target})
script(target, batchcmds_, sourcefile, {})
@@ -219,7 +218,7 @@ function _make_custom_commands(target, vcxprojdir)
for _, sourcebatch in table.orderpairs(sourcebatches) do
local rulename = sourcebatch.rulename
local sourcekind = sourcebatch.sourcekind
- if rulename ~= "c.build" and rulename ~= "c++.build" and rulename ~= "asm.build" and rulename ~= "cuda.build" and sourcekind ~= "mrc" then
+ if rulename ~= "c.build" and rulename ~= "c++.build" and not rulename:startswith("c++.build.modules") and rulename ~= "asm.build" and rulename ~= "cuda.build" and sourcekind ~= "mrc" then
_make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, "before")
_make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, nil)
_make_custom_commands_for_objectrules(commands, target, sourcebatch, vcxprojdir, "after")
@@ -256,6 +255,9 @@ function _make_targetinfo(mode, arch, target, vcxprojdir)
-- save symbols
targetinfo.symbols = target:get("symbols")
+ -- has modules
+ targetinfo.has_modules = target:data("cxx.has_modules")
+
-- save target kind
targetinfo.targetkind = target:kind()
if target:is_phony() or target:is_headeronly() then
@@ -268,9 +270,6 @@ function _make_targetinfo(mode, arch, target, vcxprojdir)
-- save symbol file
targetinfo.symbolfile = target:symbolfile()
- -- save sourcebatches
- targetinfo.sourcebatches = target:sourcebatches()
-
-- save sourcekinds
targetinfo.sourcekinds = target:sourcekinds()
@@ -289,9 +288,9 @@ function _make_targetinfo(mode, arch, target, vcxprojdir)
local sourcekind = sourcebatch.sourcekind
local rulename = sourcebatch.rulename
if sourcekind then
- for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
local compflags = compiler.compflags(sourcefile, {target = target, sourcekind = sourcekind})
- if not firstcompflags and (rulename == "c.build" or rulename == "c++.build" or rulename == "cuda.build") then
+ if not firstcompflags and (rulename == "c.build" or rulename == "c++.build" or rulename == "c++.build.modules" or rulename == "cuda.build") then
firstcompflags = compflags
end
targetinfo.compflags[sourcefile] = compflags
@@ -309,8 +308,11 @@ function _make_targetinfo(mode, arch, target, vcxprojdir)
end
end
+ -- save sourcebatches
+ targetinfo.sourcebatches = target:sourcebatches()
+
-- save linker flags
- local linkflags = linker.linkflags(target:kind(), target:sourcekinds(), {target = target})
+ local linkflags = linker.linkflags(target:is_moduleonly() and 'static' or target:kind(), target:sourcekinds(), {target = target})
targetinfo.linkflags = linkflags
if table.contains(target:sourcekinds(), "cu") then
@@ -323,7 +325,7 @@ function _make_targetinfo(mode, arch, target, vcxprojdir)
end
-- save execution dir (when executed from VS)
- targetinfo.rundir = target:rundir()
+ targetinfo.rundir = target:is_moduleonly() and "" or target:rundir()
-- save runenvs
local targetrunenvs = {}
@@ -544,6 +546,13 @@ function make(outputdir, vsinfo)
-- save file groups
_target.filegroups = table.unique(table.join(_target.filegroups or {}, target:get("filegroups")))
+ -- save references to deps
+ for _, dep in ipairs(target:orderdeps()) do
+ _target.deps = _target.deps or {}
+ local dep_name = dep:name()
+ _target.deps[dep_name] = path.relative(path.join(vsinfo.solution_dir, dep_name, dep_name .. ".vcxproj"), _target.project_dir)
+ end
+
for filegroup, groupconf in pairs(target:extraconf("filegroups")) do
_target.filegroups_extraconf = _target.filegroups_extraconf or {}
local mergedconf = _target.filegroups_extraconf[filegroup]
diff --git a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
index f5bb88d73..ee21e88b1 100644
--- a/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
+++ b/xmake/plugins/project/vstudio/impl/vs201x_vcxproj.lua
@@ -218,6 +218,17 @@ function _make_header(vcxprojfile, vsinfo)
vcxprojfile:enter("<Project DefaultTargets=\"Build\" ToolsVersion=\"%s.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">", assert(vsinfo.project_version))
end
+-- make references
+function _make_references(vcxprojfile, vsinfo, target)
+ vcxprojfile:print("<ItemGroup>")
+ for dep_name, dep_vcxprojfile in pairs(target.deps) do
+ vcxprojfile:print("<ProjectReference Include=\"%s\">", dep_vcxprojfile)
+ vcxprojfile:print("<Project>{%s}</Project>", hash.uuid4(dep_name))
+ vcxprojfile:print("</ProjectReference>")
+ end
+ vcxprojfile:print("</ItemGroup>")
+end
+
-- make tailer
function _make_tailer(vcxprojfile, vsinfo, target)
vcxprojfile:print("<Import Project=\"%$(VCTargetsPath)\\Microsoft.Cpp.targets\" />")
@@ -242,6 +253,7 @@ function _make_configurations(vcxprojfile, vsinfo, target)
binary = "Application"
, shared = "DynamicLibrary"
, static = "StaticLibrary"
+ , moduleonly = "StaticLibrary" -- emulate moduleonly with staticlib
}
-- make ProjectConfigurations
@@ -307,8 +319,10 @@ function _make_configurations(vcxprojfile, vsinfo, target)
vcxprojfile:enter("<PropertyGroup Condition=\"\'%$(Configuration)|%$(Platform)\'==\'%s|%s\'\">", targetinfo.mode, targetinfo.arch)
vcxprojfile:print("<OutDir>%s\\</OutDir>", _make_dirs(targetinfo.targetdir, target.project_dir))
vcxprojfile:print("<IntDir>%s\\</IntDir>", _make_dirs(targetinfo.objectdir, target.project_dir))
- vcxprojfile:print("<TargetName>%s</TargetName>", path.basename(targetinfo.targetfile))
- vcxprojfile:print("<TargetExt>%s</TargetExt>", path.extension(targetinfo.targetfile))
+ if targetinfo.targetfile then
+ vcxprojfile:print("<TargetName>%s</TargetName>", path.basename(targetinfo.targetfile))
+ vcxprojfile:print("<TargetExt>%s</TargetExt>", path.extension(targetinfo.targetfile))
+ end
if target.kind == "binary" then
vcxprojfile:print("<LinkIncremental>true</LinkIncremental>")
@@ -723,7 +737,7 @@ endlocal &amp; call :xmErrorLevel %errorlevel% &amp; goto :xmDone
exit /b %1
:xmDone
if %errorlevel% neq 0 goto :VCEnd]]
- vcxprojfile:print("<Command>%s</Command>", cmdstr)
+ vcxprojfile:print("<Command>%s</Command>", cmdstr:replace("<", " &lt;"):replace(">", "&gt;"):replace("/Fo ", "/Fo"))
if suffix == "after" or suffix == "after_link" then
vcxprojfile:print("</PostBuildEvent>")
elseif suffix == "before" then
@@ -742,12 +756,12 @@ end
-- make common item
function _make_common_item(vcxprojfile, vsinfo, target, targetinfo)
-
-- init the linker kinds
local linkerkinds =
{
binary = "Link"
, static = "Lib"
+ , moduleonly = "Lib" -- emulate moduleonly with staticlib
, shared = "Link"
}
if not linkerkinds[targetinfo.targetkind] then
@@ -892,6 +906,10 @@ function _make_common_item(vcxprojfile, vsinfo, target, targetinfo)
vcxprojfile:print("<LanguageStandard_C>%s</LanguageStandard_C>", cstandard)
end
+ if targetinfo.has_modules then
+ vcxprojfile:enter("<ScanSourceForModuleDependencies>true</ScanSourceForModuleDependencies>")
+ end
+
-- use c or c++ precompiled header
local pcheader = target.pcxxheader or target.pcheader
if pcheader then
@@ -959,9 +977,8 @@ function _build_common_items(vsinfo, target)
for _, sourcebatch in pairs(targetinfo.sourcebatches) do
local sourcekind = sourcebatch.sourcekind
local rulename = sourcebatch.rulename
- if (rulename == "c.build" or rulename == "c++.build" or rulename == "asm.build" or sourcekind == "mrc") then
+ if (rulename == "c.build" or rulename == "c++.build" or rulename == "c++.build.modules" or rulename == "asm.build" or sourcekind == "mrc") then
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
-
-- make compiler flags
local flags = _make_compflags(sourcefile, targetinfo, target.project_dir)
@@ -1028,7 +1045,7 @@ function _build_common_items(vsinfo, target)
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
sourceflags[sourcefile] = targetinfo.sourceflags[sourcefile]
end
- elseif rulename == "c.build" or rulename == "c++.build" then -- sourcekind maybe bind multiple rules, e.g. c++modules
+ elseif rulename == "c.build" or rulename == "c++.build" or rulename == "c++.build.modules" then -- sourcekind maybe bind multiple rules, e.g. c++modules
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
local flags = targetinfo.sourceflags[sourcefile]
local otherflags = {}
@@ -1062,7 +1079,7 @@ function _make_common_items(vcxprojfile, vsinfo, target)
-- for each mode and arch
for _, targetinfo in ipairs(target.info) do
-- make common item
- _make_common_item(vcxprojfile, vsinfo, target, targetinfo, target.project_dir)
+ _make_common_item(vcxprojfile, vsinfo, target, targetinfo)
end
end
@@ -1325,6 +1342,19 @@ function _make_source_files(vcxprojfile, vsinfo, target)
sourceinfos[sourcefile] = sourceinfos[sourcefile] or {}
table.insert(sourceinfos[sourcefile], {targetinfo = targetinfo, mode = targetinfo.mode, arch = targetinfo.arch, sourcekind = sourcekind, objectfile = objectfile, flags = flags, compargv = targetinfo.compargvs[sourcefile]})
end
+ elseif rulename == "c++.build.modules" then
+ local builder_batch = targetinfo.sourcebatches["c++.build.modules.builder"]
+ table.sort(builder_batch.objectfiles)
+ local objectfiles = builder_batch.objectfiles
+ for idx, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ local is_named_module = table.contains(builder_batch.sourcefiles, sourcefile)
+ if is_named_module then
+ local objectfile = objectfiles[idx]
+ local flags = targetinfo.sourceflags[sourcefile]
+ sourceinfos[sourcefile] = sourceinfos[sourcefile] or {}
+ table.insert(sourceinfos[sourcefile], {targetinfo = targetinfo, mode = targetinfo.mode, arch = targetinfo.arch, sourcekind = "cxx", objectfile = objectfile, flags = flags, compargv = targetinfo.compargvs[sourcefile]})
+ end
+ end
end
end
end
@@ -1386,6 +1416,9 @@ function make(vsinfo, target)
-- make source files
_make_source_files(vcxprojfile, vsinfo, target)
+ -- make deps references
+ _make_references(vcxprojfile, vsinfo, target)
+
-- make tailer
_make_tailer(vcxprojfile, vsinfo, target)
diff --git a/xmake/plugins/project/vsxmake/getinfo.lua b/xmake/plugins/project/vsxmake/getinfo.lua
index e992c1bd4..af88b51f6 100644
--- a/xmake/plugins/project/vsxmake/getinfo.lua
+++ b/xmake/plugins/project/vsxmake/getinfo.lua
@@ -154,7 +154,7 @@ function _make_targetinfo(mode, arch, target)
-- fix c++17 to cxx17 for Xmake.props
targetinfo.languages = targetinfo.languages:replace("c++", "cxx", {plain = true})
end
- if target:is_phony() or target:is_headeronly() then
+ if target:is_phony() or target:is_headeronly() or target:is_moduleonly() then
return targetinfo
end
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()
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index ecb79f65b..922841cd1 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -52,6 +52,14 @@ rule("c++.build.modules")
-- mark this target with modules
target:data_set("cxx.has_modules", true)
+
+ -- moduleonly modules are implicitly public
+ if target:is_moduleonly() then
+ local sourcebatch = target:sourcebatches()["c++.build.modules.builder"]
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ target:fileconfig_add(sourcefile, {public = true})
+ end
+ end
end
end)
@@ -76,7 +84,12 @@ rule("c++.build.modules.builder")
end
-- append std module
- table.join2(sourcebatch.sourcefiles, compiler_support.get_stdmodules(target) or {})
+ local std_modules = compiler_support.get_stdmodules(target)
+ if std_modules then
+ table.join2(sourcebatch.sourcefiles, std_modules)
+ target:fileconfig_set(std_modules[1], {external = true})
+ target:fileconfig_set(std_modules[2], {external = true})
+ end
-- extract packages modules dependencies
local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt)
@@ -84,23 +97,34 @@ rule("c++.build.modules.builder")
-- append to sourcebatch
for _, package_module_data in table.orderpairs(package_modules_data) do
table.insert(sourcebatch.sourcefiles, package_module_data.file)
- target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines})
+ target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines})
end
end
+ opt = opt or {}
opt.batchjobs = true
compiler_support.patch_sourcebatch(target, sourcebatch, opt)
local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt)
- -- build modules
- builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
+ if not target:is_moduleonly() then
+ -- avoid building non referenced modules
+ sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules)
- -- build headerunits and we need to do it before building modules
- builder.build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
+ -- build modules
+ builder.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
+
+ -- build headerunits and we need to do it before building modules
+ builder.build_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
+
+ -- cull external modules objectfile
+ compiler_support.cull_objectfiles(target, modules, sourcebatch)
+ else
+ sourcebatch.objectfiles = {}
+ end
- -- cull external modules objectfile
- compiler_support.cull_objectfiles(target, sourcebatch)
+ compiler_support.localcache():set2(target:name(), "c++.modules", modules)
+ compiler_support.localcache():save()
else
-- avoid duplicate linking of object files of non-module programs
sourcebatch.objectfiles = {}
@@ -123,7 +147,12 @@ rule("c++.build.modules.builder")
end
-- append std module
- table.join2(sourcebatch.sourcefiles, compiler_support.get_stdmodules(target) or {})
+ local std_modules = compiler_support.get_stdmodules(target)
+ if std_modules then
+ table.join2(sourcebatch.sourcefiles, std_modules)
+ target:fileconfig_set(std_modules[1], {external = true})
+ target:fileconfig_set(std_modules[2], {external = true})
+ end
-- extract packages modules dependencies
local package_modules_data = dependency_scanner.get_all_packages_modules(target, opt)
@@ -131,26 +160,39 @@ rule("c++.build.modules.builder")
-- append to sourcebatch
for _, package_module_data in table.orderpairs(package_modules_data) do
table.insert(sourcebatch.sourcefiles, package_module_data.file)
- target:fileconfig_add(package_module_data.file, {external = true, defines = package_module_data.metadata.defines})
+ target:fileconfig_set(package_module_data.file, {external = true, defines = package_module_data.metadata.defines})
end
end
+ opt = opt or {}
opt.batchjobs = false
compiler_support.patch_sourcebatch(target, sourcebatch, opt)
local modules = dependency_scanner.get_module_dependencies(target, sourcebatch, opt)
- -- build headerunits
- builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
+ if not target:is_moduleonly() then
+ -- avoid building non referenced modules
+ sourcebatch.objectfiles = dependency_scanner.sort_modules_by_dependencies(target, sourcebatch.objectfiles, modules)
+
+ -- build headerunits
+ builder.build_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
+
+ -- build modules
+ builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
- -- build modules
- builder.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
+ -- cull external modules objectfile
+ compiler_support.cull_objectfiles(target, modules, sourcebatch)
+ else
+ -- avoid duplicate linking of object files of non-module programs
+ sourcebatch.objectfiles = {}
+ end
- -- cull external modules objectfile
- compiler_support.cull_objectfiles(target, sourcebatch)
+ compiler_support.localcache():set2(target:name(), "c++.modules", modules)
+ compiler_support.localcache():save()
else
- -- avoid duplicate linking of object files of non-module programs
+ sourcebatch.sourcefiles = {}
sourcebatch.objectfiles = {}
+ sourcebatch.dependfiles = {}
end
end)
@@ -177,10 +219,14 @@ rule("c++.build.modules.install")
before_install(function (target)
import("modules_support.compiler_support")
+ import("modules_support.builder")
-- we cannot use target:data("cxx.has_modules"),
-- because on_config will be not called when installing targets
if compiler_support.contains_modules(target) then
+ local modules = compiler_support.localcache():get2(target:name(), "c++.modules")
+ builder.generate_metadata(target, modules)
+
compiler_support.install_module_target(target)
end
end)
diff --git a/xmake/scripts/vsxmake/vsproj/Xmake.props b/xmake/scripts/vsxmake/vsproj/Xmake.props
index 3e3a33298..990a95056 100644
--- a/xmake/scripts/vsxmake/vsproj/Xmake.props
+++ b/xmake/scripts/vsxmake/vsproj/Xmake.props
@@ -94,6 +94,11 @@
<ConfigurationType>Unknown</ConfigurationType>
</PropertyGroup>
</When>
+ <When Condition="'$(XmakeKind)' == 'moduleonly'">
+ <PropertyGroup>
+ <ConfigurationType>Unknown</ConfigurationType>
+ </PropertyGroup>
+ </When>
</Choose>
<ItemDefinitionGroup>