summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-11-13 14:14:02 +0800
committerGitHub <[email protected]>2021-11-13 14:14:02 +0800
commit96b5f875c2582375564ffdb051615d183e6494ad (patch)
tree77a20f28cd09d6433acd6b86176222536e1fa13a
parent15520b0859aa54c9d0853765cdeaf14c3b52960d (diff)
parentf500e8b44d60c9f94fde6d99027a992d1b85e367 (diff)
Merge pull request #1828 from xmake-io/cargo
Support cargo dependences and improve mixed c++/rust target
-rw-r--r--CHANGELOG.md8
-rw-r--r--tests/projects/rust/cargo_deps/src/main.rs12
-rw-r--r--tests/projects/rust/cargo_deps/xmake.lua8
-rw-r--r--tests/projects/rust/console/src/main.rs3
-rw-r--r--tests/projects/rust/cxx_call_rust_library/src/foo.rs3
-rw-r--r--tests/projects/rust/cxx_call_rust_library/src/main.cc3
-rw-r--r--tests/projects/rust/cxx_call_rust_library/xmake.lua3
-rw-r--r--tests/projects/rust/rust_call_cxx_library/src/foo.cc3
-rw-r--r--tests/projects/rust/shared_library/src/foo.rs3
-rw-r--r--tests/projects/rust/shared_library/src/main.rs3
-rw-r--r--tests/projects/rust/static_library/src/foo.rs3
-rw-r--r--tests/projects/rust/static_library/src/main.rs4
-rw-r--r--xmake/core/package/package.lua2
-rw-r--r--xmake/languages/rust/xmake.lua23
-rw-r--r--xmake/modules/core/tools/rustc.lua14
-rw-r--r--xmake/modules/detect/tools/find_cargo.lua52
-rw-r--r--xmake/modules/package/manager/cargo/find_package.lua58
-rw-r--r--xmake/modules/package/manager/cargo/install_package.lua99
-rw-r--r--xmake/modules/private/action/require/impl/package.lua2
-rw-r--r--xmake/rules/rust/xmake.lua6
-rw-r--r--xmake/rules/utils/inherit_links/inherit_links.lua12
-rw-r--r--xmake/templates/rust/console/project/src/main.rs3
-rw-r--r--xmake/templates/rust/static/project/src/foo.rs3
-rw-r--r--xmake/templates/rust/static/project/src/main.rs3
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));
}