From fe73b42bbc5094b643947548807fbd30c79578ea Mon Sep 17 00:00:00 2001 From: Chip Collier Date: Wed, 16 Aug 2017 16:01:48 +0200 Subject: [PATCH] Add feature 'bundled' Allows statically linking to a self-contained build of SDL2. --- Cargo.toml | 1 + sdl2-sys/Cargo.toml | 17 ++++++++ sdl2-sys/build.rs | 103 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c1e815ec..59a478b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ mixer = [] use-bindgen = ["sdl2-sys/use-bindgen"] use-pkgconfig = ["sdl2-sys/use-pkgconfig"] use_mac_framework = ["sdl2-sys/use_mac_framework"] +bundled = ["sdl2-sys/bundled"] [[example]] name = "animation" diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index 269d0166..12a97b88 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -23,9 +23,26 @@ optional = true version = "0.3.9" optional = true +[build-dependencies.cmake] +version = "0.1" +optional = true + +[build-dependencies.reqwest] +version = "0.7" +optional = true + +[build-dependencies.tar] +version = "0.4" +optional = true + +[build-dependencies.flate2] +version = "0.2" +optional = true + [features] default = [] use-pkgconfig = ["pkg-config"] use-bindgen = ["bindgen"] use_mac_framework = [] +bundled = ["cmake", "reqwest", "tar", "flate2"] diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index f40b0a1e..5e69052e 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -4,20 +4,108 @@ extern crate pkg_config; #[cfg(feature = "bindgen")] extern crate bindgen; +#[cfg(feature="bundled")] +extern crate cmake; +#[cfg(feature="bundled")] +extern crate tar; +#[cfg(feature="bundled")] +extern crate flate2; +#[cfg(feature="bundled")] +extern crate reqwest; -use std::path::PathBuf; -use std::env; -use std::fs; +use std::path::{Path, PathBuf}; +use std::{io, fs, env}; -const SDL2_BUNDLED_VERSION: &str = "2.0.6"; +// corresponds to the headers that we have in sdl2-sys/SDL2-{version} +const SDL2_HEADERS_BUNDLED_VERSION: &str = "2.0.6"; +// means the lastest stable version that can be downloaded from SDL2's source +const LASTEST_SDL2_VERSION: &str = "2.0.5"; + +#[cfg(feature="bundled")] +fn download_to(url: &str, mut dest: T) { + use io::BufRead; + + let resp = reqwest::get(url).expect(&format!("Failed to GET resource: {:?}", url)); + let size = resp.headers() + .get::() + .map(|ct_len| **ct_len) + .unwrap_or(0); + if !resp.status().is_success() { panic!("Download request failed with status: {:?}", resp.status()) } + if size == 0 { panic!("Size of content was returned was 0") } + + let mut src = io::BufReader::new(resp); + loop { + let n = { + let mut buf = src.fill_buf().unwrap(); + dest.write_all(&mut buf).unwrap(); + buf.len() + }; + if n == 0 { break; } + src.consume(n); + } +} + +#[cfg(feature="bundled")] fn main() { let target = env::var("TARGET").expect("Cargo build scripts always have TARGET"); let host = env::var("HOST").expect("Cargo build scripts always have HOST"); + let target_os = get_os_from_triple(target.as_str()).unwrap(); + + prepare_bindings(&target, &host); + + let sdl2_archive_name = format!("SDL2-{}.tar.gz", LASTEST_SDL2_VERSION); + let sdl2_archive_url = format!("http://libsdl.org/release/{}", sdl2_archive_name); + + let out_dir = env::var("OUT_DIR").unwrap(); + + let sdl2_archive_path = Path::new(&out_dir).join(sdl2_archive_name); + let sdl2_build_path = Path::new(&out_dir).join(format!("SDL2-{}", LASTEST_SDL2_VERSION)); + if !sdl2_archive_path.exists() { + let sdl2_archive = fs::File::create(&sdl2_archive_path).unwrap(); + download_to(&sdl2_archive_url, &sdl2_archive); + } + let reader = flate2::read::GzDecoder::new( + fs::File::open(&sdl2_archive_path).unwrap() + ).unwrap(); + let mut ar = tar::Archive::new(reader); + ar.unpack(&out_dir).unwrap(); + + let install_path = cmake::Config::new(sdl2_build_path) + .define("SDL_SHARED", "OFF") + .define("SDL_STATIC", "ON") + .build(); + + println!("cargo:rustc-link-search={}", install_path.join("lib").display()); + println!("cargo:rustc-link-lib=static=SDL2main"); + println!("cargo:rustc-link-lib=static=SDL2"); + + // Also linked to any required libraries for each supported platform + if target_os == "windows-msvc" { + println!("cargo:rustc-link-lib=user32"); + println!("cargo:rustc-link-lib=gdi32"); + println!("cargo:rustc-link-lib=winmm"); + println!("cargo:rustc-link-lib=imm32"); + println!("cargo:rustc-link-lib=ole32"); + println!("cargo:rustc-link-lib=oleaut32"); + println!("cargo:rustc-link-lib=version"); + println!("cargo:rustc-link-lib=uuid"); + println!("cargo:rustc-link-lib=dinput8"); + println!("cargo:rustc-link-lib=dxguid"); + } else { + // TODO: Add other platform linker options here. + } +} + +#[cfg(not(feature="bundled"))] +fn main() { + let target = env::var("TARGET").expect("Cargo build scripts always have TARGET"); + let host = env::var("HOST").expect("Cargo build scripts always have HOST"); + let target_os = get_os_from_triple(target.as_str()).unwrap(); prepare_bindings(&target, &host); - if get_os_from_triple(&target).unwrap() == "ios" { + if target_os == "ios" { println!("cargo:rustc-flags=-l framework=AVFoundation"); println!("cargo:rustc-flags=-l framework=AudioToolbox"); println!("cargo:rustc-flags=-l framework=CoreAudio"); @@ -31,12 +119,13 @@ fn main() { } } -#[cfg(not(feature = "pkg-config"))] +#[cfg(not(feature="pkg-config"))] +#[cfg(not(feature="bundled"))] fn build_pkgconfig() -> bool { false } -#[cfg(feature = "pkg-config")] +#[cfg(feature="pkg-config")] fn build_pkgconfig() -> bool { pkg_config::probe_library("sdl2").is_ok() }