app-path
Create portable applications that keep files together with the executable.
Simple, zero-dependency library for creating portable applications where configuration, data, and executable stay together as a deployable unit.
use app_path;
// Files relative to your executable - not current directory!
let config = app_path!; // → /path/to/exe/config.toml
let database = app_path!; // → /path/to/exe/data/users.db
// Environment override for deployment
let logs = app_path!;
// → Uses LOG_PATH if set, otherwise /path/to/exe/logs/app.log
// Acts like std::path::Path + creates directories
if !config.exists
Why Choose AppPath?
| Approach | Problem | AppPath Solution |
|---|---|---|
| Hardcoded paths | Breaks when moved | ✅ Works anywhere |
current_dir() |
Depends on where user runs program | ✅ Always relative to executable |
| System directories | Scatters files across system | ✅ Self-contained, portable |
current_exe() |
Manual path joining, no caching, verbose error handling | ✅ Clean API, automatic caching, ergonomic macros |
Features
- 🚀 Zero dependencies - Only standard library
- ✨ Ergonomic macro - Clean syntax with
app_path! - 🌍 Cross-platform - Windows, Linux, macOS
- ⚡ High performance - Static caching, minimal allocations
- 🔧 Flexible deployment - Environment overrides
- 🛡️ Thread-safe - Concurrent access safe
- 📦 Portable - Entire app moves as one unit
API Overview
The app_path! Macro (Recommended)
use app_path;
// Simple paths
let config = app_path!;
let database = app_path!;
// Environment overrides
let logs = app_path!;
let cache = app_path!;
// Custom override logic
let data_dir = app_path!;
// Function-based override (great for XDG support)
let config_dir = app_path!;
// Variable capturing
let version = "1.0";
let versioned_cache = app_path!;
// Directory creation
logs.create_parents?; // Creates logs/ for the file
app_path!.create_dir?; // Creates temp/ directory itself
Fallible try_app_path! Macro (Libraries)
For libraries requiring explicit error handling:
use ;
// Returns Result<AppPath, AppPathError> instead of panicking
let config = try_app_path!?;
let database = try_app_path!?;
// Variable capturing with error handling
let version = "1.0";
let versioned_cache = try_app_path!?;
// Graceful error handling
match try_app_path!
Constructor API (Alternative)
use AppPath;
let config = new;
let database = with_override;
// For libraries requiring fallible behavior
let config = try_new?;
Error Handling
AppPath uses fail-fast by default for better developer experience:
app_path!andAppPath::new()- Panic on critical system errors (executable location undetermined)try_app_path!andAppPath::try_new()- ReturnResultfor explicit error handling
This design makes sense because if the system can't determine your executable location, there's usually no point continuing - it indicates severe system corruption or unsupported platforms.
For most applications: Use the panicking variants (app_path!) - they fail fast on unrecoverable errors.
For libraries: Use the fallible variants (try_app_path!) to let callers handle errors gracefully.
use ;
// Libraries should handle errors explicitly
match try_new
Real-World Examples
Configuration Management
use app_path;
CLI Tool with File Management
use app_path;
Deployment Flexibility
use app_path;
// Same binary, different environments:
// Development: uses "./config/app.toml"
// Production: CONFIG_PATH="/etc/myapp/config.toml" overrides to absolute path
let config = app_path!;
// Conditional deployment paths
let logs = if cfg! else ;
Directory Creation
use app_path;
// Preparing to write files
let log_file = app_path!;
log_file.create_parents?; // Creates logs/ directory
// Creating directories
let cache_dir = app_path!;
cache_dir.create_dir?; // Creates cache/ directory
Path Resolution
- Relative paths → executable directory:
"config.toml"→./config.toml - Absolute paths → used as-is:
"/etc/app.conf"→/etc/app.conf - Environment overrides → replace default when set
Ecosystem Integration
app-path integrates seamlessly with popular Rust path crates, letting you combine the best tools for your specific needs:
🔗 Popular Path Crate Compatibility
| Crate | Use Case | Integration Pattern |
|---|---|---|
camino |
UTF-8 path guarantees for web apps | Utf8PathBuf::try_from(app_path)? |
typed-path |
Cross-platform type-safe paths | WindowsPath::new(&app_path) |
📝 Real-World Integration Examples
🌐 JSON-Safe Web Config (with camino)
use app_path;
use Utf8PathBuf;
let static_dir = app_path!;
let utf8_static = try_from?;
let config = json!;
🔨 Cross-Platform Build System (with typed-path)
use app_path;
use ;
let dist_dir = app_path!;
let win_path = new; // Uses \ on Windows
let unix_path = new; // Uses / on Unix
🛠 Migration-Friendly
Since AppPath implements Deref<Target=Path> and AsRef<Path>, you can:
- Drop-in replace existing
PathBufusage - Gradually adopt without rewriting entire codebases
- Mix and match with specialized path libraries
- Zero runtime overhead for standard path operations
Installation
[]
= "0.2"
Documentation
For comprehensive API documentation, examples, and guides, see docs.rs/app-path.