diff options
| author | ruki <[email protected]> | 2024-02-19 14:13:17 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-19 14:13:17 +0800 |
| commit | c20e333c5384f2c196a7945a5426da40f20aaa7e (patch) | |
| tree | 4a406a4c3c02adca9ce4c0170da17400621f61f5 /xmake/plugins | |
| parent | 7e126bdbcc883f59c43ccc94eb80f2607d612ef0 (diff) | |
| parent | a73fb131e47000b890e49b1918f36bf603c1b948 (diff) | |
Merge pull request #4746 from xmake-io/modules
Add native modules support for cmake generator
Diffstat (limited to 'xmake/plugins')
| -rw-r--r-- | xmake/plugins/project/clang/compile_commands.lua | 8 | ||||
| -rw-r--r-- | xmake/plugins/project/cmake/cmakelists.lua | 106 | ||||
| -rw-r--r-- | xmake/plugins/project/make/makefile.lua | 8 | ||||
| -rw-r--r-- | xmake/plugins/project/utils/target_cmds.lua | 33 |
4 files changed, 116 insertions, 39 deletions
diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index e3dbe9520..059173c45 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -245,8 +245,8 @@ function _add_target_commands(jsonfile, target) -- add before commands -- we use irpairs(groups), because the last group that should be given the highest priority. local cmds_before = {} - target_cmds.get_target_buildcmd(target, cmds_before, "before") - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, "before") + target_cmds.get_target_buildcmd(target, cmds_before, {suffix = "before"}) + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, {suffix = "before"}) -- rule.on_buildcmd_files should also be executed before building the target, as cmake PRE_BUILD does not work. target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups) _add_target_custom_commands(jsonfile, target, "before", cmds_before) @@ -256,8 +256,8 @@ function _add_target_commands(jsonfile, target) -- add after commands local cmds_after = {} - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, "after") - target_cmds.get_target_buildcmd(target, cmds_after, "after") + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, {suffix = "after"}) + target_cmds.get_target_buildcmd(target, cmds_after, {suffix = "after"}) _add_target_custom_commands(jsonfile, target, "after", cmds_after) end diff --git a/xmake/plugins/project/cmake/cmakelists.lua b/xmake/plugins/project/cmake/cmakelists.lua index 98a94338d..5bbcf05fe 100644 --- a/xmake/plugins/project/cmake/cmakelists.lua +++ b/xmake/plugins/project/cmake/cmakelists.lua @@ -31,16 +31,43 @@ import("private.utils.batchcmds") import("private.utils.rule_groups") import("private.utils.target", {alias = "target_utils"}) import("plugins.project.utils.target_cmds", {rootdir = os.programdir()}) +import("rules.c++.modules.modules_support.compiler_support", {alias = "module_compiler_support", rootdir = os.programdir()}) + +-- get cmake version +function _get_cmake_version() + local cmake_version = _g.cmake_version + if not cmake_version then + local cmake = find_tool("cmake", {version = true}) + if cmake and cmake.version then + cmake_version = semver.new(cmake.version) + end + _g.cmake_version = cmake_version + end + return cmake_version +end + +-- has c++ modules sources +function _has_cxxmodules_sources() + for _, target in ipairs(project.ordertargets()) do + if module_compiler_support.contains_modules(target) then + return true + end + end +end -- get minimal cmake version function _get_cmake_minver() local cmake_minver = _g.cmake_minver if not cmake_minver then - local cmake = find_tool("cmake", {version = true}) - if cmake and cmake.version then - cmake_minver = semver.new(cmake.version) + cmake_minver = _get_cmake_version() + if cmake_minver then + if _has_cxxmodules_sources() and cmake_minver:gt("3.28.0") then + cmake_minver = semver.new("3.28.0") + elseif cmake_minver:gt("3.15.0") then + cmake_minver = semver.new("3.15.0") + end end - if not cmake_minver or cmake_minver:gt("3.15.0") then + if not cmake_minver then cmake_minver = semver.new("3.15.0") end _g.cmake_minver = cmake_minver @@ -103,10 +130,10 @@ function _get_relative_unix_path_to_cmake(filepath, outputdir) return os.args(filepath) end --- get enabled languages from targets -function _get_project_languages(targets) +-- get enabled languages +function _get_project_languages() local languages = {} - for _, target in table.orderpairs(targets) do + for _, target in ipairs(project.ordertargets()) do for _, sourcekind in ipairs(target:sourcekinds()) do if sourcekind == "cc" then table.insert(languages, "C") elseif sourcekind == "cxx" then table.insert(languages, "CXX") @@ -134,16 +161,34 @@ function _get_configs_from_target(target, name) return table.unique(values) end +-- Did the current cmake native support for c++ modules? +function _can_native_support_for_cxxmodules() + local cmake_minver = _get_cmake_minver() + if cmake_minver and cmake_minver:ge("3.28") then + return true + end +end + -- this sourcebatch is built? function _sourcebatch_is_built(sourcebatch) -- we can only use rulename to filter them because sourcekind may be bound to multiple rules local rulename = sourcebatch.rulename - if rulename == "c.build" or rulename == "c++.build" or rulename == "c++.build.modules" + if rulename == "c.build" or rulename == "c++.build" or rulename == "asm.build" or rulename == "cuda.build" or rulename == "objc.build" or rulename == "objc++.build" or rulename == "win.sdk.resource" then return true end + if _can_native_support_for_cxxmodules() then + if rulename == "c++.build.modules" then + return true + end + end +end + +-- get c++ modules rules +function _get_cxxmodules_rules() + return {"c++.build.modules", "c++.build.modules.builder"} end -- translate flag @@ -206,16 +251,16 @@ function _get_flags_from_target(target, flagkind) end -- add project info -function _add_project(cmakelists, languages, outputdir) +function _add_project(cmakelists, outputdir) - local cmake_version = _get_cmake_minver() + local cmake_minver = _get_cmake_minver() cmakelists:print([[# this is the build file for project %s # it is autogenerated by the xmake build system. # do not edit by hand. ]], project.name() or "") cmakelists:print("# project") - cmakelists:print("cmake_minimum_required(VERSION %s)", cmake_version) - if cmake_version:ge("3.15.0") then + cmakelists:print("cmake_minimum_required(VERSION %s)", cmake_minver) + if cmake_minver:ge("3.15.0") then -- for MSVC_RUNTIME_LIBRARY cmakelists:print("cmake_policy(SET CMP0091 NEW)") end @@ -232,12 +277,16 @@ function _add_project(cmakelists, languages, outputdir) if project_version then project_info = project_info .. " VERSION " .. project_version end + local languages = _get_project_languages() if languages then cmakelists:print("project(%s%s LANGUAGES %s)", project_name, project_info, table.concat(languages, " ")) else cmakelists:print("project(%s%s)", project_name, project_info) end end + if _can_native_support_for_cxxmodules() then + cmakelists:print("set(CMAKE_CXX_SCAN_FOR_MODULES ON)") + end cmakelists:print("") end @@ -347,7 +396,7 @@ function _add_target_sources(cmakelists, target, outputdir) cmakelists:print("target_sources(%s PRIVATE", target:name()) local sourcebatches = target:sourcebatches() for name, sourcebatch in table.orderpairs(sourcebatches) do - if _sourcebatch_is_built(sourcebatch) and not name:startswith("c++.build.modules") then + if _sourcebatch_is_built(sourcebatch) then for _, sourcefile in ipairs(sourcebatch.sourcefiles) do cmakelists:print(" " .. _get_relative_unix_path(sourcefile, outputdir)) end @@ -809,11 +858,22 @@ function _add_target_link_libraries(cmakelists, target, outputdir) cmakelists:print(")") end + -- get c++ modules rules + local cxxmodules_rules + if _can_native_support_for_cxxmodules() then + cxxmodules_rules = _get_cxxmodules_rules() + end + if cxxmodules_rules then + cxxmodules_rules = hashset.from(cxxmodules_rules) + else + cxxmodules_rules = hashset.new() + end + -- add other object files, maybe from custom rules local objectfiles_set = hashset.new() local sourcebatches = target:sourcebatches() for _, sourcebatch in table.orderpairs(sourcebatches) do - if _sourcebatch_is_built(sourcebatch) then + if _sourcebatch_is_built(sourcebatch) or cxxmodules_rules:has(sourcebatch.rulename) then for _, objectfile in ipairs(sourcebatch.objectfiles) do objectfiles_set:insert(objectfile) end @@ -973,19 +1033,25 @@ function _add_target_custom_commands(cmakelists, target, outputdir) -- build sourcebatch groups first local sourcegroups = rule_groups.build_sourcebatch_groups(target, target:sourcebatches()) + -- ignore c++ modules rules + local ignored_rules + if _can_native_support_for_cxxmodules() then + ignored_rules = _get_cxxmodules_rules() + end + -- add before commands -- we use irpairs(groups), because the last group that should be given the highest priority. local cmds_before = {} - target_cmds.get_target_buildcmd(target, cmds_before, "before") - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, "before") + target_cmds.get_target_buildcmd(target, cmds_before, {suffix = "before", ignored_rules = ignored_rules}) + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, {suffix = "before", ignored_rules = ignored_rules}) -- rule.on_buildcmd_files should also be executed before building the target, as cmake PRE_BUILD does not work. - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups) + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, {ignored_rules = ignored_rules}) _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, "before", cmds_before) -- add after commands local cmds_after = {} - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, "after") - target_cmds.get_target_buildcmd(target, cmds_after, "after") + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, {suffix = "after", ignored_rules = ignored_rules}) + target_cmds.get_target_buildcmd(target, cmds_after, {suffix = "after", ignored_rules = ignored_rules}) _add_target_custom_commands_for_batchcmds(cmakelists, target, outputdir, "after", cmds_after) end @@ -1082,7 +1148,7 @@ end function _generate_cmakelists(cmakelists, outputdir) -- add project info - _add_project(cmakelists, _get_project_languages(project.targets()), outputdir) + _add_project(cmakelists, outputdir) -- add targets for _, target in table.orderpairs(project.targets()) do diff --git a/xmake/plugins/project/make/makefile.lua b/xmake/plugins/project/make/makefile.lua index 7d462b138..12b1b77e0 100644 --- a/xmake/plugins/project/make/makefile.lua +++ b/xmake/plugins/project/make/makefile.lua @@ -474,8 +474,8 @@ function _add_build_custom_commands_before(makefile, target, sourcegroups, outpu -- add before commands -- we use irpairs(groups), because the last group that should be given the highest priority. local cmds_before = {} - target_cmds.get_target_buildcmd(target, cmds_before, "before") - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, "before") + target_cmds.get_target_buildcmd(target, cmds_before, {suffix = "before"}) + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups, {suffix = "before"}) target_cmds.get_target_buildcmd_sourcegroups(target, cmds_before, sourcegroups) local targetname = target:name() @@ -496,8 +496,8 @@ end -- add custom commands after building target function _add_build_custom_commands_after(makefile, target, sourcegroups, outputdir) local cmds_after = {} - target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, "after") - target_cmds.get_target_buildcmd(target, cmds_after, "after") + target_cmds.get_target_buildcmd_sourcegroups(target, cmds_after, sourcegroups, {suffix = "after"}) + target_cmds.get_target_buildcmd(target, cmds_after, {suffix = "after"}) if #cmds_after > 0 then for _, cmd in ipairs(cmds_after) do local command = _get_command_string(cmd, outputdir) diff --git a/xmake/plugins/project/utils/target_cmds.lua b/xmake/plugins/project/utils/target_cmds.lua index 4c7f4f008..0b98a4ed7 100644 --- a/xmake/plugins/project/utils/target_cmds.lua +++ b/xmake/plugins/project/utils/target_cmds.lua @@ -39,28 +39,39 @@ function _sourcebatch_is_built(sourcebatch) end -- get target buildcmd commands -function get_target_buildcmd(target, cmds, suffix) +function get_target_buildcmd(target, cmds, opt) + opt = opt or {} + local suffix = opt.suffix + local ignored_rules = hashset.from(opt.ignored_rules or {}) for _, ruleinst in ipairs(target:orderules()) do - local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") - local script = ruleinst:script(scriptname) - if script then - local batchcmds_ = batchcmds.new({target = target}) - script(target, batchcmds_, {}) - if not batchcmds_:empty() then - table.join2(cmds, batchcmds_:cmds()) + if not ignored_rules:has(ruleinst:name()) then + local scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local script = ruleinst:script(scriptname) + if script then + local batchcmds_ = batchcmds.new({target = target}) + script(target, batchcmds_, {}) + if not batchcmds_:empty() then + table.join2(cmds, batchcmds_:cmds()) + end end end end end -- get target buildcmd_files commands -function get_target_buildcmd_files(target, cmds, sourcebatch, suffix) +function get_target_buildcmd_files(target, cmds, sourcebatch, opt) + opt = opt or {} -- get rule local rulename = assert(sourcebatch.rulename, "unknown rule for sourcebatch!") local ruleinst = assert(target:rule(rulename) or project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename) + local ignored_rules = hashset.from(opt.ignored_rules or {}) + if ignored_rules:has(ruleinst:name()) then + return + end -- generate commands for xx_buildcmd_files + local suffix = opt.suffix local scriptname = "buildcmd_files" .. (suffix and ("_" .. suffix) or "") local script = ruleinst:script(scriptname) if script then @@ -89,14 +100,14 @@ function get_target_buildcmd_files(target, cmds, sourcebatch, suffix) end -- get target buildcmd commands of source group -function get_target_buildcmd_sourcegroups(target, cmds, sourcegroups, suffix) +function get_target_buildcmd_sourcegroups(target, cmds, sourcegroups, opt) for idx, group in irpairs(sourcegroups) do for _, item in pairs(group) do -- buildcmd scripts are always in rule, so we need to ignore target item (item.target). local sourcebatch = item.sourcebatch if item.rule then if not _sourcebatch_is_built(sourcebatch) then - get_target_buildcmd_files(target, cmds, sourcebatch, suffix) + get_target_buildcmd_files(target, cmds, sourcebatch, opt) end end end |
