Skip to content

Commit

Permalink
iox-eclipse-iceoryx#73 Support cross compile for aarch64
Browse files Browse the repository at this point in the history
  • Loading branch information
tony-slamtec committed Dec 6, 2023
1 parent fdd6495 commit b004794
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 44 deletions.
261 changes: 217 additions & 44 deletions iceoryx-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,193 @@ use std::io::{Error, ErrorKind};
use std::process::Command;

const ICEORYX_VERSION: &str = "v2.0.3";
const ATTR_VERSION: &str = "2.5.1";
const ACL_VERSION: &str = "2.3.1";

fn make_and_install(source_dir: &str, build_dir: &str, install_dir: &str) -> std::io::Result<()> {
fn extract(archive: &str, source_dir: &str) -> std::io::Result<()> {
if !Command::new("mkdir")
.args(["-p", source_dir])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Could not create source dir for '{}'!", source_dir),
));
}

if !Command::new("tar")
.args([
"-xf",
archive,
"-C",
source_dir,
"--strip-components=1",
])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!(
"Could not extract archive '{}' to '{}'!",
archive, source_dir
),
));
}

Ok(())
}

fn autogen(source_dir: &str) -> std::io::Result<()> {
if !Command::new("./autogen.sh")
.current_dir(source_dir)
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Failed to run autogen.sh in {}", source_dir)
));
}

Ok(())
}

fn configure(source_dir: &str, build_dir: &str, install_dir: &str, toolchain_prefix: Option<&str>) -> std::io::Result<()> {
if !Command::new("mkdir")
.args(["-p", build_dir])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Could not create build dir for '{}'!", build_dir),
));
}

let mut args = Vec::new();

if let Some(toolchain_prefix) = toolchain_prefix {
args.push(format!("--host={}", toolchain_prefix));
}

args.push(format!("--prefix={}", install_dir));
args.push(format!("--enable-shared=no"));

if !Command::new(format!("{}/configure", source_dir))
.current_dir(build_dir)
.args(args)
.env("CFLAGS", format!("-I{}/include", install_dir))
.env("LDFLAGS", format!("-L{}/lib", install_dir))
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Failed to run configure in {}", source_dir)
));
}

Ok(())
}

fn make(build_dir: &str) -> std::io::Result<()> {
if !Command::new("make")
.current_dir(build_dir)
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Failed to run make in {}", build_dir)
));
}

Ok(())
}

fn make_install(build_dir: &str) -> std::io::Result<()> {
if !Command::new("make")
.current_dir(build_dir)
.args(["install"])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Failed to run make install in {}", build_dir)
));
}

Ok(())
}

fn extract_toolchain_prefix(toolchain_cmake_file: &str) -> std::io::Result<Option<String>> {
let toolchain_cmake = std::fs::read_to_string(toolchain_cmake_file);

if toolchain_cmake.is_err() {
return Err(Error::new(
ErrorKind::Other,
format!("failed to read cmake file {}", toolchain_cmake_file)
));
}

let toolchain_cmake = toolchain_cmake.unwrap();

let segs = toolchain_cmake
.lines()
.map(|l| l.trim())
.find(|line| line.starts_with("set(CMAKE_C_COMPILER"))
.map(|line| line.split_whitespace().last().unwrap().trim_matches('"'))
.map(|line| line.trim_matches(')'))
.map(|line| line.split('-').collect::<Vec<_>>());

if segs.is_none() || segs.as_ref().unwrap().is_empty() {
return Err(Error::new(
ErrorKind::Other,
format!("extracted empty triple from cmake file {}", toolchain_cmake_file)
));
}

let segs = segs.unwrap();
Ok(Some(segs[0..segs.len() - 1].join("-")))
}

fn make_and_install(archive_dir: &str, source_dir: &str, build_dir: &str, install_dir: &str) -> std::io::Result<()> {
let cmake_install_prefix = format!("-DCMAKE_INSTALL_PREFIX={}", install_dir);
let cmake_prefix_path = format!("-DCMAKE_PREFIX_PATH={}", install_dir);

let target = env::var("TARGET").expect("Target");
let host = env::var("HOST").expect("Host");

let (extra_cmake_args, toolchain_prefix) = if target == host {
(vec![], None)
} else {
let toolchain_cmake_file = format!("{}/toolchain.{}.cmake", archive_dir, target);
(vec![format!("-DCMAKE_TOOLCHAIN_FILE={}", toolchain_cmake_file)], extract_toolchain_prefix(&toolchain_cmake_file)?)
};

if let Some(toolchain_prefix) = toolchain_prefix {
// cross compiling, compile libattr and libacl on our own
// compile attr
let attr_source_dir = format!("{}/{}", source_dir, "attr");
let attr_build_dir = format!("{}/{}", build_dir, "attr");
extract(&format!("{}/attr-{}.tar.gz", archive_dir, ATTR_VERSION), &attr_source_dir)?;
autogen(&attr_source_dir)?;
configure(&attr_source_dir, &attr_build_dir, &install_dir, Some(&toolchain_prefix))?;
make(&attr_build_dir)?;
make_install(&attr_build_dir)?;

// compile acl
let acl_source_dir = format!("{}/{}", source_dir, "acl");
let acl_build_dir = format!("{}/{}", build_dir, "acl");
extract(&format!("{}/acl-{}.tar.gz", archive_dir, ACL_VERSION), &acl_source_dir)?;
configure(&acl_source_dir, &acl_build_dir, &install_dir, Some(&toolchain_prefix))?;
make(&acl_build_dir)?;
make_install(&acl_build_dir)?;
}

for iceoryx_component in ["iceoryx_hoofs", "iceoryx_posh"] {
let component_source_dir = format!("{}/{}", source_dir, iceoryx_component);
let component_build_dir = format!("{}/{}", build_dir, iceoryx_component);
Expand All @@ -28,34 +210,55 @@ fn make_and_install(source_dir: &str, build_dir: &str, install_dir: &str) -> std
));
}

let mut cmake_args = extra_cmake_args.clone();
cmake_args.push(format!("-DCMAKE_BUILD_TYPE=Release"));
cmake_args.push(format!("-DBUILD_SHARED_LIBS=OFF"));
cmake_args.push(format!("-DROUDI_ENVIRONMENT=ON"));
cmake_args.push(cmake_prefix_path.clone());
cmake_args.push(cmake_install_prefix.clone());
cmake_args.push(component_source_dir.clone());

if !Command::new("cmake")
.current_dir(&component_build_dir)
.args([
"-DCMAKE_BUILD_TYPE=Release",
"-DBUILD_SHARED_LIBS=OFF",
"-DROUDI_ENVIRONMENT=ON",
&cmake_prefix_path,
&cmake_install_prefix,
&component_source_dir,
])
.env("CFLAGS", format!("-I{}/include", install_dir))
.env("LDFLAGS", format!("-L{}/lib", install_dir))
.args(&cmake_args)
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Could not run cmake for '{}'!", iceoryx_component),
format!(
"Could not run cmake for '{}'!\nWork Dir: {}\nCommand: cmake {}",
iceoryx_component,
component_build_dir,
cmake_args.join(" ")
),
));
}

let mut cmake_args = Vec::new();
cmake_args.push(format!("--build"));
cmake_args.push(format!("."));
cmake_args.push(format!("--target"));
cmake_args.push(format!("install"));

if !Command::new("cmake")
.current_dir(&component_build_dir)
.args(["--build", ".", "--target", "install"])
.env("CFLAGS", format!("-I{}/include", install_dir))
.env("LDFLAGS", format!("-L{}/lib", install_dir))
.args(&cmake_args)
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Could not build '{}'!", iceoryx_component),
format!(
"Could not build '{}'!\nWork Dir: {}\nCommand: cmake {}",
iceoryx_component,
component_build_dir,
cmake_args.join(" ")
),
));
}
}
Expand All @@ -64,38 +267,7 @@ fn make_and_install(source_dir: &str, build_dir: &str, install_dir: &str) -> std
}

fn extract_archive(archive_dir: &str, source_dir: &str, version: &str) -> std::io::Result<()> {
if !Command::new("mkdir")
.args(["-p", source_dir])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!("Could not create source dir for '{}'!", source_dir),
));
}

if !Command::new("tar")
.args([
"-xf",
&format!("{}/{}.tar.gz", archive_dir, version),
"-C",
source_dir,
"--strip-components=1",
])
.status()?
.success()
{
return Err(Error::new(
ErrorKind::Other,
format!(
"Could not extract archive '{}' to '{}'!",
version, source_dir
),
));
}

Ok(())
extract(&format!("{}/{}.tar.gz", archive_dir, version), source_dir)
}

fn main() -> std::io::Result<()> {
Expand All @@ -110,6 +282,7 @@ fn main() -> std::io::Result<()> {
extract_archive(&iceoryx_archive_dir, &iceoryx_source_dir, ICEORYX_VERSION)?;

make_and_install(
&iceoryx_archive_dir,
&iceoryx_source_dir,
&iceoryx_build_dir,
&iceoryx_install_dir,
Expand Down
Binary file added iceoryx-sys/iceoryx-cpp/acl-2.3.1.tar.gz
Binary file not shown.
Binary file added iceoryx-sys/iceoryx-cpp/attr-2.5.1.tar.gz
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

0 comments on commit b004794

Please sign in to comment.