feat: add support for customizable installation directories in build flags
This commit is contained in:
@@ -7,6 +7,11 @@ cc = "gcc"
|
||||
cflags = ["-O2"]
|
||||
cflags += ["-pipe"]
|
||||
|
||||
# Optional install directory overrides for supported builders
|
||||
#bindir = "/usr/bin"
|
||||
#libdir = "/usr/lib"
|
||||
#sysconfdir = "/etc"
|
||||
|
||||
# Default LDFLAGS
|
||||
ldflags = ["-Wl,-O1"]
|
||||
|
||||
|
||||
@@ -13,6 +13,20 @@ cflags = ["-O2"]
|
||||
# Append additional flags (demonstrates += append support)
|
||||
cflags += ["-g"]
|
||||
|
||||
# Optional install directory overrides for supported builders
|
||||
#bindir = "/usr/bin"
|
||||
#sbindir = "/usr/bin"
|
||||
#libdir = "/usr/lib"
|
||||
#libexecdir = "/usr/lib"
|
||||
#sysconfdir = "/etc"
|
||||
#localstatedir = "/var"
|
||||
#sharedstatedir = "/var/lib"
|
||||
#includedir = "/usr/include"
|
||||
#datarootdir = "/usr/share"
|
||||
#datadir = "/usr/share"
|
||||
#mandir = "/usr/share/man"
|
||||
#infodir = "/usr/share/info"
|
||||
|
||||
# Linker flags
|
||||
ldflags = ["-Wl,-O1"]
|
||||
|
||||
|
||||
@@ -8,3 +8,8 @@ cc = "clang"
|
||||
cflags = ["-O2"]
|
||||
cflags += ["-g"]
|
||||
carch = "x86_64"
|
||||
|
||||
# Optional install directory overrides for supported builders
|
||||
#bindir = "/usr/local/bin"
|
||||
#sbindir = "/usr/local/sbin"
|
||||
#libdir = "/usr/local/lib"
|
||||
|
||||
+13
-18
@@ -442,25 +442,20 @@ fn default_configure_install_dirs(
|
||||
flags: &crate::package::BuildFlags,
|
||||
help_text: Option<&str>,
|
||||
) -> Vec<String> {
|
||||
let libdir = if flags.lib32_variant {
|
||||
"/usr/lib32"
|
||||
} else {
|
||||
"/usr/lib"
|
||||
};
|
||||
let bindir = nonempty_trimmed(&flags.bindir).unwrap_or("/usr/bin");
|
||||
let dirs = crate::builder::install_dirs(flags);
|
||||
let defaults = [
|
||||
("--bindir", bindir),
|
||||
("--sbindir", "/usr/bin"),
|
||||
("--libdir", libdir),
|
||||
("--libexecdir", libdir),
|
||||
("--sysconfdir", "/etc"),
|
||||
("--localstatedir", "/var"),
|
||||
("--sharedstatedir", "/var/lib"),
|
||||
("--includedir", "/usr/include"),
|
||||
("--datarootdir", "/usr/share"),
|
||||
("--datadir", "/usr/share"),
|
||||
("--mandir", "/usr/share/man"),
|
||||
("--infodir", "/usr/share/info"),
|
||||
("--bindir", dirs.bindir),
|
||||
("--sbindir", dirs.sbindir),
|
||||
("--libdir", dirs.libdir),
|
||||
("--libexecdir", dirs.libexecdir),
|
||||
("--sysconfdir", dirs.sysconfdir),
|
||||
("--localstatedir", dirs.localstatedir),
|
||||
("--sharedstatedir", dirs.sharedstatedir),
|
||||
("--includedir", dirs.includedir),
|
||||
("--datarootdir", dirs.datarootdir),
|
||||
("--datadir", dirs.datadir),
|
||||
("--mandir", dirs.mandir),
|
||||
("--infodir", dirs.infodir),
|
||||
];
|
||||
|
||||
defaults
|
||||
|
||||
+134
-8
@@ -35,12 +35,8 @@ pub fn build(
|
||||
let env_vars = crate::builder::standard_build_env(spec, cross, true, export_compiler_flags);
|
||||
|
||||
// Extract prefix from configure flags (cmake-style -DCMAKE_INSTALL_PREFIX=)
|
||||
let prefix = flags
|
||||
.configure
|
||||
.iter()
|
||||
.find(|s| s.contains("CMAKE_INSTALL_PREFIX="))
|
||||
.and_then(|s| s.split('=').nth(1))
|
||||
.unwrap_or(&flags.prefix);
|
||||
let prefix = cmake_cache_entry_value(&flags.configure, "CMAKE_INSTALL_PREFIX")
|
||||
.unwrap_or(flags.prefix.as_str());
|
||||
|
||||
// Generate toolchain file if cross-compiling
|
||||
let toolchain_file = if let Some(cc_cfg) = cross {
|
||||
@@ -64,6 +60,9 @@ pub fn build(
|
||||
cmake_cmd.arg("-B").arg(&build_dir);
|
||||
cmake_cmd.arg(format!("-DCMAKE_INSTALL_PREFIX={}", prefix));
|
||||
cmake_cmd.arg("-DCMAKE_BUILD_TYPE=Release");
|
||||
for arg in cmake_install_dir_args(flags) {
|
||||
cmake_cmd.arg(arg);
|
||||
}
|
||||
|
||||
// Add toolchain file for cross-compilation
|
||||
if let Some(ref tf) = toolchain_file {
|
||||
@@ -283,12 +282,47 @@ fn cmake_configure_flags_specify_generator(flags: &[String]) -> bool {
|
||||
}
|
||||
|
||||
fn cmake_configure_flags_set_make_program(flags: &[String]) -> bool {
|
||||
flags.iter().any(|flag| {
|
||||
cmake_cache_entry_value(flags, "CMAKE_MAKE_PROGRAM").is_some()
|
||||
}
|
||||
|
||||
fn cmake_cache_entry_value<'a>(flags: &'a [String], variable: &str) -> Option<&'a str> {
|
||||
let plain_prefix = format!("-D{variable}=");
|
||||
let typed_prefix = format!("-D{variable}:");
|
||||
flags.iter().find_map(|flag| {
|
||||
let trimmed = flag.trim();
|
||||
trimmed.starts_with("-DCMAKE_MAKE_PROGRAM=")
|
||||
if let Some(value) = trimmed.strip_prefix(&plain_prefix) {
|
||||
return Some(value);
|
||||
}
|
||||
trimmed
|
||||
.strip_prefix(&typed_prefix)
|
||||
.and_then(|rest| rest.split_once('=').map(|(_, value)| value))
|
||||
})
|
||||
}
|
||||
|
||||
fn cmake_install_dir_args(flags: &crate::package::BuildFlags) -> Vec<String> {
|
||||
let dirs = crate::builder::install_dirs(flags);
|
||||
let defaults = [
|
||||
("CMAKE_INSTALL_BINDIR", dirs.bindir),
|
||||
("CMAKE_INSTALL_SBINDIR", dirs.sbindir),
|
||||
("CMAKE_INSTALL_LIBDIR", dirs.libdir),
|
||||
("CMAKE_INSTALL_LIBEXECDIR", dirs.libexecdir),
|
||||
("CMAKE_INSTALL_SYSCONFDIR", dirs.sysconfdir),
|
||||
("CMAKE_INSTALL_LOCALSTATEDIR", dirs.localstatedir),
|
||||
("CMAKE_INSTALL_SHAREDSTATEDIR", dirs.sharedstatedir),
|
||||
("CMAKE_INSTALL_INCLUDEDIR", dirs.includedir),
|
||||
("CMAKE_INSTALL_DATAROOTDIR", dirs.datarootdir),
|
||||
("CMAKE_INSTALL_DATADIR", dirs.datadir),
|
||||
("CMAKE_INSTALL_MANDIR", dirs.mandir),
|
||||
("CMAKE_INSTALL_INFODIR", dirs.infodir),
|
||||
];
|
||||
|
||||
defaults
|
||||
.into_iter()
|
||||
.filter(|(variable, _)| cmake_cache_entry_value(&flags.configure, variable).is_none())
|
||||
.map(|(variable, value)| format!("-D{variable}={value}"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn num_cpus() -> usize {
|
||||
std::thread::available_parallelism()
|
||||
.map(|n| n.get())
|
||||
@@ -429,6 +463,98 @@ mod tests {
|
||||
]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_cache_entry_value_supports_plain_and_typed_entries() {
|
||||
let flags = vec![
|
||||
"-DCMAKE_INSTALL_PREFIX=/usr".to_string(),
|
||||
"-DCMAKE_INSTALL_LIBDIR:PATH=/usr/lib64".to_string(),
|
||||
];
|
||||
|
||||
assert_eq!(
|
||||
cmake_cache_entry_value(&flags, "CMAKE_INSTALL_PREFIX"),
|
||||
Some("/usr")
|
||||
);
|
||||
assert_eq!(
|
||||
cmake_cache_entry_value(&flags, "CMAKE_INSTALL_LIBDIR"),
|
||||
Some("/usr/lib64")
|
||||
);
|
||||
assert_eq!(
|
||||
cmake_cache_entry_value(&flags, "CMAKE_INSTALL_BINDIR"),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_install_dir_args_include_defaults() {
|
||||
let args = cmake_install_dir_args(&BuildFlags::default());
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_INSTALL_BINDIR=/usr/bin"));
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_INSTALL_SBINDIR=/usr/bin"));
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_INSTALL_LIBDIR=/usr/lib"));
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_LIBEXECDIR=/usr/lib")
|
||||
);
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_INSTALL_SYSCONFDIR=/etc"));
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_LOCALSTATEDIR=/var")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_SHAREDSTATEDIR=/var/lib")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_INCLUDEDIR=/usr/include")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_DATAROOTDIR=/usr/share")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_DATADIR=/usr/share")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_MANDIR=/usr/share/man")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_INSTALL_INFODIR=/usr/share/info")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_install_dir_args_respect_explicit_user_overrides() {
|
||||
let flags = BuildFlags {
|
||||
configure: vec![
|
||||
"-DCMAKE_INSTALL_SBINDIR=/sbin".to_string(),
|
||||
"-DCMAKE_INSTALL_LIBDIR:PATH=/custom/lib".to_string(),
|
||||
"-DCMAKE_INSTALL_DATADIR=/custom/share".to_string(),
|
||||
],
|
||||
..BuildFlags::default()
|
||||
};
|
||||
|
||||
let args = cmake_install_dir_args(&flags);
|
||||
assert!(
|
||||
!args
|
||||
.iter()
|
||||
.any(|a| a.starts_with("-DCMAKE_INSTALL_SBINDIR="))
|
||||
);
|
||||
assert!(
|
||||
!args
|
||||
.iter()
|
||||
.any(|a| a.starts_with("-DCMAKE_INSTALL_LIBDIR="))
|
||||
);
|
||||
assert!(
|
||||
!args
|
||||
.iter()
|
||||
.any(|a| a.starts_with("-DCMAKE_INSTALL_DATADIR="))
|
||||
);
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_INSTALL_BINDIR=/usr/bin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_actual_src_prefers_srcdir_then_specdir_and_handles_absolute() {
|
||||
let tmp = tempdir().unwrap();
|
||||
|
||||
@@ -162,10 +162,29 @@ fn meson_setup_args(
|
||||
env_vars: &[(String, String)],
|
||||
) -> Vec<String> {
|
||||
let mut args = Vec::new();
|
||||
let dirs = crate::builder::install_dirs(flags);
|
||||
|
||||
if !has_option(&flags.configure, "--prefix") {
|
||||
args.push(format!("--prefix={}", flags.prefix));
|
||||
}
|
||||
for (option, value) in [
|
||||
("--bindir", dirs.bindir),
|
||||
("--sbindir", dirs.sbindir),
|
||||
("--libdir", dirs.libdir),
|
||||
("--libexecdir", dirs.libexecdir),
|
||||
("--sysconfdir", dirs.sysconfdir),
|
||||
("--localstatedir", dirs.localstatedir),
|
||||
("--sharedstatedir", dirs.sharedstatedir),
|
||||
("--includedir", dirs.includedir),
|
||||
("--datarootdir", dirs.datarootdir),
|
||||
("--datadir", dirs.datadir),
|
||||
("--mandir", dirs.mandir),
|
||||
("--infodir", dirs.infodir),
|
||||
] {
|
||||
if !has_option(&flags.configure, option) {
|
||||
args.push(format!("{option}={value}"));
|
||||
}
|
||||
}
|
||||
if !has_option(&flags.configure, "--buildtype") {
|
||||
args.push("--buildtype=release".to_string());
|
||||
}
|
||||
@@ -275,6 +294,23 @@ mod tests {
|
||||
assert!(args.iter().any(|a| a == "--buildtype=release"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meson_setup_args_include_install_dirs() {
|
||||
let args = meson_setup_args(&BuildFlags::default(), None, &[]);
|
||||
assert!(args.iter().any(|a| a == "--bindir=/usr/bin"));
|
||||
assert!(args.iter().any(|a| a == "--sbindir=/usr/bin"));
|
||||
assert!(args.iter().any(|a| a == "--libdir=/usr/lib"));
|
||||
assert!(args.iter().any(|a| a == "--libexecdir=/usr/lib"));
|
||||
assert!(args.iter().any(|a| a == "--sysconfdir=/etc"));
|
||||
assert!(args.iter().any(|a| a == "--localstatedir=/var"));
|
||||
assert!(args.iter().any(|a| a == "--sharedstatedir=/var/lib"));
|
||||
assert!(args.iter().any(|a| a == "--includedir=/usr/include"));
|
||||
assert!(args.iter().any(|a| a == "--datarootdir=/usr/share"));
|
||||
assert!(args.iter().any(|a| a == "--datadir=/usr/share"));
|
||||
assert!(args.iter().any(|a| a == "--mandir=/usr/share/man"));
|
||||
assert!(args.iter().any(|a| a == "--infodir=/usr/share/info"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meson_setup_args_honor_explicit_prefix() {
|
||||
let flags = BuildFlags {
|
||||
@@ -288,6 +324,24 @@ mod tests {
|
||||
assert!(args.iter().any(|a| a == "--prefix=/opt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meson_setup_args_honor_explicit_install_dirs() {
|
||||
let flags = BuildFlags {
|
||||
configure: vec![
|
||||
"--sbindir=/sbin".to_string(),
|
||||
"--libdir=/custom/lib".to_string(),
|
||||
"--datadir=/custom/share".to_string(),
|
||||
],
|
||||
..BuildFlags::default()
|
||||
};
|
||||
|
||||
let args = meson_setup_args(&flags, None, &[]);
|
||||
assert!(!args.iter().any(|a| a == "--sbindir=/usr/bin"));
|
||||
assert!(!args.iter().any(|a| a == "--libdir=/usr/lib"));
|
||||
assert!(!args.iter().any(|a| a == "--datadir=/usr/share"));
|
||||
assert!(args.iter().any(|a| a == "--bindir=/usr/bin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_resolve_build_dir_uses_flag() {
|
||||
let flags = BuildFlags {
|
||||
|
||||
@@ -20,6 +20,22 @@ use std::process::{Command, Stdio};
|
||||
|
||||
pub type EnvVars = Vec<(String, String)>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct InstallDirs {
|
||||
pub bindir: String,
|
||||
pub sbindir: String,
|
||||
pub libdir: String,
|
||||
pub libexecdir: String,
|
||||
pub sysconfdir: String,
|
||||
pub localstatedir: String,
|
||||
pub sharedstatedir: String,
|
||||
pub includedir: String,
|
||||
pub datarootdir: String,
|
||||
pub datadir: String,
|
||||
pub mandir: String,
|
||||
pub infodir: String,
|
||||
}
|
||||
|
||||
pub fn set_env_var(env_vars: &mut EnvVars, key: &str, value: impl Into<String>) {
|
||||
let value = value.into();
|
||||
if let Some((_, existing)) = env_vars.iter_mut().find(|(k, _)| k == key) {
|
||||
@@ -29,6 +45,46 @@ pub fn set_env_var(env_vars: &mut EnvVars, key: &str, value: impl Into<String>)
|
||||
}
|
||||
}
|
||||
|
||||
fn default_libdir_for_variant(lib32_variant: bool) -> &'static str {
|
||||
if lib32_variant {
|
||||
"/usr/lib32"
|
||||
} else {
|
||||
"/usr/lib"
|
||||
}
|
||||
}
|
||||
|
||||
fn configured_install_dir(value: &str, default: &str) -> String {
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
default.to_string()
|
||||
} else {
|
||||
trimmed.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn install_dirs(flags: &crate::package::BuildFlags) -> InstallDirs {
|
||||
let libdir = configured_install_dir(
|
||||
&flags.libdir,
|
||||
default_libdir_for_variant(flags.lib32_variant),
|
||||
);
|
||||
let datarootdir = configured_install_dir(&flags.datarootdir, "/usr/share");
|
||||
|
||||
InstallDirs {
|
||||
bindir: configured_install_dir(&flags.bindir, "/usr/bin"),
|
||||
sbindir: configured_install_dir(&flags.sbindir, "/usr/bin"),
|
||||
libdir: libdir.clone(),
|
||||
libexecdir: configured_install_dir(&flags.libexecdir, &libdir),
|
||||
sysconfdir: configured_install_dir(&flags.sysconfdir, "/etc"),
|
||||
localstatedir: configured_install_dir(&flags.localstatedir, "/var"),
|
||||
sharedstatedir: configured_install_dir(&flags.sharedstatedir, "/var/lib"),
|
||||
includedir: configured_install_dir(&flags.includedir, "/usr/include"),
|
||||
datarootdir: datarootdir.clone(),
|
||||
datadir: configured_install_dir(&flags.datadir, &datarootdir),
|
||||
mandir: configured_install_dir(&flags.mandir, "/usr/share/man"),
|
||||
infodir: configured_install_dir(&flags.infodir, "/usr/share/info"),
|
||||
}
|
||||
}
|
||||
|
||||
fn compiler_flag_sets(
|
||||
flags: &crate::package::BuildFlags,
|
||||
) -> (Vec<String>, Vec<String>, Vec<String>, Vec<String>) {
|
||||
@@ -551,4 +607,38 @@ mod tests {
|
||||
"expected default CC to take precedence over passthrough CC"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_dirs_use_defaults_and_lib32_fallbacks() {
|
||||
let default_dirs = install_dirs(&BuildFlags::default());
|
||||
assert_eq!(default_dirs.bindir, "/usr/bin");
|
||||
assert_eq!(default_dirs.sbindir, "/usr/bin");
|
||||
assert_eq!(default_dirs.libdir, "/usr/lib");
|
||||
assert_eq!(default_dirs.libexecdir, "/usr/lib");
|
||||
assert_eq!(default_dirs.datarootdir, "/usr/share");
|
||||
assert_eq!(default_dirs.datadir, "/usr/share");
|
||||
|
||||
let lib32_dirs = install_dirs(&BuildFlags {
|
||||
lib32_variant: true,
|
||||
..BuildFlags::default()
|
||||
});
|
||||
assert_eq!(lib32_dirs.libdir, "/usr/lib32");
|
||||
assert_eq!(lib32_dirs.libexecdir, "/usr/lib32");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_dirs_respect_explicit_overrides_and_derived_defaults() {
|
||||
let dirs = install_dirs(&BuildFlags {
|
||||
bindir: "/opt/bin".into(),
|
||||
libdir: "/opt/lib64".into(),
|
||||
datarootdir: "/opt/share-root".into(),
|
||||
..BuildFlags::default()
|
||||
});
|
||||
|
||||
assert_eq!(dirs.bindir, "/opt/bin");
|
||||
assert_eq!(dirs.libdir, "/opt/lib64");
|
||||
assert_eq!(dirs.libexecdir, "/opt/lib64");
|
||||
assert_eq!(dirs.datarootdir, "/opt/share-root");
|
||||
assert_eq!(dirs.datadir, "/opt/share-root");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1274,6 +1274,72 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result<String> {
|
||||
Value::String(spec.build.flags.bindir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.sbindir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"sbindir".into(),
|
||||
Value::String(spec.build.flags.sbindir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.libdir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"libdir".into(),
|
||||
Value::String(spec.build.flags.libdir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.libexecdir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"libexecdir".into(),
|
||||
Value::String(spec.build.flags.libexecdir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.sysconfdir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"sysconfdir".into(),
|
||||
Value::String(spec.build.flags.sysconfdir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.localstatedir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"localstatedir".into(),
|
||||
Value::String(spec.build.flags.localstatedir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.sharedstatedir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"sharedstatedir".into(),
|
||||
Value::String(spec.build.flags.sharedstatedir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.includedir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"includedir".into(),
|
||||
Value::String(spec.build.flags.includedir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.datarootdir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"datarootdir".into(),
|
||||
Value::String(spec.build.flags.datarootdir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.datadir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"datadir".into(),
|
||||
Value::String(spec.build.flags.datadir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.mandir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"mandir".into(),
|
||||
Value::String(spec.build.flags.mandir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.infodir.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"infodir".into(),
|
||||
Value::String(spec.build.flags.infodir.clone()),
|
||||
);
|
||||
}
|
||||
if !spec.build.flags.binary_type.is_empty() {
|
||||
flags_tbl.insert(
|
||||
"binary_type".into(),
|
||||
@@ -1497,6 +1563,17 @@ mod tests {
|
||||
ltoflags: vec!["-flto=auto".into()],
|
||||
target: "x86_64-unknown-linux-gnu".into(),
|
||||
keep: vec!["etc/locale.gen".into()],
|
||||
sbindir: "/usr/sbin".into(),
|
||||
libdir: "/usr/lib64".into(),
|
||||
libexecdir: "/usr/libexec".into(),
|
||||
sysconfdir: "/etc/custom".into(),
|
||||
localstatedir: "/var/custom".into(),
|
||||
sharedstatedir: "/var/lib/custom".into(),
|
||||
includedir: "/usr/include/custom".into(),
|
||||
datarootdir: "/usr/share/root".into(),
|
||||
datadir: "/usr/share/custom".into(),
|
||||
mandir: "/usr/share/custom/man".into(),
|
||||
infodir: "/usr/share/custom/info".into(),
|
||||
use_lto: false,
|
||||
no_flags: true,
|
||||
no_strip: true,
|
||||
@@ -1560,6 +1637,17 @@ mod tests {
|
||||
assert!(toml.contains("target = \"x86_64-unknown-linux-gnu\""));
|
||||
assert!(toml.contains("keep = ["));
|
||||
assert!(toml.contains("\"etc/locale.gen\""));
|
||||
assert!(toml.contains("sbindir = \"/usr/sbin\""));
|
||||
assert!(toml.contains("libdir = \"/usr/lib64\""));
|
||||
assert!(toml.contains("libexecdir = \"/usr/libexec\""));
|
||||
assert!(toml.contains("sysconfdir = \"/etc/custom\""));
|
||||
assert!(toml.contains("localstatedir = \"/var/custom\""));
|
||||
assert!(toml.contains("sharedstatedir = \"/var/lib/custom\""));
|
||||
assert!(toml.contains("includedir = \"/usr/include/custom\""));
|
||||
assert!(toml.contains("datarootdir = \"/usr/share/root\""));
|
||||
assert!(toml.contains("datadir = \"/usr/share/custom\""));
|
||||
assert!(toml.contains("mandir = \"/usr/share/custom/man\""));
|
||||
assert!(toml.contains("infodir = \"/usr/share/custom/info\""));
|
||||
assert!(toml.contains("use_lto = false"));
|
||||
assert!(toml.contains("no_flags = true"));
|
||||
assert!(toml.contains("no_strip = true"));
|
||||
|
||||
@@ -342,6 +342,66 @@ impl PackageSpec {
|
||||
self.build.flags.prefix = s.to_string();
|
||||
}
|
||||
}
|
||||
"bindir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.bindir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sbindir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.sbindir = s.to_string();
|
||||
}
|
||||
}
|
||||
"libdir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.libdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"libexecdir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.libexecdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sysconfdir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.sysconfdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"localstatedir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.localstatedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sharedstatedir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.sharedstatedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"includedir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.includedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"datarootdir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.datarootdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"datadir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.datadir = s.to_string();
|
||||
}
|
||||
}
|
||||
"mandir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.mandir = s.to_string();
|
||||
}
|
||||
}
|
||||
"infodir" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.infodir = s.to_string();
|
||||
}
|
||||
}
|
||||
"chost" => {
|
||||
if let Some(s) = v.as_str() {
|
||||
self.build.flags.chost = s.to_string();
|
||||
@@ -886,6 +946,66 @@ impl PackageSpec {
|
||||
self.build.flags.prefix = s.to_string();
|
||||
}
|
||||
}
|
||||
"bindir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.bindir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sbindir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.sbindir = s.to_string();
|
||||
}
|
||||
}
|
||||
"libdir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.libdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"libexecdir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.libexecdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sysconfdir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.sysconfdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"localstatedir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.localstatedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"sharedstatedir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.sharedstatedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"includedir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.includedir = s.to_string();
|
||||
}
|
||||
}
|
||||
"datarootdir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.datarootdir = s.to_string();
|
||||
}
|
||||
}
|
||||
"datadir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.datadir = s.to_string();
|
||||
}
|
||||
}
|
||||
"mandir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.mandir = s.to_string();
|
||||
}
|
||||
}
|
||||
"infodir" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.infodir = s.to_string();
|
||||
}
|
||||
}
|
||||
"chost" => {
|
||||
if let Some(s) = values.last().and_then(|v| v.as_str()) {
|
||||
self.build.flags.chost = s.to_string();
|
||||
@@ -1773,6 +1893,11 @@ cc = "my-cc"
|
||||
cflags = ["-O2"]
|
||||
cxxflags = ["-O2", "-pipe"]
|
||||
passthrough_env = ["RUSTFLAGS"]
|
||||
bindir = "/opt/bin"
|
||||
sbindir = "/opt/sbin"
|
||||
libdir = "/opt/lib64"
|
||||
sysconfdir = "/opt/etc"
|
||||
datarootdir = "/opt/share-root"
|
||||
makeflags = "-j8"
|
||||
make_vars = ["V=1"]
|
||||
make_dirs = ["lib"]
|
||||
@@ -1867,6 +1992,14 @@ post_configure = ["echo configured"]
|
||||
"build.flags.configure_file".to_string(),
|
||||
vec![toml::Value::String("build-aux/configure".to_string())],
|
||||
);
|
||||
config.appends.insert(
|
||||
"build.flags.libexecdir".to_string(),
|
||||
vec![toml::Value::String("/opt/libexec".to_string())],
|
||||
);
|
||||
config.appends.insert(
|
||||
"build.flags.datadir".to_string(),
|
||||
vec![toml::Value::String("/opt/share-data".to_string())],
|
||||
);
|
||||
config.appends.insert(
|
||||
"build.flags.config-setting".to_string(),
|
||||
vec![toml::Value::String(
|
||||
@@ -1933,6 +2066,13 @@ post_configure = ["echo configured"]
|
||||
.passthrough_env
|
||||
.contains(&"CARGO_HOME".to_string())
|
||||
);
|
||||
assert_eq!(spec.build.flags.bindir, "/opt/bin");
|
||||
assert_eq!(spec.build.flags.sbindir, "/opt/sbin");
|
||||
assert_eq!(spec.build.flags.libdir, "/opt/lib64");
|
||||
assert_eq!(spec.build.flags.libexecdir, "/opt/libexec");
|
||||
assert_eq!(spec.build.flags.sysconfdir, "/opt/etc");
|
||||
assert_eq!(spec.build.flags.datarootdir, "/opt/share-root");
|
||||
assert_eq!(spec.build.flags.datadir, "/opt/share-data");
|
||||
assert_eq!(spec.build.flags.makeflags, "-j8 --output-sync=target");
|
||||
assert!(spec.build.flags.make_vars.contains(&"V=1".to_string()));
|
||||
assert!(spec.build.flags.make_dirs.contains(&"lib".to_string()));
|
||||
@@ -2276,6 +2416,61 @@ configure_file = "build-aux/configure"
|
||||
assert_eq!(spec.build.flags.configure_file, "build-aux/configure");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_install_dirs_from_spec() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let path = tmp.path().join("pkg.toml");
|
||||
|
||||
std::fs::write(
|
||||
&path,
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "1.0"
|
||||
description = "d"
|
||||
homepage = "h"
|
||||
license = "MIT"
|
||||
|
||||
[source]
|
||||
url = "https://example.com/foo.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "foo"
|
||||
|
||||
[build]
|
||||
type = "cmake"
|
||||
|
||||
[build.flags]
|
||||
bindir = "/custom/bin"
|
||||
sbindir = "/custom/sbin"
|
||||
libdir = "/custom/lib64"
|
||||
libexecdir = "/custom/libexec"
|
||||
sysconfdir = "/custom/etc"
|
||||
localstatedir = "/custom/var"
|
||||
sharedstatedir = "/custom/var/lib"
|
||||
includedir = "/custom/include"
|
||||
datarootdir = "/custom/share-root"
|
||||
datadir = "/custom/share"
|
||||
mandir = "/custom/share/man"
|
||||
infodir = "/custom/share/info"
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let spec = PackageSpec::from_file(&path).unwrap();
|
||||
assert_eq!(spec.build.flags.bindir, "/custom/bin");
|
||||
assert_eq!(spec.build.flags.sbindir, "/custom/sbin");
|
||||
assert_eq!(spec.build.flags.libdir, "/custom/lib64");
|
||||
assert_eq!(spec.build.flags.libexecdir, "/custom/libexec");
|
||||
assert_eq!(spec.build.flags.sysconfdir, "/custom/etc");
|
||||
assert_eq!(spec.build.flags.localstatedir, "/custom/var");
|
||||
assert_eq!(spec.build.flags.sharedstatedir, "/custom/var/lib");
|
||||
assert_eq!(spec.build.flags.includedir, "/custom/include");
|
||||
assert_eq!(spec.build.flags.datarootdir, "/custom/share-root");
|
||||
assert_eq!(spec.build.flags.datadir, "/custom/share");
|
||||
assert_eq!(spec.build.flags.mandir, "/custom/share/man");
|
||||
assert_eq!(spec.build.flags.infodir, "/custom/share/info");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_lib32_build_flags_from_spec() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
@@ -3262,6 +3457,45 @@ pub struct BuildFlags {
|
||||
/// Binary installation directory relative to DESTDIR (default: /usr/bin)
|
||||
#[serde(default = "default_bindir")]
|
||||
pub bindir: String,
|
||||
/// System binary installation directory for supported builders (default: /usr/bin).
|
||||
#[serde(default)]
|
||||
pub sbindir: String,
|
||||
/// Library installation directory for supported builders.
|
||||
///
|
||||
/// Defaults to `/usr/lib`, or `/usr/lib32` for the lib32 build variant.
|
||||
#[serde(default)]
|
||||
pub libdir: String,
|
||||
/// Library helper executable installation directory for supported builders.
|
||||
///
|
||||
/// Defaults to the effective `libdir`.
|
||||
#[serde(default)]
|
||||
pub libexecdir: String,
|
||||
/// System configuration directory for supported builders (default: /etc).
|
||||
#[serde(default)]
|
||||
pub sysconfdir: String,
|
||||
/// Variable state directory for supported builders (default: /var).
|
||||
#[serde(default)]
|
||||
pub localstatedir: String,
|
||||
/// Shared variable state directory for supported builders (default: /var/lib).
|
||||
#[serde(default)]
|
||||
pub sharedstatedir: String,
|
||||
/// Header installation directory for supported builders (default: /usr/include).
|
||||
#[serde(default)]
|
||||
pub includedir: String,
|
||||
/// Data root installation directory for supported builders (default: /usr/share).
|
||||
#[serde(default)]
|
||||
pub datarootdir: String,
|
||||
/// Architecture-independent data installation directory for supported builders.
|
||||
///
|
||||
/// Defaults to the effective `datarootdir`.
|
||||
#[serde(default)]
|
||||
pub datadir: String,
|
||||
/// Manual page installation directory for supported builders (default: /usr/share/man).
|
||||
#[serde(default)]
|
||||
pub mandir: String,
|
||||
/// Info page installation directory for supported builders (default: /usr/share/info).
|
||||
#[serde(default)]
|
||||
pub infodir: String,
|
||||
|
||||
/// Subdirectory within extracted source to use as the actual source root.
|
||||
/// Useful for monorepos like llvm-project where you want to build just one component.
|
||||
@@ -3336,6 +3570,17 @@ impl Default for BuildFlags {
|
||||
rustflags: Vec::new(),
|
||||
cargs: Vec::new(),
|
||||
bindir: default_bindir(),
|
||||
sbindir: String::new(),
|
||||
libdir: String::new(),
|
||||
libexecdir: String::new(),
|
||||
sysconfdir: String::new(),
|
||||
localstatedir: String::new(),
|
||||
sharedstatedir: String::new(),
|
||||
includedir: String::new(),
|
||||
datarootdir: String::new(),
|
||||
datadir: String::new(),
|
||||
mandir: String::new(),
|
||||
infodir: String::new(),
|
||||
source_subdir: String::new(),
|
||||
build_dir: None,
|
||||
binary_type: String::new(),
|
||||
|
||||
Reference in New Issue
Block a user