diff options
| author | ruki <[email protected]> | 2021-11-13 14:14:02 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-11-13 14:14:02 +0800 |
| commit | 96b5f875c2582375564ffdb051615d183e6494ad (patch) | |
| tree | 77a20f28cd09d6433acd6b86176222536e1fa13a | |
| parent | 15520b0859aa54c9d0853765cdeaf14c3b52960d (diff) | |
| parent | f500e8b44d60c9f94fde6d99027a992d1b85e367 (diff) | |
Merge pull request #1828 from xmake-io/cargo
Support cargo dependences and improve mixed c++/rust target
24 files changed, 303 insertions, 30 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 432e5fb03..7599eddfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#1799](https://github.com/xmake-io/xmake/issues/1799): Support mixed rust & c++ target and cargo dependences + ### Changes * Switch to Lua5.4 runtime by default @@ -1127,6 +1131,10 @@ ## master (开发中) +### 新特性 + +* [#1799](https://github.com/xmake-io/xmake/issues/1799): 支持混合 Rust 和 C++ 程序,以及集成 Cargo 依赖库 + ### 改进 * 默认切换到 Lua5.4 运行时 diff --git a/tests/projects/rust/cargo_deps/src/main.rs b/tests/projects/rust/cargo_deps/src/main.rs new file mode 100644 index 000000000..f1ec987bf --- /dev/null +++ b/tests/projects/rust/cargo_deps/src/main.rs @@ -0,0 +1,12 @@ +extern crate base64; + +use base64::{encode, decode}; + +fn main() { + let a = b"hello world"; + let b = "aGVsbG8gd29ybGQ="; + + assert_eq!(encode(a), b); + assert_eq!(a, &decode(b).unwrap()[..]); + println!("{}", encode(a)); +} diff --git a/tests/projects/rust/cargo_deps/xmake.lua b/tests/projects/rust/cargo_deps/xmake.lua new file mode 100644 index 000000000..73340dedf --- /dev/null +++ b/tests/projects/rust/cargo_deps/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.release", "mode.debug") +add_requires("cargo::base64 0.13.0") +add_requires("cargo::flate2 1.0.17", {configs = {features = "zlib"}}) + +target("test") + set_kind("binary") + add_files("src/main.rs") + add_packages("cargo::base64", "cargo::flate2") diff --git a/tests/projects/rust/console/src/main.rs b/tests/projects/rust/console/src/main.rs index e8d2ae9b2..88d5e2749 100644 --- a/tests/projects/rust/console/src/main.rs +++ b/tests/projects/rust/console/src/main.rs @@ -1,4 +1,3 @@ -fn main() -{ +fn main() { println!("hello xmake!"); } diff --git a/tests/projects/rust/cxx_call_rust_library/src/foo.rs b/tests/projects/rust/cxx_call_rust_library/src/foo.rs index 0c4975fa2..f78bfa99d 100644 --- a/tests/projects/rust/cxx_call_rust_library/src/foo.rs +++ b/tests/projects/rust/cxx_call_rust_library/src/foo.rs @@ -5,8 +5,7 @@ mod foo { } } -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/tests/projects/rust/cxx_call_rust_library/src/main.cc b/tests/projects/rust/cxx_call_rust_library/src/main.cc index c0d600fd3..d79b319f9 100644 --- a/tests/projects/rust/cxx_call_rust_library/src/main.cc +++ b/tests/projects/rust/cxx_call_rust_library/src/main.cc @@ -1,8 +1,7 @@ #include <stdio.h> #include "bridge.rs.h" -int main(int argc, char** argv) -{ +int main(int argc, char** argv) { printf("add(1, 2) == %d\n", add(1, 2)); return 0; } diff --git a/tests/projects/rust/cxx_call_rust_library/xmake.lua b/tests/projects/rust/cxx_call_rust_library/xmake.lua index fb3a48171..30d54cc02 100644 --- a/tests/projects/rust/cxx_call_rust_library/xmake.lua +++ b/tests/projects/rust/cxx_call_rust_library/xmake.lua @@ -1,9 +1,12 @@ add_rules("mode.debug", "mode.release") +add_requires("cargo::cxx 1.0") + target("foo") set_kind("static") add_files("src/foo.rs") set_values("rust.cratetype", "staticlib") + add_packages("cargo::cxx") target("test") set_kind("binary") diff --git a/tests/projects/rust/rust_call_cxx_library/src/foo.cc b/tests/projects/rust/rust_call_cxx_library/src/foo.cc index 9d989119e..bb2eb9292 100644 --- a/tests/projects/rust/rust_call_cxx_library/src/foo.cc +++ b/tests/projects/rust/rust_call_cxx_library/src/foo.cc @@ -1,4 +1,3 @@ -extern "C" int add(int a, int b) -{ +extern "C" int add(int a, int b) { return a + b; } diff --git a/tests/projects/rust/shared_library/src/foo.rs b/tests/projects/rust/shared_library/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/tests/projects/rust/shared_library/src/foo.rs +++ b/tests/projects/rust/shared_library/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/tests/projects/rust/shared_library/src/main.rs b/tests/projects/rust/shared_library/src/main.rs index 24f23d84b..205d23da3 100644 --- a/tests/projects/rust/shared_library/src/main.rs +++ b/tests/projects/rust/shared_library/src/main.rs @@ -1,7 +1,6 @@ extern crate foo; -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } diff --git a/tests/projects/rust/static_library/src/foo.rs b/tests/projects/rust/static_library/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/tests/projects/rust/static_library/src/foo.rs +++ b/tests/projects/rust/static_library/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/tests/projects/rust/static_library/src/main.rs b/tests/projects/rust/static_library/src/main.rs index 24f23d84b..de8604a65 100644 --- a/tests/projects/rust/static_library/src/main.rs +++ b/tests/projects/rust/static_library/src/main.rs @@ -1,7 +1,5 @@ extern crate foo; - -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua index 6b7f22a4e..d5d683741 100644 --- a/xmake/core/package/package.lua +++ b/xmake/core/package/package.lua @@ -1867,6 +1867,8 @@ function package.load_from_system(packagename) opt.arch = pkg:arch() opt.require_version = pkg:version_str() opt.buildhash = pkg:buildhash() + opt.cachedir = pkg:cachedir() + opt.installdir = pkg:installdir() import("package.manager.install_package")(pkg:name(), opt) end diff --git a/xmake/languages/rust/xmake.lua b/xmake/languages/rust/xmake.lua index b07617a61..ea71910b7 100644 --- a/xmake/languages/rust/xmake.lua +++ b/xmake/languages/rust/xmake.lua @@ -39,12 +39,18 @@ language("rust") } , binary = { "config.linkdirs" + , "config.frameworkdirs" , "target.linkdirs" + , "target.frameworkdirs" , "target.rpathdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.frameworkdirs" , "toolchain.rpathdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" , "config.links" , "target.links" , "toolchain.links" @@ -54,12 +60,18 @@ language("rust") } , shared = { "config.linkdirs" + , "config.frameworkdirs" , "target.linkdirs" + , "target.frameworkdirs" , "target.rpathdirs" , "target.strip" , "target.symbols" , "toolchain.linkdirs" + , "toolchain.frameworkdirs" , "toolchain.rpathdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" , "config.links" , "target.links" , "toolchain.links" @@ -68,8 +80,17 @@ language("rust") , "toolchain.syslinks" } , static = { - "target.strip" + "config.linkdirs" + , "config.frameworkdirs" + , "target.linkdirs" + , "target.frameworkdirs" + , "target.strip" , "target.symbols" + , "toolchain.linkdirs" + , "toolchain.frameworkdirs" + , "config.frameworks" + , "target.frameworks" + , "toolchain.frameworks" } } diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua index fa358e897..ab41620cd 100644 --- a/xmake/modules/core/tools/rustc.lua +++ b/xmake/modules/core/tools/rustc.lua @@ -65,6 +65,20 @@ function nf_syslink(self, lib) return nf_link(self, lib) end +-- make the frameworkdir flag, crate module dependency directories +function nf_frameworkdir(self, frameworkdir) + return {"-L", "dependency=" .. frameworkdir} +end + +-- make the framework flag, crate module +function nf_framework(self, framework) + local basename = path.basename(framework) + local cratename = basename:match("lib(.-)%-.-") or basename:match("lib(.-)") + if cratename then + return {"--extern", cratename .. "=" .. framework} + end +end + -- make the rpathdir flag function nf_rpathdir(self, dir) dir = path.translate(dir) diff --git a/xmake/modules/detect/tools/find_cargo.lua b/xmake/modules/detect/tools/find_cargo.lua new file mode 100644 index 000000000..a67b29821 --- /dev/null +++ b/xmake/modules/detect/tools/find_cargo.lua @@ -0,0 +1,52 @@ +--!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 ruki +-- @file find_cargo.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find nim +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local nim = find_cargo() +-- local nim, version = find_cargo({program = "cargo", version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "cargo", opt) + + -- find program version + local version = nil + if program and opt.version then + version = find_programver(program, opt) + end + return program, version +end diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua new file mode 100644 index 000000000..7fd151d5c --- /dev/null +++ b/xmake/modules/package/manager/cargo/find_package.lua @@ -0,0 +1,58 @@ +--!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 ruki +-- @file find_package.lua +-- + +-- imports +import("core.base.option") +import("core.base.semver") +import("core.project.config") +import("core.project.target") +import("lib.detect.find_tool") +import("lib.detect.find_file") + +-- find package using the cargo package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x") +-- +function main(name, opt) + local frameworkdirs + local frameworks + local librarydir = path.join(opt.installdir, "lib") + local libfiles = os.files(path.join(librarydir, "*.rlib")) + for _, libraryfile in ipairs(libfiles) do + local filename = path.filename(libraryfile) + if filename:startswith("lib" .. name .. "-") then + frameworkdirs = frameworkdirs or {} + frameworks = frameworks or {} + table.insert(frameworkdirs, librarydir) + table.insert(frameworks, libraryfile) + break + end + end + local result + if frameworks and frameworkdirs then + result = result or {} + result.libfiles = libfiles + result.frameworkdirs = frameworkdirs + result.frameworks = frameworks + result.version = opt.require_version + end + return result +end diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua new file mode 100644 index 000000000..a500bb6a7 --- /dev/null +++ b/xmake/modules/package/manager/cargo/install_package.lua @@ -0,0 +1,99 @@ +--!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 ruki +-- @file install_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("lib.detect.find_tool") + +-- get configurations +function configurations() + return + { + features = {description = "set the features of dependency."}, + default_features = {description = "enables or disables any defaults provided by the dependency.", default = true}, + } +end + +-- install package +-- +-- e.g. +-- add_requires("cargo::base64") +-- add_requires("cargo::base64 0.13.0") +-- add_requires("cargo::flate2 1.0.17", {configs = {features = {"zlib"}, ["default-features"] = false}}) +-- +-- @param name the package name, e.g. cargo::base64 +-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"} +-- +-- @return true or false +-- +function main(name, opt) + + -- find cargo + local cargo = find_tool("cargo") + if not cargo then + raise("cargo not found!") + end + + -- get required version + local require_version = assert(opt.require_version, "cargo::%s version not found!", name) + + -- build dependencies + local sourcedir = path.join(opt.cachedir, "source") + local cargotoml = path.join(sourcedir, "Cargo.toml") + os.tryrm(sourcedir) + local tomlfile = io.open(cargotoml, "w") + tomlfile:print("[package]") + tomlfile:print("name = \"cargodeps\"") + tomlfile:print("version = \"0.1.0\"") + tomlfile:print("edition = \"2018\"") + tomlfile:print("") + tomlfile:print("[dependencies]") + local features = opt.features + if features then + features = table.wrap(features) + tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), opt.default_features) + else + tomlfile:print("%s = \"%s\"", name, require_version) + end + tomlfile:close() + + -- generate main.rs + io.writefile(path.join(sourcedir, "src", "main.rs"), [[ +fn main() { + println!("Hello, world!"); +} + ]]) + + -- do build + local argv = {"build"} + if opt.mode ~= "debug" then + table.insert(argv, "--release") + end + if option.get("verbose") then + table.insert(argv, option.get("diagnosis") and "-vv" or "-v") + end + os.vrunv(cargo.program, argv, {curdir = sourcedir}) + + -- 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")) +end diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua index 7a8502326..3bb12ac30 100644 --- a/xmake/modules/private/action/require/impl/package.lua +++ b/xmake/modules/private/action/require/impl/package.lua @@ -950,7 +950,7 @@ function get_configs_str(package) if type(v) == "boolean" then table.insert(configs, k .. ":" .. (v and "y" or "n")) else - table.insert(configs, k .. ":" .. v) + table.insert(configs, k .. ":" .. string.serialize(v, {strip = true, indent = false})) end end end diff --git a/xmake/rules/rust/xmake.lua b/xmake/rules/rust/xmake.lua index e0952b72e..e31e2f046 100644 --- a/xmake/rules/rust/xmake.lua +++ b/xmake/rules/rust/xmake.lua @@ -32,10 +32,12 @@ rule("rust.cxxbridge") rule("rust.build") set_sourcekinds("rc") on_load(function (target) + -- set cratetype local cratetype = target:values("rust.cratetype") if cratetype == "staticlib" then assert(target:is_static(), "target(%s) must be static kind for cratetype(staticlib)!", target:name()) target:add("arflags", "--crate-type=staticlib") + target:data_set("inherit.links.exportlinks", false) elseif cratetype == "cdylib" then assert(target:is_shared(), "target(%s) must be shared kind for cratetype(cdylib)!", target:name()) target:add("shflags", "--crate-type=cdylib") @@ -55,6 +57,10 @@ rule("rust.build") elseif target:is_binary() then target:add("ldflags", "--crate-type=bin") end + + -- set edition + local edition = target:values("rust.edition") or "2018" + target:add("rcflags", "--edition", edition, {force = true}) end) on_build("build.target") diff --git a/xmake/rules/utils/inherit_links/inherit_links.lua b/xmake/rules/utils/inherit_links/inherit_links.lua index 805f535d8..79c737503 100644 --- a/xmake/rules/utils/inherit_links/inherit_links.lua +++ b/xmake/rules/utils/inherit_links/inherit_links.lua @@ -80,11 +80,13 @@ function main(target) -- @note we only export links for static target, -- and we need pass `{public = true}` to add_packages/add_links/... to export it if want to export links for shared target -- - if targetkind == "static" then - for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do - local values = _get_values_from_target(target, name) - if values and #values > 0 then - target:add(name, values, {public = true}) + if target:data("inherit.links.exportlinks") ~= false then + if targetkind == "static" then + for _, name in ipairs({"rpathdirs", "frameworkdirs", "frameworks", "linkdirs", "links", "syslinks"}) do + local values = _get_values_from_target(target, name) + if values and #values > 0 then + target:add(name, values, {public = true}) + end end end end diff --git a/xmake/templates/rust/console/project/src/main.rs b/xmake/templates/rust/console/project/src/main.rs index fe3b8813c..88d5e2749 100644 --- a/xmake/templates/rust/console/project/src/main.rs +++ b/xmake/templates/rust/console/project/src/main.rs @@ -1,4 +1,3 @@ -fn main() -{ +fn main() { println!("hello xmake!"); } diff --git a/xmake/templates/rust/static/project/src/foo.rs b/xmake/templates/rust/static/project/src/foo.rs index 277008ba4..a3a3aa4a6 100644 --- a/xmake/templates/rust/static/project/src/foo.rs +++ b/xmake/templates/rust/static/project/src/foo.rs @@ -1,5 +1,4 @@ -pub fn add(a: i32, b: i32) -> i32 -{ +pub fn add(a: i32, b: i32) -> i32 { return a + b; } diff --git a/xmake/templates/rust/static/project/src/main.rs b/xmake/templates/rust/static/project/src/main.rs index 24f23d84b..205d23da3 100644 --- a/xmake/templates/rust/static/project/src/main.rs +++ b/xmake/templates/rust/static/project/src/main.rs @@ -1,7 +1,6 @@ extern crate foo; -fn main() -{ +fn main() { println!("hello xmake!"); println!("add: {}", foo::add(1, 1)); } |
