mirror of
https://github.com/doukutsu-rs/rust-sdl2.git
synced 2026-08-24 13:05:30 -07:00
988 lines
37 KiB
Rust
988 lines
37 KiB
Rust
#![allow(unused_imports, dead_code, unused_variables)]
|
|
|
|
#[cfg(feature = "bindgen")]
|
|
extern crate bindgen;
|
|
#[macro_use]
|
|
extern crate cfg_if;
|
|
#[cfg(feature = "bundled")]
|
|
extern crate cmake;
|
|
#[cfg(feature = "pkg-config")]
|
|
extern crate pkg_config;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::Command;
|
|
use std::{env, fs, io};
|
|
|
|
#[cfg(feature = "bindgen")]
|
|
macro_rules! add_msvc_includes_to_bindings {
|
|
($bindings:expr) => {
|
|
$bindings = $bindings.clang_arg(format!(
|
|
"-IC:/Program Files (x86)/Windows Kits/8.1/Include/shared"
|
|
));
|
|
$bindings = $bindings.clang_arg(format!("-IC:/Program Files/LLVM/lib/clang/5.0.0/include"));
|
|
$bindings = $bindings.clang_arg(format!(
|
|
"-IC:/Program Files (x86)/Windows Kits/10/Include/10.0.10240.0/ucrt"
|
|
));
|
|
$bindings = $bindings.clang_arg(format!(
|
|
"-IC:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include"
|
|
));
|
|
$bindings = $bindings.clang_arg(format!(
|
|
"-IC:/Program Files (x86)/Windows Kits/8.1/Include/um"
|
|
));
|
|
};
|
|
}
|
|
|
|
#[cfg(feature = "bundled")]
|
|
fn init_submodule(sdl_path: &Path) {
|
|
if !sdl_path.join("CMakeLists.txt").exists() {
|
|
Command::new("git")
|
|
.args(["submodule", "update", "--init"])
|
|
.current_dir(sdl_path)
|
|
.status()
|
|
.expect("Git is needed to retrieve the SDL source files");
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "use-pkgconfig")]
|
|
fn pkg_config_print(statik: bool, lib_name: &str) {
|
|
pkg_config::Config::new()
|
|
.statik(statik)
|
|
.probe(lib_name)
|
|
.unwrap();
|
|
}
|
|
|
|
#[cfg(feature = "use-pkgconfig")]
|
|
fn get_pkg_config() {
|
|
let statik: bool = if cfg!(feature = "static-link") {
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
|
|
pkg_config_print(statik, "sdl2");
|
|
if cfg!(feature = "image") {
|
|
pkg_config_print(statik, "SDL2_image");
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
pkg_config_print(statik, "SDL2_ttf");
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
pkg_config_print(statik, "SDL2_mixer");
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
pkg_config_print(statik, "SDL2_gfx");
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "use-vcpkg")]
|
|
fn get_vcpkg_config() {
|
|
vcpkg::find_package("sdl2").unwrap();
|
|
if cfg!(feature = "image") {
|
|
vcpkg::find_package("sdl2-image").unwrap();
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
vcpkg::find_package("sdl2-ttf").unwrap();
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
vcpkg::find_package("sdl2-mixer").unwrap();
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
vcpkg::find_package("sdl2-gfx").unwrap();
|
|
}
|
|
}
|
|
|
|
// compile a shared or static lib depending on the feature
|
|
#[cfg(feature = "bundled")]
|
|
fn compile_sdl2(sdl2_build_path: &Path, target_os: &str) -> PathBuf {
|
|
let mut cfg = cmake::Config::new(sdl2_build_path);
|
|
if let Ok(profile) = env::var("SDL2_BUILD_PROFILE") {
|
|
cfg.profile(&profile);
|
|
cfg.define("CMAKE_CONFIGURATION_TYPES", &profile);
|
|
} else {
|
|
cfg.profile("Release");
|
|
cfg.define("CMAKE_CONFIGURATION_TYPES", "Release");
|
|
}
|
|
|
|
// Allow specifying custom toolchain specifically for SDL2.
|
|
if let Ok(toolchain) = env::var("SDL2_TOOLCHAIN") {
|
|
cfg.define("CMAKE_TOOLCHAIN_FILE", &toolchain);
|
|
} else {
|
|
// Override __FLTUSED__ to keep the _fltused symbol from getting defined in the static build.
|
|
// This conflicts and fails to link properly when building statically on Windows, likely due to
|
|
// COMDAT conflicts/breakage happening somewhere.
|
|
#[cfg(feature = "static-link")]
|
|
cfg.cflag("-D__FLTUSED__");
|
|
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
// Add common flag for affected version and above
|
|
use version_compare::{compare_to, Cmp};
|
|
if let Ok(version) = std::process::Command::new("cc")
|
|
.arg("-dumpversion")
|
|
.output()
|
|
{
|
|
let affected =
|
|
compare_to(std::str::from_utf8(&version.stdout).unwrap(), "10", Cmp::Ge)
|
|
.unwrap_or(true);
|
|
if affected {
|
|
cfg.cflag("-fcommon");
|
|
}
|
|
}
|
|
// The bundled SDL uses `bool`, `false`, and `true` which are reserved keywords in c23
|
|
cfg.define("CMAKE_C_STANDARD", "99");
|
|
}
|
|
}
|
|
|
|
if target_os == "windows-gnu" {
|
|
cfg.define("VIDEO_OPENGLES", "OFF");
|
|
}
|
|
|
|
if target_os == "android" {
|
|
let ndk_home = env::var("ANDROID_NDK_HOME")
|
|
.expect("ANDROID_NDK_HOME environment variable must be set when compiling for Android");
|
|
|
|
#[cfg(target_os = "windows")]
|
|
let ndk_home = ndk_home.replace("\\", "/");
|
|
|
|
cfg.define("ANDROID_NDK", ndk_home);
|
|
}
|
|
|
|
if cfg!(feature = "static-link") {
|
|
cfg.define("SDL_SHARED", "OFF");
|
|
cfg.define("SDL_STATIC", "ON");
|
|
// Prevent SDL to provide it own "main" which cause a conflict when this crate linked
|
|
// to C/C++ program.
|
|
cfg.define("SDL_MAIN_HANDLED", "ON");
|
|
} else {
|
|
cfg.define("SDL_SHARED", "ON");
|
|
cfg.define("SDL_STATIC", "OFF");
|
|
}
|
|
|
|
cfg.build()
|
|
}
|
|
|
|
#[cfg(not(feature = "bundled"))]
|
|
fn compute_include_paths(fallback_path: String) -> Vec<String> {
|
|
let mut include_paths: Vec<String> = vec![];
|
|
|
|
if let Ok(include_path) = env::var("SDL2_INCLUDE_PATH") {
|
|
include_paths.push(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()));
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "vcpkg")]
|
|
{
|
|
// don't print the "cargo:xxx" directives, we're just trying to get the include paths here
|
|
let vcpkg_library = vcpkg::Config::new()
|
|
.cargo_metadata(false)
|
|
.probe("sdl2")
|
|
.unwrap();
|
|
for path in vcpkg_library.include_paths {
|
|
include_paths.push(format!("{}", path.display()));
|
|
}
|
|
}
|
|
|
|
if include_paths.is_empty() {
|
|
include_paths.push(fallback_path);
|
|
}
|
|
|
|
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(all(feature = "use-vcpkg", not(feature = "bundled")))]
|
|
{
|
|
// prints the appropriate linking parameters when using pkg-config
|
|
// useless when using "bundled"
|
|
get_vcpkg_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=CoreHaptics");
|
|
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")) {
|
|
let use_mac_framework = cfg!(feature = "use_mac_framework") && target_os == "darwin";
|
|
let use_ios_framework = cfg!(feature = "use_ios_framework") && target_os == "ios";
|
|
if use_mac_framework || use_ios_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2");
|
|
} else if target_os != "emscripten" {
|
|
println!("cargo:rustc-flags=-l SDL2");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "static-link")]
|
|
{
|
|
if cfg!(feature = "bundled")
|
|
|| (cfg!(feature = "use-pkgconfig") == false && cfg!(feature = "use-vcpkg") == false)
|
|
{
|
|
println!("cargo:rustc-link-lib=static=SDL2main");
|
|
if target_os == "windows-msvc" {
|
|
println!("cargo:rustc-link-lib=static=SDL2-static");
|
|
} else {
|
|
println!("cargo:rustc-link-lib=static=SDL2");
|
|
}
|
|
|
|
// Additional SDL libraries are not supported when using "bundled"
|
|
if !cfg!(feature = "bundled") {
|
|
if cfg!(feature = "gfx") {
|
|
println!("cargo:rustc-link-lib=static=SDL2_gfx");
|
|
}
|
|
|
|
if cfg!(feature = "mixer") {
|
|
println!("cargo:rustc-link-lib=static=SDL2_mixer");
|
|
}
|
|
|
|
if cfg!(feature = "image") {
|
|
println!("cargo:rustc-link-lib=static=SDL2_image");
|
|
}
|
|
|
|
if cfg!(feature = "ttf") {
|
|
println!("cargo:rustc-link-lib=static=SDL2_ttf");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also linked to any required libraries for each supported platform
|
|
if target_os.contains("windows") {
|
|
println!("cargo:rustc-link-lib=shell32");
|
|
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");
|
|
println!("cargo:rustc-link-lib=setupapi");
|
|
println!("cargo:rustc-link-lib=advapi32");
|
|
} 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=GameController");
|
|
println!("cargo:rustc-link-lib=framework=CoreHaptics");
|
|
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=framework=Metal");
|
|
println!("cargo:rustc-link-lib=iconv");
|
|
} else if target_os == "android" {
|
|
println!("cargo:rustc-link-lib=android");
|
|
println!("cargo:rustc-link-lib=dl");
|
|
println!("cargo:rustc-link-lib=GLESv1_CM");
|
|
println!("cargo:rustc-link-lib=GLESv2");
|
|
println!("cargo:rustc-link-lib=hidapi");
|
|
println!("cargo:rustc-link-lib=log");
|
|
println!("cargo:rustc-link-lib=OpenSLES");
|
|
} else {
|
|
// TODO: Add other platform linker options here.
|
|
}
|
|
}
|
|
// SDL libraries seem to not be packed with pkgconfig file on all distros,
|
|
// and in the same distros (fedora at least) a symlink is also missing.
|
|
//
|
|
// Linking directly with file is not possible with cargo since the
|
|
// ':filename' syntax is used for renaming of libraries, which basically
|
|
// leaves it up to the user to make a symlink to the shared object so
|
|
// -lSDL2_mixer can find it.
|
|
#[cfg(all(not(feature = "use-pkgconfig"), not(feature = "static-link")))]
|
|
{
|
|
if cfg!(feature = "mixer") {
|
|
if target_os.contains("linux")
|
|
|| target_os.contains("freebsd")
|
|
|| target_os.contains("openbsd")
|
|
{
|
|
println!("cargo:rustc-flags=-l SDL2_mixer");
|
|
} else if target_os.contains("windows") {
|
|
println!("cargo:rustc-flags=-l SDL2_mixer");
|
|
} else if target_os.contains("darwin") {
|
|
let use_framework = cfg!(any(mac_framework, feature = "use_mac_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_mixer");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_mixer");
|
|
}
|
|
} else if target_os.contains("ios") {
|
|
let use_framework = cfg!(any(ios_framework, feature = "use_ios_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_mixer");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_mixer");
|
|
}
|
|
}
|
|
}
|
|
if cfg!(feature = "image") {
|
|
if target_os.contains("linux")
|
|
|| target_os.contains("freebsd")
|
|
|| target_os.contains("openbsd")
|
|
{
|
|
println!("cargo:rustc-flags=-l SDL2_image");
|
|
} else if target_os.contains("windows") {
|
|
println!("cargo:rustc-flags=-l SDL2_image");
|
|
} else if target_os.contains("darwin") {
|
|
let use_framework = cfg!(any(mac_framework, feature = "use_mac_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_image");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_image");
|
|
}
|
|
} else if target_os.contains("ios") {
|
|
let use_framework = cfg!(any(ios_framework, feature = "use_ios_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_image");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_image");
|
|
}
|
|
}
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
if target_os.contains("linux")
|
|
|| target_os.contains("freebsd")
|
|
|| target_os.contains("openbsd")
|
|
{
|
|
println!("cargo:rustc-flags=-l SDL2_ttf");
|
|
} else if target_os.contains("windows") {
|
|
println!("cargo:rustc-flags=-l SDL2_ttf");
|
|
} else if target_os.contains("darwin") {
|
|
let use_framework = cfg!(any(mac_framework, feature = "use_mac_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_ttf");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_ttf");
|
|
}
|
|
} else if target_os.contains("ios") {
|
|
let use_framework = cfg!(any(ios_framework, feature = "use_ios_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_ttf");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_ttf");
|
|
}
|
|
}
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
if target_os.contains("linux")
|
|
|| target_os.contains("freebsd")
|
|
|| target_os.contains("openbsd")
|
|
{
|
|
println!("cargo:rustc-flags=-l SDL2_gfx");
|
|
} else if target_os.contains("windows") {
|
|
println!("cargo:rustc-flags=-l SDL2_gfx");
|
|
} else if target_os.contains("darwin") {
|
|
let use_framework = cfg!(any(mac_framework, feature = "use_mac_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_gfx");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_gfx");
|
|
}
|
|
} else if target_os.contains("ios") {
|
|
let use_framework = cfg!(any(ios_framework, feature = "use_ios_framework"));
|
|
if use_framework {
|
|
println!("cargo:rustc-flags=-l framework=SDL2_gfx");
|
|
} else {
|
|
println!("cargo:rustc-flags=-l SDL2_gfx");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn find_cargo_target_dir() -> PathBuf {
|
|
// Infer the top level cargo target dir from the OUT_DIR by searching
|
|
// upwards until we get to $CARGO_TARGET_DIR/build/ (which is always one
|
|
// level up from the deepest directory containing our package name)
|
|
let pkg_name = env::var("CARGO_PKG_NAME").unwrap();
|
|
let mut out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
loop {
|
|
{
|
|
let final_path_segment = out_dir.file_name().unwrap();
|
|
if final_path_segment.to_string_lossy().contains(&pkg_name) {
|
|
break;
|
|
}
|
|
}
|
|
if !out_dir.pop() {
|
|
panic!("Malformed build path: {}", out_dir.to_string_lossy());
|
|
}
|
|
}
|
|
out_dir.pop();
|
|
out_dir.pop();
|
|
out_dir
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn copy_library_symlink(src_path: &Path, target_path: &Path) {
|
|
if let Ok(link_path) = fs::read_link(src_path) {
|
|
// Copy symlinks to:
|
|
// * target dir: as a product ship product of the build,
|
|
// * deps directory: as comment example testing doesn't pick up the library search path
|
|
// otherwise and fails.
|
|
let deps_path = target_path.join("deps");
|
|
for path in &[target_path, &deps_path] {
|
|
let dst_path = path.join(src_path.file_name().expect("Path missing filename"));
|
|
// Silently drop errors here, in case the symlink already exists.
|
|
let _ = std::os::unix::fs::symlink(&link_path, &dst_path);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(not(unix))]
|
|
fn copy_library_symlink(src_path: &Path, target_path: &Path) {}
|
|
|
|
fn copy_library_file(src_path: &Path, target_path: &Path) {
|
|
// Copy the shared libs to:
|
|
// * target dir: as a product ship product of the build,
|
|
// * deps directory: as comment example testing doesn't pick up the library search path
|
|
// otherwise and fails.
|
|
let deps_path = target_path.join("deps");
|
|
for path in &[target_path, &deps_path] {
|
|
let dst_path = path.join(src_path.file_name().expect("Path missing filename"));
|
|
|
|
fs::copy(src_path, &dst_path).unwrap_or_else(|_| {
|
|
panic!(
|
|
"Failed to copy SDL2 dynamic library from {} to {}",
|
|
src_path.to_string_lossy(),
|
|
dst_path.to_string_lossy()
|
|
)
|
|
});
|
|
}
|
|
}
|
|
|
|
fn copy_dynamic_libraries(sdl2_compiled_path: &Path, target_os: &str) {
|
|
let target_path = find_cargo_target_dir();
|
|
|
|
// Windows binaries do not embed library search paths, so successfully
|
|
// linking the DLL isn't sufficient to find it at runtime -- it must be
|
|
// either on PATH or in the current working directory when we run binaries
|
|
// linked against it. In other words, to run the test suite we need to
|
|
// copy sdl2.dll out of its build tree and down to the top level cargo
|
|
// binary output directory.
|
|
if target_os.contains("windows") {
|
|
let sdl2_dll_name = "SDL2.dll";
|
|
let sdl2_bin_path = sdl2_compiled_path.join("bin");
|
|
let src_dll_path = sdl2_bin_path.join(sdl2_dll_name);
|
|
|
|
copy_library_file(&src_dll_path, &target_path);
|
|
} else if target_os != "emscripten" {
|
|
// Find all libraries build and copy them, symlinks included.
|
|
let mut found = false;
|
|
let lib_dirs = &["lib", "lib64"];
|
|
for lib_dir in lib_dirs {
|
|
let lib_path = sdl2_compiled_path.join(lib_dir);
|
|
if lib_path.exists() {
|
|
found = true;
|
|
for entry in std::fs::read_dir(&lib_path)
|
|
.unwrap_or_else(|_| panic!("Couldn't readdir {}", lib_dir))
|
|
{
|
|
let entry = entry.expect("Error looking at lib dir");
|
|
if let Ok(file_type) = entry.file_type() {
|
|
if file_type.is_symlink() {
|
|
copy_library_symlink(&entry.path(), &target_path);
|
|
} else if file_type.is_file() {
|
|
copy_library_file(&entry.path(), &target_path)
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if !found {
|
|
panic!("Failed to find CMake output dir");
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
|
|
let sdl2_source_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("SDL");
|
|
|
|
let sdl2_compiled_path: PathBuf;
|
|
#[cfg(feature = "bundled")]
|
|
{
|
|
init_submodule(sdl2_source_path.as_path());
|
|
sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os);
|
|
|
|
println!(
|
|
"cargo:rustc-link-search={}",
|
|
sdl2_compiled_path.join("lib64").display()
|
|
);
|
|
println!(
|
|
"cargo:rustc-link-search={}",
|
|
sdl2_compiled_path.join("lib").display()
|
|
);
|
|
}
|
|
|
|
let sdl2_includes = sdl2_source_path
|
|
.join("include")
|
|
.to_str()
|
|
.unwrap()
|
|
.to_string();
|
|
|
|
#[cfg(feature = "bindgen")]
|
|
{
|
|
let include_paths: Vec<String>;
|
|
#[cfg(feature = "bundled")]
|
|
{
|
|
include_paths = vec![sdl2_includes];
|
|
}
|
|
#[cfg(not(feature = "bundled"))]
|
|
{
|
|
include_paths = compute_include_paths(sdl2_includes)
|
|
}
|
|
generate_bindings(target.as_str(), host.as_str(), include_paths.as_slice());
|
|
println!("cargo:include={}", include_paths.join(":"));
|
|
}
|
|
|
|
#[cfg(not(feature = "bindgen"))]
|
|
{
|
|
copy_pregenerated_bindings();
|
|
println!("cargo:include={}", sdl2_includes);
|
|
}
|
|
|
|
link_sdl2(target_os);
|
|
|
|
// Android builds shared libhidapi.so even for static builds.
|
|
#[cfg(all(
|
|
feature = "bundled",
|
|
any(not(feature = "static-link"), target_os = "android")
|
|
))]
|
|
{
|
|
copy_dynamic_libraries(&sdl2_compiled_path, target_os);
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "bindgen"))]
|
|
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("sdl_bindings.rs"),
|
|
out_path.join("sdl_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated bindings!");
|
|
|
|
if cfg!(feature = "image") {
|
|
fs::copy(
|
|
crate_path.join("sdl_image_bindings.rs"),
|
|
out_path.join("sdl_image_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_image bindings!");
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
fs::copy(
|
|
crate_path.join("sdl_ttf_bindings.rs"),
|
|
out_path.join("sdl_ttf_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_ttf bindings!");
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
fs::copy(
|
|
crate_path.join("sdl_mixer_bindings.rs"),
|
|
out_path.join("sdl_mixer_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_mixer bindings!");
|
|
}
|
|
|
|
if cfg!(feature = "gfx") {
|
|
fs::copy(
|
|
crate_path.join("sdl_gfx_framerate_bindings.rs"),
|
|
out_path.join("sdl_gfx_framerate_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_gfx framerate bindings!");
|
|
|
|
fs::copy(
|
|
crate_path.join("sdl_gfx_primitives_bindings.rs"),
|
|
out_path.join("sdl_gfx_primitives_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_gfx primitives bindings!");
|
|
|
|
fs::copy(
|
|
crate_path.join("sdl_gfx_imagefilter_bindings.rs"),
|
|
out_path.join("sdl_gfx_imagefilter_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_gfx imagefilter bindings!");
|
|
|
|
fs::copy(
|
|
crate_path.join("sdl_gfx_rotozoom_bindings.rs"),
|
|
out_path.join("sdl_gfx_rotozoom_bindings.rs"),
|
|
)
|
|
.expect("Couldn't find pregenerated SDL_gfx rotozoom bindings!");
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "bindgen")]
|
|
// 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(target: &str, host: &str, headers_paths: &[String]) {
|
|
let target_os = get_os_from_triple(target).unwrap();
|
|
let mut bindings = bindgen::Builder::default()
|
|
// enable no_std-friendly output by only using core definitions
|
|
.use_core()
|
|
.default_enum_style(bindgen::EnumVariation::Rust {
|
|
non_exhaustive: false,
|
|
})
|
|
.ctypes_prefix("libc");
|
|
|
|
let mut image_bindings = bindgen::Builder::default()
|
|
.use_core()
|
|
.raw_line("use crate::*;")
|
|
.ctypes_prefix("libc");
|
|
|
|
let mut ttf_bindings = bindgen::Builder::default()
|
|
.use_core()
|
|
.raw_line("use crate::*;")
|
|
.ctypes_prefix("libc");
|
|
|
|
let mut mixer_bindings = bindgen::Builder::default()
|
|
.use_core()
|
|
.raw_line("use crate::*;")
|
|
.ctypes_prefix("libc");
|
|
|
|
let mut gfx_framerate_bindings = bindgen::Builder::default().use_core().ctypes_prefix("libc");
|
|
let mut gfx_primitives_bindings = bindgen::Builder::default()
|
|
.use_core()
|
|
.raw_line("use crate::*;")
|
|
.ctypes_prefix("libc");
|
|
let mut gfx_imagefilter_bindings = bindgen::Builder::default().use_core().ctypes_prefix("libc");
|
|
let mut gfx_rotozoom_bindings = bindgen::Builder::default()
|
|
.use_core()
|
|
.raw_line("use crate::*;")
|
|
.ctypes_prefix("libc");
|
|
|
|
// Set correct target triple for bindgen when cross-compiling
|
|
if target != host {
|
|
bindings = bindings.clang_arg("-target");
|
|
bindings = bindings.clang_arg(target);
|
|
|
|
if cfg!(feature = "image") {
|
|
image_bindings = image_bindings.clang_arg("-target");
|
|
image_bindings = image_bindings.clang_arg(target);
|
|
}
|
|
|
|
if cfg!(feature = "ttf") {
|
|
ttf_bindings = ttf_bindings.clang_arg("-target");
|
|
ttf_bindings = ttf_bindings.clang_arg(target);
|
|
}
|
|
|
|
if cfg!(feature = "mixer") {
|
|
mixer_bindings = mixer_bindings.clang_arg("-target");
|
|
mixer_bindings = mixer_bindings.clang_arg(target);
|
|
}
|
|
|
|
if cfg!(feature = "gfx") {
|
|
gfx_framerate_bindings = gfx_framerate_bindings.clang_arg("-target");
|
|
gfx_framerate_bindings = gfx_framerate_bindings.clang_arg(target);
|
|
|
|
gfx_primitives_bindings = gfx_primitives_bindings.clang_arg("-target");
|
|
gfx_primitives_bindings = gfx_primitives_bindings.clang_arg(target);
|
|
|
|
gfx_imagefilter_bindings = gfx_imagefilter_bindings.clang_arg("-target");
|
|
gfx_imagefilter_bindings = gfx_imagefilter_bindings.clang_arg(target);
|
|
|
|
gfx_rotozoom_bindings = gfx_rotozoom_bindings.clang_arg("-target");
|
|
gfx_rotozoom_bindings = gfx_rotozoom_bindings.clang_arg(target);
|
|
}
|
|
}
|
|
|
|
for headers_path in headers_paths {
|
|
bindings = bindings.clang_arg(format!("-I{}", headers_path));
|
|
if cfg!(feature = "image") {
|
|
image_bindings = image_bindings.clang_arg(format!("-I{}", headers_path));
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
ttf_bindings = ttf_bindings.clang_arg(format!("-I{}", headers_path));
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
mixer_bindings = mixer_bindings.clang_arg(format!("-I{}", headers_path));
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
gfx_framerate_bindings =
|
|
gfx_framerate_bindings.clang_arg(format!("-I{}", headers_path));
|
|
gfx_primitives_bindings =
|
|
gfx_primitives_bindings.clang_arg(format!("-I{}", headers_path));
|
|
gfx_imagefilter_bindings =
|
|
gfx_imagefilter_bindings.clang_arg(format!("-I{}", headers_path));
|
|
gfx_rotozoom_bindings = gfx_rotozoom_bindings.clang_arg(format!("-I{}", headers_path));
|
|
}
|
|
}
|
|
|
|
if target_os == "windows-msvc" {
|
|
add_msvc_includes_to_bindings!(bindings);
|
|
if cfg!(feature = "image") {
|
|
add_msvc_includes_to_bindings!(image_bindings);
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
add_msvc_includes_to_bindings!(ttf_bindings);
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
add_msvc_includes_to_bindings!(mixer_bindings);
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
add_msvc_includes_to_bindings!(gfx_framerate_bindings);
|
|
add_msvc_includes_to_bindings!(gfx_primitives_bindings);
|
|
add_msvc_includes_to_bindings!(gfx_imagefilter_bindings);
|
|
add_msvc_includes_to_bindings!(gfx_rotozoom_bindings);
|
|
}
|
|
};
|
|
|
|
// SDL2 hasn't a default configuration for Linux
|
|
if target_os == "linux-gnu" {
|
|
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
if cfg!(feature = "image") {
|
|
image_bindings = image_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
image_bindings = image_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
}
|
|
if cfg!(feature = "ttf") {
|
|
ttf_bindings = ttf_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
ttf_bindings = ttf_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
}
|
|
if cfg!(feature = "mixer") {
|
|
mixer_bindings = mixer_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
mixer_bindings = mixer_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
}
|
|
if cfg!(feature = "gfx") {
|
|
gfx_framerate_bindings = gfx_framerate_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
gfx_framerate_bindings = gfx_framerate_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
gfx_primitives_bindings = gfx_primitives_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
gfx_primitives_bindings =
|
|
gfx_primitives_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
gfx_imagefilter_bindings = gfx_imagefilter_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
gfx_imagefilter_bindings =
|
|
gfx_imagefilter_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
gfx_rotozoom_bindings = gfx_rotozoom_bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
|
|
gfx_rotozoom_bindings = gfx_rotozoom_bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
|
|
}
|
|
}
|
|
|
|
let bindings = bindings
|
|
.header("wrapper.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.derive_debug(false)
|
|
.generate()
|
|
.expect("Unable to generate bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
bindings
|
|
.write_to_file(out_path.join("sdl_bindings.rs"))
|
|
.expect("Couldn't write bindings!");
|
|
|
|
if cfg!(feature = "image") {
|
|
let image_bindings = image_bindings
|
|
.header("wrapper_image.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.allowlist_type("IMG.*")
|
|
.allowlist_function("IMG.*")
|
|
.allowlist_var("IMG.*")
|
|
.blocklist_type("SDL_.*")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate image_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
image_bindings
|
|
.write_to_file(out_path.join("sdl_image_bindings.rs"))
|
|
.expect("Couldn't write image_bindings!");
|
|
}
|
|
|
|
if cfg!(feature = "ttf") {
|
|
let ttf_bindings = ttf_bindings
|
|
.header("wrapper_ttf.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.allowlist_type("TTF.*")
|
|
.allowlist_function("TTF.*")
|
|
.allowlist_var("TTF.*")
|
|
.blocklist_type("SDL_.*")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate ttf_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
ttf_bindings
|
|
.write_to_file(out_path.join("sdl_ttf_bindings.rs"))
|
|
.expect("Couldn't write ttf_bindings!");
|
|
}
|
|
|
|
if cfg!(feature = "mixer") {
|
|
let mixer_bindings = mixer_bindings
|
|
.header("wrapper_mixer.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.allowlist_type("MIX.*")
|
|
.allowlist_type("Mix.*")
|
|
.allowlist_type("MUS.*")
|
|
.allowlist_function("Mix.*")
|
|
.allowlist_var("MIX.*")
|
|
.allowlist_var("MUS.*")
|
|
.blocklist_type("SDL_.*")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate mixer_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
mixer_bindings
|
|
.write_to_file(out_path.join("sdl_mixer_bindings.rs"))
|
|
.expect("Couldn't write mixer_bindings!");
|
|
}
|
|
|
|
if cfg!(feature = "gfx") {
|
|
let gfx_framerate_bindings = gfx_framerate_bindings
|
|
.header("wrapper_gfx_framerate.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.allowlist_type("FPS.*")
|
|
.allowlist_function("SDL_.*rame.*")
|
|
.allowlist_var("FPS.*")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate gfx_framerate_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
gfx_framerate_bindings
|
|
.write_to_file(out_path.join("sdl_gfx_framerate_bindings.rs"))
|
|
.expect("Couldn't write gfx_framerate_bindings!");
|
|
|
|
let gfx_primitives_bindings = gfx_primitives_bindings
|
|
.header("wrapper_gfx_primitives.h")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.blocklist_type("SDL_.*")
|
|
.allowlist_function("pixel.*")
|
|
.allowlist_function("rectangle.*")
|
|
.allowlist_function("rounded.*")
|
|
.allowlist_function("box.*")
|
|
.allowlist_function(".*line(Color|RGBA).*")
|
|
.allowlist_function("thick.*")
|
|
.allowlist_function(".*circle.*")
|
|
.allowlist_function("arc.*")
|
|
.allowlist_function("filled.*")
|
|
.allowlist_function(".*ellipse.*")
|
|
.allowlist_function("pie.*")
|
|
.allowlist_function(".*trigon.*")
|
|
.allowlist_function(".*polygon.*")
|
|
.allowlist_function("textured.*")
|
|
.allowlist_function("bezier.*")
|
|
.allowlist_function("character.*")
|
|
.allowlist_function("string.*")
|
|
.allowlist_function("gfx.*")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate gfx_primitives_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
gfx_primitives_bindings
|
|
.write_to_file(out_path.join("sdl_gfx_primitives_bindings.rs"))
|
|
.expect("Couldn't write gfx_primitives_bindings!");
|
|
|
|
let gfx_imagefilter_bindings = gfx_imagefilter_bindings
|
|
.header("wrapper_gfx_imagefilter.h")
|
|
.allowlist_function("SDL_image.*")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate gfx_imagefilter_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
gfx_imagefilter_bindings
|
|
.write_to_file(out_path.join("sdl_gfx_imagefilter_bindings.rs"))
|
|
.expect("Couldn't write gfx_imagefilter_bindings!");
|
|
|
|
let gfx_rotozoom_bindings = gfx_rotozoom_bindings
|
|
.header("wrapper_gfx_rotozoom.h")
|
|
.blocklist_type("SDL_.*")
|
|
.allowlist_function("rotozoom.*")
|
|
.allowlist_function("zoom.*")
|
|
.allowlist_function("shrink.*")
|
|
.allowlist_function("rotate.*")
|
|
.blocklist_item("FP_NAN")
|
|
.blocklist_item("FP_INFINITE")
|
|
.blocklist_item("FP_ZERO")
|
|
.blocklist_item("FP_SUBNORMAL")
|
|
.blocklist_item("FP_NORMAL")
|
|
.blocklist_type("_IO.*|FILE")
|
|
.generate()
|
|
.expect("Unable to generate gfx_rotozoom_bindings!");
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
gfx_rotozoom_bindings
|
|
.write_to_file(out_path.join("sdl_gfx_rotozoom_bindings.rs"))
|
|
.expect("Couldn't write gfx_rotozoom_bindings!");
|
|
}
|
|
}
|
|
|
|
fn get_os_from_triple(triple: &str) -> Option<&str> {
|
|
triple.splitn(3, '-').nth(2)
|
|
}
|