From 39de31a662fec6c1ea7fbf7912697cb502fb2c46 Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Sun, 23 Jan 2022 19:07:51 -0800 Subject: [PATCH] Support conditional compilation of RomFS If the user tries to open the RomFS when one has not been added, it will result in a segfault (libctru doesn't verify the RomFS actually is configured). This avoids that scenario when used in conjunction with cargo-3ds. An alternative approach would be to do as libctru does and read the 3dsx file header, and use that to determine if RomFS is enabled at runtime. This would require more code, but it would be more accurate and compatible (wouldn't require a tool like cargo-3ds to ensure the RomFS is added). --- ctru-rs/Cargo.toml | 7 ++++++ ctru-rs/build.rs | 32 ++++++++++++++++++++++++++ ctru-rs/examples/file-explorer.rs | 5 ++-- {romfs => ctru-rs/romfs}/test-file.txt | 0 ctru-rs/src/lib.rs | 17 +++++++++++++- ctru-rs/src/romfs.rs | 14 ++++++++++- 6 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 ctru-rs/build.rs rename {romfs => ctru-rs/romfs}/test-file.txt (100%) diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml index 29323b4..5e29ef1 100644 --- a/ctru-rs/Cargo.toml +++ b/ctru-rs/Cargo.toml @@ -19,5 +19,12 @@ libc = { git = "https://github.com/Meziu/libc.git" } bitflags = "1.0.0" widestring = "0.2.2" +[build-dependencies] +toml = "0.5" + [dev-dependencies] ferris-says = "0.2.1" + +[features] +default = ["romfs"] +romfs = [] diff --git a/ctru-rs/build.rs b/ctru-rs/build.rs new file mode 100644 index 0000000..ecdef33 --- /dev/null +++ b/ctru-rs/build.rs @@ -0,0 +1,32 @@ +use std::path::PathBuf; + +fn main() { + // Open Cargo.toml + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_path = format!("{manifest_dir}/Cargo.toml"); + let manifest_str = std::fs::read_to_string(&manifest_path) + .unwrap_or_else(|e| panic!("Could not open {manifest_path}: {e}")); + let manifest_data: toml::Value = + toml::de::from_str(&manifest_str).expect("Could not parse Cargo manifest as TOML"); + + // Find the romfs setting and compute the path + let romfs_dir_setting = manifest_data + .as_table() + .and_then(|table| table.get("package")) + .and_then(toml::Value::as_table) + .and_then(|table| table.get("metadata")) + .and_then(toml::Value::as_table) + .and_then(|table| table.get("cargo-3ds")) + .and_then(toml::Value::as_table) + .and_then(|table| table.get("romfs_dir")) + .and_then(toml::Value::as_str) + .unwrap_or("romfs"); + let romfs_path = PathBuf::from(format!("{manifest_dir}/{romfs_dir_setting}")); + + // Check if the romfs path exists so we can compile the module + if romfs_path.exists() { + println!("cargo:rustc-cfg=romfs_exists"); + } + + println!("cargo:rerun-if-changed={}", manifest_dir); +} diff --git a/ctru-rs/examples/file-explorer.rs b/ctru-rs/examples/file-explorer.rs index c67c1f4..8a249f9 100644 --- a/ctru-rs/examples/file-explorer.rs +++ b/ctru-rs/examples/file-explorer.rs @@ -3,7 +3,6 @@ use ctru::applets::swkbd::{Button, Swkbd}; use ctru::console::Console; -use ctru::romfs::RomFS; use ctru::services::hid::KeyPad; use ctru::services::{Apt, Hid}; use ctru::Gfx; @@ -15,7 +14,9 @@ fn main() { let apt = Apt::init().unwrap(); let hid = Hid::init().unwrap(); let gfx = Gfx::default(); - let _romfs = RomFS::new().unwrap(); + + #[cfg(all(feature = "romfs", romfs_exists))] + let _romfs = ctru::romfs::RomFS::new().unwrap(); FileExplorer::init(&apt, &hid, &gfx).run(); } diff --git a/romfs/test-file.txt b/ctru-rs/romfs/test-file.txt similarity index 100% rename from romfs/test-file.txt rename to ctru-rs/romfs/test-file.txt diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index eef067d..a323060 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -34,11 +34,26 @@ pub mod console; pub mod error; pub mod gfx; pub mod sdmc; -pub mod romfs; pub mod services; pub mod srv; pub mod thread; +#[cfg(all(feature = "romfs", romfs_exists))] +pub mod romfs; +#[cfg(not(all(feature = "romfs", romfs_exists)))] +pub mod romfs { + //! The RomFS folder has not been detected and/or the `romfs` feature has not been enabled. + //! + //! Configure the path in Cargo.toml (the default path is "romfs"). Paths are relative to the + //! `CARGO_MANIFEST_DIR` environment variable, which is the directory containing the manifest of + //! your package. + //! + //! ```toml + //! [package.metadata.cargo-3ds] + //! romfs_dir = "romfs" + //! ``` +} + pub use crate::error::{Error, Result}; pub use crate::gfx::Gfx; diff --git a/ctru-rs/src/romfs.rs b/ctru-rs/src/romfs.rs index 09cfaa1..12190b9 100644 --- a/ctru-rs/src/romfs.rs +++ b/ctru-rs/src/romfs.rs @@ -1,3 +1,15 @@ +//! This module only gets compiled if the configured RomFS directory is found and the `romfs` +//! feature is enabled. +//! +//! Configure the path in Cargo.toml (the default path is "romfs"). Paths are relative to the +//! `CARGO_MANIFEST_DIR` environment variable, which is the directory containing the manifest of +//! your package. +//! +//! ```toml +//! [package.metadata.cargo-3ds] +//! romfs_dir = "romfs" +//! ``` + use std::ffi::CStr; #[non_exhaustive] @@ -21,4 +33,4 @@ impl Drop for RomFS { let mount_name = CStr::from_bytes_with_nul(b"romfs\0").unwrap(); unsafe { ctru_sys::romfsUnmount(mount_name.as_ptr()) }; } -} \ No newline at end of file +}