From fbbe6ef7fbc16b4eea9bdc298d83fae68263fbba Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sat, 23 Mar 2024 23:56:27 +0100 Subject: [PATCH 1/8] support -print-library-module-manifest-path for std module detection on clang --- .../clang/compiler_support.lua | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index b4535ef574..8fadb237e3 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -79,6 +79,26 @@ function _get_cpplibrary_name(target) end end +function _get_std_module_manifest_path(target) + local print_module_manifest_flag = get_printlibrarymodulemanifestpathflag(target) + if print_module_manifest_flag then + local outdata = try { function() return os.iorun(self:program() .. " " .. print_module_manifest_flag) end } + if outdata then + return outdata:trim() + end + end + + -- fallback on custom detection + -- manifest can be found in /lib subdirectory (i.e on debian it should be /lib/x86_64-unknown-linux-gnu/) + local clang_path = path.directory(get_clang_path(target)) + local clang_lib_path = path.join(clang_path, "..", "lib") + local modules_json_path = path.join(clang_lib_path, "libc++.modules.json") + if not os.isfile(modules_json_path) then + modules_json_path = find_file("*/libc++.modules.json", clang_lib_path) + end + return modules_json_path +end + -- load module support for the current target function load(target) local clangmodulesflag, modulestsflag, withoutflag = get_modulesflag(target) @@ -246,15 +266,7 @@ function get_stdmodules(target) if cpplib then if cpplib == "c++" then -- libc++ module is found by parsing libc++.modules.json - -- which can be found in /lib subdirectory (i.e on debian it should be /lib/x86_64-unknown-linux-gnu/) - -- in the futur llvm may provide a way to directory get the path of libc++.modules.json - -- @see https://github.com/llvm/llvm-project/pull/76451 (has been revert, so we need to wait) - local clang_path = path.directory(get_clang_path(target)) - local clang_lib_path = path.join(clang_path, "..", "lib") - local modules_json_path = path.join(clang_lib_path, "libc++.modules.json") - if not os.isfile(modules_json_path) then - modules_json_path = find_file("*/libc++.modules.json", clang_lib_path) - end + local modules_json_path = _get_std_module_manifest_path(target) if modules_json_path then local modules_json = json.decode(io.readfile(modules_json_path)) local std_module_directory = path.directory(modules_json.modules[1]["source-path"]) @@ -459,3 +471,15 @@ function get_moduleoutputflag(target) return moduleoutputflag or nil end +function get_printlibrarymodulemanifestpathflag(target) + local printlibrarymodulemanifestpathflag = _g.printlibrarymodulemanifestpathflag + if printlibrarymodulemanifestpathflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-print-library-module-manifest-path", "cxxflags", {flagskey = "clang_print_library_module_manifest_path", tryrun = true}) then + printlibrarymodulemanifestpathflag = "-print-library-module-manifest-path" + end + _g.printlibrarymodulemanifestpathflag = printlibrarymodulemanifestpathflag or false + end + return printlibrarymodulemanifestpathflag or nil +end + From d960686b76d491371421d32363a51201c7377ab4 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 7 Mar 2024 11:10:30 +0100 Subject: [PATCH 2/8] add _ to print library module manifest path flag function getter for better lisibility --- .../modules_support/clang/compiler_support.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 8fadb237e3..af2f3ae748 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -80,7 +80,7 @@ function _get_cpplibrary_name(target) end function _get_std_module_manifest_path(target) - local print_module_manifest_flag = get_printlibrarymodulemanifestpathflag(target) + local print_module_manifest_flag = get_print_library_module_manifest_path_flag(target) if print_module_manifest_flag then local outdata = try { function() return os.iorun(self:program() .. " " .. print_module_manifest_flag) end } if outdata then @@ -471,15 +471,15 @@ function get_moduleoutputflag(target) return moduleoutputflag or nil end -function get_printlibrarymodulemanifestpathflag(target) - local printlibrarymodulemanifestpathflag = _g.printlibrarymodulemanifestpathflag - if printlibrarymodulemanifestpathflag == nil then +function get_print_library_module_manifest_path_flag(target) + local print_library_module_manifest_path_flag = _g.print_library_module_manifest_path_flag + if print_library_module_manifest_path_flag == nil then local compinst = target:compiler("cxx") if compinst:has_flags("-print-library-module-manifest-path", "cxxflags", {flagskey = "clang_print_library_module_manifest_path", tryrun = true}) then - printlibrarymodulemanifestpathflag = "-print-library-module-manifest-path" + print_library_module_manifest_path_flag = "-print-library-module-manifest-path" end - _g.printlibrarymodulemanifestpathflag = printlibrarymodulemanifestpathflag or false + _g.print_library_module_manifest_path_flag = print_library_module_manifest_path_flag or false end - return printlibrarymodulemanifestpathflag or nil + return print_library_module_manifest_path_flag or nil end From 9845737dcaa882bd56fa46d0b0cbee39e06693e7 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 7 Mar 2024 11:17:46 +0100 Subject: [PATCH 3/8] use os.iorunv --- .../c++/modules/modules_support/clang/compiler_support.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index af2f3ae748..427a8a6a2a 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -82,7 +82,8 @@ end function _get_std_module_manifest_path(target) local print_module_manifest_flag = get_print_library_module_manifest_path_flag(target) if print_module_manifest_flag then - local outdata = try { function() return os.iorun(self:program() .. " " .. print_module_manifest_flag) end } + local compinst = target:compiler("cxx") + local outdata, _ = try { function() return os.iorunv(compinst:program(), {print_module_manifest_flag}) end } if outdata then return outdata:trim() end From 11282b572ba6e86a0dbd83fe9876f5dbe22f9ab2 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Thu, 7 Mar 2024 12:59:22 +0100 Subject: [PATCH 4/8] add missings runenvs for iorunv --- .../c++/modules/modules_support/clang/compiler_support.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 427a8a6a2a..ced45cf344 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -45,7 +45,7 @@ function _get_toolchain_includedirs_for_stlheaders(target, includedirs, clang) table.insert(argv, 1, "-stdlib=libstdc++") end end - local result = try {function () return os.iorunv(clang, argv) end} + local result = try {function () return os.iorunv(clang, argv, {envs = compinst:runenvs()}) end} if result then for _, line in ipairs(result:split("\n", {plain = true})) do line = line:trim() @@ -83,7 +83,7 @@ function _get_std_module_manifest_path(target) local print_module_manifest_flag = get_print_library_module_manifest_path_flag(target) if print_module_manifest_flag then local compinst = target:compiler("cxx") - local outdata, _ = try { function() return os.iorunv(compinst:program(), {print_module_manifest_flag}) end } + local outdata, _ = try { function() return os.iorunv(compinst:program(), {print_module_manifest_flag}, {envs = compinst:runenvs()}) end } if outdata then return outdata:trim() end From b3115d8c98fda1a727f81e47b3dd2e353c9df5e2 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 12 Mar 2024 16:59:25 +0100 Subject: [PATCH 5/8] apply PR suggestion --- .../modules/modules_support/clang/compiler_support.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index ced45cf344..7fba1054ab 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -270,11 +270,13 @@ function get_stdmodules(target) local modules_json_path = _get_std_module_manifest_path(target) if modules_json_path then local modules_json = json.decode(io.readfile(modules_json_path)) - local std_module_directory = path.directory(modules_json.modules[1]["source-path"]) - if not path.is_absolute(std_module_directory) then - std_module_directory = path.join(path.directory(modules_json_path), std_module_directory) + if modules_json and modules_json.modules and #modules_json.modules > 0 then + local std_module_directory = path.directory(modules_json.modules[1]["source-path"]) + if not path.is_absolute(std_module_directory) then + std_module_directory = path.join(path.directory(modules_json_path), std_module_directory) + end + return {path.join(std_module_directory, "std.cppm"), path.join(std_module_directory, "std.compat.cppm")} end - return {path.join(std_module_directory, "std.cppm"), path.join(std_module_directory, "std.compat.cppm")} end elseif cpplib == "stdc++" then -- libstdc++ doesn't have a std module file atm From 1d1474dbfb2b65ca90df6b22c6cad461eaebbe69 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 17 Mar 2024 17:28:32 +0100 Subject: [PATCH 6/8] handle case for clang std module detection when -print-library-module-manifest-path doesn't find libc++.module.json --- .../c++/modules/modules_support/clang/compiler_support.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 7fba1054ab..1bc4ee6bfe 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -84,7 +84,7 @@ function _get_std_module_manifest_path(target) if print_module_manifest_flag then local compinst = target:compiler("cxx") local outdata, _ = try { function() return os.iorunv(compinst:program(), {print_module_manifest_flag}, {envs = compinst:runenvs()}) end } - if outdata then + if outdata and outdata ~= "" then return outdata:trim() end end From a596970f9b49e71e7f27cc3ed66a137b3705ff0c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 17 Mar 2024 17:37:28 +0100 Subject: [PATCH 7/8] add C++23 and libc++ flags for -print-library-module-manifest-path detection --- .../c++/modules/modules_support/clang/compiler_support.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index 1bc4ee6bfe..faffa1e493 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -83,8 +83,8 @@ function _get_std_module_manifest_path(target) local print_module_manifest_flag = get_print_library_module_manifest_path_flag(target) if print_module_manifest_flag then local compinst = target:compiler("cxx") - local outdata, _ = try { function() return os.iorunv(compinst:program(), {print_module_manifest_flag}, {envs = compinst:runenvs()}) end } - if outdata and outdata ~= "" then + local outdata, _ = try { function() return os.iorunv(compinst:program(), {"-std=c++23", "-stdlib=libc++", print_module_manifest_flag}, {envs = compinst:runenvs()}) end } + if outdata and not outdata:startswith("") then return outdata:trim() end end From 808757405eef0ace00c96442174245dbf8512c18 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Sun, 24 Mar 2024 00:03:19 +0100 Subject: [PATCH 8/8] support --sdk= by adding sysroot to std module manifest detection line --- .../c++/modules/modules_support/clang/compiler_support.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua index faffa1e493..367494f7c2 100644 --- a/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua +++ b/xmake/rules/c++/modules/modules_support/clang/compiler_support.lua @@ -81,9 +81,10 @@ end function _get_std_module_manifest_path(target) local print_module_manifest_flag = get_print_library_module_manifest_path_flag(target) + local clang_path = path.directory(get_clang_path(target)) if print_module_manifest_flag then local compinst = target:compiler("cxx") - local outdata, _ = try { function() return os.iorunv(compinst:program(), {"-std=c++23", "-stdlib=libc++", print_module_manifest_flag}, {envs = compinst:runenvs()}) end } + local outdata, _ = try { function() return os.iorunv(compinst:program(), {"-std=c++23", "-stdlib=libc++", "--sysroot=" .. path.join(clang_path, ".."), print_module_manifest_flag}, {envs = compinst:runenvs()}) end } if outdata and not outdata:startswith("") then return outdata:trim() end @@ -91,7 +92,6 @@ function _get_std_module_manifest_path(target) -- fallback on custom detection -- manifest can be found in /lib subdirectory (i.e on debian it should be /lib/x86_64-unknown-linux-gnu/) - local clang_path = path.directory(get_clang_path(target)) local clang_lib_path = path.join(clang_path, "..", "lib") local modules_json_path = path.join(clang_lib_path, "libc++.modules.json") if not os.isfile(modules_json_path) then