From d0b381b22c7b6e75a607c5a61203b3f7ce7c9bdb Mon Sep 17 00:00:00 2001 From: Saikari Date: Tue, 27 Jan 2026 13:47:50 +0300 Subject: refactor: update runpath function and add support for multiple platforms; add Nim test files for static and shared libraries --- tests/projects/nim/link_library/maindll.nim | 4 ++++ tests/projects/nim/link_library/mainlib.nim | 4 ++++ tests/projects/nim/link_library/shared.nim | 11 +++++++++++ tests/projects/nim/link_library/static.nim | 6 ++++++ tests/projects/nim/link_library/xmake.lua | 20 ++++++++++++++++++++ xmake/modules/private/action/run/runenvs.lua | 24 ++++++++++++++++++------ 6 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 tests/projects/nim/link_library/maindll.nim create mode 100644 tests/projects/nim/link_library/mainlib.nim create mode 100644 tests/projects/nim/link_library/shared.nim create mode 100644 tests/projects/nim/link_library/static.nim create mode 100644 tests/projects/nim/link_library/xmake.lua diff --git a/tests/projects/nim/link_library/maindll.nim b/tests/projects/nim/link_library/maindll.nim new file mode 100644 index 000000000..0cd97df01 --- /dev/null +++ b/tests/projects/nim/link_library/maindll.nim @@ -0,0 +1,4 @@ +import shared + +echo "Calling shared lib mulTwo(10): ", mulTwo(10) +echo "Calling shared lib countWords('hello, world, hello'): ", countWords("hello, world, hello") diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim new file mode 100644 index 000000000..a99c54b41 --- /dev/null +++ b/tests/projects/nim/link_library/mainlib.nim @@ -0,0 +1,4 @@ +import static + +echo "Calling static lib addTwo(10): ", addTwo(10) +echo "Calling static lib getAlphabet(): ", getAlphabet() diff --git a/tests/projects/nim/link_library/shared.nim b/tests/projects/nim/link_library/shared.nim new file mode 100644 index 000000000..60e02b15e --- /dev/null +++ b/tests/projects/nim/link_library/shared.nim @@ -0,0 +1,11 @@ +proc mulTwo*(x: int): int = + return x * 2 + +import tables, strutils + +proc countWords*(input: string): string = + var wordFrequencies = initCountTable[string]() + for word in input.split(", "): + wordFrequencies.inc(word) + return "The most frequent word is '" & $wordFrequencies.largest & "'" + diff --git a/tests/projects/nim/link_library/static.nim b/tests/projects/nim/link_library/static.nim new file mode 100644 index 000000000..bd8847543 --- /dev/null +++ b/tests/projects/nim/link_library/static.nim @@ -0,0 +1,6 @@ +proc addTwo*(x: int): int = + return x + 2 + +proc getAlphabet*(): string = + for letter in 'a'..'z': + result.add(letter) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua new file mode 100644 index 000000000..05512a7cc --- /dev/null +++ b/tests/projects/nim/link_library/xmake.lua @@ -0,0 +1,20 @@ +set_project("link_libs") +add_rules("mode.debug", "mode.release") + +target("executablestatic") + set_kind("binary") + add_files("mainlib.nim") + add_deps("staticlib") + +target("executableshared") + set_kind("binary") + add_files("maindll.nim") + add_deps("sharedlib") + +target("staticlib") + set_kind("static") + add_files("static.nim") + +target("sharedlib") + set_kind("shared") + add_files("shared.nim") diff --git a/xmake/modules/private/action/run/runenvs.lua b/xmake/modules/private/action/run/runenvs.lua index 43d150e66..7aa97a018 100644 --- a/xmake/modules/private/action/run/runenvs.lua +++ b/xmake/modules/private/action/run/runenvs.lua @@ -21,8 +21,8 @@ -- imports import("core.base.hashset") --- add search directories for all dependent shared libraries on windows -function _make_runpath_on_windows(target) +-- add search directories for all dependent shared libraries +function _make_runpath(target, envname) local pathenv = {} local searchdirs = hashset.new() local function insert(dir) @@ -59,8 +59,8 @@ function _make_runpath_on_windows(target) end for _, toolchain in ipairs(target:toolchains()) do local runenvs = toolchain:runenvs() - if runenvs and runenvs.PATH then - for _, env in ipairs(path.splitenv(runenvs.PATH)) do + if runenvs and runenvs[envname] then + for _, env in ipairs(path.splitenv(runenvs[envname])) do insert(env) end end @@ -151,15 +151,27 @@ function make(target) -- add package run environments _add_target_pkgenvs(addenvs, target, {}) - -- add search directories for all dependent shared libraries on windows + -- add search directories for all dependent shared libraries if target:is_plat("windows") or (target:is_plat("mingw") and is_host("windows")) then local pathenv = addenvs["PATH"] or setenvs["PATH"] - local runpath = _make_runpath_on_windows(target) + local runpath = _make_runpath(target, "PATH") if pathenv == nil then addenvs["PATH"] = runpath else table.join2(pathenv, runpath) end + else + local envname = "LD_LIBRARY_PATH" + if target:is_plat("macosx") then + envname = "DYLD_LIBRARY_PATH" + end + local pathenv = addenvs[envname] or setenvs[envname] + local runpath = _make_runpath(target, envname) + if pathenv == nil then + addenvs[envname] = runpath + else + table.join2(pathenv, runpath) + end end -- deduplicate envs -- cgit v1.3.1 From dde6e30a0cd7f7476778cfe8daf224a15ff25b70 Mon Sep 17 00:00:00 2001 From: Saikari Date: Tue, 27 Jan 2026 20:46:10 +0300 Subject: feat: enhance Windows support for shared libraries and rpath handling --- xmake/modules/core/tools/nim.lua | 67 +++++++++++++++++++++++++--- xmake/modules/private/action/run/runenvs.lua | 24 +++------- xmake/rules/nim/build/target.lua | 27 +++++++++++ 3 files changed, 94 insertions(+), 24 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 94cc0645c..6d89479ac 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -92,31 +92,86 @@ end function nf_strip(self, level) if self:is_plat("linux", "macosx", "bsd") then if level == "debug" or level == "all" then - return "--passL:-s" + return "--passL:\"-s\"" end end end -- make the includedir flag function nf_includedir(self, dir) - return {"--passC:-I" .. path.translate(dir)} + return {string.format("--passC:\"-I%s\"", path.translate(dir))} end -- make the link flag function nf_link(self, lib) if self:is_plat("windows") then - return "--passL:" .. lib .. ".lib" + return string.format("--passL:\"%s.lib\"", lib) else - return "--passL:-l" .. lib + return string.format("--passL:\"-l%s\"", lib) end end -- make the linkdir flag function nf_linkdir(self, dir) if self:is_plat("windows") then - return {"--passL:-libpath:" .. path.translate(dir)} + return {string.format("--passL:\"-libpath:%s\"", path.translate(dir))} else - return {"--passL:-L" .. path.translate(dir)} + return {string.format("--passL:\"-L%s\"", path.translate(dir))} + end +end + +-- make the rpathdir flag +function nf_rpathdir(self, dir, opt) + if self:is_plat("windows") then + return + end + opt = opt or {} + local extra = opt.extra + if extra and extra.installonly then + return + end + dir = path.translate(dir) + + -- Use --passL:"-Wl,-rpath=" to pass rpath to the linker + -- We use standard -Wl,-rpath for gcc/clang on linux/macosx/bsd without check mainly. + if self:is_plat("linux", "macosx", "bsd", "iphoneos", "android") then + dir = dir:gsub("([@$][%w_]+)", function (name) + if name == "@loader_path" or name == "@executable_path" then + return "\\$ORIGIN" + elseif name == "$ORIGIN" then + return "\\$ORIGIN" + end + return name + end) + local rpath = string.format("-Wl,-rpath=%s", dir) + local flags = {string.format("--passL:\"%s\"", rpath)} + if extra then + if extra.runpath == false and self:has_flags(string.format("--passL:\"%s,--disable-new-dtags\"", rpath), "ldflags") then + flags[1] = string.format("--passL:\"%s,--disable-new-dtags\"", rpath) + elseif extra.runpath == true and self:has_flags(string.format("--passL:\"%s,--enable-new-dtags\"", rpath), "ldflags") then + flags[1] = string.format("--passL:\"%s,--enable-new-dtags\"", rpath) + end + end + return flags + end + + -- fallback + if self:has_flags(string.format("--passL:\"-Wl,-rpath=%s\"", dir), "ldflags") then + local flags = {string.format("--passL:\"-Wl,-rpath=%s\"", (dir:gsub("@[%w_]+", function (name) + local maps = { ["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN" } + return maps[name] + end)))} + -- add_rpathdirs("...", {runpath = false}) + if extra then + if extra.runpath == false and self:has_flags(string.format("--passL:\"-Wl,-rpath=%s,--disable-new-dtags\"", dir), "ldflags") then + flags[1] = string.format("--passL:\"-Wl,-rpath=%s,--disable-new-dtags\"", dir) + elseif extra.runpath == true and self:has_flags(string.format("--passL:\"-Wl,-rpath=%s,--enable-new-dtags\"", dir), "ldflags") then + flags[1] = string.format("--passL:\"-Wl,-rpath=%s,--enable-new-dtags\"", dir) + end + end + return flags + elseif self:has_flags("--passL:\"-Xlinker\" --passL:\"-rpath\" --passL:\"-Xlinker\" " .. string.format("--passL:\"%s\"", dir), "ldflags") then + return {"--passL:\"-Xlinker\"", "--passL:\"-rpath\"", "--passL:\"-Xlinker\"", string.format("--passL:\"%s\"", (dir:gsub("%$ORIGIN", "@loader_path")))} end end diff --git a/xmake/modules/private/action/run/runenvs.lua b/xmake/modules/private/action/run/runenvs.lua index 7aa97a018..43d150e66 100644 --- a/xmake/modules/private/action/run/runenvs.lua +++ b/xmake/modules/private/action/run/runenvs.lua @@ -21,8 +21,8 @@ -- imports import("core.base.hashset") --- add search directories for all dependent shared libraries -function _make_runpath(target, envname) +-- add search directories for all dependent shared libraries on windows +function _make_runpath_on_windows(target) local pathenv = {} local searchdirs = hashset.new() local function insert(dir) @@ -59,8 +59,8 @@ function _make_runpath(target, envname) end for _, toolchain in ipairs(target:toolchains()) do local runenvs = toolchain:runenvs() - if runenvs and runenvs[envname] then - for _, env in ipairs(path.splitenv(runenvs[envname])) do + if runenvs and runenvs.PATH then + for _, env in ipairs(path.splitenv(runenvs.PATH)) do insert(env) end end @@ -151,27 +151,15 @@ function make(target) -- add package run environments _add_target_pkgenvs(addenvs, target, {}) - -- add search directories for all dependent shared libraries + -- add search directories for all dependent shared libraries on windows if target:is_plat("windows") or (target:is_plat("mingw") and is_host("windows")) then local pathenv = addenvs["PATH"] or setenvs["PATH"] - local runpath = _make_runpath(target, "PATH") + local runpath = _make_runpath_on_windows(target) if pathenv == nil then addenvs["PATH"] = runpath else table.join2(pathenv, runpath) end - else - local envname = "LD_LIBRARY_PATH" - if target:is_plat("macosx") then - envname = "DYLD_LIBRARY_PATH" - end - local pathenv = addenvs[envname] or setenvs[envname] - local runpath = _make_runpath(target, envname) - if pathenv == nil then - addenvs[envname] = runpath - else - table.join2(pathenv, runpath) - end end -- deduplicate envs diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index 52599b74d..a292e7cf7 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -83,6 +83,33 @@ function build_sourcefiles(target, sourcebatch, opt) -- get compile flags local compflags = compinst:compflags({target = target}) + -- add rpathdirs to linker flags (for shared lib support) + local rpathdirs = target:get("rpathdirs") or {} + local rpathdirs_wrap = {} + if rpathdirs then + table.join2(rpathdirs_wrap, table.wrap(rpathdirs)) + end + + -- add rpathdirs from dependencies + if target:kind() == "binary" or target:kind() == "shared" then + for _, dep in ipairs(target:orderdeps()) do + if dep:kind() == "shared" then + table.insert(rpathdirs_wrap, dep:targetdir()) + end + end + end + + if #rpathdirs_wrap > 0 then + -- deduplicate + rpathdirs_wrap = table.unique(rpathdirs_wrap) + for _, rpathdir in ipairs(rpathdirs_wrap) do + local rpathflags = compinst:_tool():nf_rpathdir(rpathdir) + if rpathflags then + table.join2(compflags, rpathflags) + end + end + end + -- load dependent info local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) -- cgit v1.3.1 From 02f221f1877719da333190d203b2079b6d58513f Mon Sep 17 00:00:00 2001 From: Saikari Date: Tue, 27 Jan 2026 21:41:03 +0300 Subject: feat: add architecture-specific flags for x86, x86_64, arm, and arm64 --- xmake/modules/core/tools/nim.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 6d89479ac..5f1c509ce 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -34,6 +34,37 @@ function init(self) -- init shflags self:set("ncshflags", "--app:lib", "--noMain") + + -- init arch flags + local arch = self:arch() + if arch then + if arch == "x86" or arch == "i386" then + self:add("ncflags", "--cpu:i386", "--define:bit32") + self:add("ncshflags", "--cpu:i386", "--define:bit32") + self:add("ncarflags", "--cpu:i386", "--define:bit32") + self:add("ldflags", "--cpu:i386", "--define:bit32") + if self:is_plat("linux", "macosx", "bsd", "mingw") then + self:add("ncflags", "--passC:\"-m32\"", "--passL:\"-m32\"") + self:add("ncshflags", "--passC:\"-m32\"", "--passL:\"-m32\"") + self:add("ldflags", "--passL:\"-m32\"") + end + elseif arch == "x86_64" then + self:add("ncflags", "--cpu:amd64", "--define:bit64") + self:add("ncshflags", "--cpu:amd64", "--define:bit64") + self:add("ncarflags", "--cpu:amd64", "--define:bit64") + self:add("ldflags", "--cpu:amd64", "--define:bit64") + elseif arch == "arm64" then + self:add("ncflags", "--cpu:arm64", "--define:bit64") + self:add("ncshflags", "--cpu:arm64", "--define:bit64") + self:add("ncarflags", "--cpu:arm64", "--define:bit64") + self:add("ldflags", "--cpu:arm64", "--define:bit64") + elseif arch:startswith("arm") then + self:add("ncflags", "--cpu:arm", "--define:bit32") + self:add("ncshflags", "--cpu:arm", "--define:bit32") + self:add("ncarflags", "--cpu:arm", "--define:bit32") + self:add("ldflags", "--cpu:arm", "--define:bit32") + end + end end -- make the warning flag -- cgit v1.3.1 From a9761ddbd051326d11682be707e672158cd2710b Mon Sep 17 00:00:00 2001 From: Saikari Date: Tue, 27 Jan 2026 22:49:02 +0300 Subject: feat: implement getMsg function and update test files for static/shared libraries --- tests/projects/nim/link_library/inc/test.h | 11 +++++++++++ tests/projects/nim/link_library/maindll.nim | 1 + tests/projects/nim/link_library/mainlib.nim | 1 + tests/projects/nim/link_library/shared.nim | 8 ++++++++ tests/projects/nim/link_library/static.nim | 10 ++++++++++ tests/projects/nim/link_library/xmake.lua | 4 ++++ xmake/rules/nim/build/target.lua | 20 ++++++++++++++++++++ 7 files changed, 55 insertions(+) create mode 100644 tests/projects/nim/link_library/inc/test.h diff --git a/tests/projects/nim/link_library/inc/test.h b/tests/projects/nim/link_library/inc/test.h new file mode 100644 index 000000000..f7d68cac8 --- /dev/null +++ b/tests/projects/nim/link_library/inc/test.h @@ -0,0 +1,11 @@ + +#ifndef TEST_H +#define TEST_H + +#ifdef TEST_STATIC + #define TEST_MSG "Hello from Static Lib!" +#else + #define TEST_MSG "Hello from Shared Lib!" +#endif + +#endif diff --git a/tests/projects/nim/link_library/maindll.nim b/tests/projects/nim/link_library/maindll.nim index 0cd97df01..d5e4c8283 100644 --- a/tests/projects/nim/link_library/maindll.nim +++ b/tests/projects/nim/link_library/maindll.nim @@ -2,3 +2,4 @@ import shared echo "Calling shared lib mulTwo(10): ", mulTwo(10) echo "Calling shared lib countWords('hello, world, hello'): ", countWords("hello, world, hello") +echo "Calling shared lib getMsg('test'): ", getMsg() diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim index a99c54b41..f9fe4d85b 100644 --- a/tests/projects/nim/link_library/mainlib.nim +++ b/tests/projects/nim/link_library/mainlib.nim @@ -2,3 +2,4 @@ import static echo "Calling static lib addTwo(10): ", addTwo(10) echo "Calling static lib getAlphabet(): ", getAlphabet() +echo "Calling shared lib getMsg('test'): ", getMsg() diff --git a/tests/projects/nim/link_library/shared.nim b/tests/projects/nim/link_library/shared.nim index 60e02b15e..61a204d09 100644 --- a/tests/projects/nim/link_library/shared.nim +++ b/tests/projects/nim/link_library/shared.nim @@ -9,3 +9,11 @@ proc countWords*(input: string): string = wordFrequencies.inc(word) return "The most frequent word is '" & $wordFrequencies.largest & "'" +{.emit: """ +#include "test.h" +""".} + +proc getMsg*(): cstring {.exportc, dynlib.} = + var msg: cstring + {.emit: "`msg` = TEST_MSG;".} + return msg diff --git a/tests/projects/nim/link_library/static.nim b/tests/projects/nim/link_library/static.nim index bd8847543..1a80c5a58 100644 --- a/tests/projects/nim/link_library/static.nim +++ b/tests/projects/nim/link_library/static.nim @@ -4,3 +4,13 @@ proc addTwo*(x: int): int = proc getAlphabet*(): string = for letter in 'a'..'z': result.add(letter) + +{.emit: """ +#define TEST_STATIC +#include "test.h" +""".} + +proc getMsg*(): cstring {.exportc, dynlib.} = + var msg: cstring + {.emit: "`msg` = TEST_MSG;".} + return msg diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 05512a7cc..cbcef108b 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -14,7 +14,11 @@ target("executableshared") target("staticlib") set_kind("static") add_files("static.nim") + add_includedirs("inc") + add_headerfiles("inc/*.h") target("sharedlib") set_kind("shared") add_files("shared.nim") + add_includedirs("inc") + add_headerfiles("inc/*.h") diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index a292e7cf7..948e317f3 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -109,6 +109,26 @@ function build_sourcefiles(target, sourcebatch, opt) end end end + + -- add includedirs from dependencies (for static/shared lib with exportc) + -- the dependencies will be compiled via imported symbol at the end + -- we need pass includedirs of static/shared lib to the target + local includedirs = {} + for _, dep in ipairs(target:orderdeps()) do + if dep:kind() == "static" or dep:kind() == "shared" then + table.join2(includedirs, dep:get("includedirs")) + end + end + if #includedirs > 0 then + -- deduplicate + includedirs = table.unique(includedirs) + for _, includedir in ipairs(includedirs) do + local includeflags = compinst:_tool():nf_includedir(includedir) + if includeflags then + table.join2(compflags, includeflags) + end + end + end -- load dependent info local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) -- cgit v1.3.1 From 4489af7a955b9bef05968d69f29747cef2609e3b Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 02:53:09 +0300 Subject: feat: add syslink handling for Nim targets and update xmake.lua configurations --- tests/projects/nim/link_library/xmake.lua | 4 ++++ xmake/languages/nim/xmake.lua | 2 ++ xmake/modules/core/tools/nim.lua | 13 +++++++++++++ 3 files changed, 19 insertions(+) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index cbcef108b..3d032a0f5 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -5,20 +5,24 @@ target("executablestatic") set_kind("binary") add_files("mainlib.nim") add_deps("staticlib") + add_syslinks("pthread", "m") target("executableshared") set_kind("binary") add_files("maindll.nim") add_deps("sharedlib") + add_syslinks("pthread", "m") target("staticlib") set_kind("static") add_files("static.nim") add_includedirs("inc") add_headerfiles("inc/*.h") + add_syslinks("pthread", "m") target("sharedlib") set_kind("shared") add_files("shared.nim") add_includedirs("inc") add_headerfiles("inc/*.h") + add_syslinks("pthread", "m") diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index 65ad6429b..576ee4e0c 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -51,6 +51,7 @@ language("nim") , "toolchain.rpathdirs" , "config.links" , "target.links" + , "target.syslinks" , "toolchain.links" } , shared = { @@ -61,6 +62,7 @@ language("nim") , "toolchain.linkdirs" , "config.links" , "target.links" + , "target.syslinks" , "toolchain.links" } , static = { diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 5f1c509ce..8a76ec865 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -142,6 +142,19 @@ function nf_link(self, lib) end end +-- make the syslink flag +function nf_syslink(self, lib) + if self:is_plat("windows") then + return string.format("--passL:\"%s.lib\"", lib) + else + if lib == "pthread" then + return "--threads:on --passL:\"-lpthread\" --dynlibOverride:\"pthread\"" + else + return string.format("--passL:\"-l%s\"", lib) + end + end +end + -- make the linkdir flag function nf_linkdir(self, dir) if self:is_plat("windows") then -- cgit v1.3.1 From fe46022f5f0deca6d5cfeba757660a609fa46a78 Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 04:08:09 +0300 Subject: fix: improve syslink flag handling for pthread library in Nim --- xmake/modules/core/tools/nim.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 8a76ec865..b37d29da5 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -148,7 +148,7 @@ function nf_syslink(self, lib) return string.format("--passL:\"%s.lib\"", lib) else if lib == "pthread" then - return "--threads:on --passL:\"-lpthread\" --dynlibOverride:\"pthread\"" + return string.format("--threads:on --passL:\"-l%s\" --dynlibOverride:\"pthread\"", lib) else return string.format("--passL:\"-l%s\"", lib) end -- cgit v1.3.1 From 31738aa58d1d1ef893124e544440bf9a86981b45 Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 04:27:02 +0300 Subject: feat: add zlib dependency and implement zlibVersion function in mainlib --- tests/projects/nim/link_library/mainlib.nim | 8 ++++++++ tests/projects/nim/link_library/xmake.lua | 3 +++ 2 files changed, 11 insertions(+) diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim index f9fe4d85b..08d877c5d 100644 --- a/tests/projects/nim/link_library/mainlib.nim +++ b/tests/projects/nim/link_library/mainlib.nim @@ -1,5 +1,13 @@ import static +{.emit: """ +#include +""".} + +proc zlibVersion(): cstring {.importc: "zlibVersion", nodecl.} + +echo "Zlib Version: ", zlibVersion() + echo "Calling static lib addTwo(10): ", addTwo(10) echo "Calling static lib getAlphabet(): ", getAlphabet() echo "Calling shared lib getMsg('test'): ", getMsg() diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 3d032a0f5..c7b2713da 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -1,10 +1,13 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") +add_requires("zlib", {system = false}) + target("executablestatic") set_kind("binary") add_files("mainlib.nim") add_deps("staticlib") + add_packages("zlib") add_syslinks("pthread", "m") target("executableshared") -- cgit v1.3.1 From dc9ce57e004a18678b3d34a9502560fdbf43a742 Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 04:58:48 +0300 Subject: feat: add stb_image support and enhance include directory handling for Nim packages --- tests/projects/nim/link_library/mainlib.nim | 6 ++++++ tests/projects/nim/link_library/xmake.lua | 3 ++- xmake/modules/core/tools/nim.lua | 5 +++++ xmake/rules/nim/build/target.lua | 26 +++++++++++++++++++++++++- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim index 08d877c5d..6a8078dae 100644 --- a/tests/projects/nim/link_library/mainlib.nim +++ b/tests/projects/nim/link_library/mainlib.nim @@ -2,12 +2,18 @@ import static {.emit: """ #include +#define STB_IMAGE_IMPLEMENTATION +#include """.} proc zlibVersion(): cstring {.importc: "zlibVersion", nodecl.} +proc stbi_set_flip_vertically_on_load(flag_true_if_should_flip: cint) {.importc: "stbi_set_flip_vertically_on_load", nodecl.} echo "Zlib Version: ", zlibVersion() +stbi_set_flip_vertically_on_load(1) +echo "STB Image: Flip vertically on load set to 1" + echo "Calling static lib addTwo(10): ", addTwo(10) echo "Calling static lib getAlphabet(): ", getAlphabet() echo "Calling shared lib getMsg('test'): ", getMsg() diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index c7b2713da..a9b834a93 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -2,12 +2,13 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") add_requires("zlib", {system = false}) +add_requires("stb", {system = false}) target("executablestatic") set_kind("binary") add_files("mainlib.nim") add_deps("staticlib") - add_packages("zlib") + add_packages("zlib", "stb") add_syslinks("pthread", "m") target("executableshared") diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index b37d29da5..b327cb09c 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -133,6 +133,11 @@ function nf_includedir(self, dir) return {string.format("--passC:\"-I%s\"", path.translate(dir))} end +-- make the sysincludedir flag +function nf_sysincludedir(self, dir) + return nf_includedir(self, dir) +end + -- make the link flag function nf_link(self, lib) if self:is_plat("windows") then diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index 948e317f3..ba6750e6b 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -83,6 +83,29 @@ function build_sourcefiles(target, sourcebatch, opt) -- get compile flags local compflags = compinst:compflags({target = target}) + -- add includedirs from packages + for _, pkg in ipairs(target:orderpkgs()) do + local pkg_includedirs = pkg:get("includedirs") + if pkg_includedirs then + for _, dir in ipairs(pkg_includedirs) do + local includeflags = compinst:_tool():nf_includedir(dir) + if includeflags then + table.join2(compflags, includeflags) + end + end + end + local pkg_sysincludedirs = pkg:get("sysincludedirs") + if pkg_sysincludedirs then + for _, dir in ipairs(pkg_sysincludedirs) do + local tool = compinst:_tool() + local includeflags = tool.nf_sysincludedir and tool:nf_sysincludedir(dir) or tool:nf_includedir(dir) + if includeflags then + table.join2(compflags, includeflags) + end + end + end + end + -- add rpathdirs to linker flags (for shared lib support) local rpathdirs = target:get("rpathdirs") or {} local rpathdirs_wrap = {} @@ -115,8 +138,9 @@ function build_sourcefiles(target, sourcebatch, opt) -- we need pass includedirs of static/shared lib to the target local includedirs = {} for _, dep in ipairs(target:orderdeps()) do - if dep:kind() == "static" or dep:kind() == "shared" then + if dep:kind() == "static" or dep:kind() == "shared" or dep:kind() == "headeronly" then table.join2(includedirs, dep:get("includedirs")) + table.join2(includedirs, dep:get("sysincludedirs")) end end if #includedirs > 0 then -- cgit v1.3.1 From 8747fbba42745624a78f9410b43c8de57106df7c Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 09:10:34 +0300 Subject: feat: add header file and implement test_add_five function for Nim integration --- tests/projects/nim/link_library/headers/test_header.h | 10 ++++++++++ tests/projects/nim/link_library/maindll.nim | 11 +++++++++++ tests/projects/nim/link_library/mainlib.nim | 11 +++++++++++ tests/projects/nim/link_library/shared.nim | 10 ++++++++++ tests/projects/nim/link_library/static.nim | 10 ++++++++++ tests/projects/nim/link_library/xmake.lua | 7 +++++++ 6 files changed, 59 insertions(+) create mode 100644 tests/projects/nim/link_library/headers/test_header.h diff --git a/tests/projects/nim/link_library/headers/test_header.h b/tests/projects/nim/link_library/headers/test_header.h new file mode 100644 index 000000000..4b71d3173 --- /dev/null +++ b/tests/projects/nim/link_library/headers/test_header.h @@ -0,0 +1,10 @@ +#ifndef TEST_HEADER_H +#define TEST_HEADER_H + +#define TEST_HEADER_VAL 123 + +static int test_add_five(int x) { + return x + 5; +} + +#endif diff --git a/tests/projects/nim/link_library/maindll.nim b/tests/projects/nim/link_library/maindll.nim index d5e4c8283..b13fe1caf 100644 --- a/tests/projects/nim/link_library/maindll.nim +++ b/tests/projects/nim/link_library/maindll.nim @@ -3,3 +3,14 @@ import shared echo "Calling shared lib mulTwo(10): ", mulTwo(10) echo "Calling shared lib countWords('hello, world, hello'): ", countWords("hello, world, hello") echo "Calling shared lib getMsg('test'): ", getMsg() + +{.emit: """ +#include +""".} + +var testHeaderVal {.importc: "TEST_HEADER_VAL", nodecl.}: cint +echo "TEST_HEADER_VAL: ", testHeaderVal + +proc test_add_five(x: cint): cint {.importc: "test_add_five", nodecl.} +echo "test_add_five(80): ", test_add_five(80) + diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim index 6a8078dae..868789d0f 100644 --- a/tests/projects/nim/link_library/mainlib.nim +++ b/tests/projects/nim/link_library/mainlib.nim @@ -17,3 +17,14 @@ echo "STB Image: Flip vertically on load set to 1" echo "Calling static lib addTwo(10): ", addTwo(10) echo "Calling static lib getAlphabet(): ", getAlphabet() echo "Calling shared lib getMsg('test'): ", getMsg() + +{.emit: """ +#include +""".} + +var testHeaderVal {.importc: "TEST_HEADER_VAL", nodecl.}: cint +echo "TEST_HEADER_VAL: ", testHeaderVal + +proc test_add_five(x: cint): cint {.importc: "test_add_five", nodecl.} +echo "test_add_five(55): ", test_add_five(55) + diff --git a/tests/projects/nim/link_library/shared.nim b/tests/projects/nim/link_library/shared.nim index 61a204d09..58dacc6df 100644 --- a/tests/projects/nim/link_library/shared.nim +++ b/tests/projects/nim/link_library/shared.nim @@ -17,3 +17,13 @@ proc getMsg*(): cstring {.exportc, dynlib.} = var msg: cstring {.emit: "`msg` = TEST_MSG;".} return msg + +{.emit: """ +#include +""".} + +var testHeaderVal {.importc: "TEST_HEADER_VAL", nodecl.}: cint +echo "TEST_HEADER_VAL: ", testHeaderVal + +proc test_add_five(x: cint): cint {.importc: "test_add_five", nodecl.} +echo "test_add_five(10): ", test_add_five(10) diff --git a/tests/projects/nim/link_library/static.nim b/tests/projects/nim/link_library/static.nim index 1a80c5a58..6808d5895 100644 --- a/tests/projects/nim/link_library/static.nim +++ b/tests/projects/nim/link_library/static.nim @@ -14,3 +14,13 @@ proc getMsg*(): cstring {.exportc, dynlib.} = var msg: cstring {.emit: "`msg` = TEST_MSG;".} return msg + +{.emit: """ +#include +""".} + +var testHeaderVal {.importc: "TEST_HEADER_VAL", nodecl.}: cint +echo "TEST_HEADER_VAL: ", testHeaderVal + +proc test_add_five(x: cint): cint {.importc: "test_add_five", nodecl.} +echo "test_add_five(60): ", test_add_five(60) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index a9b834a93..76481bd6b 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -4,6 +4,11 @@ add_rules("mode.debug", "mode.release") add_requires("zlib", {system = false}) add_requires("stb", {system = false}) +target("headers") + set_kind("headeronly") + add_files("headers/*.h") + add_includedirs("headers") + target("executablestatic") set_kind("binary") add_files("mainlib.nim") @@ -23,6 +28,7 @@ target("staticlib") add_includedirs("inc") add_headerfiles("inc/*.h") add_syslinks("pthread", "m") + add_deps("headers") target("sharedlib") set_kind("shared") @@ -30,3 +36,4 @@ target("sharedlib") add_includedirs("inc") add_headerfiles("inc/*.h") add_syslinks("pthread", "m") + add_deps("headers") -- cgit v1.3.1 From c2eac69333f1e9b357f062c925f08b93463ec621 Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 17:42:23 +0300 Subject: refactor: simplify architecture flag handling in Nim initialization --- xmake/modules/core/tools/nim.lua | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index b327cb09c..a425b9b37 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -40,29 +40,15 @@ function init(self) if arch then if arch == "x86" or arch == "i386" then self:add("ncflags", "--cpu:i386", "--define:bit32") - self:add("ncshflags", "--cpu:i386", "--define:bit32") - self:add("ncarflags", "--cpu:i386", "--define:bit32") - self:add("ldflags", "--cpu:i386", "--define:bit32") if self:is_plat("linux", "macosx", "bsd", "mingw") then self:add("ncflags", "--passC:\"-m32\"", "--passL:\"-m32\"") - self:add("ncshflags", "--passC:\"-m32\"", "--passL:\"-m32\"") - self:add("ldflags", "--passL:\"-m32\"") end elseif arch == "x86_64" then self:add("ncflags", "--cpu:amd64", "--define:bit64") - self:add("ncshflags", "--cpu:amd64", "--define:bit64") - self:add("ncarflags", "--cpu:amd64", "--define:bit64") - self:add("ldflags", "--cpu:amd64", "--define:bit64") elseif arch == "arm64" then self:add("ncflags", "--cpu:arm64", "--define:bit64") - self:add("ncshflags", "--cpu:arm64", "--define:bit64") - self:add("ncarflags", "--cpu:arm64", "--define:bit64") - self:add("ldflags", "--cpu:arm64", "--define:bit64") elseif arch:startswith("arm") then self:add("ncflags", "--cpu:arm", "--define:bit32") - self:add("ncshflags", "--cpu:arm", "--define:bit32") - self:add("ncarflags", "--cpu:arm", "--define:bit32") - self:add("ldflags", "--cpu:arm", "--define:bit32") end end end -- cgit v1.3.1 From c94c14fb23d09af85672f2e7dd1081b4976822c5 Mon Sep 17 00:00:00 2001 From: Saikari Date: Wed, 28 Jan 2026 17:48:23 +0300 Subject: fix: remove unnecessary rpathdirs handling in build_sourcefiles function --- xmake/rules/nim/build/target.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index ba6750e6b..fdef292d4 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -107,11 +107,7 @@ function build_sourcefiles(target, sourcebatch, opt) end -- add rpathdirs to linker flags (for shared lib support) - local rpathdirs = target:get("rpathdirs") or {} local rpathdirs_wrap = {} - if rpathdirs then - table.join2(rpathdirs_wrap, table.wrap(rpathdirs)) - end -- add rpathdirs from dependencies if target:kind() == "binary" or target:kind() == "shared" then -- cgit v1.3.1 From d96fd6bae66d5631e555de129ce562e63b5b7f2d Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:00:59 +0300 Subject: feat: enhance syslinks handling in Nim language configuration --- xmake/languages/nim/xmake.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index 576ee4e0c..f08358843 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -51,8 +51,10 @@ language("nim") , "toolchain.rpathdirs" , "config.links" , "target.links" - , "target.syslinks" , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" } , shared = { "config.linkdirs" @@ -64,6 +66,9 @@ language("nim") , "target.links" , "target.syslinks" , "toolchain.links" + , "config.syslinks" + , "target.syslinks" + , "toolchain.syslinks" } , static = { "target.strip" -- cgit v1.3.1 From 8b51f4e9b8670a346cf0cc985de989768ec3ea0d Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:02:37 +0300 Subject: fix: remove duplicate target.syslinks entry in Nim language configuration --- xmake/languages/nim/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index f08358843..7b29bc8a7 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -64,7 +64,6 @@ language("nim") , "toolchain.linkdirs" , "config.links" , "target.links" - , "target.syslinks" , "toolchain.links" , "config.syslinks" , "target.syslinks" -- cgit v1.3.1 From 165aac84db81a518498b59d350054cd1736d56ae Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:04:49 +0300 Subject: refactor: simplify architecture checks in init function --- xmake/modules/core/tools/nim.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index a425b9b37..1fd3cab44 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -38,16 +38,16 @@ function init(self) -- init arch flags local arch = self:arch() if arch then - if arch == "x86" or arch == "i386" then + if self:is_arch("x86", "i386") then self:add("ncflags", "--cpu:i386", "--define:bit32") if self:is_plat("linux", "macosx", "bsd", "mingw") then self:add("ncflags", "--passC:\"-m32\"", "--passL:\"-m32\"") end - elseif arch == "x86_64" then + elseif self:is_arch("x64", "x86_64") then self:add("ncflags", "--cpu:amd64", "--define:bit64") - elseif arch == "arm64" then + elseif self:is_arch("arm64.*") then self:add("ncflags", "--cpu:arm64", "--define:bit64") - elseif arch:startswith("arm") then + elseif self:is_arch("arm.*") then self:add("ncflags", "--cpu:arm", "--define:bit32") end end -- cgit v1.3.1 From 028d45fc9104427f5293eac8784070aee8fbe838 Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:10:07 +0300 Subject: fix: standardize quotation marks in linker flags for consistency --- xmake/modules/core/tools/nim.lua | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 1fd3cab44..15f318b1e 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -41,7 +41,7 @@ function init(self) if self:is_arch("x86", "i386") then self:add("ncflags", "--cpu:i386", "--define:bit32") if self:is_plat("linux", "macosx", "bsd", "mingw") then - self:add("ncflags", "--passC:\"-m32\"", "--passL:\"-m32\"") + self:add("ncflags", '--passC:"-m32"', '--passL:"-m32"') end elseif self:is_arch("x64", "x86_64") then self:add("ncflags", "--cpu:amd64", "--define:bit64") @@ -109,14 +109,14 @@ end function nf_strip(self, level) if self:is_plat("linux", "macosx", "bsd") then if level == "debug" or level == "all" then - return "--passL:\"-s\"" + return '--passL:"-s"' end end end -- make the includedir flag function nf_includedir(self, dir) - return {string.format("--passC:\"-I%s\"", path.translate(dir))} + return {string.format('--passC:"-I%s"', path.translate(dir))} end -- make the sysincludedir flag @@ -127,21 +127,21 @@ end -- make the link flag function nf_link(self, lib) if self:is_plat("windows") then - return string.format("--passL:\"%s.lib\"", lib) + return string.format('--passL:"%s.lib"', lib) else - return string.format("--passL:\"-l%s\"", lib) + return string.format('--passL:"-l%s"', lib) end end -- make the syslink flag function nf_syslink(self, lib) if self:is_plat("windows") then - return string.format("--passL:\"%s.lib\"", lib) + return string.format('--passL:"%s.lib"', lib) else if lib == "pthread" then - return string.format("--threads:on --passL:\"-l%s\" --dynlibOverride:\"pthread\"", lib) + return string.format('--threads:on --passL:"-l%s" --dynlibOverride:"pthread"', lib) else - return string.format("--passL:\"-l%s\"", lib) + return string.format('--passL:"-l%s"', lib) end end end @@ -149,9 +149,9 @@ end -- make the linkdir flag function nf_linkdir(self, dir) if self:is_plat("windows") then - return {string.format("--passL:\"-libpath:%s\"", path.translate(dir))} + return {string.format('--passL:"-libpath:%s"', path.translate(dir))} else - return {string.format("--passL:\"-L%s\"", path.translate(dir))} + return {string.format('--passL:"-L%s"', path.translate(dir))} end end @@ -179,34 +179,34 @@ function nf_rpathdir(self, dir, opt) return name end) local rpath = string.format("-Wl,-rpath=%s", dir) - local flags = {string.format("--passL:\"%s\"", rpath)} + local flags = {string.format('--passL:"%s"', rpath)} if extra then - if extra.runpath == false and self:has_flags(string.format("--passL:\"%s,--disable-new-dtags\"", rpath), "ldflags") then - flags[1] = string.format("--passL:\"%s,--disable-new-dtags\"", rpath) - elseif extra.runpath == true and self:has_flags(string.format("--passL:\"%s,--enable-new-dtags\"", rpath), "ldflags") then - flags[1] = string.format("--passL:\"%s,--enable-new-dtags\"", rpath) + if extra.runpath == false and self:has_flags(string.format('--passL:"%s,--disable-new-dtags"', rpath), "ldflags") then + flags[1] = string.format('--passL:"%s,--disable-new-dtags"', rpath) + elseif extra.runpath == true and self:has_flags(string.format('--passL:"%s,--enable-new-dtags"', rpath), "ldflags") then + flags[1] = string.format('--passL:"%s,--enable-new-dtags"', rpath) end end return flags end -- fallback - if self:has_flags(string.format("--passL:\"-Wl,-rpath=%s\"", dir), "ldflags") then - local flags = {string.format("--passL:\"-Wl,-rpath=%s\"", (dir:gsub("@[%w_]+", function (name) + if self:has_flags(string.format('--passL:"-Wl,-rpath=%s"', dir), "ldflags") then + local flags = {string.format('--passL:"-Wl,-rpath=%s"', (dir:gsub("@[%w_]+", function (name) local maps = { ["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN" } return maps[name] end)))} -- add_rpathdirs("...", {runpath = false}) if extra then - if extra.runpath == false and self:has_flags(string.format("--passL:\"-Wl,-rpath=%s,--disable-new-dtags\"", dir), "ldflags") then - flags[1] = string.format("--passL:\"-Wl,-rpath=%s,--disable-new-dtags\"", dir) - elseif extra.runpath == true and self:has_flags(string.format("--passL:\"-Wl,-rpath=%s,--enable-new-dtags\"", dir), "ldflags") then - flags[1] = string.format("--passL:\"-Wl,-rpath=%s,--enable-new-dtags\"", dir) + if extra.runpath == false and self:has_flags(string.format('--passL:"-Wl,-rpath=%s,--disable-new-dtags"', dir), "ldflags") then + flags[1] = string.format('--passL:"-Wl,-rpath=%s,--disable-new-dtags"', dir) + elseif extra.runpath == true and self:has_flags(string.format('--passL:"-Wl,-rpath=%s,--enable-new-dtags"', dir), "ldflags") then + flags[1] = string.format('--passL:"-Wl,-rpath=%s,--enable-new-dtags"', dir) end end return flags - elseif self:has_flags("--passL:\"-Xlinker\" --passL:\"-rpath\" --passL:\"-Xlinker\" " .. string.format("--passL:\"%s\"", dir), "ldflags") then - return {"--passL:\"-Xlinker\"", "--passL:\"-rpath\"", "--passL:\"-Xlinker\"", string.format("--passL:\"%s\"", (dir:gsub("%$ORIGIN", "@loader_path")))} + elseif self:has_flags('--passL:"-Xlinker" --passL:"-rpath" --passL:"-Xlinker" ' .. string.format('--passL:"%s"', dir), "ldflags") then + return {'--passL:"-Xlinker"', '--passL:"-rpath"', '--passL:"-Xlinker"', string.format('--passL:"%s"', (dir:gsub("%$ORIGIN", "@loader_path")))} end end -- cgit v1.3.1 From 27acec28d45f10907646f10337cc20986c436144 Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:21:29 +0300 Subject: refactor: reorganize build_sourcefiles function to include dependency flag handling --- xmake/rules/nim/build/target.lua | 45 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index fdef292d4..4c9fdad67 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -64,24 +64,8 @@ function _generate_dependinfo(compinst, compflags, sourcefiles, dependinfo) end end --- build the source files -function build_sourcefiles(target, sourcebatch, opt) - - -- get the target file - local targetfile = target:targetfile() - - -- get source files and kind - local sourcefiles = sourcebatch.sourcefiles - local sourcekind = sourcebatch.sourcekind - - -- get depend file - local dependfile = target:dependfile(targetfile) - - -- load compiler - local compinst = compiler.load(sourcekind, {target = target}) - - -- get compile flags - local compflags = compinst:compflags({target = target}) +-- add dependency flags +function _add_dependency_flags(target, compinst, compflags) -- add includedirs from packages for _, pkg in ipairs(target:orderpkgs()) do @@ -128,7 +112,7 @@ function build_sourcefiles(target, sourcebatch, opt) end end end - + -- add includedirs from dependencies (for static/shared lib with exportc) -- the dependencies will be compiled via imported symbol at the end -- we need pass includedirs of static/shared lib to the target @@ -149,6 +133,29 @@ function build_sourcefiles(target, sourcebatch, opt) end end end +end + +-- build the source files +function build_sourcefiles(target, sourcebatch, opt) + + -- get the target file + local targetfile = target:targetfile() + + -- get source files and kind + local sourcefiles = sourcebatch.sourcefiles + local sourcekind = sourcebatch.sourcekind + + -- get depend file + local dependfile = target:dependfile(targetfile) + + -- load compiler + local compinst = compiler.load(sourcekind, {target = target}) + + -- get compile flags + local compflags = compinst:compflags({target = target}) + + -- add dependency flags + _add_dependency_flags(target, compinst, compflags) -- load dependent info local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) -- cgit v1.3.1 From 1d24aa52a9b03ef79502c8fb061e003d05e23923 Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 08:53:54 +0300 Subject: feat: add support for package link directories, links, and system links in dependency flags --- xmake/rules/nim/build/target.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index 4c9fdad67..096280aaf 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -88,6 +88,33 @@ function _add_dependency_flags(target, compinst, compflags) end end end + local pkg_linkdirs = pkg:get("linkdirs") + if pkg_linkdirs then + for _, dir in ipairs(pkg_linkdirs) do + local linkflags = compinst:_tool():nf_linkdir(dir) + if linkflags then + table.join2(compflags, linkflags) + end + end + end + local pkg_links = pkg:get("links") + if pkg_links then + for _, link in ipairs(pkg_links) do + local linkflags = compinst:_tool():nf_link(link) + if linkflags then + table.join2(compflags, {linkflags}) + end + end + end + local pkg_syslinks = pkg:get("syslinks") + if pkg_syslinks then + for _, link in ipairs(pkg_syslinks) do + local linkflags = compinst:_tool():nf_syslink(link) + if linkflags then + table.join2(compflags, {linkflags}) + end + end + end end -- add rpathdirs to linker flags (for shared lib support) -- cgit v1.3.1 From 83ccf8d991d2ad1ed29af150c35f43d1cdd66663 Mon Sep 17 00:00:00 2001 From: Saikari Date: Thu, 29 Jan 2026 10:56:36 +0300 Subject: fix: wrap syslink additions in platform check for Linux --- tests/projects/nim/link_library/xmake.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 76481bd6b..3965e4140 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -14,20 +14,26 @@ target("executablestatic") add_files("mainlib.nim") add_deps("staticlib") add_packages("zlib", "stb") - add_syslinks("pthread", "m") + if is_plat("linux") then + add_syslinks("pthread", "m") + end target("executableshared") set_kind("binary") add_files("maindll.nim") add_deps("sharedlib") - add_syslinks("pthread", "m") + if is_plat("linux") then + add_syslinks("pthread", "m") + end target("staticlib") set_kind("static") add_files("static.nim") add_includedirs("inc") add_headerfiles("inc/*.h") - add_syslinks("pthread", "m") + if is_plat("linux") then + add_syslinks("pthread", "m") + end add_deps("headers") target("sharedlib") @@ -35,5 +41,7 @@ target("sharedlib") add_files("shared.nim") add_includedirs("inc") add_headerfiles("inc/*.h") - add_syslinks("pthread", "m") + if is_plat("linux") then + add_syslinks("pthread", "m") + end add_deps("headers") -- cgit v1.3.1 From 72283d163a02abe02d2e53dd44a6050f80b9e956 Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 06:10:58 +0300 Subject: feat: enable shared configuration for zlib dependency in project --- tests/projects/nim/link_library/xmake.lua | 2 +- xmake/modules/core/tools/nim.lua | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 3965e4140..46fa1bbe8 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -1,7 +1,7 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") -add_requires("zlib", {system = false}) +add_requires("zlib", {system = false, config = {shared = true}}) add_requires("stb", {system = false}) target("headers") diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index 15f318b1e..a05d9a346 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -169,7 +169,16 @@ function nf_rpathdir(self, dir, opt) -- Use --passL:"-Wl,-rpath=" to pass rpath to the linker -- We use standard -Wl,-rpath for gcc/clang on linux/macosx/bsd without check mainly. - if self:is_plat("linux", "macosx", "bsd", "iphoneos", "android") then + if self:is_plat("macosx", "iphoneos") then + dir = dir:gsub("([@$][%w_]+)", function (name) + if name == "$ORIGIN" then + return "@loader_path" + end + return name + end) + local rpath = string.format("-Wl,-rpath,%s", dir) + return {string.format('--passL:"%s"', rpath)} + elseif self:is_plat("linux", "bsd", "android") then dir = dir:gsub("([@$][%w_]+)", function (name) if name == "@loader_path" or name == "@executable_path" then return "\\$ORIGIN" -- cgit v1.3.1 From 06d23505b48a3099f95f6dd66bc12af8d435ed3c Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 06:27:00 +0300 Subject: just typo i guess sorry :( --- tests/projects/nim/link_library/mainlib.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/nim/link_library/mainlib.nim b/tests/projects/nim/link_library/mainlib.nim index 868789d0f..1a1fae06c 100644 --- a/tests/projects/nim/link_library/mainlib.nim +++ b/tests/projects/nim/link_library/mainlib.nim @@ -16,7 +16,7 @@ echo "STB Image: Flip vertically on load set to 1" echo "Calling static lib addTwo(10): ", addTwo(10) echo "Calling static lib getAlphabet(): ", getAlphabet() -echo "Calling shared lib getMsg('test'): ", getMsg() +echo "Calling static lib getMsg('test'): ", getMsg() {.emit: """ #include -- cgit v1.3.1 From 21cb0aed94b5e395e419d0035bdd2acdf03bcf79 Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 07:31:46 +0300 Subject: Update xmake.lua --- tests/projects/nim/link_library/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 46fa1bbe8..edc577e9e 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -1,7 +1,7 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") -add_requires("zlib", {system = false, config = {shared = true}}) +add_requires("zlib", {system = false, configs = {shared = true}}) add_requires("stb", {system = false}) target("headers") -- cgit v1.3.1 From be12d7fdddf16b8b501b9fcbce53b6f5d5173c98 Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 10:10:30 +0300 Subject: try improve --- tests/projects/nim/link_library/xmake.lua | 2 +- xmake/modules/core/tools/nim.lua | 2 +- xmake/rules/nim/build/target.lua | 108 ++++++++++++++---------------- 3 files changed, 54 insertions(+), 58 deletions(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index edc577e9e..11f1b7073 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -1,7 +1,7 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") -add_requires("zlib", {system = false, configs = {shared = true}}) +add_requires("zlib", {system = false, configs = {shared = false}}) add_requires("stb", {system = false}) target("headers") diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua index a05d9a346..415d102f2 100644 --- a/xmake/modules/core/tools/nim.lua +++ b/xmake/modules/core/tools/nim.lua @@ -139,7 +139,7 @@ function nf_syslink(self, lib) return string.format('--passL:"%s.lib"', lib) else if lib == "pthread" then - return string.format('--threads:on --passL:"-l%s" --dynlibOverride:"pthread"', lib) + return {"--threads:on", string.format('--passL:"-l%s"', lib), '--dynlibOverride:"pthread"'} else return string.format('--passL:"-l%s"', lib) end diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index 096280aaf..181d3dc2a 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -25,6 +25,16 @@ import("core.tool.compiler") import("core.project.depend") import("utils.progress") +-- get values from target +-- @see https://github.com/xmake-io/xmake/issues/3930 +local function _get_values_from_target(target, name) + local values = {} + for _, value in ipairs((target:get_from(name, "*"))) do + table.join2(values, value) + end + return table.unique(values) +end + -- generate dependency info function _generate_dependinfo(compinst, compflags, sourcefiles, dependinfo) @@ -67,52 +77,42 @@ end -- add dependency flags function _add_dependency_flags(target, compinst, compflags) - -- add includedirs from packages - for _, pkg in ipairs(target:orderpkgs()) do - local pkg_includedirs = pkg:get("includedirs") - if pkg_includedirs then - for _, dir in ipairs(pkg_includedirs) do - local includeflags = compinst:_tool():nf_includedir(dir) - if includeflags then - table.join2(compflags, includeflags) - end - end - end - local pkg_sysincludedirs = pkg:get("sysincludedirs") - if pkg_sysincludedirs then - for _, dir in ipairs(pkg_sysincludedirs) do - local tool = compinst:_tool() - local includeflags = tool.nf_sysincludedir and tool:nf_sysincludedir(dir) or tool:nf_includedir(dir) - if includeflags then - table.join2(compflags, includeflags) - end - end + -- add flags from target (includedirs, links, ...) + local pathmaps = { + {"includedirs", "includedir"}, + {"sysincludedirs", "sysincludedir"}, + {"linkdirs", "linkdir"} + } + for _, pathmap in ipairs(pathmaps) do + local flags = compiler.map_flags("nim", pathmap[2], _get_values_from_target(target, pathmap[1])) + if flags then + table.join2(compflags, flags) end - local pkg_linkdirs = pkg:get("linkdirs") - if pkg_linkdirs then - for _, dir in ipairs(pkg_linkdirs) do - local linkflags = compinst:_tool():nf_linkdir(dir) - if linkflags then - table.join2(compflags, linkflags) - end - end + end + + local linkmaps = { + {"links", "link"}, + {"syslinks", "syslink"} + } + for _, linkmap in ipairs(linkmaps) do + local flags = compiler.map_flags("nim", linkmap[2], _get_values_from_target(target, linkmap[1])) + if flags then + table.join2(compflags, flags) end - local pkg_links = pkg:get("links") - if pkg_links then - for _, link in ipairs(pkg_links) do - local linkflags = compinst:_tool():nf_link(link) - if linkflags then - table.join2(compflags, {linkflags}) - end + end + + -- add flags from packages + for _, pkg in ipairs(target:orderpkgs()) do + for _, pathmap in ipairs(pathmaps) do + local flags = compiler.map_flags("nim", pathmap[2], pkg:get(pathmap[1])) + if flags then + table.join2(compflags, flags) end end - local pkg_syslinks = pkg:get("syslinks") - if pkg_syslinks then - for _, link in ipairs(pkg_syslinks) do - local linkflags = compinst:_tool():nf_syslink(link) - if linkflags then - table.join2(compflags, {linkflags}) - end + for _, linkmap in ipairs(linkmaps) do + local flags = compiler.map_flags("nim", linkmap[2], pkg:get(linkmap[1])) + if flags then + table.join2(compflags, flags) end end end @@ -121,9 +121,9 @@ function _add_dependency_flags(target, compinst, compflags) local rpathdirs_wrap = {} -- add rpathdirs from dependencies - if target:kind() == "binary" or target:kind() == "shared" then + if target:is_binary() or target:is_shared() then for _, dep in ipairs(target:orderdeps()) do - if dep:kind() == "shared" then + if dep:is_shared() then table.insert(rpathdirs_wrap, dep:targetdir()) end end @@ -132,11 +132,9 @@ function _add_dependency_flags(target, compinst, compflags) if #rpathdirs_wrap > 0 then -- deduplicate rpathdirs_wrap = table.unique(rpathdirs_wrap) - for _, rpathdir in ipairs(rpathdirs_wrap) do - local rpathflags = compinst:_tool():nf_rpathdir(rpathdir) - if rpathflags then - table.join2(compflags, rpathflags) - end + local rpathflags = compiler.map_flags("nim", "rpathdir", rpathdirs_wrap) + if rpathflags then + table.join2(compflags, rpathflags) end end @@ -146,18 +144,16 @@ function _add_dependency_flags(target, compinst, compflags) local includedirs = {} for _, dep in ipairs(target:orderdeps()) do if dep:kind() == "static" or dep:kind() == "shared" or dep:kind() == "headeronly" then - table.join2(includedirs, dep:get("includedirs")) - table.join2(includedirs, dep:get("sysincludedirs")) + table.join2(includedirs, table.wrap(dep:get("includedirs"))) + table.join2(includedirs, table.wrap(dep:get("sysincludedirs"))) end end if #includedirs > 0 then -- deduplicate includedirs = table.unique(includedirs) - for _, includedir in ipairs(includedirs) do - local includeflags = compinst:_tool():nf_includedir(includedir) - if includeflags then - table.join2(compflags, includeflags) - end + local includeflags = compiler.map_flags("nim", "includedir", includedirs) + if includeflags then + table.join2(compflags, includeflags) end end end -- cgit v1.3.1 From b32c1a47791a21919bae96a9e5dffe12f044615e Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 10:12:19 +0300 Subject: fix: update dependency check to use is_headeronly method --- xmake/rules/nim/build/target.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index 181d3dc2a..dd12c8ae7 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -143,7 +143,7 @@ function _add_dependency_flags(target, compinst, compflags) -- we need pass includedirs of static/shared lib to the target local includedirs = {} for _, dep in ipairs(target:orderdeps()) do - if dep:kind() == "static" or dep:kind() == "shared" or dep:kind() == "headeronly" then + if dep:kind() == "static" or dep:kind() == "shared" or dep:is_headeronly() then table.join2(includedirs, table.wrap(dep:get("includedirs"))) table.join2(includedirs, table.wrap(dep:get("sysincludedirs"))) end -- cgit v1.3.1 From 484b4d116e54eeced612b250344d7d3bf428d187 Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 13:22:44 +0300 Subject: Update xmake.lua --- tests/projects/nim/link_library/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index 11f1b7073..edc577e9e 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -1,7 +1,7 @@ set_project("link_libs") add_rules("mode.debug", "mode.release") -add_requires("zlib", {system = false, configs = {shared = false}}) +add_requires("zlib", {system = false, configs = {shared = true}}) add_requires("stb", {system = false}) target("headers") -- cgit v1.3.1 From 9ac89545c1cb1845b2e2006b98cbe185c8ee64fb Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 31 Jan 2026 00:32:27 +0800 Subject: improve nim supports --- tests/projects/nim/link_library/xmake.lua | 8 +-- xmake/languages/nim/xmake.lua | 11 +++- xmake/rules/nim/build/target.lua | 97 ------------------------------- 3 files changed, 13 insertions(+), 103 deletions(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index edc577e9e..f15417cb1 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -7,13 +7,13 @@ add_requires("stb", {system = false}) target("headers") set_kind("headeronly") add_files("headers/*.h") - add_includedirs("headers") + add_includedirs("headers", {public = true}) target("executablestatic") set_kind("binary") add_files("mainlib.nim") add_deps("staticlib") - add_packages("zlib", "stb") + add_packages("zlib", "stb", {public = true}) if is_plat("linux") then add_syslinks("pthread", "m") end @@ -29,7 +29,7 @@ target("executableshared") target("staticlib") set_kind("static") add_files("static.nim") - add_includedirs("inc") + add_includedirs("inc", {public = true}) add_headerfiles("inc/*.h") if is_plat("linux") then add_syslinks("pthread", "m") @@ -39,7 +39,7 @@ target("staticlib") target("sharedlib") set_kind("shared") add_files("shared.nim") - add_includedirs("inc") + add_includedirs("inc", {public = true}) add_headerfiles("inc/*.h") if is_plat("linux") then add_syslinks("pthread", "m") diff --git a/xmake/languages/nim/xmake.lua b/xmake/languages/nim/xmake.lua index 7b29bc8a7..458cd1d33 100644 --- a/xmake/languages/nim/xmake.lua +++ b/xmake/languages/nim/xmake.lua @@ -39,10 +39,13 @@ language("nim") , "target.optimize:check" , "target.vectorexts:check" , "target.includedirs" + , "target.sysincludedirs" , "toolchain.includedirs" } , binary = { "config.linkdirs" + , "target.includedirs" + , "target.sysincludedirs" , "target.linkdirs" , "target.rpathdirs" , "target.strip" @@ -52,12 +55,14 @@ language("nim") , "config.links" , "target.links" , "toolchain.links" - , "config.syslinks" - , "target.syslinks" + , "config.syslinks" + , "target.syslinks" , "toolchain.syslinks" } , shared = { "config.linkdirs" + , "target.includedirs" + , "target.sysincludedirs" , "target.linkdirs" , "target.strip" , "target.symbols" @@ -72,6 +77,8 @@ language("nim") , static = { "target.strip" , "target.symbols" + , "target.includedirs" + , "target.sysincludedirs" } } diff --git a/xmake/rules/nim/build/target.lua b/xmake/rules/nim/build/target.lua index dd12c8ae7..52599b74d 100644 --- a/xmake/rules/nim/build/target.lua +++ b/xmake/rules/nim/build/target.lua @@ -25,16 +25,6 @@ import("core.tool.compiler") import("core.project.depend") import("utils.progress") --- get values from target --- @see https://github.com/xmake-io/xmake/issues/3930 -local function _get_values_from_target(target, name) - local values = {} - for _, value in ipairs((target:get_from(name, "*"))) do - table.join2(values, value) - end - return table.unique(values) -end - -- generate dependency info function _generate_dependinfo(compinst, compflags, sourcefiles, dependinfo) @@ -74,90 +64,6 @@ function _generate_dependinfo(compinst, compflags, sourcefiles, dependinfo) end end --- add dependency flags -function _add_dependency_flags(target, compinst, compflags) - - -- add flags from target (includedirs, links, ...) - local pathmaps = { - {"includedirs", "includedir"}, - {"sysincludedirs", "sysincludedir"}, - {"linkdirs", "linkdir"} - } - for _, pathmap in ipairs(pathmaps) do - local flags = compiler.map_flags("nim", pathmap[2], _get_values_from_target(target, pathmap[1])) - if flags then - table.join2(compflags, flags) - end - end - - local linkmaps = { - {"links", "link"}, - {"syslinks", "syslink"} - } - for _, linkmap in ipairs(linkmaps) do - local flags = compiler.map_flags("nim", linkmap[2], _get_values_from_target(target, linkmap[1])) - if flags then - table.join2(compflags, flags) - end - end - - -- add flags from packages - for _, pkg in ipairs(target:orderpkgs()) do - for _, pathmap in ipairs(pathmaps) do - local flags = compiler.map_flags("nim", pathmap[2], pkg:get(pathmap[1])) - if flags then - table.join2(compflags, flags) - end - end - for _, linkmap in ipairs(linkmaps) do - local flags = compiler.map_flags("nim", linkmap[2], pkg:get(linkmap[1])) - if flags then - table.join2(compflags, flags) - end - end - end - - -- add rpathdirs to linker flags (for shared lib support) - local rpathdirs_wrap = {} - - -- add rpathdirs from dependencies - if target:is_binary() or target:is_shared() then - for _, dep in ipairs(target:orderdeps()) do - if dep:is_shared() then - table.insert(rpathdirs_wrap, dep:targetdir()) - end - end - end - - if #rpathdirs_wrap > 0 then - -- deduplicate - rpathdirs_wrap = table.unique(rpathdirs_wrap) - local rpathflags = compiler.map_flags("nim", "rpathdir", rpathdirs_wrap) - if rpathflags then - table.join2(compflags, rpathflags) - end - end - - -- add includedirs from dependencies (for static/shared lib with exportc) - -- the dependencies will be compiled via imported symbol at the end - -- we need pass includedirs of static/shared lib to the target - local includedirs = {} - for _, dep in ipairs(target:orderdeps()) do - if dep:kind() == "static" or dep:kind() == "shared" or dep:is_headeronly() then - table.join2(includedirs, table.wrap(dep:get("includedirs"))) - table.join2(includedirs, table.wrap(dep:get("sysincludedirs"))) - end - end - if #includedirs > 0 then - -- deduplicate - includedirs = table.unique(includedirs) - local includeflags = compiler.map_flags("nim", "includedir", includedirs) - if includeflags then - table.join2(compflags, includeflags) - end - end -end - -- build the source files function build_sourcefiles(target, sourcebatch, opt) @@ -177,9 +83,6 @@ function build_sourcefiles(target, sourcebatch, opt) -- get compile flags local compflags = compinst:compflags({target = target}) - -- add dependency flags - _add_dependency_flags(target, compinst, compflags) - -- load dependent info local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {}) -- cgit v1.3.1 From 62b7806dd006540fda8c8c85d173973ae2479fbf Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 31 Jan 2026 00:34:40 +0800 Subject: fix header files --- tests/projects/nim/link_library/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/projects/nim/link_library/xmake.lua b/tests/projects/nim/link_library/xmake.lua index f15417cb1..ba56fcbf2 100644 --- a/tests/projects/nim/link_library/xmake.lua +++ b/tests/projects/nim/link_library/xmake.lua @@ -6,7 +6,7 @@ add_requires("stb", {system = false}) target("headers") set_kind("headeronly") - add_files("headers/*.h") + add_headerfiles("headers/*.h") add_includedirs("headers", {public = true}) target("executablestatic") -- cgit v1.3.1 From 5b723b0208d95d3734f6c467e6aaefda3201eded Mon Sep 17 00:00:00 2001 From: charles seizilles Date: Fri, 30 Jan 2026 18:36:49 +0100 Subject: find_cuda: revert breaking change --- xmake/modules/core/tools/gcc/has_flags.lua | 2 +- xmake/modules/detect/sdks/find_cuda.lua | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/modules/core/tools/gcc/has_flags.lua b/xmake/modules/core/tools/gcc/has_flags.lua index c743f91fb..5539fc0f4 100644 --- a/xmake/modules/core/tools/gcc/has_flags.lua +++ b/xmake/modules/core/tools/gcc/has_flags.lua @@ -125,7 +125,7 @@ function _check_try_running(flags, opt, islinker) if not cuda_gpu_flags then local cuda = get_config("cuda") local cuda_sdk = find_cuda(cuda) - local cuda_sdkver = cuda_sdk and cuda_sdk.sdkver or "7.0" + local cuda_sdkver = cuda_sdk and cuda_sdk.version or "7.0" if cuda_sdkver and semver.compare(cuda_sdkver, "12.0") >= 0 then table.insert(args, 1, "--cuda-gpu-arch=sm_80") end diff --git a/xmake/modules/detect/sdks/find_cuda.lua b/xmake/modules/detect/sdks/find_cuda.lua index b767e8e34..5a90cc581 100644 --- a/xmake/modules/detect/sdks/find_cuda.lua +++ b/xmake/modules/detect/sdks/find_cuda.lua @@ -131,7 +131,7 @@ function _find_cuda(sdkdir, sdkver) local includedirs = {path.join(sdkdir, "include")} -- get version - local sdkver = find_programver(path.join(bindir, "nvcc"), {parse = "release (%d+%.%d+),"}) + local version = find_programver(path.join(bindir, "nvcc"), {parse = "release (%d+%.%d+),"}) -- find msbuildextensionsdir on windows local msbuildextensionsdir @@ -140,7 +140,7 @@ function _find_cuda(sdkdir, sdkver) end -- get toolchains - return {sdkdir = sdkdir, bindir = bindir, sdkver = sdkver, linkdirs = linkdirs, includedirs = includedirs, msbuildextensionsdir = msbuildextensionsdir} + return {sdkdir = sdkdir, bindir = bindir, version = version, linkdirs = linkdirs, includedirs = includedirs, msbuildextensionsdir = msbuildextensionsdir} end -- find cuda sdk toolchains @@ -176,7 +176,7 @@ function main(sdkdir, opt) -- save to config config.set("cuda", cuda.sdkdir, {force = true, readonly = true}) - config.set("cuda_sdkver", cuda.sdkver, {force = true, readonly = true}) + config.set("cuda_sdkver", cuda.version, {force = true, readonly = true}) -- trace if opt.verbose or option.get("verbose") then -- cgit v1.3.1 From b006af493bff65fcffd198db70ec2c8046f6575e Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 20:42:57 +0300 Subject: enhance compile_commands support and add test cases --- tests/projects/policy/compile_commands/src/disabled.c | 3 +++ tests/projects/policy/compile_commands/src/main.c | 3 +++ tests/projects/policy/compile_commands/xmake.lua | 10 ++++++++++ xmake/core/base/os.lua | 5 ++++- xmake/core/project/policy.lua | 2 ++ xmake/plugins/project/clang/compile_commands.lua | 5 +++++ 6 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/projects/policy/compile_commands/src/disabled.c create mode 100644 tests/projects/policy/compile_commands/src/main.c create mode 100644 tests/projects/policy/compile_commands/xmake.lua diff --git a/tests/projects/policy/compile_commands/src/disabled.c b/tests/projects/policy/compile_commands/src/disabled.c new file mode 100644 index 000000000..9b130982d --- /dev/null +++ b/tests/projects/policy/compile_commands/src/disabled.c @@ -0,0 +1,3 @@ +int main(int argc, char** argv) { + return 0; +} diff --git a/tests/projects/policy/compile_commands/src/main.c b/tests/projects/policy/compile_commands/src/main.c new file mode 100644 index 000000000..9b130982d --- /dev/null +++ b/tests/projects/policy/compile_commands/src/main.c @@ -0,0 +1,3 @@ +int main(int argc, char** argv) { + return 0; +} diff --git a/tests/projects/policy/compile_commands/xmake.lua b/tests/projects/policy/compile_commands/xmake.lua new file mode 100644 index 000000000..03f8a788d --- /dev/null +++ b/tests/projects/policy/compile_commands/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.debug", "mode.release") + +target("enabled") + set_kind("binary") + add_files("src/main.c") + +target("disabled") + set_kind("binary") + add_files("src/main.c") + set_policy("build.compile_commands", false) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 12bc30c1d..9332f2c61 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1187,7 +1187,10 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - return os._access(filepath, "x") + if os._access then + return os._access(filepath, "x") + end + return true end return false end diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 1cecfd01a..51631e408 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -98,6 +98,8 @@ function policy.policies() -- Force C++ modules fallback dependency scanner for msvc ["build.c++.modules.msvc.fallbackscanner"] = {description = "Force msvc fallback module dependency scanner.", default = false, type = "boolean"}, ["build.c++.msvc.fallbackscanner"] = {description = "Force msvc fallback module dependency scanner. (deprecated)", default = false, type = "boolean"}, + -- Enable compile_commands + ["build.compile_commands"] = {description = "Enable compile_commands.", default = true, type = "boolean"}, -- Force C++ modules fallback dependency scanner for gcc ["build.c++.modules.gcc.fallbackscanner"] = {description = "Force gcc fallback module dependency scanner.", default = false, type = "boolean"}, ["build.c++.gcc.fallbackscanner"] = {description = "Force gcc fallback module dependency scanner. (deprecated)", default = false, type = "boolean"}, diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 4f01354fa..28f4a876b 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -266,6 +266,11 @@ function _add_target(jsonfile, target) -- https://github.com/xmake-io/xmake/issues/2337 target:data_set("plugin.project.kind", "compile_commands") + -- disable compile_commands? + if target:policy("build.compile_commands") == false then + return + end + -- enter package environments local oldenvs = os.addenvs(target:pkgenvs()) -- cgit v1.3.1 From 5646519958738a45b448a264e1be81f305fed677 Mon Sep 17 00:00:00 2001 From: Saikari Date: Fri, 30 Jan 2026 21:07:03 +0300 Subject: Simplify file access check in os.lua --- xmake/core/base/os.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 9332f2c61..12bc30c1d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1187,10 +1187,7 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - if os._access then - return os._access(filepath, "x") - end - return true + return os._access(filepath, "x") end return false end -- cgit v1.3.1 From 5db59f35d5770790d008d6fdc1c1bdea1f16d9b3 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 13:49:14 +0300 Subject: refactor compile_commands policy to use generator namespace --- xmake/core/project/policy.lua | 4 ++-- xmake/plugins/project/clang/compile_commands.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua index 51631e408..5123f0a5c 100644 --- a/xmake/core/project/policy.lua +++ b/xmake/core/project/policy.lua @@ -98,8 +98,6 @@ function policy.policies() -- Force C++ modules fallback dependency scanner for msvc ["build.c++.modules.msvc.fallbackscanner"] = {description = "Force msvc fallback module dependency scanner.", default = false, type = "boolean"}, ["build.c++.msvc.fallbackscanner"] = {description = "Force msvc fallback module dependency scanner. (deprecated)", default = false, type = "boolean"}, - -- Enable compile_commands - ["build.compile_commands"] = {description = "Enable compile_commands.", default = true, type = "boolean"}, -- Force C++ modules fallback dependency scanner for gcc ["build.c++.modules.gcc.fallbackscanner"] = {description = "Force gcc fallback module dependency scanner.", default = false, type = "boolean"}, ["build.c++.gcc.fallbackscanner"] = {description = "Force gcc fallback module dependency scanner. (deprecated)", default = false, type = "boolean"}, @@ -194,6 +192,8 @@ function policy.policies() ["network.mode"] = {description = "Set the network mode", type = "string"}, -- Set the compatibility version, e.g. 2.0, 3.0 ["compatibility.version"] = {description = "Set the compatibility version", type = "string", default = "3.0", values = {"2.0", "3.0"}}, + -- Enable compile_commands + ["generator.compile_commands"] = {description = "Enable compile_commands.", default = true, type = "boolean"}, -- Generate the solution file in root output directory -- @see https://github.com/xmake-io/xmake/issues/6519 ["generator.vsxmake.root_sln"] = {description = "Generate the solution file in root output directory", default = false, type = "boolean"} diff --git a/xmake/plugins/project/clang/compile_commands.lua b/xmake/plugins/project/clang/compile_commands.lua index 28f4a876b..909184800 100644 --- a/xmake/plugins/project/clang/compile_commands.lua +++ b/xmake/plugins/project/clang/compile_commands.lua @@ -267,7 +267,7 @@ function _add_target(jsonfile, target) target:data_set("plugin.project.kind", "compile_commands") -- disable compile_commands? - if target:policy("build.compile_commands") == false then + if target:policy("generator.compile_commands") == false then return end -- cgit v1.3.1 From a0848dab701b4f64a4345c6ef8ace61c9532dc41 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 13:51:23 +0300 Subject: fix: update policy for disabled target to use generator.compile_commands --- tests/projects/policy/compile_commands/src/disabled.c | 3 --- tests/projects/policy/compile_commands/xmake.lua | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 tests/projects/policy/compile_commands/src/disabled.c diff --git a/tests/projects/policy/compile_commands/src/disabled.c b/tests/projects/policy/compile_commands/src/disabled.c deleted file mode 100644 index 9b130982d..000000000 --- a/tests/projects/policy/compile_commands/src/disabled.c +++ /dev/null @@ -1,3 +0,0 @@ -int main(int argc, char** argv) { - return 0; -} diff --git a/tests/projects/policy/compile_commands/xmake.lua b/tests/projects/policy/compile_commands/xmake.lua index 03f8a788d..1ccf48af6 100644 --- a/tests/projects/policy/compile_commands/xmake.lua +++ b/tests/projects/policy/compile_commands/xmake.lua @@ -7,4 +7,4 @@ target("enabled") target("disabled") set_kind("binary") add_files("src/main.c") - set_policy("build.compile_commands", false) + set_policy("generator.compile_commands", false) -- cgit v1.3.1 From e494d44263b18e2981cb35041817b052a2bdda6a Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 17:29:44 +0300 Subject: add winos_processes function to retrieve process information on Windows --- core/src/xmake/engine.c | 2 + core/src/xmake/os/processes.c | 86 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 core/src/xmake/os/processes.c diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index eb07fe2b5..df5ae06be 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -278,6 +278,7 @@ tb_int_t xm_winos_registry_query(lua_State *lua); tb_int_t xm_winos_registry_keys(lua_State *lua); tb_int_t xm_winos_registry_values(lua_State *lua); tb_int_t xm_winos_short_path(lua_State *lua); +tb_int_t xm_winos_processes(lua_State* lua); #endif // the utf8 functions @@ -483,6 +484,7 @@ static luaL_Reg const g_winos_functions[] = { { "registry_keys", xm_winos_registry_keys }, { "registry_values", xm_winos_registry_values }, { "short_path", xm_winos_short_path }, + { "processes", xm_winos_processes }, { tb_null, tb_null }, }; #endif diff --git a/core/src/xmake/os/processes.c b/core/src/xmake/os/processes.c new file mode 100644 index 000000000..a50ffbe1c --- /dev/null +++ b/core/src/xmake/os/processes.c @@ -0,0 +1,86 @@ +/*!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, Xmake Open Source Community. + * + * @author ruki + * @file processes.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "processes" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" +#ifdef TB_CONFIG_OS_WINDOWS +#include +#include +#endif + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ + +tb_int_t xm_winos_processes(lua_State* lua) { +#ifdef TB_CONFIG_OS_WINDOWS + // init result table + lua_newtable(lua); + + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) { + PROCESSENTRY32W pe32; + pe32.dwSize = sizeof(PROCESSENTRY32W); + + if (Process32FirstW(hSnapshot, &pe32)) { + tb_int_t i = 1; + do { + // new process entry table + lua_newtable(lua); + + // name + tb_char_t name[MAX_PATH * 4]; + tb_size_t size = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE, TB_CHARSET_TYPE_UTF8, (tb_byte_t const*)pe32.szExeFile, tb_wcslen(pe32.szExeFile) * sizeof(tb_wchar_t), (tb_byte_t*)name, sizeof(name)); + if (size != -1) { + lua_pushlstring(lua, name, size); + } else { + lua_pushstring(lua, ""); + } + lua_setfield(lua, -2, "name"); + + // pid + lua_pushinteger(lua, (tb_int_t)pe32.th32ProcessID); + lua_setfield(lua, -2, "pid"); + + // ppid + lua_pushinteger(lua, (tb_int_t)pe32.th32ParentProcessID); + lua_setfield(lua, -2, "ppid"); + + // result[i++] = entry + lua_rawseti(lua, -2, i++); + + } while (Process32NextW(hSnapshot, &pe32)); + } + CloseHandle(hSnapshot); + } + return 1; +#else + return 0; +#endif +} -- cgit v1.3.1 From b56818e7a2f96f1750545deda8a0e7bae53baf68 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 19:29:14 +0300 Subject: add process retrieval for Windows in tty and winos modules --- xmake/core/base/tty.lua | 61 ++++++++++++++++++++++++++---------- xmake/core/base/winos.lua | 5 +++ xmake/core/sandbox/modules/winos.lua | 1 + 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/xmake/core/base/tty.lua b/xmake/core/base/tty.lua index b3ac35b2b..8d506336d 100644 --- a/xmake/core/base/tty.lua +++ b/xmake/core/base/tty.lua @@ -237,11 +237,53 @@ end -- find the shell from the parent process (linux) function tty._find_shell_from_parent() + local shell + if os.host() == "windows" then + local winos = require("base/winos") + if winos.processes then + local processes = winos.processes() + if processes then + local pid = os.getpid() + local processes_map = {} + for _, process in ipairs(processes) do + processes_map[process.pid] = process + end + local count = 0 + while pid and pid ~= 0 and count < 10 do + count = count + 1 + local process = processes_map[pid] + if not process then + break + end + local name = process.name + if name then + name = name:lower() + if name:sub(-4) == ".exe" then + name = name:sub(1, #name - 4) + end + for _, shellname in ipairs({"zsh", "bash", "fish", "nu", "elvish", "pwsh", "powershell", "cmd", "sh"}) do + if name == shellname then + shell = shellname + break + end + end + end + if shell then + break + end + pid = process.ppid + end + end + end + end + if shell then + return shell + end + if os.host() ~= "linux" or not os.isfile("/proc/self/stat") then return end - local shell local pid = os.getpid() local count = 0 while pid ~= 0 and count < 4 do @@ -295,22 +337,7 @@ function tty.shell() if os.getenv("NU_VERSION") then shell = "nu" end - if not shell then - local subhost = xmake._SUBHOST - if subhost == "windows" then - if os.getenv("PROMPT") then - shell = "cmd" - else - local ok, result = os.iorun("pwsh -v") - if ok then - shell = "pwsh" - else - shell = "powershell" - end - end - end - end - -- try to find the shell from the parent process (linux) + -- try to find the shell from the parent process if not shell then shell = tty._find_shell_from_parent() end diff --git a/xmake/core/base/winos.lua b/xmake/core/base/winos.lua index 73657662e..9d786fdfc 100644 --- a/xmake/core/base/winos.lua +++ b/xmake/core/base/winos.lua @@ -31,6 +31,7 @@ winos._oem_cp = winos._oem_cp or winos.oem_cp winos._registry_query = winos._registry_query or winos.registry_query winos._registry_keys = winos._registry_keys or winos.registry_keys winos._registry_values = winos._registry_values or winos.registry_values +winos._processes = winos._processes or winos.processes function winos.ansi_cp() if not winos._ANSI_CP then @@ -46,6 +47,10 @@ function winos.oem_cp() return winos._OEM_CP end +if not winos.processes then + winos.processes = winos._processes +end + -- get windows version from name function winos._version_from_name(name) winos._VERSIONS = winos._VERSIONS or { diff --git a/xmake/core/sandbox/modules/winos.lua b/xmake/core/sandbox/modules/winos.lua index fec1d07df..eddcf91d4 100644 --- a/xmake/core/sandbox/modules/winos.lua +++ b/xmake/core/sandbox/modules/winos.lua @@ -33,6 +33,7 @@ sandbox_winos.console_cp = winos.console_cp sandbox_winos.console_output_cp = winos.console_output_cp sandbox_winos.logical_drives = winos.logical_drives sandbox_winos.cmdargv = winos.cmdargv +sandbox_winos.processes = winos.processes sandbox_winos.inherit_handles_safely = winos.inherit_handles_safely -- get windows system version -- cgit v1.3.1 From b86a88d31acbf64c4e6b5b2137c08d7b5b179b39 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 11:10:36 +0800 Subject: improve to detect vs/msvc to check env length limit --- xmake/modules/detect/sdks/find_vstudio.lua | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index cf56fcca9..488615a3f 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -93,6 +93,9 @@ local vsenvs = , ["4.2"] = "VS42COMNTOOLS" } +-- the original environment variables +local _env_orgs = {} + -- get all known Visual Studio environment variables function get_vcvars() local realvcvars = vcvars @@ -381,6 +384,40 @@ function _strip_toolset_ver(vs_toolset) return vs_toolset end +-- check if the environment variables are truncated +-- https://github.com/xmake-io/xmake/issues/7281 +function _check_vcvarsall_env(vars) + local check_vars = {"PATH", "INCLUDE", "LIBPATH"} + for _, name in ipairs(check_vars) do + local value_org = _env_orgs[name] + if value_org == nil then + value_org = os.getenv(name) + _env_orgs[name] = value_org or false + end + local value_new = vars[name] + if value_org and value_new and #value_org > 0 then + -- we only check the first/last 512 bytes to verify if the original path is present + -- because the path maybe too long and be truncated + local part = value_org + if #part > 512 then + part = part:sub(1, 512) + end + if not value_new:find(part, 1, true) then + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) + break + end + local part_end = value_org + if #part_end > 512 then + part_end = part_end:sub(#part_end - 512 + 1) + end + if not value_new:find(part_end, 1, true) then + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) + break + end + end + end +end + function _load_vcvarsall(vcvarsall, vsver, arch, opt) opt = opt or {} local vs_toolset = opt.toolset or opt.vcvars_ver @@ -407,6 +444,9 @@ function _load_vcvarsall(vcvarsall, vsver, arch, opt) result = _load_vcvarsall_impl(vcvarsall, vsver, arch, opt) end end + if result then + _check_vcvarsall_env(result) + end return result end @@ -414,6 +454,9 @@ end function _find_vstudio(opt) opt = opt or {} + -- clear local cache of environment variables + _env_orgs = {} + -- find the single current MSVC/VS from environment variables local VCInstallDir = os.getenv("VCInstallDir") if VCInstallDir and (VCInstallDir ~= "") then -- cgit v1.3.1 From a153273143ef8d3b8d43b6eb5b6b2dfb7c02944b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 11:39:30 +0800 Subject: improve to check envs --- xmake/modules/detect/sdks/find_vstudio.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 488615a3f..c898657a1 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -313,6 +313,9 @@ function _load_vcvarsall_impl(vcvarsall, vsver, arch, opt) variables[name] = value end end + + -- check if the environment variables are truncated + _check_vcvarsall_env(variables) if not variables.path then return end @@ -394,7 +397,7 @@ function _check_vcvarsall_env(vars) value_org = os.getenv(name) _env_orgs[name] = value_org or false end - local value_new = vars[name] + local value_new = vars[name] or vars[name:lower()] if value_org and value_new and #value_org > 0 then -- we only check the first/last 512 bytes to verify if the original path is present -- because the path maybe too long and be truncated @@ -444,9 +447,6 @@ function _load_vcvarsall(vcvarsall, vsver, arch, opt) result = _load_vcvarsall_impl(vcvarsall, vsver, arch, opt) end end - if result then - _check_vcvarsall_env(result) - end return result end -- cgit v1.3.1 From 8588d0bdbc8d49cbef094a89538ac5daf96e6a1a Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:33:37 +0800 Subject: improve vs check --- xmake/modules/detect/sdks/find_vstudio.lua | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index c898657a1..70cf93d14 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -390,7 +390,7 @@ end -- check if the environment variables are truncated -- https://github.com/xmake-io/xmake/issues/7281 function _check_vcvarsall_env(vars) - local check_vars = {"PATH", "INCLUDE", "LIBPATH"} + local check_vars = {"PATH", "INCLUDE", "LIB", "LIBPATH"} for _, name in ipairs(check_vars) do local value_org = _env_orgs[name] if value_org == nil then @@ -399,23 +399,12 @@ function _check_vcvarsall_env(vars) end local value_new = vars[name] or vars[name:lower()] if value_org and value_new and #value_org > 0 then - -- we only check the first/last 512 bytes to verify if the original path is present - -- because the path maybe too long and be truncated - local part = value_org - if #part > 512 then - part = part:sub(1, 512) - end - if not value_new:find(part, 1, true) then - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) - break - end - local part_end = value_org - if #part_end > 512 then - part_end = part_end:sub(#part_end - 512 + 1) - end - if not value_new:find(part_end, 1, true) then - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) - break + for _, p in ipairs(path.splitenv(value_org)) do + if not value_new:find(p, 1, true) then + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) + wprint(" > %s", p) + break + end end end end -- cgit v1.3.1 From 5a257a3471bc29e1ad9ac496b6389f874f394227 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:35:42 +0800 Subject: improve tips --- xmake/modules/detect/sdks/find_vstudio.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 70cf93d14..be0eed658 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -401,8 +401,7 @@ function _check_vcvarsall_env(vars) if value_org and value_new and #value_org > 0 then for _, p in ipairs(path.splitenv(value_org)) do if not value_new:find(p, 1, true) then - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!", name) - wprint(" > %s", p) + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) break end end -- cgit v1.3.1 From 9f2b25fb6b4682b0e82ca1bdcfc0ae24ff9e668d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:37:57 +0800 Subject: improve tips --- xmake/modules/detect/sdks/find_vstudio.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index be0eed658..0035a88ce 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -401,7 +401,7 @@ function _check_vcvarsall_env(vars) if value_org and value_new and #value_org > 0 then for _, p in ipairs(path.splitenv(value_org)) do if not value_new:find(p, 1, true) then - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p:sub(1, 1024)) break end end -- cgit v1.3.1 From 58ca9ee7a7bb05fe5a8706f9c3966ded3534163f Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:50:41 +0800 Subject: improve tips --- xmake/modules/detect/sdks/find_vstudio.lua | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 0035a88ce..82cdfb643 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -21,6 +21,7 @@ -- imports import("core.base.option") import("core.base.semver") +import("core.base.hashset") import("core.project.config") import("lib.detect.find_file") import("lib.detect.find_tool") @@ -395,13 +396,24 @@ function _check_vcvarsall_env(vars) local value_org = _env_orgs[name] if value_org == nil then value_org = os.getenv(name) - _env_orgs[name] = value_org or false + if value_org then + _env_orgs[name] = path.splitenv(value_org) + else + _env_orgs[name] = false + end + value_org = _env_orgs[name] end local value_new = vars[name] or vars[name:lower()] if value_org and value_new and #value_org > 0 then - for _, p in ipairs(path.splitenv(value_org)) do - if not value_new:find(p, 1, true) then - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p:sub(1, 1024)) + local values_new = hashset.from(path.splitenv(value_new)) + for _, p in ipairs(value_org) do + if not values_new:has(p) then + if option.get("diagnosis") then + if #p > 256 then + p = p:sub(1, 256) .. "..." + end + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) + end break end end -- cgit v1.3.1 From 609c7ebe102b01068a8e6bfa201c99fb660d8fc7 Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:55:44 +0800 Subject: improve check --- xmake/modules/detect/sdks/find_vstudio.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 82cdfb643..b39c216ad 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -391,7 +391,10 @@ end -- check if the environment variables are truncated -- https://github.com/xmake-io/xmake/issues/7281 function _check_vcvarsall_env(vars) - local check_vars = {"PATH", "INCLUDE", "LIB", "LIBPATH"} + if not option.get("diagnosis") then + return + end + local check_vars = {"PATH", "INCLUDE", "LIBPATH"} for _, name in ipairs(check_vars) do local value_org = _env_orgs[name] if value_org == nil then @@ -408,12 +411,10 @@ function _check_vcvarsall_env(vars) local values_new = hashset.from(path.splitenv(value_new)) for _, p in ipairs(value_org) do if not values_new:has(p) then - if option.get("diagnosis") then - if #p > 256 then - p = p:sub(1, 256) .. "..." - end - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) + if #p > 256 then + p = p:sub(1, 256) .. "..." end + cprint("${color.warning}%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) break end end -- cgit v1.3.1 From cc2157942e41b7fc19a965e997855b74a447981d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 12:57:38 +0800 Subject: revert tips --- xmake/modules/detect/sdks/find_vstudio.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index b39c216ad..2ffe2bdf1 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -414,7 +414,7 @@ function _check_vcvarsall_env(vars) if #p > 256 then p = p:sub(1, 256) .. "..." end - cprint("${color.warning}%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) + wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) break end end -- cgit v1.3.1 From b9647966c8332c833113df9554a191e1db93a6af Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 13:19:47 +0800 Subject: fix _check_vcvarsall_env --- xmake/modules/detect/sdks/find_vstudio.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 2ffe2bdf1..127fb1322 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -398,9 +398,9 @@ function _check_vcvarsall_env(vars) for _, name in ipairs(check_vars) do local value_org = _env_orgs[name] if value_org == nil then - value_org = os.getenv(name) - if value_org then - _env_orgs[name] = path.splitenv(value_org) + local value_str = os.getenv(name) + if value_str then + _env_orgs[name] = path.splitenv(value_str) else _env_orgs[name] = false end -- cgit v1.3.1 From 9e715b0c81e3cec987b720f7c113a91302345f6c Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 13:21:08 +0800 Subject: fix tips --- xmake/modules/detect/sdks/find_vstudio.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index 127fb1322..e7e76047d 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -414,7 +414,7 @@ function _check_vcvarsall_env(vars) if #p > 256 then p = p:sub(1, 256) .. "..." end - wprint("%%%s%% is too long and truncated, detect msvc may be failed, please clear some unused variables!\n > %s", name, p) + wprint("%%%s%% is too long and truncated, msvc detection may fail, please clear some unused variables!\n > %s", name, p) break end end -- cgit v1.3.1 From ac0a3e5909f3d0c4b6a630526b230c8a2085839b Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 1 Feb 2026 14:12:50 +0800 Subject: check lib in vs detection --- xmake/modules/detect/sdks/find_vstudio.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua index e7e76047d..22f5dea6b 100644 --- a/xmake/modules/detect/sdks/find_vstudio.lua +++ b/xmake/modules/detect/sdks/find_vstudio.lua @@ -394,7 +394,7 @@ function _check_vcvarsall_env(vars) if not option.get("diagnosis") then return end - local check_vars = {"PATH", "INCLUDE", "LIBPATH"} + local check_vars = {"PATH", "INCLUDE", "LIB", "LIBPATH"} for _, name in ipairs(check_vars) do local value_org = _env_orgs[name] if value_org == nil then -- cgit v1.3.1 From b4b656b1f6ddbe8003ec3a872b6f8d6e3ab0c42c Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 10:38:43 +0300 Subject: refactor: improve process retrieval for Windows and Linux in tty module --- core/src/xmake/os/processes.c | 4 +- xmake/core/base/tty.lua | 99 +++++++++++++++++++++++++++---------------- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/core/src/xmake/os/processes.c b/core/src/xmake/os/processes.c index a50ffbe1c..8dbb92aa2 100644 --- a/core/src/xmake/os/processes.c +++ b/core/src/xmake/os/processes.c @@ -56,7 +56,7 @@ tb_int_t xm_winos_processes(lua_State* lua) { // name tb_char_t name[MAX_PATH * 4]; - tb_size_t size = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE, TB_CHARSET_TYPE_UTF8, (tb_byte_t const*)pe32.szExeFile, tb_wcslen(pe32.szExeFile) * sizeof(tb_wchar_t), (tb_byte_t*)name, sizeof(name)); + tb_size_t size = tb_wtoa(name, pe32.szExeFile, sizeof(name)); if (size != -1) { lua_pushlstring(lua, name, size); } else { @@ -70,7 +70,7 @@ tb_int_t xm_winos_processes(lua_State* lua) { // ppid lua_pushinteger(lua, (tb_int_t)pe32.th32ParentProcessID); - lua_setfield(lua, -2, "ppid"); + lua_setfield(lua, -2, "parent_pid"); // result[i++] = entry lua_rawseti(lua, -2, i++); diff --git a/xmake/core/base/tty.lua b/xmake/core/base/tty.lua index 8d506336d..c3681cdd3 100644 --- a/xmake/core/base/tty.lua +++ b/xmake/core/base/tty.lua @@ -235,57 +235,68 @@ function tty.flush() return tty end --- find the shell from the parent process (linux) -function tty._find_shell_from_parent() +function tty._find_shell_from_parent_on_windows() local shell - if os.host() == "windows" then - local winos = require("base/winos") - if winos.processes then - local processes = winos.processes() - if processes then - local pid = os.getpid() - local processes_map = {} - for _, process in ipairs(processes) do - processes_map[process.pid] = process + local winos = require("base/winos") + if winos.processes then + local processes = winos.processes() + if processes then + local pid = os.getpid() + local processes_map = {} + for _, process in ipairs(processes) do + processes_map[process.pid] = process + end + local count = 0 + while pid and pid ~= 0 and count < 10 do + count = count + 1 + local process = processes_map[pid] + if not process then + break end - local count = 0 - while pid and pid ~= 0 and count < 10 do - count = count + 1 - local process = processes_map[pid] - if not process then - break + local name = process.name + if name then + name = name:lower() + if name:sub(-4) == ".exe" then + name = name:sub(1, #name - 4) end - local name = process.name - if name then - name = name:lower() - if name:sub(-4) == ".exe" then - name = name:sub(1, #name - 4) - end - for _, shellname in ipairs({"zsh", "bash", "fish", "nu", "elvish", "pwsh", "powershell", "cmd", "sh"}) do - if name == shellname then - shell = shellname - break - end + for _, shellname in ipairs({"zsh", "bash", "fish", "nu", "elvish", "pwsh", "powershell", "cmd", "sh"}) do + if name == shellname then + shell = shellname + break end end - if shell then - break - end - pid = process.ppid end + if shell then + break + end + pid = process.parent_pid or process.ppid -- for backward compatibility end end end - if shell then - return shell - end - if os.host() ~= "linux" or not os.isfile("/proc/self/stat") then - return + if not shell then + local subhost = xmake._SUBHOST + if subhost == "windows" then + if os.getenv("PROMPT") then + shell = "cmd" + else + local ok, result = os.iorun("pwsh -v") + if ok then + shell = "pwsh" + else + shell = "powershell" + end + end + end end + return shell +end + +function tty._find_shell_from_parent_on_linux() local pid = os.getpid() local count = 0 + local shell while pid ~= 0 and count < 4 do count = count + 1 local shell_name = nil @@ -330,6 +341,20 @@ function tty._find_shell_from_parent() return shell end +-- find the shell from the parent process +function tty._find_shell_from_parent() + + -- for windows + if os.host() == "windows" then + return tty._find_shell_from_parent_on_windows() + end + + -- for linux + if os.host() == "linux" and os.isfile("/proc/self/stat") then + return tty._find_shell_from_parent_on_linux() + end +end + -- get shell name function tty.shell() local shell = tty._SHELL -- cgit v1.3.1