mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Possibility to use bindgen & bundled together
* Also supports opt-in static linking
This commit is contained in:
@@ -39,10 +39,14 @@ optional = true
|
||||
version = "0.2"
|
||||
optional = true
|
||||
|
||||
[build-dependencies]
|
||||
cfg-if = "0.1"
|
||||
|
||||
[features]
|
||||
|
||||
default = []
|
||||
use-pkgconfig = ["pkg-config"]
|
||||
use-bindgen = ["bindgen"]
|
||||
static-link = []
|
||||
use_mac_framework = []
|
||||
bundled = ["cmake", "reqwest", "tar", "flate2"]
|
||||
|
||||
+171
-95
@@ -13,6 +13,9 @@ extern crate flate2;
|
||||
#[cfg(feature="bundled")]
|
||||
extern crate reqwest;
|
||||
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{io, fs, env};
|
||||
|
||||
@@ -46,105 +49,187 @@ fn download_to<T: io::Write>(url: &str, mut dest: T) {
|
||||
}
|
||||
}
|
||||
|
||||
#[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();
|
||||
#[cfg(feature = "use-pkgconfig")]
|
||||
#[cfg(feature = "static-link")]
|
||||
fn get_pkg_config() -> pkg_config::Library {
|
||||
pkg_config::Config::new()
|
||||
.statik(false)
|
||||
.probe("sdl2").unwrap()
|
||||
}
|
||||
|
||||
prepare_bindings(&target, &host);
|
||||
#[cfg(feature = "use-pkgconfig")]
|
||||
#[cfg(not(feature = "static-link"))]
|
||||
fn get_pkg_config() -> pkg_config::Library {
|
||||
pkg_config::Config::new()
|
||||
.statik(true)
|
||||
.probe("sdl2").unwrap()
|
||||
}
|
||||
|
||||
// returns the location of the downloaded source
|
||||
#[cfg(feature = "bundled")]
|
||||
fn download_sdl2() -> PathBuf {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
|
||||
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));
|
||||
|
||||
// avoid re-downloading the archive if it already exists
|
||||
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();
|
||||
sdl2_build_path
|
||||
}
|
||||
|
||||
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 t
|
||||
arget_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 if target_os.contains("linux") {
|
||||
println!("cargo:rustc-link-lib=sndio");
|
||||
} else if target_os == "darwin" {
|
||||
println!("cargo:rustc-link-lib=framework=Cocoa");
|
||||
println!("cargo:rustc-link-lib=framework=IOKit");
|
||||
println!("cargo:rustc-link-lib=framework=Carbon");
|
||||
println!("cargo:rustc-link-lib=framework=ForceFeedback");
|
||||
println!("cargo:rustc-link-lib=framework=CoreVideo");
|
||||
println!("cargo:rustc-link-lib=framework=CoreAudio");
|
||||
println!("cargo:rustc-link-lib=framework=AudioToolbox");
|
||||
println!("cargo:rustc-link-lib=iconv");
|
||||
// compile a shared or static lib depending on the feature
|
||||
#[cfg(feature = "bundled")]
|
||||
fn compile_sdl2(sdl2_build_path: &Path) -> PathBuf {
|
||||
let install_path = if cfg!(feature = "static-link") {
|
||||
cmake::Config::new(sdl2_build_path)
|
||||
.define("SDL_SHARED", "OFF")
|
||||
.define("SDL_STATIC", "ON")
|
||||
.build()
|
||||
} else {
|
||||
// TODO: Add other platform linker options here.
|
||||
cmake::Config::new(sdl2_build_path)
|
||||
.define("SDL_SHARED", "ON")
|
||||
.define("SDL_STATIC", "OFF")
|
||||
.build()
|
||||
};
|
||||
|
||||
install_path
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "bundled"))]
|
||||
fn compute_include_paths() -> Vec<String> {
|
||||
let mut include_paths: Vec<String> = vec!();
|
||||
|
||||
if let Ok(include_path) = env::var("SDL2_INCLUDE_PATH") {
|
||||
include_paths.push(format!("{}", include_path));
|
||||
};
|
||||
|
||||
#[cfg(feature = "pkg-config")] {
|
||||
// don't print the "cargo:xxx" directives, we're just trying to get the include paths here
|
||||
let pkg_config_library = pkg_config::Config::new().print_system_libs(false).probe("sdl2").unwrap();
|
||||
for path in pkg_config_library.include_paths {
|
||||
include_paths.push(format!("{}", path.display()));
|
||||
};
|
||||
}
|
||||
|
||||
include_paths
|
||||
}
|
||||
|
||||
fn link_sdl2(target_os: &str) {
|
||||
#[cfg(all(feature = "use-pkgconfig", not(feature = "bundled")))] {
|
||||
// prints the appropriate linking parameters when using pkg-config
|
||||
// useless when using "bundled"
|
||||
get_pkg_config();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "static-link"))] {
|
||||
if target_os == "ios" {
|
||||
// iOS requires additional linking to function properly
|
||||
println!("cargo:rustc-flags=-l framework=AVFoundation");
|
||||
println!("cargo:rustc-flags=-l framework=AudioToolbox");
|
||||
println!("cargo:rustc-flags=-l framework=CoreAudio");
|
||||
println!("cargo:rustc-flags=-l framework=CoreGraphics");
|
||||
println!("cargo:rustc-flags=-l framework=CoreMotion");
|
||||
println!("cargo:rustc-flags=-l framework=Foundation");
|
||||
println!("cargo:rustc-flags=-l framework=GameController");
|
||||
println!("cargo:rustc-flags=-l framework=OpenGLES");
|
||||
println!("cargo:rustc-flags=-l framework=QuartzCore");
|
||||
println!("cargo:rustc-flags=-l framework=UIKit");
|
||||
}
|
||||
|
||||
// pkg-config automatically prints this output when probing,
|
||||
// however pkg_config isn't used with the feature "bundled"
|
||||
if cfg!(feature = "bundled") || cfg!(not(feature = "use-pkgconfig")) {
|
||||
if cfg!(feature = "use_mac_framework") && target_os == "darwin" {
|
||||
println!("cargo:rustc-flags=-l framework=SDL2");
|
||||
} else {
|
||||
println!("cargo:rustc-flags=-l SDL2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "static-link")] {
|
||||
if cfg!(feature = "bundled") || cfg!(feature = "use-pkgconfig") == false {
|
||||
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 if target_os.contains("linux") {
|
||||
println!("cargo:rustc-link-lib=sndio");
|
||||
} else if target_os == "darwin" {
|
||||
println!("cargo:rustc-link-lib=framework=Cocoa");
|
||||
println!("cargo:rustc-link-lib=framework=IOKit");
|
||||
println!("cargo:rustc-link-lib=framework=Carbon");
|
||||
println!("cargo:rustc-link-lib=framework=ForceFeedback");
|
||||
println!("cargo:rustc-link-lib=framework=CoreVideo");
|
||||
println!("cargo:rustc-link-lib=framework=CoreAudio");
|
||||
println!("cargo:rustc-link-lib=framework=AudioToolbox");
|
||||
println!("cargo:rustc-link-lib=iconv");
|
||||
} 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);
|
||||
#[cfg(feature = "bundled")] {
|
||||
let sdl2_source_path = download_sdl2();
|
||||
let sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path());
|
||||
|
||||
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");
|
||||
println!("cargo:rustc-flags=-l framework=CoreGraphics");
|
||||
println!("cargo:rustc-flags=-l framework=CoreMotion");
|
||||
println!("cargo:rustc-flags=-l framework=Foundation");
|
||||
println!("cargo:rustc-flags=-l framework=GameController");
|
||||
println!("cargo:rustc-flags=-l framework=OpenGLES");
|
||||
println!("cargo:rustc-flags=-l framework=QuartzCore");
|
||||
println!("cargo:rustc-flags=-l framework=UIKit");
|
||||
let sdl2_downloaded_include_path = sdl2_source_path.join("include");
|
||||
let sdl2_compiled_lib_path = sdl2_compiled_path.join("lib");
|
||||
|
||||
println!("cargo:rustc-link-search={}", sdl2_compiled_lib_path.display());
|
||||
|
||||
#[cfg(feature = "bindgen")] {
|
||||
let include_paths = vec!(String::from(sdl2_downloaded_include_path.to_str().unwrap()));
|
||||
generate_bindings(target.as_str(), host.as_str(), include_paths.as_slice())
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(all(not(feature = "bundled"), feature = "bindgen"))] {
|
||||
let include_paths: Vec<String> = compute_include_paths();
|
||||
generate_bindings(target.as_str(), host.as_str(), include_paths.as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature="pkg-config"))]
|
||||
#[cfg(not(feature="bundled"))]
|
||||
fn build_pkgconfig() -> bool {
|
||||
false
|
||||
}
|
||||
#[cfg(not(feature = "bindgen"))] {
|
||||
copy_pregenerated_bindings();
|
||||
}
|
||||
|
||||
#[cfg(feature="pkg-config")]
|
||||
fn build_pkgconfig() -> bool {
|
||||
pkg_config::probe_library("sdl2").is_ok()
|
||||
link_sdl2(target_os);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "bindgen"))]
|
||||
fn prepare_bindings(target: &str, host: &str) {
|
||||
add_explicit_linker_flags(get_os_from_triple(target).unwrap());
|
||||
fn copy_pregenerated_bindings() {
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
fs::copy(crate_path.join("pregenerated_bindings.rs"), out_path.join("bindings.rs"))
|
||||
@@ -152,36 +237,35 @@ fn prepare_bindings(target: &str, host: &str) {
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindgen")]
|
||||
fn prepare_bindings(target: &str, host: &str) {
|
||||
// headers_path is a list of directories where the SDL2 headers are expected
|
||||
// to be found by bindgen (should point to the include/ directories)
|
||||
fn generate_bindings<S: AsRef<str> + ::std::fmt::Debug>(target: &str, host: &str, headers_paths: &[S]) {
|
||||
let target_os = get_os_from_triple(target).unwrap();
|
||||
let mut bindings = bindgen::Builder::default();
|
||||
|
||||
// Set correct target triple when cross-compiling
|
||||
// Set correct target triple for bindgen when cross-compiling
|
||||
if target != host {
|
||||
bindings = bindings.clang_arg("-target");
|
||||
bindings = bindings.clang_arg(target.clone());
|
||||
}
|
||||
|
||||
if let Ok(include_path) = env::var("SDL2_INCLUDE_PATH") {
|
||||
bindings = bindings.clang_arg(String::from("-I") + &include_path);
|
||||
add_explicit_linker_flags(get_os_from_triple(target).unwrap());
|
||||
} else if build_pkgconfig() {
|
||||
#[cfg(feature = "pkg-config")]
|
||||
for path in &pkg_config::find_library("sdl2").unwrap().include_paths {
|
||||
bindings = bindings.clang_arg(String::from("-I") +
|
||||
&path.clone().into_os_string().into_string().unwrap());
|
||||
}
|
||||
} else {
|
||||
if headers_paths.len() == 0 {
|
||||
// if no paths are being provided, fall back to the headers included in this repo
|
||||
let mut include_path: PathBuf = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
include_path.push(String::from("SDL2-") + SDL2_BUNDLED_VERSION);
|
||||
include_path.push(format!("SDL2-{}", SDL2_HEADERS_BUNDLED_VERSION));
|
||||
include_path.push("include");
|
||||
bindings = bindings.clang_arg(String::from("-I") +
|
||||
&include_path.into_os_string().into_string().unwrap());
|
||||
// SDL2 hasn't a default configuration for Linux
|
||||
if get_os_from_triple(target).unwrap() == "linux" {
|
||||
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
||||
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
||||
bindings = bindings.clang_arg(format!("-I{}", include_path.display()));
|
||||
} else {
|
||||
// if paths are included, use them for bindgen. Bindgen should use the first one.
|
||||
for headers_path in headers_paths {
|
||||
bindings = bindings.clang_arg(format!("-I{}", headers_path.as_ref()))
|
||||
}
|
||||
add_explicit_linker_flags(get_os_from_triple(target).unwrap());
|
||||
}
|
||||
|
||||
// SDL2 hasn't a default configuration for Linux
|
||||
if target_os == "linux" {
|
||||
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
||||
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
||||
}
|
||||
|
||||
let bindings = bindings
|
||||
@@ -206,12 +290,4 @@ fn prepare_bindings(target: &str, host: &str) {
|
||||
fn get_os_from_triple(triple: &str) -> Option<&str>
|
||||
{
|
||||
triple.split("-").nth(2)
|
||||
}
|
||||
|
||||
fn add_explicit_linker_flags(target_os: &str) {
|
||||
if cfg!(feature = "use_mac_framework") && target_os == "darwin" {
|
||||
println!("cargo:rustc-flags=-l framework=SDL2");
|
||||
} else {
|
||||
println!("cargo:rustc-flags=-l SDL2");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user