oak-ffmpeg-link: link the prebuilt shared FFmpeg on Windows
The Windows CI/CD archive (BtbN) is a shared build whose seven MSVC import libraries have canonical names and whose .pc files carry no external Libs.private, so pkg-config resolution is unnecessary there. When neither pkg-config nor pkgconf exists, the script now emits the fixed link line instead of panicking — but only on Windows: everywhere else a static FFmpeg still needs the transitive list from its .pc files, and MSYS2 local builds keep using pkg-config. The FFmpeg 9 note in oak-codec's manifest is refreshed as well.
This commit is contained in:
@@ -14,17 +14,18 @@ oak-core = { path = "../oak-core" }
|
||||
# Real media decode/encode. The C++ ffmpeg_bridge library existed only to
|
||||
# absorb FFmpeg API churn; the Rust crate calls ffmpeg-next directly.
|
||||
#
|
||||
# ffmpeg-next 9.x pairs with FFmpeg 8.x headers, which most distros do
|
||||
# not ship yet — build a matching GPL FFmpeg (all free-license codecs +
|
||||
# per-OS hardware acceleration, static+PIC) with
|
||||
# ffmpeg-next 9.x compiles against the FFmpeg 8.x and 9.x headers (both
|
||||
# verified locally with the project FFmpeg build), but most distros do
|
||||
# not ship a matching prebuilt library yet — build one (all free-license
|
||||
# codecs + per-OS hardware acceleration, static+PIC) with
|
||||
# tooling/ffmpeg/build-ffmpeg.sh and point cargo at it via FFMPEG_DIR
|
||||
# (see docs/build.md). The `static` feature makes the linker prefer the
|
||||
# archives.
|
||||
# archives. CI/CD uses the same script on Linux/macOS and BtbN's
|
||||
# prebuilt shared archive on Windows.
|
||||
#
|
||||
# ffmpeg-next's own `build` feature is NOT usable: it clones
|
||||
# release/<crate-version>, and every such pairing is broken upstream
|
||||
# (9.0.0 -> FFmpeg 9.0 removed AVCodec fields; 8.1.0 -> FFmpeg 8.1 added
|
||||
# enum variants; 8.0.0 -> FFmpeg 8.0 renamed FF_PROFILE_*).
|
||||
# ffmpeg-next's own `build` cargo feature is still not what we use: it
|
||||
# clones release/<crate-version>, tying the FFmpeg version to the crate
|
||||
# version instead of the project-pinned one.
|
||||
ffmpeg-next = { version = "9", features = ["static"] }
|
||||
# `std::error::Error` impls for the crate-internal error enum.
|
||||
thiserror = "2"
|
||||
|
||||
@@ -50,7 +50,7 @@ fn main() {
|
||||
assert!(
|
||||
pc_dir.exists(),
|
||||
"FFMPEG_DIR={dir} has no lib/pkgconfig — point it at a full install prefix \
|
||||
(the output of tooling/ffmpeg/build-ffmpeg.sh)"
|
||||
(the output of tooling/ffmpeg/build-ffmpeg.sh, or the prebuilt archive on Windows)"
|
||||
);
|
||||
println!("cargo:rerun-if-env-changed=FFMPEG_DIR");
|
||||
let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -100,9 +100,24 @@ fn main() {
|
||||
Some(custom) => run(&custom).expect("PKG_CONFIG points at a program that failed to run"),
|
||||
None => match run("pkg-config") {
|
||||
Ok(output) => output,
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
run("pkgconf").expect("pkg-config/pkgconf is required when FFMPEG_DIR is set")
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => match run("pkgconf") {
|
||||
Ok(output) => output,
|
||||
Err(pkgconf_err) if pkgconf_err.kind() == std::io::ErrorKind::NotFound => {
|
||||
// Windows CI/CD links the prebuilt SHARED FFmpeg (the
|
||||
// BtbN archive, see the workflows): its import libraries
|
||||
// carry canonical names and the archive is
|
||||
// self-contained, so the fixed link line replaces
|
||||
// pkg-config there (no pkg-config is installed).
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
link_prebuilt_shared(&dir);
|
||||
return;
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
panic!("pkg-config/pkgconf is required when FFMPEG_DIR is set");
|
||||
}
|
||||
Err(pkgconf_err) => panic!("failed to run pkgconf: {pkgconf_err}"),
|
||||
},
|
||||
Err(e) => panic!("failed to run pkg-config: {e}"),
|
||||
},
|
||||
};
|
||||
@@ -173,6 +188,29 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit the link directives for the prebuilt SHARED FFmpeg archive the
|
||||
/// Windows CI/CD jobs use (BtbN's build): the seven FFmpeg import
|
||||
/// libraries with their canonical MSVC names. The archive is
|
||||
/// self-contained — its `.pc` files carry no external `Libs.private` — so
|
||||
/// no pkg-config resolution is needed (and no pkg-config binary is
|
||||
/// installed there). MSYS2 local builds keep using pkg-config because
|
||||
/// theirs is a static FFmpeg with the full transitive codec list.
|
||||
#[cfg(target_os = "windows")]
|
||||
fn link_prebuilt_shared(dir: &str) {
|
||||
let libdir = PathBuf::from(dir).join("lib");
|
||||
assert!(
|
||||
libdir.join("avcodec.lib").exists(),
|
||||
"FFMPEG_DIR={dir} has no lib/avcodec.lib — point it at the prebuilt shared \
|
||||
archive (ffmpeg-n8.1-latest-win64-gpl-shared-8.1.zip)"
|
||||
);
|
||||
println!("cargo:rustc-link-search=native={}", libdir.display());
|
||||
for lib in [
|
||||
"avformat", "avcodec", "avfilter", "avdevice", "avutil", "swscale", "swresample",
|
||||
] {
|
||||
println!("cargo:rustc-link-lib={lib}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads `key` from the process environment, falling back to the `.env`
|
||||
/// file at the workspace root (this crate lives in crates/oakffmpeg-link,
|
||||
/// so the root is two levels up). The .env syntax is the common one:
|
||||
|
||||
Reference in New Issue
Block a user