diff options
| author | ruki <[email protected]> | 2023-08-09 12:39:44 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-09 12:39:44 +0800 |
| commit | ef2ba39e335136945cec07d04bd5da4bcd1725a8 (patch) | |
| tree | 01b3d47f30fb28371fbd4ff66c5d183d2123b937 | |
| parent | d56fd4e78dd1d5a64409df3b8c889a54a4f740eb (diff) | |
| parent | 415f8da47b8b182a7072190dec91061ed6563c88 (diff) | |
Merge pull request #4054 from w568w/rust
Use `cargo metadata` to fetch the name set of cargo libraries
4 files changed, 120 insertions, 24 deletions
diff --git a/tests/projects/rust/cargo_deps_cross_build/Cargo.toml b/tests/projects/rust/cargo_deps_cross_build/Cargo.toml index 6761593dc..fdc6c3132 100644 --- a/tests/projects/rust/cargo_deps_cross_build/Cargo.toml +++ b/tests/projects/rust/cargo_deps_cross_build/Cargo.toml @@ -5,3 +5,6 @@ edition = "2021" [dependencies] spin = "^0.9" + +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = "^9.3" 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 7d58553e6..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 -- @@ -55,11 +56,7 @@ function main(name, opt) -- get target -- e.g. x86_64-pc-windows-msvc, aarch64-unknown-none -- @see https://github.com/xmake-io/xmake/issues/4049 - local target - local arch = opt.arch - if arch and #arch:split("%-") > 1 then - target = arch - end + local target = check_target(opt.arch, true) and opt.arch or nil -- generate Cargo.toml local sourcedir = path.join(opt.cachedir, "source") 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 |
