From 0936ad49411c55cf4130793750336e011366ebbf Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 14 Feb 2023 00:07:38 +0800 Subject: improve clang for stdmodules --- .../modules/detect/tools/find_clang_scan_deps.lua | 55 ++++++++++++++++ xmake/rules/c++/modules/modules_support/clang.lua | 76 +++++++++++++++++----- xmake/rules/c++/modules/modules_support/common.lua | 2 +- 3 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 xmake/modules/detect/tools/find_clang_scan_deps.lua diff --git a/xmake/modules/detect/tools/find_clang_scan_deps.lua b/xmake/modules/detect/tools/find_clang_scan_deps.lua new file mode 100644 index 000000000..f4b9cd87b --- /dev/null +++ b/xmake/modules/detect/tools/find_clang_scan_deps.lua @@ -0,0 +1,55 @@ +--!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 +-- @file find_clang_scan_deps.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find clang-scan-deps +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local clang_scan_deps = find_clang_scan_deps() +-- local clang_scan_deps, version = find_clang_scan_deps({program = "clang-scan-deps", version = true}) +-- +-- @endcode +-- +function main(opt) + opt = opt or {} + local program = find_program(opt.program or "clang-scan-deps", opt) + if not program and is_host("macosx") then + local llvm = try {function () return os.iorunv("brew", {"--prefix", "llvm"}) end} + if llvm then + opt.paths = opt.paths or {} + opt.force = true + table.insert(opt.paths, path.join(llvm:trim(), "bin")) + program = find_program(opt.program or "clang-scan-deps", opt) + end + end + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 1078c4176..763cfb6cd 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -32,6 +32,47 @@ import("private.action.build.object", {alias = "objectbuilder"}) import("common") import("stl_headers") +-- get clang version +function _get_clang_version(target) + local clang_version = _g.clang_version + if not clang_version then + local program, toolname = target:tool("cxx") + if program and (toolname == "clang" or toolname == "clangxx") then + local clang = find_tool("clang", {program = program, version = true}) + if clang then + clang_version = clang.version + end + end + clang_version = clang_version or false + _g.clang_version = clang_version + end + return clang_version or nil +end + +-- get clang-scan-deps +function _get_clang_scan_deps(target) + local clang_scan_deps = _g.clang_scan_deps + if not clang_scan_deps then + local program, toolname = target:tool("cxx") + if program and (toolname == "clang" or toolname == "clangxx") then + local dir = path.directory(program) + local basename = path.basename(program) + local extension = path.extension(program) + program = (basename:gsub("clang", "clang-scan-deps")) .. extension + if os.isdir(dir) then + program = path.join(dir, program) + end + local result = find_tool("clang-scan-deps", {program = program, version = true}) + if result then + clang_scan_deps = result.program + end + end + clang_scan_deps = clang_scan_deps or false + _g.clang_scan_deps = clang_scan_deps + end + return clang_scan_deps or nil +end + -- add a module or an header unit into the mapper -- -- e.g @@ -82,7 +123,7 @@ function load(target) -- add module flags target:add("cxxflags", modulesflag) - if not modulesflag or target:is_plat("macosx") then + if not modulesflag then target:add("cxxflags", modulestsflag) end @@ -257,13 +298,13 @@ function generate_dependencies(target, sourcebatch, opt) local outputdir = common.get_outputdir(target, sourcefile) local jsonfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".json")) if has_clangscandepssupport(target) and not target:policy("build.c++.clang.fallbackscanner") then - local clangscandeps = find_tool("clang-scan-deps") + local clangscandeps = _get_clang_scan_deps(target) local compinst = target:compiler("cxx") local compflags = compinst:compflags({sourcefile = file, target = target}) local flags = table.join({"--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile)}, compflags) - vprint(table.concat(table.join(clangscandeps.program, flags), " ")) - local outdata, errdata = os.iorunv(clangscandeps.program, flags) + vprint(table.concat(table.join(clangscandeps, flags), " ")) + local outdata, errdata = os.iorunv(clangscandeps, flags) assert(errdata, errdata) io.writefile(jsonfile, outdata) @@ -301,13 +342,15 @@ function generate_dependencies(target, sourcebatch, opt) break end end + if has_std_modules then - assert(not (has_std_modules and not target:policy("build.c++.clang.stdmodules")), - [[On llvm <= 16 standard C++ modules are not supported ; - they can be emulated through clang modules and supported only on libc++ ; - please add -stdlib=libc++ cxx flag or disable strict mode]]) + -- we need clang >= 17.0 or use clang stdmodules if the current target contains std module + local clang_version = _get_clang_version(target) + assert((clang_version and semver.compare(clang_version, "17.0") >= 0) or target:policy("build.c++.clang.stdmodules"), + [[On llvm <= 16 standard C++ modules are not supported ; + they can be emulated through clang modules and supported only on libc++ ; + please add -stdlib=libc++ cxx flag or disable strict mode]]) - if has_std_modules then target:data_set("cxx.modules.use_libc++", true) if target:data("cxx.modules.use_libc++") then _enable_libcxx(target) @@ -771,9 +814,9 @@ function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then local compinst = target:compiler("cxx") - local modulesflag, moduletsflag = get_modulesflag(target) - if compinst:has_flags(modulesflag or moduletsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags(modulesflag or moduletsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then + local modulesflag, modulestsflag = get_modulesflag(target) + if compinst:has_flags(modulesflag or modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags(modulesflag or modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false @@ -784,8 +827,9 @@ end function has_clangscandepssupport(target) local support_clangscandeps = _g.support_clangscandeps if support_clangscandeps == nil then - local clangscandeps = find_tool("clang-scan-deps", {version = true}) - if clangscandeps and clangscandeps.version and semver.compare(clangscandeps.version, "16.0") >= 0 then + local clangscandeps = _get_clang_scan_deps(target) + local clang_version = _get_clang_version(target) + if clangscandeps and clang_version and semver.compare(clang_version, "16.0") >= 0 then support_clangscandeps = true end _g.support_clangscandeps = support_clangscandeps or false @@ -797,8 +841,8 @@ function get_moduleoutputflag(target) local moduleoutputflag = _g.moduleoutputflag if moduleoutputflag == nil then local compinst = target:compiler("cxx") - local clang = find_tool("clang", {version = true}) - if compinst:has_flags("-fmodule-output=", "cxxflags", {flagskey = "clang_module_output", tryrun = true}) and semver.compare(clang.version, "16.0") >= 0 then + local clang_version = _get_clang_version(target) + if compinst:has_flags("-fmodule-output=", "cxxflags", {flagskey = "clang_module_output", tryrun = true}) and semver.compare(clang_version, "16.0") >= 0 then moduleoutputflag = "-fmodule-output=" end _g.moduleoutputflag = moduleoutputflag or false diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 7a43cd5f2..8996d0ddf 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -740,4 +740,4 @@ function get_outputdir(target, module) end return moduledir end -end \ No newline at end of file +end -- cgit v1.3.1 From e288951c41b72f3ccf3cfed495417fea7dee1e79 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 15 Feb 2023 22:46:13 +0800 Subject: add snippet to has_flags --- xmake/modules/detect/tools/cl/has_flags.lua | 6 +++--- xmake/modules/detect/tools/gcc/has_flags.lua | 5 +++-- xmake/modules/detect/tools/nvcc/has_flags.lua | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/xmake/modules/detect/tools/cl/has_flags.lua b/xmake/modules/detect/tools/cl/has_flags.lua index fe57e38b0..e1e986303 100644 --- a/xmake/modules/detect/tools/cl/has_flags.lua +++ b/xmake/modules/detect/tools/cl/has_flags.lua @@ -54,10 +54,10 @@ end function _check_try_running(flags, opt) -- make an stub source file - local tmpdir = path.join(os.tmpdir(), "detect") - local sourcefile = path.join(tmpdir, "cl_has_flags" .. _get_extension(opt)) + local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}" + local sourcefile = os.tmpfile("cl_has_flags:" .. snippet) .. _get_extension(opt) if not os.isfile(sourcefile) then - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + io.writefile(sourcefile, snippet) end -- check it diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua index 64fa70df8..6ab7ce810 100644 --- a/xmake/modules/detect/tools/gcc/has_flags.lua +++ b/xmake/modules/detect/tools/gcc/has_flags.lua @@ -77,9 +77,10 @@ end function _check_try_running(flags, opt, islinker) -- make an stub source file - local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flags" .. _get_extension(opt)) + local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}" + local sourcefile = os.tmpfile("gcc_has_flags:" .. snippet) .. _get_extension(opt) if not os.isfile(sourcefile) then - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + io.writefile(sourcefile, snippet) end -- check flags for linker diff --git a/xmake/modules/detect/tools/nvcc/has_flags.lua b/xmake/modules/detect/tools/nvcc/has_flags.lua index d96ffdfe8..c75f6e114 100644 --- a/xmake/modules/detect/tools/nvcc/has_flags.lua +++ b/xmake/modules/detect/tools/nvcc/has_flags.lua @@ -101,13 +101,13 @@ end function _check_try_running(flags, opt, islinker) -- make an stub source file - local sourcefile = path.join(os.tmpdir(), "detect", "nvcc_has_flags.cu") + local snippet = opt.snippet or "int main(int argc, char** argv)\n{return 0;}" + local sourcefile = os.tmpfile("nvcc_has_flags:" .. snippet) .. ".cu" if not os.isfile(sourcefile) then - io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}") + io.writefile(sourcefile, snippet) end local args = table.join("-o", os.nuldev(), sourcefile) - if not islinker then table.insert(args, 1, "-c") end -- cgit v1.3.1 From 3cdbc4183fe807d2bf4bbcb19aef1f85e33c1d6d Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 14 Feb 2023 18:45:42 +0100 Subject: remove useless flags to build modules on clang --- xmake/rules/c++/modules/modules_support/clang.lua | 37 +++++++++++------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 763cfb6cd..54be2c80f 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -116,22 +116,16 @@ end -- load module support for the current target function load(target) - local modulesflag, modulestsflag = get_modulesflag(target) - local builtinmodulemapflag = get_builtinmodulemapflag(target) - local implicitmodulesflag = get_implicitmodulesflag(target) - local noimplicitmodulemapsflag = get_noimplicitmodulemapsflag(target) + local clangmodulesflag, modulestsflag, withoutflag = get_modulesflag(target) -- add module flags - target:add("cxxflags", modulesflag) - if not modulesflag then + if not withoutflag then target:add("cxxflags", modulestsflag) end + -- enable clang modules to emulate std modules if target:policy("build.c++.clang.stdmodules") then - target:add("cxxflags", builtinmodulemapflag, {force = true}) - target:add("cxxflags", implicitmodulesflag, {force = true}) - else - target:add("cxxflags", noimplicitmodulemapsflag, {force = true}) + target:add("cxxflags", clangmodulesflag) end -- fix default visibility for functions and variables [-fvisibility] differs in PCH file vs. current file @@ -698,21 +692,25 @@ function get_bmi_extension() end function get_modulesflag(target) - local modulesflag = _g.modulesflag + local clangmodulesflag = _g.clangmodulesflag local modulestsflag = _g.modulestsflag - if modulesflag == nil and modulestsflag == nil then + local withoutflag = _g.withoutflag + if clangmodulesflag == nil and modulestsflag == nil then local compinst = target:compiler("cxx") if compinst:has_flags("-fmodules", "cxxflags", {flagskey = "clang_modules"}) then - modulesflag = "-fmodules" + clangmodulesflag = "-fmodules" end if compinst:has_flags("-fmodules-ts", "cxxflags", {flagskey = "clang_modules_ts"}) then modulestsflag = "-fmodules-ts" end - assert(modulesflag or modulestsflag, "compiler(clang): does not support c++ module!") - _g.modulesflag = modulesflag or false + local clang_version = _get_clang_version(target) + withoutflag = semver.compare(clang_version, "16.0") >= 0 + assert(withoutflag or modulestsflag, "compiler(clang): does not support c++ module!") + _g.clangmodulesflag = clangmodulesflag or false _g.modulestsflag = modulestsflag or false + _g.withoutflag = withoutflag or false end - return modulesflag or nil, modulestsflag or nil + return clangmodulesflag or nil, modulestsflag or nil, withoutflag or nil end function get_builtinmodulemapflag(target) @@ -814,9 +812,10 @@ function has_headerunitsupport(target) local support_headerunits = _g.support_headerunits if support_headerunits == nil then local compinst = target:compiler("cxx") - local modulesflag, modulestsflag = get_modulesflag(target) - if compinst:has_flags(modulesflag or modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags(modulesflag or modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then + local _, modulestsflag, withoutflag = get_modulesflag(target) + modulestsflag = withoutflag and "" or modulestsflag + if compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false -- cgit v1.3.1 From 3dff84c9e8fe939d1ed29123797060db56925e26 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:14:02 +0100 Subject: fix compilation of non .cpp private module with clang --- xmake/rules/c++/modules/modules_support/clang.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 54be2c80f..3a7ad13b9 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -230,6 +230,8 @@ function _build_modulefile(target, sourcefile, opt) else bmiflags = table.join("-x", "c++-module", "--precompile", compflags, common_args, requiresflags) end + else + compileflags = {"-x", "c++"} end if bmiflags then -- cgit v1.3.1 From 51fad68409dc0ac9c70702397d0d344ca0aaf3f9 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:14:15 +0100 Subject: fix libc++ link --- xmake/rules/c++/modules/modules_support/clang.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 3a7ad13b9..06425ff40 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -111,7 +111,8 @@ end -- enable libc++ function _enable_libcxx(target) target:add("cxxflags", "-stdlib=libc++") - target:add("syslinks", "c++") + target:add("ldflags", "-stdlib=libc++") + target:add("shflags", "-stdlib=libc++") end -- load module support for the current target -- cgit v1.3.1 From 475734e6f4a27a3e3f2cdab3d3a93a5e949b7b0e Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:15:06 +0100 Subject: use -fmodule-file== for named module on clang --- xmake/rules/c++/modules/modules_support/clang.lua | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 06425ff40..df3cd066b 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -79,15 +79,21 @@ end -- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.pcm -- -fmodule-file=build/.gens/Foo/rules/modules/cache/iostream.pcm -- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm +-- on LLVM >= 16 +-- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/iostream.pcm +-- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- -function _add_module_to_mapper(target, name, bmifile, deps) +function _add_module_to_mapper(target, name, bmifile, deps, namedmodule) local modulemap = _get_modulemap_from_mapper(target, name) if modulemap then return end + local clang_version = _get_clang_version(target) + namedmodule = namedmodule and semver.compare(clang_version, "16.0") >= 0 local modulefileflag = get_modulefileflag(target) - local mapflag = modulefileflag .. bmifile + local mapflag = namedmodule and format("%s%s=%s", modulefileflag, name, bmifile) or modulefileflag .. bmifile modulemap = {flag = mapflag, deps = deps} common.localcache():set2(_mapper_cachekey(target), "modulemap" .. name, modulemap) end @@ -596,7 +602,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) if provide then - _add_module_to_mapper(target, name, bmifile, requiresflags) + _add_module_to_mapper(target, name, bmifile, requiresflags, true) end elseif requiresflags then local cxxflags = {} @@ -658,7 +664,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op if provide then _batchcmds_compile(batchcmds, target, table.join(flags, {"-x", "c++-module", "--precompile", "-c", path(cppfile), "-o", path(provide.bmi)})) - _add_module_to_mapper(target, name, provide.bmi) + _add_module_to_mapper(target, name, provide.bmi, nil, true) end _batchcmds_compile(batchcmds, target, file, table.join(flags, not provide and {"-x", "c++"} or {}, {"-c", file, "-o", path(objectfile)})) -- cgit v1.3.1 From 4220ee54e0f12461ef2186f8ccf4a7823ece2ee7 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:15:27 +0100 Subject: fix libc++ detection --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index df3cd066b..e8d52dcba 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -157,7 +157,7 @@ function load(target) -- on ubuntu: -- sudo apt install libc++-dev libc++abi-15-dev -- - local flags = table.join(target:get("cxxflags"), get_config("cxxflags") or {}) + local flags = table.join(target:get("cxxflags") or {}, get_config("cxxflags") or {}) target:data_set("cxx.modules.use_libc++", table.contains(flags, "-stdlib=libc++", "clang::-stdlib=libc++")) if target:data("cxx.modules.use_libc++") then _enable_libcxx(target) -- cgit v1.3.1 From f6b9179af9ff16461e023f00ef10535b6e575ced Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:15:42 +0100 Subject: fix headerunit clang support detection --- xmake/rules/c++/modules/modules_support/clang.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index e8d52dcba..d505d779c 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -823,8 +823,8 @@ function has_headerunitsupport(target) local compinst = target:compiler("cxx") local _, modulestsflag, withoutflag = get_modulesflag(target) modulestsflag = withoutflag and "" or modulestsflag - if compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {flagskey = "clang_system_header_unit_support", tryrun = true}) then + if compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {snippet = "inline int foo() { return 0; }", flagskey = "clang_user_header_unit_support", tryrun = true}) and + compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {snippet = "inline int foo() { return 0; }", flagskey = "clang_system_header_unit_support", tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false -- cgit v1.3.1 From 0765350a8935fe493e0846543081dc29463ea953 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:29:10 +0100 Subject: fix clang module vprint --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index d505d779c..3d45fd43f 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -246,7 +246,7 @@ function _build_modulefile(target, sourcefile, opt) end compileflags = table.join2(compileflags, compflags, common_args, requiresflags or {}) - vprint(compinst:compcmd(bmifile or sourcefile, objectfile, {compflags = compileflags, rawargs = true})) + vprint(compinst:compcmd(bmiflags and bmifile or sourcefile, objectfile, {compflags = compileflags, rawargs = true})) if not dryrun then -- cgit v1.3.1 From 46e033b7beaba56ed7dba4587ab98992b1d9f646 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 18:57:29 +0100 Subject: fix compflags for clang-scan module dependencies scan --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 3d45fd43f..40c91981e 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -303,7 +303,7 @@ function generate_dependencies(target, sourcebatch, opt) if has_clangscandepssupport(target) and not target:policy("build.c++.clang.fallbackscanner") then local clangscandeps = _get_clang_scan_deps(target) local compinst = target:compiler("cxx") - local compflags = compinst:compflags({sourcefile = file, target = target}) + local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) local flags = table.join({"--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile)}, compflags) vprint(table.concat(table.join(clangscandeps, flags), " ")) -- cgit v1.3.1 From d39fdee559df35b35c03ba616558f5614b126a9b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 15 Feb 2023 19:04:13 +0100 Subject: remove clang module flags deduplication --- xmake/rules/c++/modules/modules_support/clang.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 40c91981e..9d5911775 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -233,7 +233,7 @@ function _build_modulefile(target, sourcefile, opt) bmifile = opt.provide.bmifile if moduleoutputflag then - compileflags = table.join("-x", "c++-module", moduleoutputflag .. bmifile, compflags, common_args, requiresflags) + compileflags = table.join("-x", "c++-module", moduleoutputflag .. bmifile, requiresflags) else bmiflags = table.join("-x", "c++-module", "--precompile", compflags, common_args, requiresflags) end -- cgit v1.3.1 From 32f6a7942a263bfb60ea39f2a48bd75a441109ec Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 08:09:17 +0800 Subject: fix tests --- tests/projects/package/depconfigs/xmake.lua | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/projects/package/depconfigs/xmake.lua b/tests/projects/package/depconfigs/xmake.lua index 2559ced03..377c8899b 100644 --- a/tests/projects/package/depconfigs/xmake.lua +++ b/tests/projects/package/depconfigs/xmake.lua @@ -1,11 +1,8 @@ add_requires("libpng", {system = false, configs = {vs_runtime = "MD"}}) add_requires("libtiff", {system = false, configs = {vs_runtime = "MD", zlib = true}}) -add_requires("libwebp") -add_requireconfs("libwebp", {system = false, configs = {shared = true, vs_runtime = "MD"}}) add_requireconfs("libpng.zlib", {system = false, override = true, configs = {cxflags = "-DTEST1"}, version = "1.2.10"}) add_requireconfs("libtiff.*|cmake", {system = false, configs = {cxflags = "-DTEST2"}}) -add_requireconfs("libwebp.**|cmake", {system = false, configs = {cxflags = "-DTEST3"}}) target("test") set_kind("binary") @@ -39,18 +36,3 @@ target("test2") end end) -target("test3") - set_kind("binary") - add_files("src/*.c") - add_packages("libwebp") - before_build(function (target) - if target:pkg("libwebp") then - local found - for _, linkdir in ipairs(target:pkg("libwebp"):get("linkdirs")) do - if linkdir:find("zlib", 1, true) then - found = true - end - end - assert(found, "package(zlib) not found!") - end - end) -- cgit v1.3.1 From 3761c27bb3fa4ee92f73662e1bb9979fcc83f87a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 22:32:42 +0800 Subject: format code --- xmake/rules/c++/modules/modules_support/clang.lua | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 9d5911775..6766fae1a 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -84,17 +84,18 @@ end -- -fmodule-file=build/.gens/Foo/rules/modules/cache/iostream.pcm -- -fmodule-file=build/.gens/Foo/rules/modules/cache/bar.hpp.pcm -- -function _add_module_to_mapper(target, name, bmifile, deps, namedmodule) +function _add_module_to_mapper(target, name, bmifile, opt) + opt = opt or {} local modulemap = _get_modulemap_from_mapper(target, name) if modulemap then return end local clang_version = _get_clang_version(target) - namedmodule = namedmodule and semver.compare(clang_version, "16.0") >= 0 + local namedmodule = opt.namedmodule and semver.compare(clang_version, "16.0") >= 0 local modulefileflag = get_modulefileflag(target) local mapflag = namedmodule and format("%s%s=%s", modulefileflag, name, bmifile) or modulefileflag .. bmifile - modulemap = {flag = mapflag, deps = deps} + modulemap = {flag = mapflag, deps = opt.deps} common.localcache():set2(_mapper_cachekey(target), "modulemap" .. name, modulemap) end @@ -602,7 +603,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op target:add("objectfiles", objectfile) if provide then - _add_module_to_mapper(target, name, bmifile, requiresflags, true) + _add_module_to_mapper(target, name, bmifile, {deps = requiresflags, namedmodule = true}) end elseif requiresflags then local cxxflags = {} @@ -664,7 +665,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op if provide then _batchcmds_compile(batchcmds, target, table.join(flags, {"-x", "c++-module", "--precompile", "-c", path(cppfile), "-o", path(provide.bmi)})) - _add_module_to_mapper(target, name, provide.bmi, nil, true) + _add_module_to_mapper(target, name, provide.bmi, {namedmodule = true}) end _batchcmds_compile(batchcmds, target, file, table.join(flags, not provide and {"-x", "c++"} or {}, {"-c", file, "-o", path(objectfile)})) @@ -823,8 +824,14 @@ function has_headerunitsupport(target) local compinst = target:compiler("cxx") local _, modulestsflag, withoutflag = get_modulesflag(target) modulestsflag = withoutflag and "" or modulestsflag - if compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", {snippet = "inline int foo() { return 0; }", flagskey = "clang_user_header_unit_support", tryrun = true}) and - compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", {snippet = "inline int foo() { return 0; }", flagskey = "clang_system_header_unit_support", tryrun = true}) then + if compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-user-header", "cxxflags", { + snippet = "inline int foo() { return 0; }", + flagskey = "clang_user_header_unit_support", + tryrun = true}) and + compinst:has_flags(modulestsflag .. " -std=c++20 -x c++-system-header", "cxxflags", { + snippet = "inline int foo() { return 0; }", + flagskey = "clang_system_header_unit_support", + tryrun = true}) then support_headerunits = true end _g.support_headerunits = support_headerunits or false @@ -850,7 +857,8 @@ function get_moduleoutputflag(target) if moduleoutputflag == nil then local compinst = target:compiler("cxx") local clang_version = _get_clang_version(target) - if compinst:has_flags("-fmodule-output=", "cxxflags", {flagskey = "clang_module_output", tryrun = true}) and semver.compare(clang_version, "16.0") >= 0 then + if compinst:has_flags("-fmodule-output=", "cxxflags", {flagskey = "clang_module_output", tryrun = true}) and + semver.compare(clang_version, "16.0") >= 0 then moduleoutputflag = "-fmodule-output=" end _g.moduleoutputflag = moduleoutputflag or false -- cgit v1.3.1 From 44053082b5aa4765d9b6a10322a1ad8fc253a762 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 23:30:58 +0800 Subject: fix visibility differs --- xmake/rules/c++/modules/modules_support/clang.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 6766fae1a..71127da77 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -139,17 +139,19 @@ function load(target) -- fix default visibility for functions and variables [-fvisibility] differs in PCH file vs. current file -- module.pcm cannot be loaded due to a configuration mismatch with the current compilation. -- - -- it will happen in binary target depend ont shared target with modules, and enable release mode at same time. + -- it will happen in binary target depend on library target with modules, and enable release mode at same time. + -- + -- @see https://github.com/xmake-io/xmake/issues/3358#issuecomment-1432586767 local dep_symbols - local has_shared_deps = false + local has_library_deps = false for _, dep in ipairs(target:orderdeps()) do - if dep:is_shared() then + if dep:is_shared() or dep:is_static() or dep:is_object() then dep_symbols = dep:get("symbols") - has_shared_deps = true + has_library_deps = true break end end - if has_shared_deps then + if has_library_deps then target:set("symbols", dep_symbols and dep_symbols or "none") end -- cgit v1.3.1 From a7dea61c3953b96ef3335f0cac64b7bc2634bc03 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 23:41:48 +0800 Subject: improve stdlib for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 71127da77..6c538373b 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -234,7 +234,6 @@ function _build_modulefile(target, sourcefile, opt) local bmiflags if opt.provide then bmifile = opt.provide.bmifile - if moduleoutputflag then compileflags = table.join("-x", "c++-module", moduleoutputflag .. bmifile, requiresflags) else @@ -244,6 +243,16 @@ function _build_modulefile(target, sourcefile, opt) compileflags = {"-x", "c++"} end + -- we can also enable libc++ when building modules + -- + -- @see https://github.com/xmake-io/xmake/issues/3373 + if target:data("cxx.modules.use_libc++") then + if bmiflags then + table.insert(bmiflags, "-stdlib=libc++") + end + table.insert(compileflags, "-stdlib=libc++") + end + if bmiflags then vprint(compinst:compcmd(sourcefile, bmifile, {compflags = bmiflags, rawargs = true})) end @@ -307,8 +316,13 @@ function generate_dependencies(target, sourcebatch, opt) local clangscandeps = _get_clang_scan_deps(target) local compinst = target:compiler("cxx") local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) - local flags = table.join({"--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile)}, compflags) - + local flags = table.join("--format=p1689", "--", + compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile), + compflags) + -- we can also enable libc++ when scaning deps + if target:data("cxx.modules.use_libc++") then + table.insert(flags, "-stdlib=libc++") + end vprint(table.concat(table.join(clangscandeps, flags), " ")) local outdata, errdata = os.iorunv(clangscandeps, flags) assert(errdata, errdata) -- cgit v1.3.1 From 9e8183b512ccf2bd2d9a14c9ca1caaabb3fdc2ef Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 23:43:06 +0800 Subject: improve scan std modules --- xmake/rules/c++/modules/modules_support/clang.lua | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 6c538373b..86ec44e9e 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -243,16 +243,6 @@ function _build_modulefile(target, sourcefile, opt) compileflags = {"-x", "c++"} end - -- we can also enable libc++ when building modules - -- - -- @see https://github.com/xmake-io/xmake/issues/3373 - if target:data("cxx.modules.use_libc++") then - if bmiflags then - table.insert(bmiflags, "-stdlib=libc++") - end - table.insert(compileflags, "-stdlib=libc++") - end - if bmiflags then vprint(compinst:compcmd(sourcefile, bmifile, {compflags = bmiflags, rawargs = true})) end @@ -319,7 +309,6 @@ function generate_dependencies(target, sourcebatch, opt) local flags = table.join("--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile), compflags) - -- we can also enable libc++ when scaning deps if target:data("cxx.modules.use_libc++") then table.insert(flags, "-stdlib=libc++") end @@ -352,7 +341,10 @@ function generate_dependencies(target, sourcebatch, opt) local has_std_modules = false for _, r in ipairs(dependinfo.rules) do for _, required in ipairs(r.requires) do - if required["logical-name"] == "std" or required["logical-name"] == "std.compat" then + -- it may be `std:utility`, .. + -- @see https://github.com/xmake-io/xmake/issues/3373 + local logical_name = required["logical-name"] + if logical_name and (logical_name == "std" or logical_name:startswith("std.") or logical_name:startswith("std:")) then has_std_modules = true break end -- cgit v1.3.1 From e76a80fe2b54d04c555529127496e0912cd83a09 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 23:43:42 +0800 Subject: improve scandeps --- xmake/rules/c++/modules/modules_support/clang.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 86ec44e9e..5adeba4fa 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -308,10 +308,8 @@ function generate_dependencies(target, sourcebatch, opt) local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) local flags = table.join("--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile), + "-stdlib=libc++", compflags) - if target:data("cxx.modules.use_libc++") then - table.insert(flags, "-stdlib=libc++") - end vprint(table.concat(table.join(clangscandeps, flags), " ")) local outdata, errdata = os.iorunv(clangscandeps, flags) assert(errdata, errdata) -- cgit v1.3.1 From 4b32e484b54f61f649e46a94823f99ee940c9ed3 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 16 Feb 2023 23:59:53 +0800 Subject: improve stdlib --- xmake/rules/c++/modules/modules_support/clang.lua | 42 ++++++++++++++--------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 5adeba4fa..8f233b58a 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -115,11 +115,19 @@ function _get_modulemap_from_mapper(target, name) return common.localcache():get2(_mapper_cachekey(target), "modulemap" .. name) or nil end --- enable libc++ -function _enable_libcxx(target) - target:add("cxxflags", "-stdlib=libc++") - target:add("ldflags", "-stdlib=libc++") - target:add("shflags", "-stdlib=libc++") +-- use the given stdlib? e.g. libc++ or libstdc++ +function _use_stdlib(target, name) + local stdlib = target:data("cxx.modules.stdlib") or "libstdc++" + return stdlib == name +end + +-- set stdlib flags, it will use libstdc++ if we do not set `-stdlib=` +function _set_stdlib_flags(target) + if _use_stdlib(target, "libc++") then + target:add("cxxflags", "-stdlib=libc++") + target:add("ldflags", "-stdlib=libc++") + target:add("shflags", "-stdlib=libc++") + end end -- load module support for the current target @@ -161,10 +169,12 @@ function load(target) -- sudo apt install libc++-dev libc++abi-15-dev -- local flags = table.join(target:get("cxxflags") or {}, get_config("cxxflags") or {}) - target:data_set("cxx.modules.use_libc++", table.contains(flags, "-stdlib=libc++", "clang::-stdlib=libc++")) - if target:data("cxx.modules.use_libc++") then - _enable_libcxx(target) + if table.contains(flags, "-stdlib=libc++", "clang::-stdlib=libc++") then + target:data_set("cxx.modules.stdlib", "libc++") + elseif table.contains(flags, "-stdlib=libstdc++", "clang::-stdlib=libstdc++") then + target:data_set("cxx.modules.stdlib", "libstdc++") end + _set_stdlib_flags(target) end -- get includedirs for stl headers @@ -178,7 +188,7 @@ function _get_toolchain_includedirs_for_stlheaders(target, includedirs, clang) local tmpfile = os.tmpfile() .. ".cc" io.writefile(tmpfile, "#include ") local argv = {"-E", "-x", "c++", tmpfile} - if target:data("cxx.modules.use_libc++") then + if _use_stdlib(target, "libc++") then table.insert(argv, 1, "-stdlib=libc++") end local result = try {function () return os.iorunv(clang, argv) end} @@ -308,7 +318,6 @@ function generate_dependencies(target, sourcebatch, opt) local compflags = compinst:compflags({sourcefile = sourcefile, target = target}) local flags = table.join("--format=p1689", "--", compinst:program(), "-x", "c++", "-c", sourcefile, "-o", target:objectfile(sourcefile), - "-stdlib=libc++", compflags) vprint(table.concat(table.join(clangscandeps, flags), " ")) local outdata, errdata = os.iorunv(clangscandeps, flags) @@ -335,7 +344,7 @@ function generate_dependencies(target, sourcebatch, opt) local rawdependinfo = io.readfile(jsonfile) if rawdependinfo then local dependinfo = json.decode(rawdependinfo) - if not target:data("cxx.modules.use_libc++") then + if target:data("cxx.modules.stdlib") == nil then local has_std_modules = false for _, r in ipairs(dependinfo.rules) do for _, required in ipairs(r.requires) do @@ -361,10 +370,9 @@ function generate_dependencies(target, sourcebatch, opt) they can be emulated through clang modules and supported only on libc++ ; please add -stdlib=libc++ cxx flag or disable strict mode]]) - target:data_set("cxx.modules.use_libc++", true) - if target:data("cxx.modules.use_libc++") then - _enable_libcxx(target) - end + -- we use libc++ by default if we do not explicitly specify -stdlib:libstdc++ + target:data_set("cxx.modules.stdlib", "libc++") + _set_stdlib_flags(target) end end end @@ -403,7 +411,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) -- libc++ have a builtin module mapper - if not target:data_set("cxx.modules.use_libc++") then + if not _use_stdlib(target, "libc++") then _add_module_to_mapper(target, headerunit.name, bmifile) end end, {rootjob = flushjob}) @@ -431,7 +439,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, _batchcmds_compile(batchcmds, target, flags) end -- libc++ have a builtin module mapper - if not target:data_set("cxx.modules.use_libc++") then + if not _use_stdlib(target, "libc++") then _add_module_to_mapper(target, headerunit.name, bmifile) end depmtime = math.max(depmtime, os.mtime(bmifile)) -- cgit v1.3.1