Skip to content

fix: Cross compilation sysroot options #103

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

Merged
merged 1 commit into from
Apr 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 17 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,21 @@ jobs:
container: jrottenberg/ffmpeg:${{ matrix.ffmpeg_version }}-ubuntu
strategy:
matrix:
ffmpeg_version: ['3.3', '3.4', '4.0', '4.1', '4.2', '4.3', '4.4', '5.0', '5.1', '6.0', '6.1', '7.0']
ffmpeg_version:
[
"3.3",
"3.4",
"4.0",
"4.1",
"4.2",
"4.3",
"4.4",
"5.0",
"5.1",
"6.0",
"6.1",
"7.0",
]
fail-fast: false
env:
FEATURES: avcodec,avdevice,avfilter,avformat,postproc,swresample,swscale
Expand All @@ -20,9 +34,9 @@ jobs:
- name: Install dependencies
run: |
apt update
apt install -y --no-install-recommends clang curl pkg-config
apt install -y --no-install-recommends clang curl pkg-config ca-certificates
- name: Set up Rust
uses: actions-rs/toolchain@v1
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
override: true
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ build-lib-x265 = ["build"]
build-lib-avs = ["build"]
build-lib-xvid = ["build"]

# hardware accelleration
build-videotoolbox = ["build"]
build-audiotoolbox = ["build"]

# protocols
build-lib-smbclient = ["build"]
build-lib-ssh = ["build"]
Expand Down
88 changes: 83 additions & 5 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::env;
use std::fmt::Write as FmtWrite;
use std::fs::{self, File};
use std::io::{self, BufRead, BufReader, Write};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;

Expand Down Expand Up @@ -195,7 +195,43 @@ fn get_ffmpet_target_os() -> String {
}
}

fn build() -> io::Result<()> {
/// Find the sysroot required for a cross compilation by ffmpeg **and** bindgen
/// @see https://github.com/rust-lang/rust-bindgen/issues/1229
fn find_sysroot() -> Option<String> {
if env::var("CARGO_FEATURE_BUILD").is_err() || env::var("HOST") == env::var("TARGET") {
return None;
}

if let Ok(sysroot) = env::var("SYSROOT") {
return Some(sysroot.to_string());
}

if env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("ios") {
let xcode_output = Command::new("xcrun")
.args(["--sdk", "iphoneos", "--show-sdk-path"])
.output()
.expect("failed to run xcrun");

if !xcode_output.status.success() {
panic!("Failed to run xcrun to get the ios sysroot, please install xcode tools or provide sysroot using $SYSROOT env. Error: {}", String::from_utf8_lossy(&xcode_output.stderr));
}

let string = String::from_utf8(xcode_output.stdout)
.expect("Failed to parse xcrun output")
.replace("\n", "");

if !Path::new(&string).exists() {
panic!("xcrun returned invalid sysroot path: {}", string);
}

return Some(string);
}

println!("cargo:warnning=Detected cross compilation but sysroot not provided");
None
}

fn build(sysroot: Option<&str>) -> io::Result<()> {
let source_dir = source();

// Command's path is not relative to command's current_dir
Expand Down Expand Up @@ -233,7 +269,27 @@ fn build() -> io::Result<()> {
"--arch={}",
env::var("CARGO_CFG_TARGET_ARCH").unwrap()
));
configure.arg(format!("--target_os={}", get_ffmpet_target_os()));
configure.arg(format!("--target-os={}", get_ffmpet_target_os()));
}

// for ios it is required to provide sysroot for both configure and bindgen
// for macos the easiest way is to run xcrun, for other platform we support $SYSROOT var
if env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("ios") {
let sysroot = sysroot.expect("The sysroot is required for ios cross compilation, make sure to have available xcode or provide the $SYSROOT env var");
configure.arg(format!("--sysroot={}", sysroot));

let cc = Command::new("xcrun")
.args(["--sdk", "iphoneos", "-f", "clang"])
.output()
.expect("failed to run xcrun")
.stdout;

configure.arg(format!(
"--cc={}",
str::from_utf8(&cc)
.expect("Failed to parse xcrun output")
.trim()
));
}

// control debug build
Expand Down Expand Up @@ -348,6 +404,23 @@ fn build() -> io::Result<()> {
enable!(configure, "BUILD_LIB_AVS", "libavs");
enable!(configure, "BUILD_LIB_XVID", "libxvid");

if env::var("CARGO_FEATURE_BUILD_VIDEOTOOLBOX").is_ok() {
configure.arg("--enable-videotoolbox");

if target != host && env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("ios") {
configure.arg("--extra-cflags=-mios-version-min=11.0");
}

if target != host && env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") {
configure.arg("--extra-cflags=-mmacosx-version-min=10.11");
}
}

if env::var("CARGO_FEATURE_BUILD_AUDIOTOOLBOX").is_ok() {
configure.arg("--enable-audiotoolbox");
configure.arg("--extra-cflags=-mios-version-min=11.0");
}

// other external libraries
enable!(configure, "BUILD_LIB_DRM", "libdrm");
enable!(configure, "BUILD_NVENC", "nvenc");
Expand Down Expand Up @@ -671,6 +744,7 @@ fn main() {
let statik = env::var("CARGO_FEATURE_STATIC").is_ok();
let ffmpeg_major_version: u32 = env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap();

let sysroot = find_sysroot();
let include_paths: Vec<PathBuf> = if env::var("CARGO_FEATURE_BUILD").is_ok() {
println!(
"cargo:rustc-link-search=native={}",
Expand All @@ -680,7 +754,7 @@ fn main() {
if fs::metadata(search().join("lib").join("libavutil.a")).is_err() {
fs::create_dir_all(output()).expect("failed to create build directory");
fetch().unwrap();
build().unwrap();
build(sysroot.as_deref()).unwrap();
}

// Check additional required libraries.
Expand All @@ -696,7 +770,7 @@ fn main() {
if line.starts_with("EXTRALIBS") {
Some(
line.split('=')
.last()
.next_back()
.unwrap()
.split(' ')
.map(|s| s.to_string())
Expand Down Expand Up @@ -1253,6 +1327,10 @@ fn main() {
.size_t_is_usize(true)
.parse_callbacks(Box::new(Callbacks));

if let Some(sysroot) = sysroot.as_deref() {
builder = builder.clang_arg(format!("--sysroot={}", sysroot));
}

// The input headers we would like to generate
// bindings for.
if env::var("CARGO_FEATURE_AVCODEC").is_ok() {
Expand Down
Loading