From 8d08f0cc65c7d998265e247660ebf19bc1ba0caa Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Sun, 6 Jul 2025 02:43:56 +0530 Subject: fix: rust static and shared library failing to find extern crate in windows-msvc 1. rustc requires lib*.rlib, *.dll but produces *.rlib, *.dll. 2. shared library are `foo.dll`, `foo.dll.lib` and it links for `foo.dll`. --- xmake/rules/rust/xmake.lua | 22 +++++++++++++++++++--- xmake/rules/utils/inherit_links/inherit_links.lua | 10 ++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index dfdf1d047..56d54fb38 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -32,6 +32,9 @@ rule("rust.cxxbridge") rule("rust.build") set_sourcekinds("rc") on_load(function (target) + -- set cratename + local cratename = target:values("rust.cratename") or target:name() + target:set("basename", cratename) -- set cratetype local cratetype = target:values("rust.cratetype") if cratetype == "staticlib" then @@ -43,19 +46,32 @@ rule("rust.build") target:add("shflags", "--crate-type=cdylib", {force = true}) target:add("shflags", "-C prefer-dynamic", {force = true}) elseif target:is_static() then + cratetype = "lib" + target:set("values", "rust.cratetype", cratetype) + if is_plat("windows") then + target:set("prefixname", "lib") + end target:set("extension", ".rlib") - target:add("arflags", "--crate-type=lib", {force = true}) + target:add("arflags", "--crate-type=" .. cratetype, {force = true}) target:data_set("inherit.links.deplink", false) elseif target:is_shared() then - target:add("shflags", "--crate-type=dylib", {force = true}) + cratetype = "dylib" + target:set("values", "rust.cratetype", cratetype) + target:add("shflags", "--crate-type=" .. cratetype, {force = true}) -- fix cannot satisfy dependencies so `std` only shows up once -- https://github.com/rust-lang/rust/issues/19680 -- -- but it will link dynamic @rpath/libstd-xxx.dylib, -- so we can no longer modify and set other rpath paths target:add("shflags", "-C prefer-dynamic", {force = true}) + -- don't add links and instead use --extern CRATE[=PATH] + -- also, it'll automatically link from linkdirs (-L) even if no --extern + -- https://github.com/xmake-io/xmake/issues/6604 + target:data_set("inherit.links.deplink", false) elseif target:is_binary() then - target:add("ldflags", "--crate-type=bin", {force = true}) + cratetype = "bin" + target:set("values", "rust.cratetype", cratetype) + target:add("ldflags", "--crate-type=" .. cratetype, {force = true}) end -- set edition diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index 8a61a2874..cdac9ace6 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -91,6 +91,16 @@ function main(target) -- we need to add includedirs to support import modules for golang _add_export_value(target, "includedirs", path.directory(targetfile)) end + + if target:rule("rust") then + local cratetype = target:values("rust.cratetype") + -- only bin, lib, rlib, dylib can make use of --extern CRATE[=PATH] + if cratetype ~= "staticlib" and cratetype ~= "cdylib" then + local cratename = target:values("rust.cratename") or target:name() + local extern_crate_opt = string.format('--extern %s=%s', cratename, target:targetfile()) + _add_export_value(target, "rcldflags", extern_crate_opt) + end + end end -- we export all links and linkdirs in self/packages/options to the parent target by default -- cgit v1.3.1 From 207f0a10dc931ffc744a8e50eab00004c5d5da5e Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Sun, 6 Jul 2025 03:48:09 +0530 Subject: feat(template): add rust shared library template - built using -C prefer-dynamic hence, requires libstd-*.[so|dll|dylib] add DYLD_LIBRARY_PATH to search libstd --- xmake/templates/rust/shared/project/src/foo.rs | 4 ++++ xmake/templates/rust/shared/project/src/main.rs | 6 ++++++ xmake/templates/rust/shared/project/xmake.lua | 18 ++++++++++++++++++ xmake/templates/rust/shared/template.lua | 2 ++ 4 files changed, 30 insertions(+) create mode 100644 xmake/templates/rust/shared/project/src/foo.rs create mode 100644 xmake/templates/rust/shared/project/src/main.rs create mode 100644 xmake/templates/rust/shared/project/xmake.lua create mode 100644 xmake/templates/rust/shared/template.lua diff --git a/xmake/templates/rust/shared/project/src/foo.rs b/xmake/templates/rust/shared/project/src/foo.rs new file mode 100644 index 000000000..a3a3aa4a6 --- /dev/null +++ b/xmake/templates/rust/shared/project/src/foo.rs @@ -0,0 +1,4 @@ +pub fn add(a: i32, b: i32) -> i32 { + return a + b; +} + diff --git a/xmake/templates/rust/shared/project/src/main.rs b/xmake/templates/rust/shared/project/src/main.rs new file mode 100644 index 000000000..205d23da3 --- /dev/null +++ b/xmake/templates/rust/shared/project/src/main.rs @@ -0,0 +1,6 @@ +extern crate foo; + +fn main() { + println!("hello xmake!"); + println!("add: {}", foo::add(1, 1)); +} diff --git a/xmake/templates/rust/shared/project/xmake.lua b/xmake/templates/rust/shared/project/xmake.lua new file mode 100644 index 000000000..12b177466 --- /dev/null +++ b/xmake/templates/rust/shared/project/xmake.lua @@ -0,0 +1,18 @@ +target("foo") + set_kind("shared") + add_files("src/foo.rs") + +target("${TARGETNAME}_demo") + set_kind("binary") + add_deps("foo") + add_files("src/main.rs") + + --- Make sure libstd shared library is available + before_run(function (target) + local outdata, errdata = os.iorun("rustc --print=sysroot") + assert(not errdata or errdata == "", "failed to find rust sysroot:\n" .. errdata) + local libstd = path.join(outdata:trim(), "bin") + os.addenvs({PATH = libstd, LD_LIBRARY_PATH = libstd, DYLD_LIBRARY_PATH = libstd}) + end) + +${FAQ} diff --git a/xmake/templates/rust/shared/template.lua b/xmake/templates/rust/shared/template.lua new file mode 100644 index 000000000..d7ec5bae4 --- /dev/null +++ b/xmake/templates/rust/shared/template.lua @@ -0,0 +1,2 @@ +template("shared") + add_configfiles("xmake.lua") -- cgit v1.3.1 From 77ac26ceefd28ce8091a65e3f6ff19d51bed8bab Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Sun, 6 Jul 2025 22:08:52 +0530 Subject: refactor: use rustc.nf_framework instead of directly creating extern flags --- xmake/rules/utils/inherit_links/inherit_links.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index cdac9ace6..e729ddf7d 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -96,9 +96,9 @@ function main(target) local cratetype = target:values("rust.cratetype") -- only bin, lib, rlib, dylib can make use of --extern CRATE[=PATH] if cratetype ~= "staticlib" and cratetype ~= "cdylib" then - local cratename = target:values("rust.cratename") or target:name() - local extern_crate_opt = string.format('--extern %s=%s', cratename, target:targetfile()) - _add_export_value(target, "rcldflags", extern_crate_opt) + local extern_crate_opt = rustc:nf_framework(target:targetfile()) + local extern_crate = table.concat(extern_crate_opt, " ") + _add_export_value(target, "rcflags", extern_crate) end end end -- cgit v1.3.1 From fe3a4b2a9fa7e75a5ba760401e19b312028d27ee Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Sun, 6 Jul 2025 23:14:48 +0530 Subject: refactor: simplify rust shared lib template and use rule to add libstd in env --- xmake/rules/rust/xmake.lua | 12 ++++++++++++ xmake/templates/rust/shared/project/xmake.lua | 8 -------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index 56d54fb38..8f62392b9 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -97,6 +97,18 @@ rule("rust.build") end) on_build("build.target") + before_run(function (target) + import("lib.detect.find_tool") + + -- Make sure libstd shared library is available + local rc = find_tool("rustc") + assert(rc, "rustc not found. Failed to add libstd in env") + local outdata, errdata = os.iorunv(rc.program, {"--print=sysroot"}) + assert(not errdata or errdata == "", "failed to find rust sysroot:\n" .. errdata) + local libstd = path.join(outdata:trim(), "bin") + os.addenvs({PATH = libstd, LD_LIBRARY_PATH = libstd, DYLD_LIBRARY_PATH = libstd}) + end) + rule("rust") add_deps("rust.build") add_deps("utils.inherit.links") diff --git a/xmake/templates/rust/shared/project/xmake.lua b/xmake/templates/rust/shared/project/xmake.lua index 12b177466..d20b6f5d7 100644 --- a/xmake/templates/rust/shared/project/xmake.lua +++ b/xmake/templates/rust/shared/project/xmake.lua @@ -7,12 +7,4 @@ target("${TARGETNAME}_demo") add_deps("foo") add_files("src/main.rs") - --- Make sure libstd shared library is available - before_run(function (target) - local outdata, errdata = os.iorun("rustc --print=sysroot") - assert(not errdata or errdata == "", "failed to find rust sysroot:\n" .. errdata) - local libstd = path.join(outdata:trim(), "bin") - os.addenvs({PATH = libstd, LD_LIBRARY_PATH = libstd, DYLD_LIBRARY_PATH = libstd}) - end) - ${FAQ} -- cgit v1.3.1 From a3ba17738500e6a0c093da6a0687119f93a89eff Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:35:38 +0530 Subject: refactor: use on_config to add runenvs instead of before_run --- xmake/rules/rust/xmake.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index 8f62392b9..7dbd0c488 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -97,16 +97,18 @@ rule("rust.build") end) on_build("build.target") - before_run(function (target) + on_config(function (target) import("lib.detect.find_tool") - -- Make sure libstd shared library is available + -- Ensure libstd shared library is available when running local rc = find_tool("rustc") assert(rc, "rustc not found. Failed to add libstd in env") local outdata, errdata = os.iorunv(rc.program, {"--print=sysroot"}) assert(not errdata or errdata == "", "failed to find rust sysroot:\n" .. errdata) local libstd = path.join(outdata:trim(), "bin") - os.addenvs({PATH = libstd, LD_LIBRARY_PATH = libstd, DYLD_LIBRARY_PATH = libstd}) + target:add("runenvs", "PATH", libstd) + target:add("runenvs", "LD_LIBRARY_PATH", libstd) + target:add("runenvs", "DYLD_LIBRARY_PATH", libstd) end) rule("rust") -- cgit v1.3.1 From 1dfed55f3b621c81672894eeea80b11c37b29df8 Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:36:31 +0530 Subject: refactor: add extern crate using frameworks instead of rcflags --- xmake/rules/utils/inherit_links/inherit_links.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index e729ddf7d..b4b293d66 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -96,9 +96,7 @@ function main(target) local cratetype = target:values("rust.cratetype") -- only bin, lib, rlib, dylib can make use of --extern CRATE[=PATH] if cratetype ~= "staticlib" and cratetype ~= "cdylib" then - local extern_crate_opt = rustc:nf_framework(target:targetfile()) - local extern_crate = table.concat(extern_crate_opt, " ") - _add_export_value(target, "rcflags", extern_crate) + _add_export_value(target, "frameworks", target:targetfile()) end end end -- cgit v1.3.1 From f1858dac8ef6e7a9f74a116610e5911b7941e72a Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Wed, 9 Jul 2025 18:50:44 +0530 Subject: fix: rust libstd not found in non-windows - In non-windows, it's located at /lib --- xmake/rules/rust/xmake.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index 7dbd0c488..3875f10ff 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -105,10 +105,17 @@ rule("rust.build") assert(rc, "rustc not found. Failed to add libstd in env") local outdata, errdata = os.iorunv(rc.program, {"--print=sysroot"}) assert(not errdata or errdata == "", "failed to find rust sysroot:\n" .. errdata) - local libstd = path.join(outdata:trim(), "bin") - target:add("runenvs", "PATH", libstd) - target:add("runenvs", "LD_LIBRARY_PATH", libstd) - target:add("runenvs", "DYLD_LIBRARY_PATH", libstd) + local rustc_sysroot = outdata:trim() + if target:is_plat("windows") then + local libstd = path.join(rustc_sysroot, "bin") + target:add("runenvs", "PATH", libstd) + elseif target:is_plat("macosx") then + local libstd = path.join(rustc_sysroot, "lib") + target:add("runenvs", "DYLD_LIBRARY_PATH", libstd) + else + local libstd = path.join(rustc_sysroot, "lib") + target:add("runenvs", "LD_LIBRARY_PATH", libstd) + end end) rule("rust") -- cgit v1.3.1