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

Refactor cross compile assistance #769

Merged
merged 28 commits into from
Feb 8, 2024
Merged
Changes from 10 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2da914b
Refactor cross compilation assistance
runesoerensen Feb 1, 2024
47ddc1f
No need to assign linker value to variable
runesoerensen Feb 1, 2024
99ac631
Prefer pattern matching
runesoerensen Feb 1, 2024
276b1e7
Simplify expression
runesoerensen Feb 1, 2024
52c6ec1
Move error handling logic
runesoerensen Feb 1, 2024
533665e
Combine functions
runesoerensen Feb 1, 2024
5954ba8
Provide better help text
runesoerensen Feb 1, 2024
84b4d8c
Update help text to better fit output
runesoerensen Feb 1, 2024
dcb5f12
Decrease help text verbosity level
runesoerensen Feb 1, 2024
de1aec0
Use underscores in CC_* env vars
runesoerensen Feb 1, 2024
a7510c8
Fully qualify OS and ARCH name references
runesoerensen Feb 2, 2024
cc5af13
Avoid declaring new target variable
runesoerensen Feb 2, 2024
cab120b
Explicitly match supported mac archs
runesoerensen Feb 2, 2024
81d9bf3
Add indoc dependency to libcnb-package
runesoerensen Feb 2, 2024
6d02966
Reduce line length
runesoerensen Feb 2, 2024
0504c41
Use indoc for multiline help text readability
runesoerensen Feb 2, 2024
1d3670b
Prefer formatdoc macro
runesoerensen Feb 2, 2024
d2b7be7
Add whitespace
runesoerensen Feb 2, 2024
aa2ea7c
Add comment explaining musl-gcc env logic
runesoerensen Feb 2, 2024
7b170d3
Don't use raw string literal
runesoerensen Feb 2, 2024
32cce40
Remove newline
runesoerensen Feb 2, 2024
8e53c80
Fix gcc-x86-64 compiler package name
runesoerensen Feb 2, 2024
c5a046b
Add required packages to help text
runesoerensen Feb 2, 2024
bffcc40
Add required amd64 packages
runesoerensen Feb 2, 2024
c32607a
Update changelog `libcnb-package` changes
runesoerensen Feb 5, 2024
e9bcd4c
Adjust help text wrapping
runesoerensen Feb 8, 2024
e040fee
Rename gcc_path to gcc_binary_name
runesoerensen Feb 8, 2024
f9fb1cf
Move changelog entries to top level
runesoerensen Feb 8, 2024
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
132 changes: 58 additions & 74 deletions libcnb-package/src/cross_compile.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::env::consts;
use std::ffi::OsString;
use which::which;

Expand All @@ -7,95 +8,71 @@ use which::which;
/// look for the required tools and returns a human-readable help text if they can't be found or
/// any other issue has been detected.
pub fn cross_compile_assistance(target_triple: impl AsRef<str>) -> CrossCompileAssistance {
// Background: https://omarkhawaja.com/cross-compiling-rust-from-macos-to-linux/
if target_triple.as_ref() == X86_64_UNKNOWN_LINUX_MUSL && cfg!(target_os = "macos") {
// There is more than just one binary name here since we also support the binary name for
// an older version cross_compile_assistance which suggested installing a different
// toolchain.
let possible_gcc_binary_names = ["x86_64-unknown-linux-musl-gcc", "x86_64-linux-musl-gcc"];
let target = target_triple.as_ref();
runesoerensen marked this conversation as resolved.
Show resolved Hide resolved
let (gcc_path, help_text) = match (target, consts::OS, consts::ARCH) {
(AARCH64_UNKNOWN_LINUX_MUSL, OS_LINUX, ARCH_X86_64) => (
"aarch64-linux-gnu-gcc",
"To install an aarch64 cross-compiler on Ubuntu:\nsudo apt-get install g++-aarch64-linux-gnu",
),
(AARCH64_UNKNOWN_LINUX_MUSL, OS_MACOS, _) => (
Malax marked this conversation as resolved.
Show resolved Hide resolved
"aarch64-unknown-linux-musl-gcc",
"To install an aarch64 cross-compiler on macOS:\nbrew install messense/macos-cross-toolchains/aarch64-unknown-linux-musl",
),
(AARCH64_UNKNOWN_LINUX_MUSL, OS_LINUX, ARCH_AARCH64) | (X86_64_UNKNOWN_LINUX_MUSL, OS_LINUX, ARCH_X86_64) => (
"musl-gcc",
"To install musl-tools on Ubuntu:\nsudo apt-get install musl-tools",
),
(X86_64_UNKNOWN_LINUX_MUSL, OS_LINUX, ARCH_AARCH64) => (
"x86_64-linux-gnu-gcc",
"To install an x86_64 cross-compiler on Ubuntu:\nsudo apt-get install g++-x86_64-linux-gnu",
),
(X86_64_UNKNOWN_LINUX_MUSL, OS_MACOS, _) => (
"x86_64-unknown-linux-musl-gcc",
"To install an x86_64 cross-compiler on macOS:\nbrew install messense/macos-cross-toolchains/x86_64-unknown-linux-musl",
),
Malax marked this conversation as resolved.
Show resolved Hide resolved
_ => return CrossCompileAssistance::NoAssistance,
};

possible_gcc_binary_names
.iter()
.find_map(|binary_name| which(binary_name).ok())
.map_or_else(|| CrossCompileAssistance::HelpText(String::from(
r"For cross-compilation from macOS to x86_64-unknown-linux-musl, a C compiler and
linker for the target platform must be installed on your computer.

The easiest way to install the required cross-compilation toolchain is to run:
brew install messense/macos-cross-toolchains/x86_64-unknown-linux-musl

For more information, see:
https://github.com/messense/homebrew-macos-cross-toolchains

You will also need to install the Rust target, using:
rustup target add x86_64-unknown-linux-musl",
)), |gcc_binary_path| {
match which(gcc_path) {
Ok(_) => {
if gcc_path == "musl-gcc" {
CrossCompileAssistance::Configuration {
cargo_env: Vec::new(),
}
Malax marked this conversation as resolved.
Show resolved Hide resolved
} else {
CrossCompileAssistance::Configuration {
cargo_env: vec![
(
// Required until Cargo can auto-detect the musl-cross gcc/linker itself,
// since otherwise it checks for a binary named 'musl-gcc':
// https://github.com/FiloSottile/homebrew-musl-cross/issues/16
// since otherwise it checks for a binary named 'musl-gcc' (which is handled above):
// https://github.com/rust-lang/cargo/issues/4133
OsString::from("CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER"),
OsString::from(&gcc_binary_path),
OsString::from(format!(
"CARGO_TARGET_{}_LINKER",
target.to_uppercase().replace('-', "_")
)),
OsString::from(gcc_path),
),
(
// Required so that any crates that call out to gcc are also cross-compiled:
// https://github.com/alexcrichton/cc-rs/issues/82
OsString::from("CC_x86_64_unknown_linux_musl"),
OsString::from(&gcc_binary_path),
OsString::from(format!("CC_{}", target.replace('-', "_"))),
OsString::from(gcc_path),
),
],
}
})
} else if target_triple.as_ref() == X86_64_UNKNOWN_LINUX_MUSL && cfg!(target_os = "linux") {
match which("musl-gcc") {
Ok(_) => CrossCompileAssistance::Configuration {
cargo_env: Vec::new(),
},
Err(_) => CrossCompileAssistance::HelpText(String::from(
r"For cross-compilation from Linux to x86_64-unknown-linux-musl, a C compiler and
linker for the target platform must be installed on your computer.

The easiest way to install 'musl-gcc' is to install the 'musl-tools' package:
- https://packages.ubuntu.com/focal/musl-tools
- https://packages.debian.org/bullseye/musl-tools

You will also need to install the Rust target, using:
rustup target add x86_64-unknown-linux-musl",
)),
}
}
} else if target_triple.as_ref() == AARCH64_UNKNOWN_LINUX_MUSL && cfg!(target_os = "linux") {
let gcc_binary_path = "aarch64-linux-gnu-gcc";
match which(gcc_binary_path) {
Ok(_) => CrossCompileAssistance::Configuration {
cargo_env: vec![
(
OsString::from("CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER"),
OsString::from(gcc_binary_path),
),
(
OsString::from("CC_aarch64_unknown_linux_musl"),
OsString::from(gcc_binary_path),
),
],
},
Err(_) => CrossCompileAssistance::HelpText(String::from(
r"For cross-compilation from Linux to aarch64-unknown-linux-musl, a C compiler and
linker for the target platform must installed on your computer.

The easiest way to install the 'g++-aarch64-linux-gnu', 'libc6-dev-arm64-cross', and 'musl-tools' packages:
- https://packages.ubuntu.com/focal/g++-aarch64-linux-gnu
- https://packages.ubuntu.com/focal/musl-tools
- https://packages.ubuntu.com/focal/libc6-dev-arm64-cross
Err(_) => CrossCompileAssistance::HelpText(format!(
r"For cross-compilation from {0} {1} to {target}, a C compiler and
linker for the target platform must be installed:

You will also need to install the Rust target, using:
rustup target add aarch64-unknown-linux-musl",
)),
}
} else {
CrossCompileAssistance::NoAssistance
{help_text}

You will also need to install the Rust target:
rustup target add {target}",
consts::ARCH,
consts::OS
)),
Malax marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand All @@ -111,5 +88,12 @@ pub enum CrossCompileAssistance {
},
}

// Constants for supported target triples
const AARCH64_UNKNOWN_LINUX_MUSL: &str = "aarch64-unknown-linux-musl";
const X86_64_UNKNOWN_LINUX_MUSL: &str = "x86_64-unknown-linux-musl";

// Constants for OS and ARCH
runesoerensen marked this conversation as resolved.
Show resolved Hide resolved
const OS_LINUX: &str = "linux";
const OS_MACOS: &str = "macos";
const ARCH_X86_64: &str = "x86_64";
const ARCH_AARCH64: &str = "aarch64";
Loading