Permissive Mode gives you explicit control over workspace discovery and program exclusions. Perfect for multi-workspace repositories and complex build scenarios.
Permissive mode provides fine-grained control:
- Multi-workspace support - specify multiple
Cargo.tomlworkspaces - Flexible denials - deny programs by pattern
- Global + local denials - apply denials across all workspaces or per-workspace
- Explicit configuration - everything is specified, nothing is assumed
[package.metadata.elf-magic]
mode = "permissive"
workspaces = [
{ manifest_path = "./Cargo.toml" }
][package.metadata.elf-magic]
mode = "permissive"
workspaces = [
{ manifest_path = "./Cargo.toml", deny = ["target:test*", "package:dev*"] },
{ manifest_path = "examples/basic/Cargo.toml", deny = ["target:*_example"] }
][package.metadata.elf-magic]
mode = "permissive"
global_deny = ["package:apl-token", "target:*_test"]
workspaces = [
{ manifest_path = "./Cargo.toml", deny = ["target:dev*"] },
{ manifest_path = "examples/Cargo.toml" }
]Permissive mode supports three pattern types:
Match against the target name (what becomes the constant):
deny = ["target:test*", "target:*_example", "target:benchmark_*"]Match against the package name:
deny = ["package:dev*", "package:*-test", "package:example-*"]Match against the manifest path:
deny = ["path:*/examples/*", "path:*/tests/*", "path:*/benchmarks/*"]*- matches any number of characters?- matches a single character- Standard glob patterns supported
Applied to all workspaces:
global_deny = ["package:*-test", "target:bench*"]Applied to specific workspace:
{ manifest_path = "./Cargo.toml", deny = ["target:dev*"] }Global and local exclusions are merged for each workspace:
- Global:
["package:*-test"] - Local:
["target:dev*"] - Effective:
["package:*-test", "target:dev*"]
Both field names are supported for flexibility:
# These are equivalent:
{ manifest_path = "./Cargo.toml", deny = ["target:test*"] }
{ manifest_path = "./Cargo.toml", exclude = ["target:test*"] }Perfect for projects like Arch Network (main workspace + examples):
[package.metadata.elf-magic]
mode = "permissive"
global_deny = ["package:*-test", "target:bench*"]
workspaces = [
{ manifest_path = "./Cargo.toml", deny = ["target:example*"] },
{ manifest_path = "examples/basic/Cargo.toml", deny = ["target:*_demo"] },
{ manifest_path = "examples/advanced/Cargo.toml" },
{ manifest_path = "tests/integration/Cargo.toml", deny = ["path:*/integration/*"] }
]Permissive mode shows detailed exclusion information:
$ cargo build
Mode: permissive (3 workspaces specified)
Workspace: ./Cargo.toml
+ token_manager
+ governance
- test_program (denied by pattern)
- benchmark_suite (denied by pattern)
Workspace: examples/basic/Cargo.toml
+ swap_example
- basic_demo (denied by pattern)
Generated constants with 3 Solana programs✅ Perfect for:
- Multi-workspace repositories
- Projects with test/example programs to exclude
- Complex monorepos (like Anza/Agave with 50+ programs)
- Production builds needing specific exclusions
- When you need explicit control over what gets built
❌ Overkill for:
- Simple single-workspace projects
- Quick prototyping
- When you want all programs included
Typical multi-workspace setup:
arch-network/
├── Cargo.toml # Main workspace
├── elves/
│ ├── build.rs # elf_magic::build().unwrap();
│ └── Cargo.toml # Permissive config
├── programs/ # Main programs
│ ├── orderbook/
│ ├── apl-token/ # Excluded via global_deny
│ └── governance/
└── examples/ # Separate workspaces
├── basic/
│ └── Cargo.toml # Independent workspace
└── advanced/
└── Cargo.toml # Another independent workspace
[package.metadata.elf-magic]
mode = "permissive"
# Missing workspaces field - will errorError: Invalid elf-magic config: missing field 'workspaces'
Invalid patterns are warned about but don't fail the build:
Warning: Invalid deny pattern 'invalid-pattern'. Use 'target:', 'package:', or 'path:' prefix.
Error: Failed to obtain package metadata
Solution: Verify manifest_path points to valid Cargo.toml
Use verbose patterns and check global vs local exclusions are correctly configured.
If all programs are excluded, you'll get empty generated constants with warning.
Next Steps:
- Need even more precision? → Laser Eyes Mode
- Want simpler auto-discovery? → Magic Mode
- Ready to use your generated constants? → Usage Guide