Skip to content

Commit 126f802

Browse files
committed
add LibraryTypes
1 parent 56656f8 commit 126f802

File tree

2 files changed

+93
-61
lines changed

2 files changed

+93
-61
lines changed

src/build.rs

+89-53
Original file line numberDiff line numberDiff line change
@@ -102,28 +102,27 @@ fn build_pc_files(
102102

103103
fn patch_target(
104104
pkg: &mut Package,
105-
libkinds: &[&str],
105+
library_types: LibraryTypes,
106106
capi_config: &CApiConfig,
107107
) -> anyhow::Result<()> {
108108
use cargo::core::compiler::CrateType;
109109

110110
let manifest = pkg.manifest_mut();
111111
let targets = manifest.targets_mut();
112112

113-
let kinds: Vec<_> = libkinds
114-
.iter()
115-
.map(|&kind| match kind {
116-
"staticlib" => CrateType::Staticlib,
117-
"cdylib" => CrateType::Cdylib,
118-
_ => unreachable!(),
119-
})
120-
.collect();
113+
let mut kinds = Vec::with_capacity(2);
121114

122-
for target in targets.iter_mut() {
123-
if target.is_lib() {
124-
target.set_kind(TargetKind::Lib(kinds.clone()));
125-
target.set_name(&capi_config.library.name);
126-
}
115+
if library_types.staticlib {
116+
kinds.push(CrateType::Staticlib);
117+
}
118+
119+
if library_types.cdylib {
120+
kinds.push(CrateType::Cdylib);
121+
}
122+
123+
for target in targets.iter_mut().filter(|t| t.is_lib()) {
124+
target.set_kind(TargetKind::Lib(kinds.to_vec()));
125+
target.set_name(&capi_config.library.name);
127126
}
128127

129128
Ok(())
@@ -952,7 +951,7 @@ impl CPackage {
952951
fn from_package(
953952
pkg: &mut Package,
954953
args: &ArgMatches,
955-
libkinds: &[&str],
954+
library_types: LibraryTypes,
956955
rustc_target: &target::Target,
957956
root_output: &Path,
958957
) -> anyhow::Result<CPackage> {
@@ -961,7 +960,7 @@ impl CPackage {
961960
let root_path = pkg.root().to_path_buf();
962961
let capi_config = load_manifest_capi_config(pkg, rustc_target)?;
963962

964-
patch_target(pkg, libkinds, &capi_config)?;
963+
patch_target(pkg, library_types, &capi_config)?;
965964

966965
let name = &capi_config.library.name;
967966

@@ -970,7 +969,7 @@ impl CPackage {
970969
name,
971970
rustc_target,
972971
root_output,
973-
libkinds,
972+
library_types,
974973
&capi_config,
975974
args.get_flag("meson"),
976975
)?;
@@ -998,6 +997,58 @@ fn deprecation_warnings(ws: &Workspace, args: &ArgMatches) -> anyhow::Result<()>
998997
Ok(())
999998
}
1000999

1000+
/// What library types to build
1001+
#[derive(Debug, Clone, Copy)]
1002+
pub struct LibraryTypes {
1003+
pub staticlib: bool,
1004+
pub cdylib: bool,
1005+
}
1006+
1007+
impl LibraryTypes {
1008+
fn from_target(target: &target::Target) -> Self {
1009+
// for os == "none", cdylib does not make sense. By default cdylib is also not built on
1010+
// musl, but that can be overriden by the user. That is useful when musl is being used as
1011+
// main libc, e.g. in Alpine, Gentoo and OpenWRT
1012+
Self {
1013+
staticlib: true,
1014+
cdylib: target.os != "none" && target.env != "musl",
1015+
}
1016+
}
1017+
1018+
fn from_args(target: &target::Target, args: &ArgMatches) -> Self {
1019+
match args.get_many::<String>("library-type") {
1020+
Some(library_types) => Self::from_library_types(target, library_types),
1021+
None => Self::from_target(target),
1022+
}
1023+
}
1024+
1025+
pub(crate) fn from_library_types<S: AsRef<str>>(
1026+
target: &target::Target,
1027+
library_types: impl Iterator<Item = S>,
1028+
) -> Self {
1029+
let (mut staticlib, mut cdylib) = (false, false);
1030+
1031+
for library_type in library_types {
1032+
staticlib |= library_type.as_ref() == "staticlib";
1033+
cdylib |= library_type.as_ref() == "cdylib";
1034+
}
1035+
1036+
// when os is none, a cdylib cannot be produced
1037+
// forcing a cdylib for musl is allowed here (see [`LibraryTypes::from_target`])
1038+
cdylib &= target.os != "none";
1039+
1040+
Self { staticlib, cdylib }
1041+
}
1042+
1043+
const fn only_staticlib(self) -> bool {
1044+
self.staticlib && !self.cdylib
1045+
}
1046+
1047+
const fn only_cdylib(self) -> bool {
1048+
self.cdylib && !self.staticlib
1049+
}
1050+
}
1051+
10011052
pub fn cbuild(
10021053
ws: &mut Workspace,
10031054
config: &GlobalContext,
@@ -1006,28 +1057,15 @@ pub fn cbuild(
10061057
) -> anyhow::Result<(Vec<CPackage>, CompileOptions)> {
10071058
deprecation_warnings(ws, args)?;
10081059

1009-
let rustc = config.load_global_rustc(Some(ws))?;
1010-
let targets = args.targets()?;
1011-
let (target, is_target_overridden) = match targets.len() {
1012-
0 => (rustc.host.to_string(), false),
1013-
1 => (targets[0].to_string(), true),
1014-
_ => {
1015-
anyhow::bail!("Multiple targets not supported yet");
1016-
}
1060+
let (target, is_target_overridden) = match args.targets()?.as_slice() {
1061+
[] => (config.load_global_rustc(Some(ws))?.host.to_string(), false),
1062+
[target] => (target.to_string(), true),
1063+
[..] => anyhow::bail!("Multiple targets not supported yet"),
10171064
};
10181065

10191066
let rustc_target = target::Target::new(Some(&target), is_target_overridden)?;
10201067

1021-
let default_kind = || match (rustc_target.os.as_str(), rustc_target.env.as_str()) {
1022-
("none", _) | (_, "musl") => vec!["staticlib"],
1023-
_ => vec!["staticlib", "cdylib"],
1024-
};
1025-
1026-
let libkinds = args
1027-
.get_many::<String>("library-type")
1028-
.map_or_else(default_kind, |v| v.map(String::as_str).collect::<Vec<_>>());
1029-
let only_staticlib = !libkinds.contains(&"cdylib");
1030-
let only_cdylib = !libkinds.contains(&"staticlib");
1068+
let library_types = LibraryTypes::from_args(&rustc_target, args);
10311069

10321070
let profile = args.get_profile_name(default_profile, ProfileChecking::Custom)?;
10331071

@@ -1043,10 +1081,7 @@ pub fn cbuild(
10431081
.join(PathBuf::from(target))
10441082
.join(profiles.get_dir_name());
10451083

1046-
let capi_feature = InternedString::new("capi");
1047-
10481084
let mut members = Vec::new();
1049-
10501085
let mut pristine = false;
10511086

10521087
let requested: Vec<_> = compile_opts
@@ -1056,22 +1091,23 @@ pub fn cbuild(
10561091
.map(|p| p.package_id())
10571092
.collect();
10581093

1059-
for m in ws.members_mut().filter(|m| {
1060-
m.library().is_some()
1061-
&& m.summary().features().contains_key(&capi_feature)
1062-
&& requested.contains(&m.package_id())
1063-
}) {
1064-
let cpkg = CPackage::from_package(m, args, &libkinds, &rustc_target, &root_output)?;
1094+
let capi_feature = InternedString::new("capi");
1095+
let is_relevant_package = |package: &Package| {
1096+
package.library().is_some()
1097+
&& package.summary().features().contains_key(&capi_feature)
1098+
&& requested.contains(&package.package_id())
1099+
};
1100+
1101+
for m in ws.members_mut().filter(|p| is_relevant_package(p)) {
1102+
let cpkg = CPackage::from_package(m, args, library_types, &rustc_target, &root_output)?;
10651103

1066-
pristine = pristine || cpkg.finger_print.load_previous().is_err();
1104+
pristine |= cpkg.finger_print.load_previous().is_err();
10671105

10681106
members.push(cpkg);
10691107
}
10701108

1071-
if pristine {
1072-
// If the cache is somehow missing force a full rebuild;
1073-
compile_opts.build_config.force_rebuild = true;
1074-
}
1109+
// If the cache is somehow missing force a full rebuild;
1110+
compile_opts.build_config.force_rebuild |= pristine;
10751111

10761112
let exec = Arc::new(Exec::default());
10771113
let out_dirs = compile_with_exec(
@@ -1111,7 +1147,7 @@ pub fn cbuild(
11111147
// if the hash value does not match.
11121148
if new_build && !cpkg.finger_print.is_valid() {
11131149
let name = &cpkg.capi_config.library.name;
1114-
let static_libs = if only_cdylib {
1150+
let static_libs = if library_types.only_cdylib() {
11151151
"".to_string()
11161152
} else {
11171153
exec.link_line
@@ -1126,14 +1162,14 @@ pub fn cbuild(
11261162
let build_targets = &cpkg.build_targets;
11271163

11281164
let mut pc = PkgConfig::from_workspace(name, &cpkg.install_paths, args, capi_config);
1129-
if only_staticlib {
1165+
if library_types.only_staticlib() {
11301166
pc.add_lib(&static_libs);
11311167
}
11321168
pc.add_lib_private(&static_libs);
11331169

11341170
build_pc_files(ws, &capi_config.pkg_config.filename, &root_output, &pc)?;
11351171

1136-
if !only_staticlib && capi_config.library.import_library {
1172+
if !library_types.only_staticlib() && capi_config.library.import_library {
11371173
let lib_name = name;
11381174
build_def_file(ws, lib_name, &rustc_target, &root_output)?;
11391175
build_implib_file(ws, lib_name, &rustc_target, &root_output)?;
@@ -1159,7 +1195,7 @@ pub fn cbuild(
11591195
&name.replace('-', "_"),
11601196
&rustc_target,
11611197
&root_output,
1162-
&libkinds,
1198+
library_types,
11631199
capi_config,
11641200
args.get_flag("meson"),
11651201
)?;

src/build_targets.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::ffi::OsString;
22
use std::path::{Path, PathBuf};
33

4-
use crate::build::{CApiConfig, InstallTarget};
4+
use crate::build::{CApiConfig, InstallTarget, LibraryTypes};
55
use crate::install::LibType;
66
use crate::target::Target;
77

@@ -63,7 +63,7 @@ impl BuildTargets {
6363
name: &str,
6464
target: &Target,
6565
targetdir: &Path,
66-
libkinds: &[&str],
66+
library_types: LibraryTypes,
6767
capi_config: &CApiConfig,
6868
use_meson_naming_convention: bool,
6969
) -> anyhow::Result<BuildTargets> {
@@ -82,15 +82,11 @@ impl BuildTargets {
8282
));
8383
};
8484

85-
// Bare metal does not support shared objects
86-
let build_shared_lib = libkinds.contains(&"cdylib") && target.os.as_str() != "none";
87-
let build_static_lib = libkinds.contains(&"staticlib");
88-
8985
Ok(BuildTargets {
9086
pc,
9187
include,
92-
static_lib: build_static_lib.then_some(file_names.static_lib),
93-
shared_lib: build_shared_lib.then_some(file_names.shared_lib),
88+
static_lib: library_types.staticlib.then_some(file_names.static_lib),
89+
shared_lib: library_types.cdylib.then_some(file_names.shared_lib),
9490
impl_lib: file_names.impl_lib,
9591
debug_info: file_names.debug_info,
9692
def: file_names.def,

0 commit comments

Comments
 (0)