diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..876130392 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gdal-src/source"] + path = gdal-src/source + url = https://github.com/OSGeo/gdal diff --git a/CHANGES.md b/CHANGES.md index cba870e20..1d8b895d0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ # Changes ## Unreleased +- Add a `bundled` feature for `gdal-sys` that allows to build and statically link a minimal bundled version of gdal during `cargo build` - Add `DriverIterator` format to iterate through drivers, as well as `DriverManager::all()` method that provides the iterator. - diff --git a/Cargo.toml b/Cargo.toml index 0c0ef3c1d..32a36ce9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ tempfile = "3.8" arrow2 = "0.18" [workspace] -members = ["gdal-sys"] +members = [ "gdal-src","gdal-sys"] # docs.rs-specific configuration [package.metadata.docs.rs] @@ -44,3 +44,8 @@ members = ["gdal-sys"] features = ["array"] # define attribute `docsrs` for feature badges rustdoc-args = ["--cfg", "docsrs"] + + +[patch.crates-io] +proj-sys = { git = "https://github.com/GiGainfosystems/proj", rev = "54716dd8955d4f0561ce9bf8a83610b605e3c007" } +libsqlite3-sys = { git = "https://github.com/rusqlite/rusqlite/", rev = "42a82fb" } diff --git a/gdal-src/Cargo.toml b/gdal-src/Cargo.toml new file mode 100644 index 000000000..6267432cf --- /dev/null +++ b/gdal-src/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "gdal-src" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +proj-sys = { version = "0.23.2", features = ["bundled_proj"] } +libsqlite3-sys = { version = "0.27.0", features = ["bundled"] } + +[build-dependencies] +cmake = "0.1.50" diff --git a/gdal-src/build.rs b/gdal-src/build.rs new file mode 100644 index 000000000..66a42f751 --- /dev/null +++ b/gdal-src/build.rs @@ -0,0 +1,58 @@ +fn main() { + let sqlite3_include_dir = + std::env::var("DEP_SQLITE3_INCLUDE").expect("This is set by libsqlite3-sys"); + let sqlite3_lib_dir = std::env::var("DEP_SQLITE3_LIB_DIR").expect("set by libsqlite3-sys"); + let proj_root = PathBuf::from(std::env::var("DEP_PROJ_ROOT").expect("set by proj-sys")); + let proj_lib = if proj_root.join("lib").join("proj_d.lib").exists() { + "proj_d.lib" + } else if proj_root.join("lib").join("proj.lib").exists() { + "proj.lib" + } else { + "libproj.a" + }; + + let res = cmake::Config::new("source") + .define("GDAL_BUILD_OPTIONAL_DRIVERS", "OFF") + .define("OGR_BUILD_OPTIONAL_DRIVERS", "OFF") + .define("GDAL_USE_INTERNAL_LIBS", "ON") + .define("GDAL_USE_EXTERNAL_LIBS", "OFF") + .define("BUILD_SHARED_LIBS", "OFF") + .define("BUILD_STATIC_LIBS", "ON") + .define("BUILD_APPS", "OFF") + .define("BUILD_DOCS", "OFF") + .define("BUILD_TESTING", "OFF") + .define("BUILD_GMOCK", "OFF") + .define("PROJ_INCLUDE_DIR", format!("{proj_root}/include")) + .define("PROJ_LIBRARY", format!("{proj_root}/lib/{proj_lib}")) + // enable the gpkg driver + .define("GDAL_USE_SQLITE3", "ON") + .define("SQLite3_INCLUDE_DIR", sqlite3_include_dir) + .define("SQLite3_LIBRARY", format!("{sqlite3_lib_dir}/libsqlite3.a")) + .define("OGR_ENABLE_DRIVER_GPKG", "ON") + .pic(true) + .build(); + + // sometimes it's lib and sometimes it's lib64 and sometimes `build/lib` + let lib_dir = res.join("lib64"); + println!( + "cargo:rustc-link-search=native={}", + lib_dir.to_str().unwrap() + ); + let lib_dir = res.join("lib"); + println!( + "cargo:rustc-link-search=native={}", + lib_dir.to_str().unwrap() + ); + let lib_dir = res.join("build/lib"); + println!( + "cargo:rustc-link-search=native={}", + lib_dir.to_str().unwrap() + ); + + //gdal likes to create gdal_d when configured as debug and on MSVC, so link to that one if it exists + if res.join("lib").join("gdald.lib").exists() { + println!("cargo:rustc-link-lib=static=gdald"); + } else { + println!("cargo:rustc-link-lib=static=gdal"); + } +} diff --git a/gdal-src/source b/gdal-src/source new file mode 160000 index 000000000..654f4907a --- /dev/null +++ b/gdal-src/source @@ -0,0 +1 @@ +Subproject commit 654f4907abbbf6bf4226d58a8c067d134eaf3ce9 diff --git a/gdal-src/src/lib.rs b/gdal-src/src/lib.rs new file mode 100644 index 000000000..b40735f84 --- /dev/null +++ b/gdal-src/src/lib.rs @@ -0,0 +1,2 @@ +extern crate libsqlite3_sys; +extern crate proj_sys; diff --git a/gdal-sys/Cargo.toml b/gdal-sys/Cargo.toml index 4a2cad506..8a16045ad 100644 --- a/gdal-sys/Cargo.toml +++ b/gdal-sys/Cargo.toml @@ -12,8 +12,14 @@ links="gdal" [dependencies] libc = "0.2" +gdal-src = { path = "../gdal-src/", optional = true} [build-dependencies] bindgen = { version = "0.69", optional = true } pkg-config = "0.3" semver = "1.0" + + +[features] +default = [] +bundled = ["dep:gdal-src"] diff --git a/gdal-sys/build.rs b/gdal-sys/build.rs index 0fccd63bc..c927a1288 100644 --- a/gdal-sys/build.rs +++ b/gdal-sys/build.rs @@ -68,7 +68,7 @@ fn main() { // Hardcode a prebuilt binding version while generating docs. // Otherwise docs.rs will explode due to not actually having libgdal installed. - if std::env::var("DOCS_RS").is_ok() { + if std::env::var("DOCS_RS").is_ok() || cfg!(feature = "bundled") { let version = Version::parse("3.8.0").expect("invalid version for docs.rs"); println!( "cargo:rustc-cfg=gdal_sys_{}_{}_{}", diff --git a/gdal-sys/src/lib.rs b/gdal-sys/src/lib.rs index 98d15c1b7..f8c611e1a 100644 --- a/gdal-sys/src/lib.rs +++ b/gdal-sys/src/lib.rs @@ -4,4 +4,7 @@ #![allow(clippy::upper_case_acronyms)] #![allow(rustdoc::bare_urls)] +#[cfg(feature = "bundled")] +extern crate gdal_src; + include!(concat!(env!("OUT_DIR"), "/bindings.rs"));