use std::env;
use std::path::{Path, PathBuf};
use std::process::exit;
#[cfg(feature = "raylib_shared")]
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
fn main() {
println!("cargo::rerun-if-changed=build.rs");
let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
let _ = env::current_dir()
.unwrap()
.join("raylib")
.read_dir()
.unwrap_or_else(|_| {
eprintln!(" ERROR Could not find the raylib source code directory");
exit(1)
})
.next()
.unwrap_or_else(|| {
eprintln!(
" ERROR You need to initialize the submodules of this repository to compile the library."
);
exit(1)
});
if target.contains("wasm") {
panic!("Currently wasm is not supported");
}
let (platform, platform_os) = platform_from_target(&target);
let src = cp_raylib();
build_with_cmake(&src);
link(platform, platform_os);
}
#[cfg(feature = "nobuild")]
fn build_with_cmake(_src_path: &str) {}
#[cfg(not(feature = "nobuild"))]
fn build_with_cmake(src_path: &str) {
fn join_cmake_lib_directory(path: PathBuf) -> PathBuf {
let possible_cmake_lib_directories = ["lib", "lib64", "lib32"];
for lib_directory in &possible_cmake_lib_directories {
let lib_path = path.join(lib_directory);
if lib_path.exists() {
return lib_path;
}
}
path
}
let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
let (platform, platform_os) = platform_from_target(&target);
let mut conf = cmake::Config::new(src_path);
let mut builder;
let profile;
#[cfg(debug_assertions)]
{
builder = conf.profile("Debug");
builder = builder.define("CMAKE_BUILD_TYPE", "Debug");
profile = "Debug";
}
#[cfg(not(debug_assertions))]
{
builder = conf.profile("Release");
builder = builder.define("CMAKE_BUILD_TYPE", "Release");
profile = "Release";
}
builder
.define("BUILD_EXAMPLES", "OFF")
.define("CMAKE_BUILD_TYPE", profile)
.define("SUPPORT_BUSY_WAIT_LOOP", "OFF")
.define("SUPPORT_FILEFORMAT_JPG", "ON")
.define("RAYMATH_STATIC_INLINE", "ON");
#[cfg(feature = "custom_frame_control")]
{
builder.define("SUPPORT_CUSTOM_FRAME_CONTROL", "ON");
}
#[cfg(feature = "wayland")]
{
builder.define("USE_WAYLAND", "ON");
builder.define("USE_EXTERNAL_GLFW", "ON"); }
#[cfg(feature = "raylib_shared")]
builder.define("BUILD_SHARED_LIBS", "ON");
#[cfg(not(feature = "wayland"))]
builder.define("USE_WAYLAND", "OFF");
{
#[cfg(feature = "opengl_33")]
builder.define("OPENGL_VERSION", "3.3");
#[cfg(feature = "opengl_21")]
builder.define("OPENGL_VERSION", "2.1");
#[cfg(feature = "opengl_es_20")]
builder.define("OPENGL_VERSION", "ES 2.0");
#[cfg(not(any(
feature = "opengl_33",
feature = "opengl_21",
// feature = "opengl_11",
feature = "opengl_es_20"
)))]
builder.define("OPENGL_VERSION", "OFF");
}
match platform {
Platform::Desktop => conf.define("PLATFORM", "Desktop"),
Platform::Web => conf
.define("PLATFORM", "Web")
.define("CMAKE_C_FLAGS", "-s ASYNCIFY"),
};
let dst = conf.build();
let dst_lib = join_cmake_lib_directory(dst.to_path_buf());
#[cfg(feature = "raylib_shared")]
{
let mut target_dst = None;
let mut out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
while let Some(parent) = out_path.parent() {
if parent.ends_with(&profile) {
target_dst = Some(parent.to_path_buf());
break;
}
out_path = parent.to_path_buf();
}
if platform_os == PlatformOS::Osx {
let lib = format!("{}raylib.550{}", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
let lib = format!("{}raylib.5.5.0{}", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
let lib = format!("{}raylib{}", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
} else if platform_os == PlatformOS::Linux {
let lib = format!("{}raylib{}.550", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
let lib = format!("{}raylib{}.5.5.0", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
let lib = format!("{}raylib{}", DLL_PREFIX, DLL_SUFFIX);
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
} else if platform_os == PlatformOS::Windows {
let lib = "raylib.lib";
std::fs::copy(
dst_lib.join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(&lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
let lib = format!("raylib{}", DLL_SUFFIX);
std::fs::copy(
dst.join("bin").join(&lib),
target_dst
.clone()
.expect("could not find target directory")
.join(lib),
)
.expect(
format!(
"failed to copy shared library to {}",
target_dst.clone().unwrap().display()
)
.as_str(),
);
}
println!(
"cargo::rustc-link-search=native={}",
target_dst.unwrap().display()
);
}
#[cfg(not(feature = "raylib_shared"))]
{
if platform_os == PlatformOS::Windows {
if Path::new(&dst_lib.join("raylib.lib")).exists() {
} else if Path::new(&dst_lib.join("raylib_static.lib")).exists() {
std::fs::copy(
dst_lib.join("raylib_static.lib"),
dst_lib.join("raylib.lib"),
)
.expect("failed to create windows library");
} else if Path::new(&dst_lib.join("libraylib_static.a")).exists() {
std::fs::copy(
dst_lib.join("libraylib_static.a"),
dst_lib.join("libraylib.a"),
)
.expect("failed to create windows library");
} else if Path::new(&dst_lib.join("libraylib.a")).exists() {
} else {
panic!("failed to create windows library");
}
} if platform == Platform::Web && !Path::new(&dst_lib.join("libraylib.a")).exists() {
std::fs::copy(dst_lib.join("libraylib.bc"), dst_lib.join("libraylib.a"))
.expect("failed to create wasm library");
}
println!("cargo::rustc-link-search=native={}", dst_lib.display());
}
}
#[cfg(feature = "nobuild")]
fn link(_platform: Platform, _platform_os: PlatformOS) {}
#[cfg(not(feature = "nobuild"))]
fn link(platform: Platform, platform_os: PlatformOS) {
match platform_os {
PlatformOS::Windows => {
println!("cargo::rustc-link-lib=dylib=winmm");
println!("cargo::rustc-link-lib=dylib=gdi32");
println!("cargo::rustc-link-lib=dylib=user32");
println!("cargo::rustc-link-lib=dylib=shell32");
}
PlatformOS::Linux => {
#[cfg(not(feature = "wayland"))]
{
println!("cargo::rustc-link-search=/usr/local/lib");
println!("cargo::rustc-link-lib=X11");
}
#[cfg(feature = "wayland")]
{
println!("cargo::rustc-link-search=/usr/local/lib");
println!("cargo::rustc-link-lib=wayland-client");
println!("cargo::rustc-link-lib=glfw"); }
}
PlatformOS::Osx => {
println!("cargo::rustc-link-search=native=/usr/local/lib");
println!("cargo::rustc-link-lib=framework=OpenGL");
println!("cargo::rustc-link-lib=framework=Cocoa");
println!("cargo::rustc-link-lib=framework=IOKit");
}
_ => (),
}
if platform == Platform::Web {
println!("cargo::rustc-link-lib=glfw");
}
#[cfg(not(feature = "raylib_shared"))]
println!("cargo::rustc-link-lib=static=raylib");
#[cfg(feature = "raylib_shared")]
println!("cargo::rustc-link-lib=dylib=raylib");
}
fn cp_raylib() -> String {
let out = env::var("OUT_DIR").unwrap();
let out = Path::new(&out);
let mut options = fs_extra::dir::CopyOptions::new();
options.skip_exist = true;
fs_extra::dir::copy("raylib", out, &options)
.unwrap_or_else(|_| panic!("failed to copy raylib source to {}", &out.to_string_lossy()));
out.join("raylib").to_string_lossy().to_string()
}
fn platform_from_target(target: &str) -> (Platform, PlatformOS) {
let platform = if target.contains("wasm") {
Platform::Web
} else {
Platform::Desktop
};
let platform_os = if platform == Platform::Desktop {
if env::var("OS")
.unwrap_or("".to_owned())
.contains("Windows_NT")
|| env::var("TARGET")
.unwrap_or("".to_owned())
.contains("windows")
{
PlatformOS::Windows
} else {
let un: &str = &uname();
match un {
"Linux" => PlatformOS::Linux,
"FreeBSD" => PlatformOS::Bsd,
"OpenBSD" => PlatformOS::Bsd,
"NetBSD" => PlatformOS::Bsd,
"DragonFly" => PlatformOS::Bsd,
"Darwin" => PlatformOS::Osx,
_ => panic!("Unknown platform {}", uname()),
}
}
} else {
PlatformOS::Unknown
};
(platform, platform_os)
}
fn uname() -> String {
use std::process::Command;
String::from_utf8_lossy(
&Command::new("uname")
.output()
.expect("failed to run uname")
.stdout,
)
.trim()
.to_owned()
}
#[derive(Clone, Copy, Debug, PartialEq)]
enum Platform {
Web,
Desktop,
}
#[derive(Clone, Copy, Debug, PartialEq)]
enum PlatformOS {
Windows,
Linux,
Bsd,
Osx,
Unknown,
}