summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-04-23 22:49:40 +0800
committerruki <[email protected]>2025-04-23 11:30:31 +0800
commit81c8589d494d42bfc64393955b2d62ae22c90039 (patch)
tree208c0f093e92ad29ac4be924a5e22967fd231d32
parenta0d18574febebd378cfa481ec733581f01c2a41e (diff)
improve implib
-rw-r--r--xmake/core/tool/linker.lua20
-rw-r--r--xmake/modules/core/tools/gcc.lua682
-rw-r--r--xmake/modules/core/tools/link.lua25
-rw-r--r--xmake/modules/core/tools/nvcc.lua32
-rw-r--r--xmake/modules/private/action/build/link_objects.lua4
-rw-r--r--xmake/modules/private/action/require/impl/actions/patch_sources.lua4
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)