| Crates.io | path_macro2 |
| lib.rs | path_macro2 |
| version | 0.1.3 |
| created_at | 2025-11-04 05:04:43.162715+00 |
| updated_at | 2025-11-04 08:01:44.373609+00 |
| description | Cross-platform path construction macro supporting both slash (/) and comma (,) syntax with variable interpolation |
| homepage | |
| repository | https://github.com/yuniqueunic/path_macro2 |
| max_upload_size | |
| id | 1915765 |
| size | 46,835 |
A cross-platform path construction macro for Rust that provides an intuitive syntax for building file paths while automatically handling platform-specific path separators.
/) or comma (,) separators\ on
Windows, / on Unix-like systems)path! for runtime with variable interpolation,
path_const! for compile-time constantsAdd this to your Cargo.toml:
[dependencies]
path_macro2 = "0.1.3"
path!The path! macro creates PathBuf instances at runtime and supports variable
interpolation.
use path_macro2::path;
// Slash syntax
let path1 = path!(vendor / dll / windivert.c);
// Comma syntax
let path2 = path!(vendor, dll, windivert.c);
// Both produce the same result:
// Windows: "vendor\dll\windivert.c"
// Unix: "vendor/dll/windivert.c"
use path_macro2::path;
let path = path!(vendor / include); // Simple identifiers
let file = path!(config / settings.json); // Dotted identifiers
use path_macro2::path;
let path = path!("my folder" / "sub folder" / file.txt);
let docs = path!("Program Files" / "MyApp" / readme.md);
use path_macro2::path;
let base = "vendor";
let version = "1.0";
// Variables wrapped in curly braces
let path = path!({base} / dll / file.txt);
let versioned = path!(libs / {format!("v{}", version)} / library.so);
use path_macro2::path;
let abs_path = path!("/" / "usr" / "local" / "bin" / "myapp");
// Result: "/usr/local/bin/myapp"
use path_macro2::path;
// Drive letter paths
let win_path = path!("C:\\" / "Program Files" / "MyApp" / "app.exe");
// Result: "C:\Program Files\MyApp\app.exe"
// UNC network paths
let unc_path = path!("\\\\" / "server" / "share" / "file.txt");
// Result: "\\server\share\file.txt"
path_const!The path_const! macro generates compile-time string constants, perfect for use
with concat! and in const contexts.
use path_macro2::path_const;
// Compile-time constants
const CONFIG_PATH: &str = path_const!(config / app.toml);
const LIB_PATH: &str = path_const!(vendor / dll / windivert.c);
// Results:
// Windows: "config\\app.toml", "vendor\\dll\\windivert.c"
// Unix: "config/app.toml", "vendor/dll/windivert.c"
concat! for Build Flagsuse path_macro2::path_const;
// Perfect for build scripts and compiler flags
const DEF_FLAG: &str = concat!("/DEF:", path_const!(vendor / dll / windivert.def));
const INCLUDE_FLAG: &str = concat!("/I", path_const!(vendor / include));
// Use in arrays
const BUILD_ARGS: &[&str] = &[
"/nologo",
"/W1",
concat!("/I", path_const!(vendor / include)),
concat!("/DEF:", path_const!(vendor / dll / windivert.def)),
path_const!(vendor / dll / windivert.c),
];
use path_macro2::path_const;
// Handles spaces and special characters
const DOC_PATH: &str = path_const!("my folder" / "sub folder" / file.txt);
const MIXED_PATH: &str = path_const!(vendor / "include files" / windivert.h);
// Dotted identifiers work seamlessly
const SOURCE_FILE: &str = path_const!(src / lib.rs);
const ARCHIVE: &str = path_const!(backup / data.tar.gz);
use path_macro2::path;
fn main() {
let project_root = std::env::var("PROJECT_ROOT").unwrap_or_else(|_| ".".to_string());
let build_type = "release";
// Mixed usage with variables and literals
let output_path = path!({project_root} / "target" / {build_type} / "myapp.exe");
// Handling paths with spaces
let data_path = path!({project_root} / "test data" / "sample files" / input.csv);
// Cross-platform configuration
let config_path = if cfg!(windows) {
path!("C:\\" / "ProgramData" / "MyApp" / config.toml)
} else {
path!("/" / "etc" / "myapp" / config.toml)
};
println!("Output: {}", output_path.display());
println!("Data: {}", data_path.display());
println!("Config: {}", config_path.display());
}
use path_macro2::path_const;
// build.rs
const DYNAMIC_CL_ARGS: &[&str] = &[
concat!("/I", path_const!(vendor / include)),
"/ZI",
"/JMC",
"/nologo",
"/TC",
"/FC",
"/errorReport:queue",
path_const!(vendor / dll / windivert.c),
"/link",
"advapi32.lib",
"/NODEFAULTLIB",
concat!("/DEF:", path_const!(vendor / dll / windivert.def)),
"/MANIFEST",
"/DLL",
];
fn main() {
// let mut compiler = cc::Build::new().get_compiler().to_command();
let mut command = std::process::Command::new("cl");
for &flag in DYNAMIC_CL_ARGS {
// compiler.arg(flag);
command.arg(flag);
}
// ... rest of build logic
}
path! Macro (Runtime)The path! macro processes path segments and automatically:
vendor becomes "vendor"file.txt becomes "file.txt""my folder" stays as-is{base_path} evaluates the variablestd::path::PathBuf::push() for proper platform
handlingThe result is always a std::path::PathBuf that uses the correct path
separators for the target platform.
path_const! Macro (Compile-Time)The path_const! macro generates compile-time string constants:
vendor becomes "vendor"file.txt becomes "file.txt""my folder" stays as-isconcat! for zero-runtime-costpath! for
variables)The result is always a &'static str with platform-appropriate separators.
| Method | Cross-platform | Readable | Variables | Compile-time | Runtime |
|---|---|---|---|---|---|
path_macro2::path! |
✅ | ✅ | ✅ | ❌ | ✅ |
path_macro2::path_const! |
✅ | ✅ | ❌ | ✅ | ✅ |
std::path::Path::join() |
✅ | ❌ | ✅ | ❌ | ✅ |
| String concatenation | ❌ | ❌ | ✅ | ✅ | ✅ |
format!() with / |
❌ | ⚠️ | ✅ | ❌ | ✅ |
concat!() with / |
❌ | ⚠️ | ❌ | ✅ | ✅ |
Use path! when you need:
PathBuf instancesUse path_const! when you need:
concat! macroLicensed under either of
at your option.
Contributions are welcome! Please feel free to submit a Pull Request.