164 lines
5.3 KiB
Rust
164 lines
5.3 KiB
Rust
//! Debian build types (`dpkg-buildpackage -b/-B/-A/-S/-g/-G/--build=...`)
|
|
//! and their mapping to `debian/rules` targets.
|
|
|
|
/// Build type bit flags, mirroring `Dpkg::BuildTypes`.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct BuildType(u8);
|
|
|
|
/// Source build component (`-S`, `--build=source`).
|
|
pub const SOURCE: BuildType = BuildType(0x1);
|
|
/// Arch-dependent binary build component (`-B`, `--build=any`).
|
|
pub const ARCH_DEP: BuildType = BuildType(0x2);
|
|
/// Arch-independent binary build component (`-A`, `--build=all`).
|
|
pub const ARCH_INDEP: BuildType = BuildType(0x4);
|
|
|
|
/// Any binary component.
|
|
pub const BINARY: BuildType = BuildType(ARCH_DEP.0 | ARCH_INDEP.0);
|
|
/// Normal full build: source + binaries (`-F`, default).
|
|
pub const FULL: BuildType = BuildType(SOURCE.0 | BINARY.0);
|
|
/// Source + arch-dependent (`-G`).
|
|
pub const SOURCE_ARCH_DEP: BuildType = BuildType(SOURCE.0 | ARCH_DEP.0);
|
|
/// Source + arch-indep (`-g`).
|
|
pub const SOURCE_ARCH_INDEP: BuildType = BuildType(SOURCE.0 | ARCH_INDEP.0);
|
|
|
|
impl BuildType {
|
|
/// Construct from raw bits.
|
|
pub const fn from_bits(bits: u8) -> Self {
|
|
BuildType(bits)
|
|
}
|
|
|
|
/// Raw bits.
|
|
pub const fn bits(self) -> u8 {
|
|
self.0
|
|
}
|
|
|
|
/// True if any of `other`'s components are set.
|
|
pub fn has_any(self, other: BuildType) -> bool {
|
|
self.0 & other.0 != 0
|
|
}
|
|
|
|
/// True if all of `other`'s components are set.
|
|
pub fn has_all(self, other: BuildType) -> bool {
|
|
self.0 & other.0 == other.0
|
|
}
|
|
|
|
/// True if none of `other`'s components are set.
|
|
pub fn has_none(self, other: BuildType) -> bool {
|
|
self.0 & other.0 == 0
|
|
}
|
|
|
|
/// Parse a comma-separated `--build=<type>[,...]` option value.
|
|
///
|
|
/// Valid components: `full`, `source`, `binary`, `any`, `all`.
|
|
pub fn from_options(value: &str) -> Result<BuildType, String> {
|
|
let mut result = BuildType(0);
|
|
for part in value.split(',') {
|
|
match part.trim() {
|
|
"full" => result = FULL,
|
|
"source" => result = BuildType(result.0 | SOURCE.0),
|
|
"binary" => result = BuildType(result.0 | BINARY.0),
|
|
"any" => result = BuildType(result.0 | ARCH_DEP.0),
|
|
"all" => result = BuildType(result.0 | ARCH_INDEP.0),
|
|
other => return Err(format!("unknown build type component '{}'", other)),
|
|
}
|
|
}
|
|
if result.0 == 0 {
|
|
return Err("empty build type".to_string());
|
|
}
|
|
Ok(result)
|
|
}
|
|
|
|
/// Canonical comma-separated representation (as passed to
|
|
/// `dpkg-genchanges --build=` / `dpkg-genbuildinfo --build=`).
|
|
pub fn to_options(self) -> String {
|
|
let mut parts = Vec::new();
|
|
if self.has_any(SOURCE) {
|
|
parts.push("source");
|
|
}
|
|
if self.has_all(BINARY) {
|
|
parts.push("binary");
|
|
} else {
|
|
if self.has_any(ARCH_DEP) {
|
|
parts.push("any");
|
|
}
|
|
if self.has_any(ARCH_INDEP) {
|
|
parts.push("all");
|
|
}
|
|
}
|
|
parts.join(",")
|
|
}
|
|
|
|
/// The `debian/rules` build target for this type:
|
|
/// `build`, `build-arch` or `build-indep`.
|
|
pub fn build_target(self) -> &'static str {
|
|
if self.has_all(BINARY) || self.has_none(BINARY) {
|
|
"build"
|
|
} else if self.has_any(ARCH_DEP) {
|
|
"build-arch"
|
|
} else {
|
|
"build-indep"
|
|
}
|
|
}
|
|
|
|
/// The `debian/rules` binary target for this type:
|
|
/// `binary`, `binary-arch` or `binary-indep`.
|
|
pub fn binary_target(self) -> &'static str {
|
|
if self.has_all(BINARY) || self.has_none(BINARY) {
|
|
"binary"
|
|
} else if self.has_any(ARCH_DEP) {
|
|
"binary-arch"
|
|
} else {
|
|
"binary-indep"
|
|
}
|
|
}
|
|
|
|
/// The architecture suffix used in artifact file names:
|
|
/// host arch, `all` or `source`.
|
|
pub fn arch_suffix(self, host_arch: &str) -> &str {
|
|
if self.has_any(ARCH_DEP) {
|
|
host_arch
|
|
} else if self.has_any(ARCH_INDEP) {
|
|
"all"
|
|
} else {
|
|
"source"
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn parse_options() {
|
|
assert_eq!(BuildType::from_options("full").unwrap(), FULL);
|
|
assert_eq!(BuildType::from_options("source").unwrap(), SOURCE);
|
|
assert_eq!(
|
|
BuildType::from_options("source,any").unwrap(),
|
|
SOURCE_ARCH_DEP
|
|
);
|
|
assert_eq!(BuildType::from_options("any,all").unwrap(), BINARY);
|
|
assert!(BuildType::from_options("bogus").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn roundtrip_options() {
|
|
for t in [FULL, SOURCE, BINARY, SOURCE_ARCH_DEP, SOURCE_ARCH_INDEP] {
|
|
assert_eq!(BuildType::from_options(&t.to_options()).unwrap(), t);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn targets() {
|
|
assert_eq!(FULL.build_target(), "build");
|
|
assert_eq!(FULL.binary_target(), "binary");
|
|
assert_eq!(ARCH_DEP.build_target(), "build-arch");
|
|
assert_eq!(ARCH_DEP.binary_target(), "binary-arch");
|
|
assert_eq!(ARCH_INDEP.build_target(), "build-indep");
|
|
assert_eq!(ARCH_INDEP.binary_target(), "binary-indep");
|
|
assert_eq!(SOURCE.arch_suffix("amd64"), "source");
|
|
assert_eq!(ARCH_DEP.arch_suffix("amd64"), "amd64");
|
|
assert_eq!(ARCH_INDEP.arch_suffix("amd64"), "all");
|
|
}
|
|
}
|