use std::env;
use std::fs;
use std::io;
use std::path::PathBuf;
use std::process::Command;
fn version() -> String {
let major: u8 = env::var("CARGO_PKG_VERSION_MAJOR").unwrap().parse().unwrap();
let minor: u8 = env::var("CARGO_PKG_VERSION_MINOR").unwrap().parse().unwrap();
let patch: u8 = env::var("CARGO_PKG_VERSION_PATCH").unwrap().parse().unwrap();
if patch == 0 {
format!("{}.{}", major, minor)
}
else {
format!("{}.{}.{}", major, minor, patch)
}
}
fn output() -> PathBuf {
PathBuf::from(env::var("OUT_DIR").unwrap())
}
fn source() -> PathBuf {
output().join(format!("ffmpeg-{}", version()))
}
fn search() -> PathBuf {
let mut absolute = env::current_dir().unwrap();
absolute.push(&output());
absolute.push("dist");
absolute
}
fn fetch() -> io::Result<()> {
let url = format!("http://ffmpeg.org/releases/ffmpeg-{}.tar.bz2", version());
let status = try!(if cfg!(target_os = "linux") {
Command::new("wget")
.current_dir(&output())
.arg(url)
.arg("-c")
.arg("-O")
.arg("ffmpeg.tar.bz2")
.status()
}
else {
unimplemented!();
});
if status.success() {
Ok(())
}
else {
Err(io::Error::new(io::ErrorKind::Other, "fetch failed"))
}
}
fn extract() -> io::Result<()> {
let status = try!(if cfg!(target_os = "linux") {
Command::new("tar")
.current_dir(&output())
.arg("xf")
.arg("ffmpeg.tar.bz2")
.status()
}
else {
unimplemented!();
});
if status.success() {
Ok(())
}
else {
Err(io::Error::new(io::ErrorKind::Other, "extract failed"))
}
}
fn build() -> io::Result<()> {
let mut configure = Command::new("./configure");
configure.current_dir(&source());
configure.arg(format!("--prefix={}", search().to_string_lossy()));
if env::var("TARGET").unwrap() != env::var("HOST").unwrap() {
configure.arg(format!("--cross-prefix={}-", env::var("TARGET").unwrap()));
}
if env::var("DEBUG").is_ok() {
configure.arg("--enable-debug");
configure.arg("--disable-stripping");
}
else {
configure.arg("--disable-debug");
configure.arg("--enable-stripping");
}
configure.arg("--enable-static");
configure.arg("--disable-shared");
configure.arg("--disable-programs");
macro_rules! switch {
($conf:expr, $feat:expr, $name:expr) => (
if env::var(concat!("CARGO_FEATURE_", $feat)).is_ok() {
$conf.arg(concat!("--enable-", $name));
}
else {
$conf.arg(concat!("--disable-", $name));
}
)
}
macro_rules! enable {
($conf:expr, $feat:expr, $name:expr) => (
if env::var(concat!("CARGO_FEATURE_", $feat)).is_ok() {
$conf.arg(concat!("--enable-", $name));
}
)
}
macro_rules! disable {
($conf:expr, $feat:expr, $name:expr) => (
if env::var(concat!("CARGO_FEATURE_", $feat)).is_err() {
$conf.arg(concat!("--disable-", $name));
}
)
}
switch!(configure, "BUILD_LICENSE_GPL", "gpl");
switch!(configure, "BUILD_LICENSE_VERSION3", "version3");
switch!(configure, "BUILD_LICENSE_NONFREE", "nonfree");
switch!(configure, "AVCODEC", "avcodec");
switch!(configure, "AVDEVICE", "avdevice");
switch!(configure, "AVFILTER", "avfilter");
switch!(configure, "AVFORMAT", "avformat");
switch!(configure, "AVRESAMPLE", "avresample");
switch!(configure, "POSTPROC", "postproc");
switch!(configure, "SWRESAMPLE", "swresample");
switch!(configure, "SWSCALE", "swscale");
enable!(configure, "BUILD_LIB_GNUTLS", "gnutls");
enable!(configure, "BUILD_LIB_OPENSSL", "openssl");
enable!(configure, "BUILD_LIB_FONTCONFIG", "fontconfig");
enable!(configure, "BUILD_LIB_FREI0R", "frei0r");
enable!(configure, "BUILD_LIB_LADSPA", "ladspa");
enable!(configure, "BUILD_LIB_ASS", "libass");
enable!(configure, "BUILD_LIB_FREETYPE", "libfreetype");
enable!(configure, "BUILD_LIB_FRIBIDI", "libfribidi");
enable!(configure, "BUILD_LIB_OPENCV", "libopencv");
enable!(configure, "BUILD_LIB_AACPLUS", "libaacplus");
enable!(configure, "BUILD_LIB_CELT", "libcelt");
enable!(configure, "BUILD_LIB_DCADEC", "libdcadec");
enable!(configure, "BUILD_LIB_FAAC", "libfaac");
enable!(configure, "BUILD_LIB_FDK_AAC", "libfdk-aac");
enable!(configure, "BUILD_LIB_GSM", "libgsm");
enable!(configure, "BUILD_LIB_ILBC", "libilbc");
enable!(configure, "BUILD_LIB_VAZAAR", "libvazaar");
enable!(configure, "BUILD_LIB_MP3LAME", "libmp3lame");
enable!(configure, "BUILD_LIB_OPENCORE_AMRNB", "libopencore-amrnb");
enable!(configure, "BUILD_LIB_OPENCORE_AMRWB", "libopencore-amrwrb");
enable!(configure, "BUILD_LIB_OPENH264", "libopenh264");
enable!(configure, "BUILD_LIB_OPENH265", "libopenh265");
enable!(configure, "BUILD_LIB_OPENJPEG", "libopenjpeg");
enable!(configure, "BUILD_LIB_OPUS", "libopus");
enable!(configure, "BUILD_LIB_SCHROEDINGER", "libschroedinger");
enable!(configure, "BUILD_LIB_SHINE", "libshine");
enable!(configure, "BUILD_LIB_SNAPPY", "libsnappy");
enable!(configure, "BUILD_LIB_SPEEX", "libspeex");
enable!(configure, "BUILD_LIB_STAGEFRIGHT_H264", "libstagefright-h264");
enable!(configure, "BUILD_LIB_THEORA", "libtheora");
enable!(configure, "BUILD_LIB_TWOLAME", "libtwolame");
enable!(configure, "BUILD_LIB_UTVIDEO", "libutvideo");
enable!(configure, "BUILD_LIB_VO_AACENC", "libvo-aacenc");
enable!(configure, "BUILD_LIB_VO_AMRWBENC", "libvo-amrwbenc");
enable!(configure, "BUILD_LIB_VORBIS", "libvorbis");
enable!(configure, "BUILD_LIB_VPX", "libvpx");
enable!(configure, "BUILD_LIB_WAVPACK", "libwavpack");
enable!(configure, "BUILD_LIB_WEBP", "libwebp");
enable!(configure, "BUILD_LIB_X264", "libx264");
enable!(configure, "BUILD_LIB_X265", "libx265");
enable!(configure, "BUILD_LIB_AVS", "libavs");
enable!(configure, "BUILD_LIB_XVID", "libxvid");
enable!(configure, "BUILD_LIB_SMBCLIENT", "libsmbclient");
enable!(configure, "BUILD_LIB_SSH", "libssh");
if !try!(configure.status()).success() {
return Err(io::Error::new(io::ErrorKind::Other, "configure failed"));
}
if !try!(Command::new("make").current_dir(&source()).status()).success() {
return Err(io::Error::new(io::ErrorKind::Other, "make failed"));
}
if !try!(Command::new("make").current_dir(&source()).arg("install").status()).success() {
return Err(io::Error::new(io::ErrorKind::Other, "make install failed"));
}
Ok(())
}
fn main() {
if env::var("CARGO_FEATURE_BUILD").is_err() {
return;
}
println!("cargo:rustc-link-search=native={}", search().join("lib").to_string_lossy());
if fs::metadata(&search().join("lib").join("libavutil.a")).is_ok() {
return;
}
fs::create_dir_all(&output()).ok().expect("failed to create build directory");
fetch().unwrap();
extract().unwrap();
build().unwrap();
}