Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for feature selection #108

Merged
merged 12 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ The pairs can also be generator expressions, as they will be evaluated using $<G
For example this may be useful if the build scripts of crates look for environment variables.
This feature requires CMake >= 3.19.0.

Cargo crates sometimes offer features, which traditionally can be specified with `cargo build` on the
command line as opt-in. You can select the features to use for a crate imported with Corrosion by
setting the `CORROSION_FEATURES` target list property on the targets created by `corrosion_import_crate`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the README would benefit from an example


### Developer/Maintainer Options
These options are not used in the course of normal Corrosion usage, but are used to configure how
Corrosion is built and installed. Only applies to Corrosion builds and subdirectory uses.
Expand Down
5 changes: 4 additions & 1 deletion cmake/Corrosion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ function(_add_cargo_build)

if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.19.0)
set(build_env_variable_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target_name},CORROSION_ENVIRONMENT_VARIABLES>>")

set(features_target_property "$<GENEX_EVAL:$<TARGET_PROPERTY:${target_name},CORROSION_FEATURES>>")
set(features_genex "$<$<BOOL:${features_target_property}>:--features=$<JOIN:${features_target_property},$<COMMA>>>")

set(if_not_host_build_condition "$<NOT:$<BOOL:$<TARGET_PROPERTY:${target_name},CORROSION_USE_HOST_BUILD>>>")

Expand All @@ -192,7 +195,6 @@ function(_add_cargo_build)
endif()
endforeach()


add_custom_target(
cargo-build_${target_name}
ALL
Expand All @@ -215,6 +217,7 @@ function(_add_cargo_build)
--manifest-path "${path_to_toml}"
build-crate
$<$<NOT:$<OR:$<CONFIG:Debug>,$<CONFIG:>>>:--release>
${features_genex}
${cargo_target_option}
--package ${package_name}
# Copy crate artifacts to the binary dir
Expand Down
18 changes: 18 additions & 0 deletions generator/src/subcommands/build_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const RELEASE: &str = "release";
const PACKAGE: &str = "package";
const TARGET: &str = "target";

// build-crate features list
const FEATURES: &str = "features";

pub fn subcommand() -> App<'static, 'static> {
SubCommand::with_name(BUILD_CRATE)
.arg(Arg::with_name(RELEASE).long("release"))
Expand All @@ -26,20 +29,35 @@ pub fn subcommand() -> App<'static, 'static> {
.required(true)
.help("The name of the package being built with cargo"),
)
.arg(
Arg::with_name(FEATURES)
.long("features")
.value_name("features")
.takes_value(true)
.multiple(true)
.require_delimiter(true)
.help("Specifies which features of the crate to use"),
)
}

pub fn invoke(
args: &crate::GeneratorSharedArgs,
matches: &ArgMatches,
) -> Result<(), Box<dyn std::error::Error>> {
let target = matches.value_of(TARGET).unwrap();
let features = matches
.values_of(FEATURES)
.map_or(Vec::new(), |c| c.collect())
.join(" ");

let mut cargo = process::Command::new(&args.cargo_executable);

cargo.args(&[
"build",
"--target",
target,
"--features",
&features,
"--package",
matches.value_of(PACKAGE).unwrap(),
"--manifest-path",
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_subdirectory(workspace)
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.19.0)
add_subdirectory(envvar)
add_subdirectory(hostbuild)
add_subdirectory(features)
endif()

# Config tests don't work if this is the top level directory.
Expand Down
19 changes: 19 additions & 0 deletions test/features/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
corrosion_import_crate(MANIFEST_PATH rust/Cargo.toml)

add_executable(features-cpp-exe main.cpp)
target_link_libraries(features-cpp-exe PUBLIC rust-feature-lib)
set_property(
TARGET features-cpp-exe
APPEND
PROPERTY app_features myfeature
)
set_property(
TARGET features-cpp-exe
APPEND
PROPERTY app_features secondfeature
)
set_property(
TARGET rust-feature-lib
APPEND
PROPERTY CORROSION_FEATURES $<TARGET_PROPERTY:features-cpp-exe,app_features>
)
9 changes: 9 additions & 0 deletions test/features/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
extern "C" void rust_function(char const *name);

int main(int argc, char **argv) {
if (argc < 2) {
rust_function("C++");
} else {
rust_function(argv[1]);
}
}
7 changes: 7 additions & 0 deletions test/features/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions test/features/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "rust-feature-lib"
version = "0.1.0"
authors = ["Andrew Gaspar <andrew.gaspar@outlook.com>"]
license = "MIT"
edition = "2018"

[dependencies]

[lib]
crate-type=["staticlib"]

[features]
default = []
myfeature = []
secondfeature = []
16 changes: 16 additions & 0 deletions test/features/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#[cfg(feature = "myfeature")]
use std::os::raw::c_char;

#[no_mangle]
#[cfg(feature = "myfeature")]
pub extern "C" fn rust_function(name: *const c_char) {
let name = unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() };
println!("Hello, {}! I'm Rust!", name);
}

#[no_mangle]
#[cfg(feature = "secondfeature")]
pub extern "C" fn rust_second_function(name: *const c_char) {
let name = unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() };
println!("Hello, {}! I'm Rust again!", name);
}