Skip to content

Commit

Permalink
Merge pull request #3168 from Arthapz/cpp23-msvc-stdlib
Browse files Browse the repository at this point in the history
add support of C++23 standard modules on msvc
  • Loading branch information
waruqi authored Dec 17, 2022
2 parents f6ce7c1 + 1ba0ad7 commit 47f6392
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 48 deletions.
4 changes: 0 additions & 4 deletions tests/projects/c++/modules/stdmodules/src/my_module.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
module my_module;

#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

auto my_sum(size_t a, size_t b) -> size_t { return a + b; }
4 changes: 0 additions & 4 deletions tests/projects/c++/modules/stdmodules/src/my_module.mpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
export module my_module;

#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

export auto my_sum(size_t a, size_t b) -> size_t;
1 change: 1 addition & 0 deletions tests/projects/c++/modules/stdmodules/test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
inherit(".test_msvc")
4 changes: 0 additions & 4 deletions tests/projects/c++/modules/stdmodules/test/test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

import my_module;

Expand Down
5 changes: 3 additions & 2 deletions tests/projects/c++/modules/stdmodules/xmake.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
add_rules("mode.debug", "mode.release")
set_languages("c++20")

add_cxxflags("clang::-stdlib=libc++")

set_languages("c++latest")

target("mod")
set_kind("shared")
set_kind("static")
add_files("src/*.cpp", "src/*.mpp")

target("test")
Expand Down
14 changes: 12 additions & 2 deletions tests/projects/c++/modules/test_msvc.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import("lib.detect.find_tool")
import("core.base.semver")
import("core.tool.toolchain")

function _build()
local ci = (os.getenv("CI") or os.getenv("GITHUB_ACTIONS") or ""):lower()
Expand All @@ -12,7 +13,16 @@ end

function main(t)
if is_subhost("windows") then
os.exec("xmake f -c")
_build()
local msvc = toolchain.load("msvc")
if msvc and msvc:check() then
local vcvars = msvc:config("vcvars")
if vcvars and vcvars.VCInstallDir and vcvars.VCToolsVersion and semver.compare(vcvars.VCToolsVersion, "14.35") then
local stdmodulesdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "modules")
if os.isdir(stdmodulesdir) then
os.exec("xmake f -c")
_build()
end
end
end
end
end
6 changes: 6 additions & 0 deletions xmake/rules/c++/modules/modules_support/clang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,12 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
_flush_mapper(target)
end

-- not supported atm
function get_stdmodules(target)
local modules = {}
return modules
end

function get_bmi_extension()
return ".pcm"
end
Expand Down
1 change: 1 addition & 0 deletions xmake/rules/c++/modules/modules_support/common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ function get_module_dependencies(target, sourcebatch, opt)
if changed or modules == nil then
local moduleinfos = load_moduleinfos(target, sourcebatch)
modules = _parse_dependencies_data(target, moduleinfos)
modules = table.join(modules or {}, modules_support(target).get_stdmodules(target))
if modules then
_check_circular_dependencies(modules)
end
Expand Down
6 changes: 6 additions & 0 deletions xmake/rules/c++/modules/modules_support/gcc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,12 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
batchcmds:set_depmtime(depmtime)
end

-- not supported atm
function get_stdmodules(target)
local modules = {}
return modules
end

function get_bmi_extension()
return ".gcm"
end
Expand Down
97 changes: 65 additions & 32 deletions xmake/rules/c++/modules/modules_support/msvc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import("core.project.project")
import("core.project.depend")
import("core.project.config")
import("core.base.hashset")
import("core.base.semver")
import("utils.progress")
import("private.action.build.object", {alias = "objectbuilder"})
import("common")
Expand Down Expand Up @@ -79,7 +80,7 @@ function _add_objectfile_to_link_arguments(target, objectfile)
if table.contains(cache, objectfile) then
return
end
table.insert(cache, path.translate(objectfile))
table.insert(cache, objectfile)
common.localcache():set(cachekey, cache)
common.localcache():save(cachekey)
end
Expand Down Expand Up @@ -127,27 +128,29 @@ function load(target)
local modulesflag = get_modulesflag(target)
target:add("cxxflags", modulesflag)

-- add stdifcdir in case of if the user ask for it
local stdifcdirflag = get_stdifcdirflag(target)
if stdifcdirflag then
-- enable std modules if c++23 by defaults
if target:data("c++.msvc.enable_std_import") == nil then
local languages = target:get("languages")
local isatleastcpp23 = false
for _, language in ipairs(languages) do
if language:startswith("c++") or language:startswith("cxx") then
isatleastcpp23 = true
local version = tonumber(language:match("%d+"))
if not version or version <= 20 then
isatleastcpp23 = false
break
end
end
end
local stdmodulesdir
local msvc = target:toolchain("msvc")
if msvc then
local vcvars = msvc:config("vcvars")
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
local arch
if target:is_arch("x64", "x86_64") then
arch = "x64"
elseif target:is_arch("x86", "i386") then
arch = "x86"
end
if arch then
local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", arch)
if os.isdir(stdifcdir) then
target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false})
end
end
if vcvars.VCInstallDir and vcvars.VCToolsVersion and semver.compare(vcvars.VCToolsVersion, "14.35") then
stdmodulesdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "modules")
end
end
target:data_set("c++.msvc.enable_std_import", isatleastcpp23 and os.isdir(stdmodulesdir))
end
end

Expand Down Expand Up @@ -441,6 +444,13 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
_flush_mapper(target)
end, {rootjob = opt.rootjob})

if target:data("c++.msvc.enable_std_import") then
for objectfile, module in pairs(get_stdmodules(target)) do
table.insert(objectfiles, objectfile)
modules[objectfile] = module
end
end

local modulesjobs = {}
for _, objectfile in ipairs(objectfiles) do
local module = modules[objectfile]
Expand Down Expand Up @@ -490,7 +500,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
name = name or module.cppfile,
flags = _flags,
progress = (index * 100) / total})
target:add("objectfiles", objectfile)
_add_objectfile_to_link_arguments(target, path(objectfile))
elseif requiresflags then
requiresflags = get_requiresflags(target, module.requires)
target:fileconfig_add(cppfile, {force = {cxxflags = table.join(flags, requiresflags)}})
Expand Down Expand Up @@ -519,6 +529,13 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
local referenceflag = get_referenceflag(target)
local internalpartitionflag = get_internalpartitionflag(target)

if target:data("c++.msvc.enable_std_import") then
for objectfile, module in pairs(get_stdmodules(target)) do
table.insert(objectfiles, objectfile)
modules[objectfile] = module
end
end

-- build modules
local depmtime = 0
for _, objectfile in ipairs(objectfiles) do
Expand Down Expand Up @@ -555,7 +572,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
batchcmds:mkdir(path.directory(objectfile))
batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), table.join(flags, requiresflags or {})), {envs = msvc:runenvs()})
batchcmds:add_depfiles(cppfile)
target:add("objectfiles", objectfile)
_add_objectfile_to_link_arguments(target, path(objectfile))
if provide then
_add_module_to_mapper(target, referenceflag, name, name, objectfile, provide.bmi, requiresflags)
end
Expand All @@ -571,6 +588,34 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
_flush_mapper(target)
end

function get_stdmodules(target)
local modules = {}

-- build c++23 standard modules if needed
if target:data("c++.msvc.enable_std_import") then
local msvc = target:toolchain("msvc")
if msvc then
local vcvars = msvc:config("vcvars")
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
local stdmodulesdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "modules")
assert(stdmodulesdir, "Can't enable C++23 std modules, directory missing !")

local stlcachedir = common.stlmodules_cachedir(target)
local modulefile = path.join(stdmodulesdir, "std.ixx")
local bmifile = path.join(stlcachedir, "std.ixx" .. get_bmi_extension())
local objfile = bmifile .. ".obj"
modules[objfile] = {provides = {std = {interface = true, sourcefile = modulefile, bmi = bmifile}}}
stlcachedir = common.stlmodules_cachedir(target)
modulefile = path.join(stdmodulesdir, "std.compat.ixx")
bmifile = path.join(stlcachedir, "std.compat.ixx" .. get_bmi_extension())
objfile = bmifile .. ".obj"
modules[objfile] = {provides = {["std.compat"] = {interface = true, sourcefile = modulefile, bmi = bmifile}}, requires = {std = {unique = false, method = "by-name"}}}
end
end
end
return modules
end

function get_bmi_extension()
return ".ifc"
end
Expand Down Expand Up @@ -679,18 +724,6 @@ function get_exportheaderflag(target)
return exportheaderflag or nil
end

function get_stdifcdirflag(target)
local stdifcdirflag = _g.stdifcdirflag
if stdifcdirflag == nil then
local compinst = target:compiler("cxx")
if compinst:has_flags("-stdIfcDir", "cxxflags", {flagskey = "cl_std_ifc_dir"}) then
stdifcdirflag = "-stdIfcDir"
end
_g.stdifcdirflag = stdifcdirflag or false
end
return stdifcdirflag or nil
end

function get_scandependenciesflag(target)
local scandependenciesflag = _g.scandependenciesflag
if scandependenciesflag == nil then
Expand Down Expand Up @@ -785,4 +818,4 @@ function get_internalpartitionflag(target)
_g.internalpartitionflag = internalpartitionflag or false
end
return internalpartitionflag or nil
end
end

0 comments on commit 47f6392

Please sign in to comment.