summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2023-08-09 13:35:49 +0800
committerGitHub <[email protected]>2023-08-09 13:35:49 +0800
commitcc8c1a35e4b1dd6053b86fd279ce263cffc96321 (patch)
treef6682ffaceb907be68b200d4057c711efbed1ee1
parent4182b1a29d085d59e1aca2389a2fc7ec53451885 (diff)
parentef2ba39e335136945cec07d04bd5da4bcd1725a8 (diff)
Merge pull request #4052 from xmake-io/rust
Improve rust to support cross build deps
-rw-r--r--tests/projects/rust/cargo_deps_cross_build/Cargo.toml10
-rw-r--r--tests/projects/rust/cargo_deps_cross_build/src/main.rs10
-rw-r--r--tests/projects/rust/cargo_deps_cross_build/xmake.lua14
-rw-r--r--xmake/modules/package/manager/cargo/configurations.lua8
-rw-r--r--xmake/modules/package/manager/cargo/find_package.lua58
-rw-r--r--xmake/modules/package/manager/cargo/install_package.lua48
-rw-r--r--xmake/modules/private/tools/rust/check_target.lua76
-rw-r--r--xmake/toolchains/rust/xmake.lua15
-rw-r--r--xmake/toolchains/xcode/load_macosx.lua3
9 files changed, 207 insertions, 35 deletions
diff --git a/tests/projects/rust/cargo_deps_cross_build/Cargo.toml b/tests/projects/rust/cargo_deps_cross_build/Cargo.toml
new file mode 100644
index 000000000..fdc6c3132
--- /dev/null
+++ b/tests/projects/rust/cargo_deps_cross_build/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "demo"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+spin = "^0.9"
+
+[target.'cfg(target_arch = "aarch64")'.dependencies]
+aarch64-cpu = "^9.3"
diff --git a/tests/projects/rust/cargo_deps_cross_build/src/main.rs b/tests/projects/rust/cargo_deps_cross_build/src/main.rs
new file mode 100644
index 000000000..c7ce4ff1c
--- /dev/null
+++ b/tests/projects/rust/cargo_deps_cross_build/src/main.rs
@@ -0,0 +1,10 @@
+// src/main.rs
+#![no_main]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(_panic: &PanicInfo<'_>) -> ! {
+ loop {}
+}
diff --git a/tests/projects/rust/cargo_deps_cross_build/xmake.lua b/tests/projects/rust/cargo_deps_cross_build/xmake.lua
new file mode 100644
index 000000000..e02e14f82
--- /dev/null
+++ b/tests/projects/rust/cargo_deps_cross_build/xmake.lua
@@ -0,0 +1,14 @@
+-- rustup target add aarch64-unknown-none
+-- xmake f -a aarch64-unknown-none
+
+set_arch("aarch64-unknown-none")
+add_rules("mode.release", "mode.debug")
+add_requires("cargo::test", {configs = {
+ std = false,
+ main = false,
+ cargo_toml = path.join(os.projectdir(), "Cargo.toml")}})
+
+target("test")
+ set_kind("binary")
+ add_files("src/main.rs")
+ add_packages("cargo::test")
diff --git a/xmake/modules/package/manager/cargo/configurations.lua b/xmake/modules/package/manager/cargo/configurations.lua
index 9a8b7f89f..f151c1802 100644
--- a/xmake/modules/package/manager/cargo/configurations.lua
+++ b/xmake/modules/package/manager/cargo/configurations.lua
@@ -22,8 +22,10 @@
function main()
return
{
- features = {description = "set the features of dependency."},
- default_features = {description = "enables or disables any defaults provided by the dependency.", default = true},
- cargo_toml = {description = "set Cargo.toml file path"}
+ features = {description = "Set the features of dependency."},
+ default_features = {description = "Enable or disable any defaults provided by the dependency.", default = true},
+ std = {description = "Enable or disable std module."},
+ main = {description = "Enable or disable main entry function."},
+ cargo_toml = {description = "Set Cargo.toml file path"}
}
end
diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua
index ec351d84e..58064d9a9 100644
--- a/xmake/modules/package/manager/cargo/find_package.lua
+++ b/xmake/modules/package/manager/cargo/find_package.lua
@@ -22,10 +22,12 @@
import("core.base.option")
import("core.base.semver")
import("core.base.hashset")
+import("core.base.json")
import("core.project.config")
import("core.project.target")
import("lib.detect.find_tool")
import("lib.detect.find_file")
+import("private.tools.rust.check_target")
-- get cargo registry directory
function _get_cargo_registrydir()
@@ -82,30 +84,48 @@ function _get_libname(name)
end
-- get the name set of libraries
-function _get_names_of_libraries(name, configs)
+function _get_names_of_libraries(name, opt)
+ local configs = opt.configs or {}
local names = hashset.new()
if configs.cargo_toml then
- local dependencies = false
- local cargo_file = io.open(configs.cargo_toml)
- for line in cargo_file:lines() do
- line = line:trim()
- if not dependencies and line == "[dependencies]" then
- dependencies = true
- elseif dependencies then
- if not line:startswith("[") then
- local splitinfo = line:split("=", {plain = true})
- if splitinfo and #splitinfo > 1 then
- name = splitinfo[1]:trim()
- if #name > 0 then
- names:insert(_get_libname(name))
- end
- end
- else
+ local cargo = assert(find_tool("cargo"), "cargo not found!")
+ local cargo_args = {"metadata", "--format-version", "1", "--manifest-path", configs.cargo_toml, "--color", "never"}
+ local target = check_target(opt.arch, true) and opt.arch or nil
+ if target then
+ table.insert(cargo_args, "--filter-platform")
+ table.insert(cargo_args, target)
+ end
+ if configs.features then
+ table.insert(cargo_args, "--features")
+ table.insert(cargo_args, table.concat(configs.features, ","))
+ end
+ if configs.default_features == false then
+ table.insert(cargo_args, "--no-default-features")
+ end
+
+ local output = os.iorunv(cargo.program, cargo_args)
+ local metadata = json.decode(output)
+
+ -- fetch the direct dependencies list regradless of the target platform
+ table.insert(cargo_args, "--no-deps")
+ output = os.iorunv(cargo.program, cargo_args)
+ local metadata_no_deps = json.decode(output)
+ -- FIXME: should consider the case of multiple packages in a workspace!
+ local direct_deps = metadata_no_deps.packages[1].dependencies
+
+ -- get the intersection of the direct dependencies and all dependencies for the target platform
+ for _, dep in ipairs(direct_deps) do
+ local dep_metadata
+ for _, pkg in ipairs(metadata.packages) do
+ if pkg.name == dep.name then
+ dep_metadata = pkg
break
end
end
+ if dep_metadata then
+ names:insert(_get_libname(dep.name))
+ end
end
- cargo_file:close()
else
names:insert(_get_libname(name))
end
@@ -124,7 +144,7 @@ function main(name, opt)
local configs = opt.configs or {}
-- get names of libraries
- local names = _get_names_of_libraries(name, configs)
+ local names = _get_names_of_libraries(name, opt)
assert(not names:empty())
local frameworkdirs
diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua
index 23955b1cc..9daa665cd 100644
--- a/xmake/modules/package/manager/cargo/install_package.lua
+++ b/xmake/modules/package/manager/cargo/install_package.lua
@@ -22,6 +22,7 @@
import("core.base.option")
import("core.project.config")
import("lib.detect.find_tool")
+import("private.tools.rust.check_target")
-- install package
--
@@ -52,6 +53,11 @@ function main(name, opt)
require_version = "*"
end
+ -- get target
+ -- e.g. x86_64-pc-windows-msvc, aarch64-unknown-none
+ -- @see https://github.com/xmake-io/xmake/issues/4049
+ local target = check_target(opt.arch, true) and opt.arch or nil
+
-- generate Cargo.toml
local sourcedir = path.join(opt.cachedir, "source")
local cargotoml = path.join(sourcedir, "Cargo.toml")
@@ -86,12 +92,38 @@ function main(name, opt)
tomlfile:close()
end
+ -- generate .cargo/config.toml
+ local configtoml = path.join(sourcedir, ".cargo", "config.toml")
+ if target then
+ io.writefile(configtoml, format([[
+[build]
+target = "%s"
+]], target))
+ end
+
-- generate main.rs
- io.writefile(path.join(sourcedir, "src", "main.rs"), [[
-fn main() {
- println!("Hello, world!");
-}
- ]])
+ local file = io.open(path.join(sourcedir, "src", "main.rs"), "w")
+ if configs.main == false then
+ file:print("#![no_main]")
+ end
+ if configs.std == false then
+ file:print("#![no_std]")
+ end
+ if configs.main == false then
+ file:print([[
+ use core::panic::PanicInfo;
+
+ #[panic_handler]
+ fn panic(_panic: &PanicInfo<'_>) -> ! {
+ loop {}
+ }]])
+ else
+ file:print([[
+ fn main() {
+ println!("Hello, world!");
+ }]])
+ end
+ file:close()
-- do build
local argv = {"build"}
@@ -106,5 +138,9 @@ fn main() {
-- do install
local installdir = opt.installdir
os.tryrm(path.join(installdir, "lib"))
- os.vcp(path.join(sourcedir, "target", opt.mode == "debug" and "debug" or "release", "deps"), path.join(installdir, "lib"))
+ if target then
+ os.vcp(path.join(sourcedir, "target", target, opt.mode == "debug" and "debug" or "release", "deps"), path.join(installdir, "lib"))
+ else
+ os.vcp(path.join(sourcedir, "target", opt.mode == "debug" and "debug" or "release", "deps"), path.join(installdir, "lib"))
+ end
end
diff --git a/xmake/modules/private/tools/rust/check_target.lua b/xmake/modules/private/tools/rust/check_target.lua
new file mode 100644
index 000000000..fdc06458b
--- /dev/null
+++ b/xmake/modules/private/tools/rust/check_target.lua
@@ -0,0 +1,76 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author w568w
+-- @file check_target.lua
+--
+
+-- imports
+import("lib.detect.find_tool")
+
+-- get rustc supported targets
+--
+-- @return the supported target list. If rustc not found, return nil
+function _get_rustc_supported_target()
+ local rustc = find_tool("rustc")
+ if not rustc then
+ return nil
+ end
+ local output = os.iorunv(rustc.program, {"--print", "target-list"})
+ return output:split('\n')
+end
+
+-- check whether the target is supported by rustc
+--
+-- @param arch the target name, e.g. x86_64-unknown-linux-gnu
+-- @param precise whether to check the target precisely (i.e. check by rustc), otherwise only by syntax
+--
+-- @return true if arch != nil and the target is supported by rustc, otherwise false
+function main(arch, precise)
+
+ if not arch then
+ return false
+ end
+
+ -- 1: check by syntax
+ local result = false
+ local archs = arch:split("%-")
+ if #archs >= 2 then
+ result = true
+ else
+ wprint("the arch \"%s\" is NOT a valid target triple, will be IGNORED and may cause compilation errors, please check it again", arch)
+ end
+
+ -- 2: check by rustc
+ if not precise then
+ return result
+ end
+ result = false
+ local rustc_supported_target = _get_rustc_supported_target()
+ if rustc_supported_target then
+ for _, v in ipairs(rustc_supported_target) do
+ if v == arch then
+ result = true
+ break
+ end
+ end
+ if not result then
+ wprint("the arch \"%s\" is NOT supported by rustc, will be IGNORED and may cause compilation errors, please check it again", arch)
+ end
+ end
+
+ return result
+end
diff --git a/xmake/toolchains/rust/xmake.lua b/xmake/toolchains/rust/xmake.lua
index 3329b73b7..e997eaa21 100644
--- a/xmake/toolchains/rust/xmake.lua
+++ b/xmake/toolchains/rust/xmake.lua
@@ -18,21 +18,24 @@
-- @file xmake.lua
--
--- define toolchain
toolchain("rust")
- -- set homepage
set_homepage("https://www.rust-lang.org/")
set_description("Rust Programming Language Compiler")
- -- set toolset
set_toolset("rc", "$(env RC)", "rustc")
set_toolset("rcld", "$(env RC)", "rustc")
set_toolset("rcsh", "$(env RC)", "rustc")
set_toolset("rcar", "$(env RC)", "rustc")
- -- on load
on_load(function (toolchain)
- toolchain:set("rcshflags", "")
- toolchain:set("rcldflags", "")
+ -- e.g. x86_64-pc-windows-msvc, aarch64-unknown-none
+ local arch = toolchain:arch()
+ if arch and #arch:split("%-") > 1 then
+ toolchain:add("rcshflags", "--target=" .. arch)
+ toolchain:add("rcldflags", "--target=" .. arch)
+ else
+ toolchain:set("rcshflags", "")
+ toolchain:set("rcldflags", "")
+ end
end)
diff --git a/xmake/toolchains/xcode/load_macosx.lua b/xmake/toolchains/xcode/load_macosx.lua
index 69afce0e9..fb7c3d615 100644
--- a/xmake/toolchains/xcode/load_macosx.lua
+++ b/xmake/toolchains/xcode/load_macosx.lua
@@ -78,7 +78,8 @@ function main(toolchain)
-- init flags for c/c++
toolchain:add("ldflags", "-stdlib=libc++")
toolchain:add("shflags", "-stdlib=libc++")
- toolchain:add("syslinks", "z")
+ toolchain:add("ldflags", "-lz")
+ toolchain:add("shflags", "-lz")
-- init flags for objc/c++ (with ldflags and shflags)
-- we can use `add_mxflags("-fno-objc-arc")` to override it in xmake.lua