diff options
| author | ruki <[email protected]> | 2025-04-23 22:49:40 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-04-23 11:30:31 +0800 |
| commit | 81c8589d494d42bfc64393955b2d62ae22c90039 (patch) | |
| tree | 208c0f093e92ad29ac4be924a5e22967fd231d32 | |
| parent | a0d18574febebd378cfa481ec733581f01c2a41e (diff) | |
improve implib
| -rw-r--r-- | xmake/core/tool/linker.lua | 20 | ||||
| -rw-r--r-- | xmake/modules/core/tools/gcc.lua | 682 | ||||
| -rw-r--r-- | xmake/modules/core/tools/link.lua | 25 | ||||
| -rw-r--r-- | xmake/modules/core/tools/nvcc.lua | 32 | ||||
| -rw-r--r-- | xmake/modules/private/action/build/link_objects.lua | 4 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/actions/patch_sources.lua | 4 |
6 files changed, 403 insertions, 364 deletions
diff --git a/xmake/core/tool/linker.lua b/xmake/core/tool/linker.lua index d91da81d8..973b8696e 100644 --- a/xmake/core/tool/linker.lua +++ b/xmake/core/tool/linker.lua @@ -144,6 +144,9 @@ function linker.load(targetkind, sourcekinds, target) local arch = linkertool:arch() or config.arch() or os.arch() local cachekey = targetkind .. "_" .. linkerinfo.linkerkind .. (linkerinfo.program or "") .. plat .. arch cachekey = cachekey .. table.concat(sourcekinds, "") -- @see https://github.com/xmake-io/xmake/issues/5360 + if target then + cachekey = cachekey .. tostring(target) + end -- get it directly from cache dirst builder._INSTANCES = builder._INSTANCES or {} @@ -226,17 +229,20 @@ end function linker:link(objectfiles, targetfile, opt) opt = opt or {} local linkflags = opt.linkflags or self:linkflags(opt) - opt = table.copy(opt) - opt.target = self:target() profiler:enter(self:name(), "link", targetfile) - local ok, errors = sandbox.load(self:_tool().link, self:_tool(), table.wrap(objectfiles), self:_targetkind(), targetfile, linkflags, opt) + local ok, errors = sandbox.load(self:_tool().link, self:_tool(), + table.wrap(objectfiles), self:_targetkind(), targetfile, linkflags, + table.join(opt, {target = self:target()})) profiler:leave(self:name(), "link", targetfile) return ok, errors end -- get the link arguments list function linker:linkargv(objectfiles, targetfile, opt) - return self:_tool():linkargv(table.wrap(objectfiles), self:_targetkind(), targetfile, opt.linkflags or self:linkflags(opt), opt) + opt = opt or {} + return self:_tool():linkargv(table.wrap(objectfiles), + self:_targetkind(), targetfile, opt.linkflags or self:linkflags(opt), + table.join(opt, {target = self:target()})) end -- get the link command @@ -250,14 +256,10 @@ end -- e.g. {target = ..., targetkind = "static", configs = {ldflags = "", links = "", linkdirs = "", ...}} -- function linker:linkflags(opt) - - -- init options opt = opt or {} -- get target - local target = opt.target - - -- get target kind + local target = opt.target or self:target() local targetkind = opt.targetkind if not targetkind and target and target:type() == "target" then targetkind = target:kind() diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index e59898efa..073529e87 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -33,6 +33,348 @@ import("private.cache.build_cache") import("private.service.distcc_build.client", {alias = "distcc_build_client"}) import("rules.c++.modules.support", {rootdir = os.programdir()}) +-- has -static-libstdc++? +function _has_static_libstdcxx(self) + local has_static_libstdcxx = _g._HAS_STATIC_LIBSTDCXX + if has_static_libstdcxx == nil then + if self:has_flags("-static-libstdc++ -Werror", "ldflags", {flagskey = "gcc_static_libstdcxx"}) then + has_static_libstdcxx = true + end + has_static_libstdcxx = has_static_libstdcxx or false + _g._HAS_STATIC_LIBSTDCXX = has_static_libstdcxx + end + return has_static_libstdcxx +end + +-- get implib file +function _get_implibfile(self, targetkind, targetfile, opt) + if targetkind == "shared" and self:is_plat("mingw") then + local target = opt and opt.target + local implibfile + if target and target:type() == "target" then + implibfile = target:artifactfile("implib") + end + if not implibfile then + implibfile = path.join(path.directory(targetfile), path.basename(targetfile) .. ".a") + end + return implibfile + end +end + +-- get `-MMD -MF depfile.d` flags, some old gcc does not support it at same time +function _get_depfile_flags(self) + local depfile_flags = _g._DEPFILE_FLAGS + if depfile_flags == nil then + local nuldev = os.nuldev() + if self:name():startswith("cosmoc") then + nuldev = os.tmpfile() + end + if self:has_flags({"-MMD", "-MF", nuldev}, "cxflags", { flagskey = "-MMD -MF" }) then + depfile_flags = {"-MMD", "-MF"} + end + _g._DEPFILE_FLAGS = depfile_flags or false + end + return depfile_flags +end + +-- get color diagnostics flag +function _get_color_diagnostics_flag(self) + local colors_diagnostics = _g._COLOR_DIAGNOSTICS + if colors_diagnostics == nil then + if io.isatty() and (tty.has_color8() or tty.has_color256()) then + local theme = colors.theme() + if theme and theme:name() ~= "plain" then + -- for gcc + if self:has_flags("-fdiagnostics-color=always", "cxflags") then + colors_diagnostics = "-fdiagnostics-color=always" + -- for clang + elseif self:has_flags("-fcolor-diagnostics", "cxflags") then + colors_diagnostics = "-fcolor-diagnostics" + end + + -- enable color output for windows, @see https://github.com/xmake-io/xmake-vscode/discussions/260 + if colors_diagnostics and self:name() == "clang" and is_host("windows") and + self:has_flags("-fansi-escape-codes", "cxflags") then + colors_diagnostics = table.join(colors_diagnostics, "-fansi-escape-codes") + end + end + end + colors_diagnostics = colors_diagnostics or false + _g._COLOR_DIAGNOSTICS = colors_diagnostics + end + return colors_diagnostics +end + +-- has gnu-line-marker flag? +function _has_gnu_line_marker_flag(self) + local gnu_line_marker = _g._HAS_GNU_LINE_MARKER + if gnu_line_marker == nil then + if self:has_flags({"-Wno-gnu-line-marker", "-Werror"}, "cxflags") then + gnu_line_marker = true + end + gnu_line_marker = gnu_line_marker or false + _g._HAS_GNU_LINE_MARKER = gnu_line_marker + end + return gnu_line_marker +end + +-- get preprocess file path +function _get_cppfile(sourcefile, objectfile) + return path.join(path.directory(objectfile), "__cpp_" .. path.basename(objectfile) .. path.extension(sourcefile)) +end + +-- do preprocess +function _preprocess(program, argv, opt) + + -- is gcc or clang? + local tool = opt.tool + local is_gcc = false + local is_clang = false + if tool then + if tool:name() == "gcc" or tool:name() == "gxx" then + is_gcc = true + elseif tool:name():startswith("clang") then + is_clang = true + elseif tool:name() == "circle" then + return + end + end + + -- enable "-fdirectives-only"? we need to enable it manually + -- + -- @see https://github.com/xmake-io/xmake/issues/2603 + -- https://github.com/xmake-io/xmake/issues/2425 + local directives_only + if is_gcc then + local cachekey = "core.tools." .. tool:name() + directives_only = memcache.get(cachekey, "directives_only") + if directives_only == nil then + if os.isfile(os.projectfile()) and project.policy("preprocessor.gcc.directives_only") then + directives_only = true + end + memcache.set(cachekey, "directives_only", directives_only) + end + end + + -- get flags and source file + local flags = {} + local cppflags = {} + local skipped = program:endswith("cache") and 1 or 0 + for _, flag in ipairs(argv) do + if flag == "-o" then + break + end + + -- get preprocessor flags + table.insert(cppflags, flag) + + -- for c++ modules, we cannot support it for clang now + if is_clang and flag:startswith("-fmodules") then + return + end + + -- we cannot enable "-fdirectives-only" + if directives_only and (flag:startswith("-D__TIME__=") or + flag:startswith("-D__DATE__=") or flag:startswith("-D__TIMESTAMP__=")) then + directives_only = false + end + + -- get compiler flags + if flag == "-MMD" or (flag:startswith("-I") and #flag > 2) or flag:startswith("--sysroot=") then + skipped = 1 + elseif flag == "-MF" or + flag == "-I" or flag == "-isystem" or flag == "-include" or flag == "-include-pch" or + flag == "-isysroot" or flag == "-gcc-toolchain" then + skipped = 2 + elseif flag:endswith("xcrun") then + skipped = 4 + end + if skipped > 0 then + skipped = skipped - 1 + else + table.insert(flags, flag) + end + end + local objectfile = argv[#argv - 1] + local sourcefile = argv[#argv] + assert(objectfile and sourcefile, "%s: iorunv(%s): invalid arguments!", self, program) + + -- is precompiled header? + if objectfile:endswith(".gch") or objectfile:endswith(".pch") then + return + end + + -- disable linemarkers? + local linemarkers = _g.linemarkers + if linemarkers == nil then + if os.isfile(os.projectfile()) and project.policy("preprocessor.linemarkers") == false then + linemarkers = false + else + linemarkers = true + end + _g.linemarkers = linemarkers + end + + -- do preprocess + local cppfile = _get_cppfile(sourcefile, objectfile) + local cppfiledir = path.directory(cppfile) + if not os.isdir(cppfiledir) then + os.mkdir(cppfiledir) + end + table.insert(cppflags, "-E") + -- it will be faster for preprocessing + -- when preprocessing, handle directives, but do not expand macros. + if directives_only then + table.insert(cppflags, "-fdirectives-only") + end + if linemarkers == false then + table.insert(cppflags, "-P") + end + -- if we want to support pch for gcc, we need to enable this flag + -- and clang need not this flag, it will use '-include-pch' to include and preprocess header files + -- but it will be slower than non-ccache mode. + -- + -- @see https://github.com/xmake-io/xmake/issues/5858 + -- https://musescore.org/en/node/182331 + if is_gcc then + table.insert(cppflags, "-fpch-preprocess") + end + table.insert(cppflags, "-o") + table.insert(cppflags, cppfile) + table.insert(cppflags, sourcefile) + + -- we need to mark as it when compiling the preprocessed source file + -- it will indicate to the preprocessor that the input file has already been preprocessed. + if is_gcc then + table.insert(flags, "-fpreprocessed") + end + -- with -fpreprocessed, predefinition of command line and most builtin macros is disabled. + if directives_only then + table.insert(flags, "-fdirectives-only") + end + + -- suppress -Wgnu-line-marker warnings + -- @see https://github.com/xmake-io/xmake/issues/5737 + if (is_gcc or is_clang) and _has_gnu_line_marker_flag(tool) then + table.insert(flags, "-Wno-gnu-line-marker") + end + + -- do preprocess + local cppinfo = try {function () + if is_host("windows") then + cppflags = winos.cmdargv(cppflags, {escape = true}) + end + local outdata, errdata = os.iorunv(program, cppflags, opt) + return {outdata = outdata, errdata = errdata, + sourcefile = sourcefile, objectfile = objectfile, cppfile = cppfile, cppflags = flags} + end} + if not cppinfo then + if is_gcc then + local cachekey = "core.tools." .. tool:name() + memcache.set(cachekey, "directives_only", false) + end + end + return cppinfo +end + +-- compile preprocessed file +function _compile_preprocessed_file(program, cppinfo, opt) + local argv = table.join(cppinfo.cppflags, "-o", cppinfo.objectfile, cppinfo.cppfile) + if is_host("windows") then + argv = winos.cmdargv(argv, {escape = true}) + end + local outdata, errdata = os.iorunv(program, argv, opt) + -- we need to get warning information from output + -- and we need to reserve warnings output from preprocessing + -- @see https://github.com/xmake-io/xmake/issues/5858 + if outdata then + cppinfo.outdata = (cppinfo.outdata or "") .. outdata + end + if errdata then + cppinfo.errdata = (cppinfo.errdata or "") .. errdata + end +end + +-- do compile +function _compile(self, sourcefile, objectfile, compflags, opt) + opt = opt or {} + local program, argv = compargv(self, sourcefile, objectfile, compflags, opt) + local function _compile_fallback() + local runargv = argv + if is_host("windows") then + runargv = winos.cmdargv(argv, {escape = true}) + end + return os.iorunv(program, runargv, {envs = self:runenvs(), shell = opt.shell}) + end + local cppinfo + if distcc_build_client.is_distccjob() and distcc_build_client.singleton():has_freejobs() then + cppinfo = distcc_build_client.singleton():compile(program, argv, {envs = self:runenvs(), + preprocess = _preprocess, compile = _compile_preprocessed_file, compile_fallback = _compile_fallback, + tool = self, remote = true, shell = opt.shell}) + elseif build_cache.is_enabled(opt.target) and build_cache.is_supported(self:kind()) then + cppinfo = build_cache.build(program, argv, {envs = self:runenvs(), + preprocess = _preprocess, compile = _compile_preprocessed_file, compile_fallback = _compile_fallback, + tool = self, shell = opt.shell}) + end + if cppinfo then + return cppinfo.outdata, cppinfo.errdata + else + return _compile_fallback() + end +end + +-- remove "-include xxx.h" and "-include-pch xxx.pch" +function _remove_flags_for_pch(self, flags, opt) + opt = opt or {} + local result = {} + local include = false + local pchfile = opt.pchfile + for _, flag in ipairs(flags) do + local inserted = false + if not flag:startswith("-include") then + if not include then + inserted = true + end + include = false + else + include = true + end + if pchfile and flag:startswith("-fmodules") then + inserted = false + end + if inserted then + table.insert(result, flag) + end + end + return result +end + +-- make the compile arguments list for the precompiled header +function _translate_flags_for_pch(self, flags) + local pchflags = _remove_flags_for_pch(self, flags, {pchfile = true}) + if self:kind() == "cxx" then + table.insert(pchflags, "-x") + table.insert(pchflags, "c++-header") + elseif self:kind() == "cc" then + table.insert(pchflags, "-x") + table.insert(pchflags, "c-header") + elseif self:kind() == "mxx" then + table.insert(pchflags, "-x") + table.insert(pchflags, "objective-c++-header") + elseif self:kind() == "mm" then + table.insert(pchflags, "-x") + table.insert(pchflags, "objective-c-header") + end + return pchflags +end + +-- remove the force includes for c++modules +-- @see https://github.com/xmake-io/xmake/issues/4051#issuecomment-2795707800 +function _translate_flags_for_mpp(self, flags) + return _remove_flags_for_pch(self, flags) +end + +-- init it function init(self) -- init mxflags @@ -190,19 +532,6 @@ function nf_vectorext(self, extension) return maps[extension] end --- has -static-libstdc++? -function _has_static_libstdcxx(self) - local has_static_libstdcxx = _g._HAS_STATIC_LIBSTDCXX - if has_static_libstdcxx == nil then - if self:has_flags("-static-libstdc++ -Werror", "ldflags", {flagskey = "gcc_static_libstdcxx"}) then - has_static_libstdcxx = true - end - has_static_libstdcxx = has_static_libstdcxx or false - _g._HAS_STATIC_LIBSTDCXX = has_static_libstdcxx - end - return has_static_libstdcxx -end - -- make the runtime flag function nf_runtime(self, runtime, opt) opt = opt or {} @@ -574,9 +903,9 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) end -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc - if targetkind == "shared" and self:is_plat("mingw") then - local implib = opt.implib or path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a") - table.insert(flags_extra, "-Wl,--out-implib," .. implib) + local implibfile = _get_implibfile(self, targetkind, targetfile, opt) + if implibfile then + table.insert(flags_extra, "-Wl,--out-implib," .. implibfile) end -- init arguments @@ -596,12 +925,10 @@ end function link(self, objectfiles, targetkind, targetfile, flags, opt) opt = opt or {} - -- ensure the target directory os.mkdir(path.directory(targetfile)) - - -- ensure the implib directory - if opt.implib then - os.mkdir(path.directory(opt.implib)) + local implibfile = _get_implibfile(self, targetkind, targetfile, opt) + if implibfile then + os.mkdir(path.directory(implibfile)) end local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags, opt) @@ -612,319 +939,6 @@ function link(self, objectfiles, targetkind, targetfile, flags, opt) end end --- get `-MMD -MF depfile.d` flags, some old gcc does not support it at same time -function _get_depfile_flags(self) - local depfile_flags = _g._DEPFILE_FLAGS - if depfile_flags == nil then - local nuldev = os.nuldev() - if self:name():startswith("cosmoc") then - nuldev = os.tmpfile() - end - if self:has_flags({"-MMD", "-MF", nuldev}, "cxflags", { flagskey = "-MMD -MF" }) then - depfile_flags = {"-MMD", "-MF"} - end - _g._DEPFILE_FLAGS = depfile_flags or false - end - return depfile_flags -end - --- get color diagnostics flag -function _get_color_diagnostics_flag(self) - local colors_diagnostics = _g._COLOR_DIAGNOSTICS - if colors_diagnostics == nil then - if io.isatty() and (tty.has_color8() or tty.has_color256()) then - local theme = colors.theme() - if theme and theme:name() ~= "plain" then - -- for gcc - if self:has_flags("-fdiagnostics-color=always", "cxflags") then - colors_diagnostics = "-fdiagnostics-color=always" - -- for clang - elseif self:has_flags("-fcolor-diagnostics", "cxflags") then - colors_diagnostics = "-fcolor-diagnostics" - end - - -- enable color output for windows, @see https://github.com/xmake-io/xmake-vscode/discussions/260 - if colors_diagnostics and self:name() == "clang" and is_host("windows") and - self:has_flags("-fansi-escape-codes", "cxflags") then - colors_diagnostics = table.join(colors_diagnostics, "-fansi-escape-codes") - end - end - end - colors_diagnostics = colors_diagnostics or false - _g._COLOR_DIAGNOSTICS = colors_diagnostics - end - return colors_diagnostics -end - --- has gnu-line-marker flag? -function _has_gnu_line_marker_flag(self) - local gnu_line_marker = _g._HAS_GNU_LINE_MARKER - if gnu_line_marker == nil then - if self:has_flags({"-Wno-gnu-line-marker", "-Werror"}, "cxflags") then - gnu_line_marker = true - end - gnu_line_marker = gnu_line_marker or false - _g._HAS_GNU_LINE_MARKER = gnu_line_marker - end - return gnu_line_marker -end - --- get preprocess file path -function _get_cppfile(sourcefile, objectfile) - return path.join(path.directory(objectfile), "__cpp_" .. path.basename(objectfile) .. path.extension(sourcefile)) -end - --- do preprocess -function _preprocess(program, argv, opt) - - -- is gcc or clang? - local tool = opt.tool - local is_gcc = false - local is_clang = false - if tool then - if tool:name() == "gcc" or tool:name() == "gxx" then - is_gcc = true - elseif tool:name():startswith("clang") then - is_clang = true - elseif tool:name() == "circle" then - return - end - end - - -- enable "-fdirectives-only"? we need to enable it manually - -- - -- @see https://github.com/xmake-io/xmake/issues/2603 - -- https://github.com/xmake-io/xmake/issues/2425 - local directives_only - if is_gcc then - local cachekey = "core.tools." .. tool:name() - directives_only = memcache.get(cachekey, "directives_only") - if directives_only == nil then - if os.isfile(os.projectfile()) and project.policy("preprocessor.gcc.directives_only") then - directives_only = true - end - memcache.set(cachekey, "directives_only", directives_only) - end - end - - -- get flags and source file - local flags = {} - local cppflags = {} - local skipped = program:endswith("cache") and 1 or 0 - for _, flag in ipairs(argv) do - if flag == "-o" then - break - end - - -- get preprocessor flags - table.insert(cppflags, flag) - - -- for c++ modules, we cannot support it for clang now - if is_clang and flag:startswith("-fmodules") then - return - end - - -- we cannot enable "-fdirectives-only" - if directives_only and (flag:startswith("-D__TIME__=") or - flag:startswith("-D__DATE__=") or flag:startswith("-D__TIMESTAMP__=")) then - directives_only = false - end - - -- get compiler flags - if flag == "-MMD" or (flag:startswith("-I") and #flag > 2) or flag:startswith("--sysroot=") then - skipped = 1 - elseif flag == "-MF" or - flag == "-I" or flag == "-isystem" or flag == "-include" or flag == "-include-pch" or - flag == "-isysroot" or flag == "-gcc-toolchain" then - skipped = 2 - elseif flag:endswith("xcrun") then - skipped = 4 - end - if skipped > 0 then - skipped = skipped - 1 - else - table.insert(flags, flag) - end - end - local objectfile = argv[#argv - 1] - local sourcefile = argv[#argv] - assert(objectfile and sourcefile, "%s: iorunv(%s): invalid arguments!", self, program) - - -- is precompiled header? - if objectfile:endswith(".gch") or objectfile:endswith(".pch") then - return - end - - -- disable linemarkers? - local linemarkers = _g.linemarkers - if linemarkers == nil then - if os.isfile(os.projectfile()) and project.policy("preprocessor.linemarkers") == false then - linemarkers = false - else - linemarkers = true - end - _g.linemarkers = linemarkers - end - - -- do preprocess - local cppfile = _get_cppfile(sourcefile, objectfile) - local cppfiledir = path.directory(cppfile) - if not os.isdir(cppfiledir) then - os.mkdir(cppfiledir) - end - table.insert(cppflags, "-E") - -- it will be faster for preprocessing - -- when preprocessing, handle directives, but do not expand macros. - if directives_only then - table.insert(cppflags, "-fdirectives-only") - end - if linemarkers == false then - table.insert(cppflags, "-P") - end - -- if we want to support pch for gcc, we need to enable this flag - -- and clang need not this flag, it will use '-include-pch' to include and preprocess header files - -- but it will be slower than non-ccache mode. - -- - -- @see https://github.com/xmake-io/xmake/issues/5858 - -- https://musescore.org/en/node/182331 - if is_gcc then - table.insert(cppflags, "-fpch-preprocess") - end - table.insert(cppflags, "-o") - table.insert(cppflags, cppfile) - table.insert(cppflags, sourcefile) - - -- we need to mark as it when compiling the preprocessed source file - -- it will indicate to the preprocessor that the input file has already been preprocessed. - if is_gcc then - table.insert(flags, "-fpreprocessed") - end - -- with -fpreprocessed, predefinition of command line and most builtin macros is disabled. - if directives_only then - table.insert(flags, "-fdirectives-only") - end - - -- suppress -Wgnu-line-marker warnings - -- @see https://github.com/xmake-io/xmake/issues/5737 - if (is_gcc or is_clang) and _has_gnu_line_marker_flag(tool) then - table.insert(flags, "-Wno-gnu-line-marker") - end - - -- do preprocess - local cppinfo = try {function () - if is_host("windows") then - cppflags = winos.cmdargv(cppflags, {escape = true}) - end - local outdata, errdata = os.iorunv(program, cppflags, opt) - return {outdata = outdata, errdata = errdata, - sourcefile = sourcefile, objectfile = objectfile, cppfile = cppfile, cppflags = flags} - end} - if not cppinfo then - if is_gcc then - local cachekey = "core.tools." .. tool:name() - memcache.set(cachekey, "directives_only", false) - end - end - return cppinfo -end - --- compile preprocessed file -function _compile_preprocessed_file(program, cppinfo, opt) - local argv = table.join(cppinfo.cppflags, "-o", cppinfo.objectfile, cppinfo.cppfile) - if is_host("windows") then - argv = winos.cmdargv(argv, {escape = true}) - end - local outdata, errdata = os.iorunv(program, argv, opt) - -- we need to get warning information from output - -- and we need to reserve warnings output from preprocessing - -- @see https://github.com/xmake-io/xmake/issues/5858 - if outdata then - cppinfo.outdata = (cppinfo.outdata or "") .. outdata - end - if errdata then - cppinfo.errdata = (cppinfo.errdata or "") .. errdata - end -end - --- do compile -function _compile(self, sourcefile, objectfile, compflags, opt) - opt = opt or {} - local program, argv = compargv(self, sourcefile, objectfile, compflags, opt) - local function _compile_fallback() - local runargv = argv - if is_host("windows") then - runargv = winos.cmdargv(argv, {escape = true}) - end - return os.iorunv(program, runargv, {envs = self:runenvs(), shell = opt.shell}) - end - local cppinfo - if distcc_build_client.is_distccjob() and distcc_build_client.singleton():has_freejobs() then - cppinfo = distcc_build_client.singleton():compile(program, argv, {envs = self:runenvs(), - preprocess = _preprocess, compile = _compile_preprocessed_file, compile_fallback = _compile_fallback, - tool = self, remote = true, shell = opt.shell}) - elseif build_cache.is_enabled(opt.target) and build_cache.is_supported(self:kind()) then - cppinfo = build_cache.build(program, argv, {envs = self:runenvs(), - preprocess = _preprocess, compile = _compile_preprocessed_file, compile_fallback = _compile_fallback, - tool = self, shell = opt.shell}) - end - if cppinfo then - return cppinfo.outdata, cppinfo.errdata - else - return _compile_fallback() - end -end - --- remove "-include xxx.h" and "-include-pch xxx.pch" -function _remove_flags_for_pch(self, flags, opt) - opt = opt or {} - local result = {} - local include = false - local pchfile = opt.pchfile - for _, flag in ipairs(flags) do - local inserted = false - if not flag:startswith("-include") then - if not include then - inserted = true - end - include = false - else - include = true - end - if pchfile and flag:startswith("-fmodules") then - inserted = false - end - if inserted then - table.insert(result, flag) - end - end - return result -end - --- make the compile arguments list for the precompiled header -function _translate_flags_for_pch(self, flags) - local pchflags = _remove_flags_for_pch(self, flags, {pchfile = true}) - if self:kind() == "cxx" then - table.insert(pchflags, "-x") - table.insert(pchflags, "c++-header") - elseif self:kind() == "cc" then - table.insert(pchflags, "-x") - table.insert(pchflags, "c-header") - elseif self:kind() == "mxx" then - table.insert(pchflags, "-x") - table.insert(pchflags, "objective-c++-header") - elseif self:kind() == "mm" then - table.insert(pchflags, "-x") - table.insert(pchflags, "objective-c-header") - end - return pchflags -end - --- remove the force includes for c++modules --- @see https://github.com/xmake-io/xmake/issues/4051#issuecomment-2795707800 -function _translate_flags_for_mpp(self, flags) - return _remove_flags_for_pch(self, flags) -end - -- make the compile arguments list function compargv(self, sourcefile, objectfile, flags, opt) diff --git a/xmake/modules/core/tools/link.lua b/xmake/modules/core/tools/link.lua index 12bad4a0d..70266c4c7 100644 --- a/xmake/modules/core/tools/link.lua +++ b/xmake/modules/core/tools/link.lua @@ -22,6 +22,14 @@ import("core.project.config") import("private.tools.vstool") +-- get implib file +function _get_implibfile(self, opt) + local target = opt and opt.target + if target and target:type() == "target" then + return target:artifactfile("implib") + end +end + -- init it function init(self) @@ -137,8 +145,9 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) table.insert(argv, 1, "-lib") elseif targetkind == "shared" then table.insert(argv, 1, "-dll") - if opt.implib then - table.insert(argv, "/IMPLIB:" .. opt.implib) + local implibfile = _get_implibfile(self, opt) + if implibfile then + table.insert(argv, "/implib:" .. implibfile) end end return self:program(), argv @@ -146,13 +155,13 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags, opt) + opt = opt or {} - -- ensure the target directory + -- ensure the target file directory exists os.mkdir(path.directory(targetfile)) - - -- ensure the implib directory - if opt and opt.implib then - os.mkdir(path.directory(opt.implib)) + local implibfile = _get_implibfile(self, opt) + if implibfile then + os.mkdir(path.directory(implibfile)) end try @@ -161,6 +170,7 @@ function link(self, objectfiles, targetkind, targetfile, flags, opt) local toolchain = self:toolchain() local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags, opt) + if toolchain and toolchain:name() == "masm32" then os.iorunv(program, argv, {envs = self:runenvs()}) else @@ -185,4 +195,3 @@ function link(self, objectfiles, targetkind, targetfile, flags, opt) } } end - diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index ec0e15874..02b6ab069 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -28,6 +28,21 @@ import("core.language.language") import("core.project.policy") import("utils.progress") +-- get implib file +function _get_implibfile(self, targetkind, targetfile, opt) + if targetkind == "shared" and self:is_plat("mingw") then + local target = opt and opt.target + local implibfile + if target and target:type() == "target" then + implibfile = target:artifactfile("implib") + end + if not implibfile then + implibfile = path.join(path.directory(targetfile), path.basename(targetfile) .. ".a") + end + return implibfile + end +end + -- init it function init(self) @@ -287,10 +302,10 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags, opt) end -- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc - if targetkind == "shared" and self:is_plat("mingw") then - local implib = opt.implib or path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a") + local implibfile = _get_implibfile(self, targetkind, targetfile, opt) + if implibfile then table.insert(flags_extra, "-Xlinker") - table.insert(flags_extra, "-Wl,--out-implib," .. implib) + table.insert(flags_extra, "-Wl,--out-implib," .. implibfile) end -- make link args @@ -299,13 +314,12 @@ end -- link the target file function link(self, objectfiles, targetkind, targetfile, flags, opt) - - -- ensure the target directory - os.mkdir(path.directory(targetfile)) + opt = opt or {} - -- ensure the implib directory - if opt and opt.implib then - os.mkdir(path.directory(opt.implib)) + os.mkdir(path.directory(targetfile)) + local implibfile = _get_implibfile(self, targetkind, targetfile, opt) + if implibfile then + os.mkdir(path.directory(implibfile)) end local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags, opt) diff --git a/xmake/modules/private/action/build/link_objects.lua b/xmake/modules/private/action/build/link_objects.lua index 4ed1a0a41..abf81bfea 100644 --- a/xmake/modules/private/action/build/link_objects.lua +++ b/xmake/modules/private/action/build/link_objects.lua @@ -49,11 +49,11 @@ function _do_link_target(target, opt) if verbose then -- show the full link command with raw arguments, it will expand @xxx.args for msvc/link on windows - print(linkinst:linkcmd(objectfiles, targetfile, {linkflags = linkflags, implib = target:artifactfile("implib"), rawargs = true})) + print(linkinst:linkcmd(objectfiles, targetfile, {linkflags = linkflags, rawargs = true})) end if not dryrun then - assert(linkinst:link(objectfiles, targetfile, {linkflags = linkflags, implib = target:artifactfile("implib")})) + assert(linkinst:link(objectfiles, targetfile, {linkflags = linkflags})) end end, {dependfile = target:dependfile(), lastmtime = os.mtime(target:targetfile()), diff --git a/xmake/modules/private/action/require/impl/actions/patch_sources.lua b/xmake/modules/private/action/require/impl/actions/patch_sources.lua index b6eba7fc1..3fa747f50 100644 --- a/xmake/modules/private/action/require/impl/actions/patch_sources.lua +++ b/xmake/modules/private/action/require/impl/actions/patch_sources.lua @@ -109,9 +109,9 @@ function _patch(package, patchinfo) os.tryrm(patchdir_tmp) local errors local ok = try { - function() + function() archive.extract(patch_file, patchdir_tmp) - return true + return true end, catch { function (errs) |
