diff --git a/platform/rust/Cargo.toml b/platform/rust/Cargo.toml index 566fc294065..d5b7d327b43 100644 --- a/platform/rust/Cargo.toml +++ b/platform/rust/Cargo.toml @@ -1,10 +1,11 @@ [package] -name = "maplibre-native-cxx" +name = "maplibre-native" version = "0.1.0" edition = "2021" [dependencies] cxx = "1.0" +clap = { version = "4.5.27", features = ["derive", "env"] } [build-dependencies] cmake = "0.1" diff --git a/platform/rust/build.rs b/platform/rust/build.rs index eb6beb5fa2f..317ceee22cb 100644 --- a/platform/rust/build.rs +++ b/platform/rust/build.rs @@ -1,16 +1,15 @@ use std::env; use std::path::PathBuf; -//noinspection RsConstantConditionIf fn main() { let project_root = { let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let root = manifest.join("core-src"); if root.is_symlink() || root.is_dir() { - // Use the symlinked directory to allow packaging + // Use the symlinked directory to allow crate packaging root } else { - // Modeled from the kuzu project + // Modeled from the kuzu project. // If the path is not directory, this is probably an in-source build on windows where the symlink is unreadable. manifest.parent().unwrap().parent().unwrap().to_path_buf() } @@ -37,6 +36,11 @@ fn main() { // cxx build let mut cxx = cxx_build::bridge("src/lib.rs"); cxx.include(project_root.join("include")) + .file("src/wrapper.cc") .flag_if_supported("-std=c++20") .compile("maplibre_rust_bindings"); + + println!("cargo:rerun-if-changed=src/lib.rs"); + println!("cargo:rerun-if-changed=src/wrapper.cc"); + println!("cargo:rerun-if-changed=include/wrapper.h"); } diff --git a/platform/rust/core-src/ARCHITECTURE.md b/platform/rust/core-src/ARCHITECTURE.md deleted file mode 120000 index 9719fcb6afc..00000000000 --- a/platform/rust/core-src/ARCHITECTURE.md +++ /dev/null @@ -1 +0,0 @@ -../../../ARCHITECTURE.md \ No newline at end of file diff --git a/platform/rust/include/wrapper.h b/platform/rust/include/wrapper.h new file mode 100644 index 00000000000..86224cdc58e --- /dev/null +++ b/platform/rust/include/wrapper.h @@ -0,0 +1,11 @@ +#pragma once +#include "rust/cxx.h" +#include "mbgl/math/log2.hpp" + +namespace ml { +namespace rust { + +uint32_t get_42(); + +} // namespace rust +} // namespace ml diff --git a/platform/rust/src/bin/render.rs b/platform/rust/src/bin/render.rs new file mode 100644 index 00000000000..5d0c0db035b --- /dev/null +++ b/platform/rust/src/bin/render.rs @@ -0,0 +1,75 @@ +use clap::Parser; + +/// MapLibre Native render tool +#[derive(Parser, Debug)] +struct Args { + /// Rendering backend + #[arg(long)] + backend: Option, + + /// API key + #[arg(short = 't', long = "apikey", env = "MLN_API_KEY")] + apikey: Option, + + /// Map stylesheet + #[arg(short = 's', long = "style")] + style: Option, + + /// Output file name + #[arg(short = 'o', long = "output", default_value = "out.png")] + output: String, + + /// Cache database file name + #[arg(short = 'c', long = "cache", default_value = "cache.sqlite")] + cache: String, + + /// Directory to which asset:// URLs will resolve + #[arg(short = 'a', long = "assets", default_value = ".")] + assets: String, + + /// Debug mode + #[arg(long)] + debug: bool, + + /// Image scale factor + #[arg(short = 'r', long = "ratio", default_value_t = 1.0)] + ratio: f64, + + /// Zoom level + #[arg(short = 'z', long = "zoom", default_value_t = 0.0)] + zoom: f64, + + /// Longitude + #[arg(short = 'x', long = "lon", default_value_t = 0.0)] + lon: f64, + + /// Latitude + #[arg(short = 'y', long = "lat", default_value_t = 0.0)] + lat: f64, + + /// Bearing + #[arg(short = 'b', long = "bearing", default_value_t = 0.0)] + bearing: f64, + + /// Pitch + #[arg(short = 'p', long = "pitch", default_value_t = 0.0)] + pitch: f64, + + /// Image width + #[arg(long = "width", default_value_t = 512)] + width: u32, + + /// Image height + #[arg(long = "height", default_value_t = 512)] + height: u32, + + /// Map mode (e.g. 'static', 'tile', 'continuous') + #[arg(short = 'm', long = "mode")] + mode: Option, +} + +fn main() { + let args = Args::parse(); + + println!("Parsed arguments: {:?}", args); +} diff --git a/platform/rust/src/lib.rs b/platform/rust/src/lib.rs index e47d74f11c2..40750c493bb 100644 --- a/platform/rust/src/lib.rs +++ b/platform/rust/src/lib.rs @@ -1,10 +1,8 @@ -// platform/rust/src/lib.rs - -#[cxx::bridge(namespace = "mbgl::util")] +#[cxx::bridge] mod ffi { - // cxx allows including C++ headers directly: + // C++ types exposed to Rust. unsafe extern "C++" { - include!("mbgl/math/log2.hpp"); + include!("maplibre-native/include/wrapper.h"); // We specify the C++ namespace and the free function name exactly. // cxx can bind free functions directly if they have a compatible signature. @@ -12,18 +10,28 @@ mod ffi { // "uint32_t ceil_log2(uint64_t x);" // // We'll express that to Rust as (u64 -> u32). + #[namespace = "mbgl::util"] pub fn ceil_log2(x: u64) -> u32; + + // A function defined in the C++ rust wrapper rather than the core lib. + #[namespace = "ml::rust"] + pub fn get_42() -> u32; } } -/// A safe Rust wrapper so you can call `ceil_log2` from your code: -pub fn ceil_log2(x: u64) -> u32 { - ffi::ceil_log2(x) -} +// Re-export native functions that do not need safety wrappers. +pub use ffi::{get_42, ceil_log2}; #[cfg(test)] mod tests { use super::*; + + #[test] + fn test_rust_wrapper() { + let result = get_42(); + assert_eq!(result, 42, "get_42() = 42"); + } + #[test] fn test_log2() { let result = ceil_log2(1); diff --git a/platform/rust/src/wrapper.cc b/platform/rust/src/wrapper.cc new file mode 100644 index 00000000000..c70acf7c360 --- /dev/null +++ b/platform/rust/src/wrapper.cc @@ -0,0 +1,12 @@ +#include "maplibre-native/include/wrapper.h" +#include "maplibre-native/src/lib.rs.h" + +namespace ml { +namespace rust { + +uint32_t get_42() { + return 42; +} + +} // namespace rust +} // namespace ml