mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
183 lines
5.6 KiB
Rust
183 lines
5.6 KiB
Rust
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
use std::{collections::HashSet, path::Path, path::PathBuf, process::Command};
|
|
|
|
fn is_distribution_lib_dir(path: &Path) -> bool {
|
|
let Some(path) = path.to_str() else {
|
|
return false;
|
|
};
|
|
path.starts_with("/usr/lib") || path.starts_with("/lib")
|
|
}
|
|
|
|
const NATIVE_SHIM_SOURCES: [&str; 17] = [
|
|
"src/webp_animation.c",
|
|
"src/native_shim/hdr_color.c",
|
|
"src/native_shim/av_input.c",
|
|
"src/native_shim/av_frame_rgba.c",
|
|
"src/native_shim/vips_image.c",
|
|
"src/native_shim/gif_validation.c",
|
|
"src/native_shim/gif_timing.c",
|
|
"src/native_shim/gif_filter.c",
|
|
"src/native_shim/gif_transform.c",
|
|
"src/native_shim/apng_validation.c",
|
|
"src/native_shim/animation_decode.c",
|
|
"src/native_shim/heif_pixels.c",
|
|
"src/native_shim/heif_decode.c",
|
|
"src/native_shim/animated_webp.c",
|
|
"src/native_shim/video_frame.c",
|
|
"src/native_shim/nsfw_frame.c",
|
|
"src/native_shim/nsfw_webp.c",
|
|
];
|
|
|
|
const NATIVE_SHIM_HEADERS: [&str; 4] = [
|
|
"src/native_shim/hdr_color.h",
|
|
"src/vips_shim.h",
|
|
"src/webp_animation.h",
|
|
"src/native_shim/native_shim_internal.h",
|
|
];
|
|
|
|
const NATIVE_BUILD_ENVIRONMENT: [&str; 6] = [
|
|
"CARGO_CFG_TARGET_OS",
|
|
"HOMEBREW_PREFIX",
|
|
"PKG_CONFIG",
|
|
"PKG_CONFIG_LIBDIR",
|
|
"PKG_CONFIG_PATH",
|
|
"PKG_CONFIG_SYSROOT_DIR",
|
|
];
|
|
|
|
fn homebrew_prefix() -> PathBuf {
|
|
if let Ok(prefix) = std::env::var("HOMEBREW_PREFIX") {
|
|
return PathBuf::from(prefix);
|
|
}
|
|
let output = Command::new("brew")
|
|
.arg("--prefix")
|
|
.output()
|
|
.expect("libyuv needs a Homebrew prefix: set HOMEBREW_PREFIX or install Homebrew");
|
|
assert!(output.status.success(), "`brew --prefix` failed");
|
|
PathBuf::from(
|
|
String::from_utf8(output.stdout)
|
|
.expect("`brew --prefix` printed invalid UTF-8")
|
|
.trim(),
|
|
)
|
|
}
|
|
|
|
fn main() {
|
|
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
|
|
for variable in NATIVE_BUILD_ENVIRONMENT {
|
|
println!("cargo:rerun-if-env-changed={variable}");
|
|
}
|
|
for header in NATIVE_SHIM_HEADERS {
|
|
println!("cargo:rerun-if-changed={header}");
|
|
}
|
|
for source in NATIVE_SHIM_SOURCES {
|
|
println!("cargo:rerun-if-changed={source}");
|
|
}
|
|
|
|
let mut shim = cc::Build::new();
|
|
shim.include("src")
|
|
.flag("-std=c11")
|
|
.warnings_into_errors(true);
|
|
for source in NATIVE_SHIM_SOURCES {
|
|
shim.file(source);
|
|
}
|
|
|
|
let mut link_paths: Vec<PathBuf> = Vec::new();
|
|
let mut link_files: Vec<PathBuf> = Vec::new();
|
|
let mut framework_paths: Vec<PathBuf> = Vec::new();
|
|
let mut frameworks: Vec<String> = Vec::new();
|
|
let mut libs: Vec<String> = Vec::new();
|
|
let mut ld_args: Vec<Vec<String>> = Vec::new();
|
|
|
|
for lib in [
|
|
"vips",
|
|
"libheif",
|
|
"libavformat",
|
|
"libavcodec",
|
|
"libavfilter",
|
|
"libavutil",
|
|
"libswscale",
|
|
"lcms2",
|
|
"libwebpdemux",
|
|
"libwebpmux",
|
|
"libwebp",
|
|
] {
|
|
let probed = pkg_config::Config::new()
|
|
.cargo_metadata(false)
|
|
.probe(lib)
|
|
.unwrap_or_else(|err| panic!("pkg-config could not find {lib}: {err}"));
|
|
for include in probed.include_paths {
|
|
shim.include(include);
|
|
}
|
|
link_paths.extend(probed.link_paths);
|
|
link_files.extend(probed.link_files);
|
|
framework_paths.extend(probed.framework_paths);
|
|
frameworks.extend(probed.frameworks);
|
|
libs.extend(probed.libs);
|
|
ld_args.extend(probed.ld_args);
|
|
}
|
|
|
|
libs.push("yuv".into());
|
|
|
|
if target_os == "macos" {
|
|
let prefix = homebrew_prefix();
|
|
let header = prefix.join("include/libyuv.h");
|
|
assert!(
|
|
header.is_file(),
|
|
"libyuv header missing at {}: run `brew install libyuv`",
|
|
header.display()
|
|
);
|
|
let has_library = ["lib/libyuv.dylib", "lib/libyuv.a"]
|
|
.iter()
|
|
.any(|candidate| prefix.join(candidate).is_file());
|
|
assert!(
|
|
has_library,
|
|
"libyuv library missing under {}: run `brew install libyuv`",
|
|
prefix.join("lib").display()
|
|
);
|
|
shim.include(prefix.join("include"));
|
|
link_paths.push(prefix.join("lib"));
|
|
}
|
|
|
|
shim.compile("fluxer_vips_shim");
|
|
|
|
let (source_built_link_paths, distribution_link_paths): (Vec<PathBuf>, Vec<PathBuf>) =
|
|
link_paths
|
|
.into_iter()
|
|
.partition(|path| !is_distribution_lib_dir(path));
|
|
|
|
let mut emitted_link_paths: HashSet<PathBuf> = HashSet::new();
|
|
for path in source_built_link_paths
|
|
.into_iter()
|
|
.chain(distribution_link_paths)
|
|
{
|
|
if !emitted_link_paths.insert(path.clone()) {
|
|
continue;
|
|
}
|
|
println!("cargo:rustc-link-search=native={}", path.display());
|
|
if target_os == "macos" {
|
|
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", path.display());
|
|
}
|
|
}
|
|
for path in framework_paths {
|
|
println!("cargo:rustc-link-search=framework={}", path.display());
|
|
}
|
|
for file in link_files {
|
|
println!("cargo:rustc-link-arg={}", file.display());
|
|
}
|
|
for args in ld_args {
|
|
if !args.is_empty() {
|
|
println!("cargo:rustc-link-arg=-Wl,{}", args.join(","));
|
|
}
|
|
}
|
|
for framework in frameworks {
|
|
println!("cargo:rustc-link-lib=framework={framework}");
|
|
}
|
|
let mut emitted_libs: HashSet<String> = HashSet::new();
|
|
for lib in libs {
|
|
if !emitted_libs.insert(lib.clone()) {
|
|
continue;
|
|
}
|
|
println!("cargo:rustc-link-lib={lib}");
|
|
}
|
|
}
|