Skip to content

Commit b00f7c1

Browse files
Merge pull request #715 from zirco-lang/autodetect-outfmt
feat: auto-detect output format based on `-o` filename
2 parents 03bddd4 + d76288f commit b00f7c1

7 files changed

Lines changed: 59 additions & 62 deletions

File tree

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ If you aim to contribute to the Zirco compiler itself, please follow the instruc
2929

3030
**New to Zirco?** Check out our comprehensive [Getting Started Guide](./docs/GETTING_STARTED.md) for step-by-step instructions on:
3131

32-
- Installing prerequisites
33-
- Building the compiler
34-
- Writing and compiling your first program
35-
- Using compiler options and output formats
36-
- Troubleshooting common issues
32+
- Installing prerequisites
33+
- Building the compiler
34+
- Writing and compiling your first program
35+
- Using compiler options and output formats
36+
- Troubleshooting common issues
3737

3838
### Quick Start
3939

@@ -67,7 +67,7 @@ For experienced developers who want to get running quickly:
6767
4. **Compile your first program:**
6868
```bash
6969
# Create hello.zr with your favorite editor, then:
70-
zrc --emit object -o hello.o hello.zr
70+
zrc -o hello.o hello.zr
7171
clang -o hello hello.o -lc
7272
./hello
7373
```
@@ -82,7 +82,7 @@ For a comprehensive guide to the Zirco language syntax, semantics, and behavior,
8282

8383
If you are directly invoking the compiler with `cargo`, replace `zrc` with `cargo run --` in the below commands.
8484

85-
You can compile a single Zirco file to a `.o` object with `zrc --emit object -o main.o main.zr`. Otherwise, `zrc main.zr` will emit LLVM IR. This is soon to change.
85+
You can compile a single Zirco file to a `.o` object with `zrc -o main.o main.zr`. Otherwise, `zrc main.zr` will emit LLVM IR. This is soon to change.
8686

8787
For more usage help, refer to `zrc --help`.
8888

book/src/ch01-02-hello-world.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@ fn main() -> i32 {
2424
Save the file and run the following commands to compile, link, and run the program:
2525

2626
```
27-
$ zrc main.zr --emit object -o main.o
27+
$ zrc main.zr -o main.o
2828
$ ld -lc -lzr main.o -o main
2929
$ ./main
3030
Hello, World!
3131
```
3232

33-
| Command | Explanation |
34-
| ------------------------------------- | ---------------------------------------------------------------------------------------------------- |
35-
| `zrc main.zr --emit object -o main.o` | Compiles `main.zr` to an object file `main.o`. |
36-
| `ld -lc -lzr main.o -o main` | Links `main.o` with the C and Zirco standard libraries (`-lc -lzr`) to produce an executable `main`. |
37-
| `./main` | Runs the `main` executable, which prints "Hello, World!" to the terminal. |
33+
| Command | Explanation |
34+
| ---------------------------- | ---------------------------------------------------------------------------------------------------- |
35+
| `zrc main.zr -o main.o` | Compiles `main.zr` to an object file `main.o`. |
36+
| `ld -lc -lzr main.o -o main` | Links `main.o` with the C and Zirco standard libraries (`-lc -lzr`) to produce an executable `main`. |
37+
| `./main` | Runs the `main` executable, which prints "Hello, World!" to the terminal. |
3838

3939
If you see "Hello, World!" printed to the terminal, congratulations! You've successfully written and
4040
run your first Zirco program! If you don't see the expected output, take a look at the

compiler/zrc_cli/src/cli.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use zrc::{OutputFormat, codegen::OptimizationLevel};
1111
/// The official Zirco compiler
1212
#[derive(Parser)]
1313
#[command(version=None)]
14-
#[expect(clippy::struct_excessive_bools)]
1514
pub struct Cli {
1615
/// See what version of zrc you are using
1716
#[arg(short, long)]
@@ -28,13 +27,7 @@ pub struct Cli {
2827

2928
/// What output format to emit
3029
#[arg(long)]
31-
#[clap(default_value_t = FrontendOutputFormat::Llvm)]
32-
pub emit: FrontendOutputFormat,
33-
34-
/// Allow emitting raw object code to stdout. This may mess up your
35-
/// terminal!
36-
#[arg(long)]
37-
pub force: bool,
30+
pub emit: Option<FrontendOutputFormat>,
3831

3932
/// Set the target triple to generate output for. Defaults to native.
4033
#[arg(short, long)]
@@ -110,7 +103,7 @@ impl From<FrontendOptLevel> for OptimizationLevel {
110103
/// The list of possible outputs `zrc` can emit in
111104
///
112105
/// Usually you will want to use `llvm`.
113-
#[derive(Debug, Clone, clap::ValueEnum, PartialEq, Eq)]
106+
#[derive(Debug, Clone, Copy, clap::ValueEnum, PartialEq, Eq)]
114107
pub enum FrontendOutputFormat {
115108
/// LLVM IR
116109
Llvm,

compiler/zrc_cli/src/main.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,28 @@ fn main() -> Result<(), Box<dyn Error>> {
103103
let mut source_content = String::new();
104104
input.read_to_string(&mut source_content)?;
105105

106-
if cli.emit == FrontendOutputFormat::Object
107-
&& !cli.force
108-
&& cli.out_file.as_os_str().to_str().unwrap_or("-") == "-"
109-
{
110-
return Err(Box::new(CliError(
111-
"emitting raw object code to stdout is not allowed. use --force to override this"
112-
.into(),
113-
)));
114-
}
106+
let emit = cli.emit.unwrap_or_else(|| {
107+
#[allow(clippy::case_sensitive_file_extension_comparisons)]
108+
match cli
109+
.out_file
110+
.as_os_str()
111+
.to_str()
112+
.expect("output file should be a valid str")
113+
.to_lowercase()
114+
{
115+
// ends with .o or .obj, emit object code
116+
out if out.ends_with(".o") || out.ends_with(".obj") => FrontendOutputFormat::Object,
117+
// ends with .s or .asm, emit assembly
118+
out if out.ends_with(".s") || out.ends_with(".asm") => FrontendOutputFormat::Asm,
119+
// otherwise, emit LLVM IR
120+
_ => FrontendOutputFormat::Llvm,
121+
}
122+
});
115123

116124
let result = compile(
117125
&version_string(),
118126
&cli::get_include_paths(&cli),
119-
&cli.emit.into(),
127+
&emit.into(),
120128
&directory_name,
121129
&file_name,
122130
&std::env::args().collect::<Vec<_>>().join(" "),

docs/GETTING_STARTED.md

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ Welcome to Zirco! This guide will help you get up and running with the Zirco pro
44

55
## What You'll Learn
66

7-
- How to install all necessary prerequisites
8-
- How to build the Zirco compiler from source
9-
- How to write and compile your first Zirco program
10-
- How to use the compiler's various output formats
11-
- How to troubleshoot common issues
7+
- How to install all necessary prerequisites
8+
- How to build the Zirco compiler from source
9+
- How to write and compile your first Zirco program
10+
- How to use the compiler's various output formats
11+
- How to troubleshoot common issues
1212

1313
## Prerequisites
1414

@@ -172,19 +172,19 @@ fn main() {
172172

173173
This program:
174174

175-
- Declares the C `printf` function (external function declaration)
176-
- Defines a `main` function that calls `printf` to print "Hello, World!"
175+
- Declares the C `printf` function (external function declaration)
176+
- Defines a `main` function that calls `printf` to print "Hello, World!"
177177

178178
### Step 2: Compile to Object File
179179

180180
Compile your program to an object file:
181181

182182
```bash
183183
# If you installed zrc system-wide:
184-
zrc --emit object -o hello.o hello.zr
184+
zrc -o hello.o hello.zr
185185

186186
# Or using cargo:
187-
cargo run -- --emit object -o hello.o hello.zr
187+
cargo run -- -o hello.o hello.zr
188188
```
189189

190190
### Step 3: Link and Create Executable
@@ -234,7 +234,7 @@ zrc --emit llvm -o hello.ll hello.zr
234234
Compiled object code that can be linked with a C compiler:
235235

236236
```bash
237-
zrc --emit object -o hello.o hello.zr
237+
zrc -o hello.o hello.zr
238238
```
239239

240240
### Assembly
@@ -292,22 +292,21 @@ zrc --target aarch64-unknown-linux-gnu hello.zr
292292
Include debugging information in the output:
293293

294294
```bash
295-
zrc -g --emit object -o hello.o hello.zr
295+
zrc -g -o hello.o hello.zr
296296
```
297297

298298
### Complete Example with Options
299299

300300
```bash
301-
zrc --emit object -o hello.o -O 3 -g --target x86_64-unknown-linux-gnu hello.zr
301+
zrc -o hello.o -O 3 -g --target x86_64-unknown-linux-gnu hello.zr
302302
```
303303

304304
This command:
305305

306-
- Emits an object file (`--emit object`)
307-
- Outputs to `hello.o` (`-o hello.o`)
308-
- Uses aggressive optimization (`-O 3`)
309-
- Includes debug information (`-g`)
310-
- Targets x86_64 Linux (`--target x86_64-unknown-linux-gnu`)
306+
- Outputs to the object file `hello.o` (`-o hello.o`)
307+
- Uses aggressive optimization (`-O 3`)
308+
- Includes debug information (`-g`)
309+
- Targets x86_64 Linux (`--target x86_64-unknown-linux-gnu`)
311310

312311
## More Examples
313312

@@ -419,7 +418,6 @@ Now that you have Zirco up and running, here's what you can explore next:
419418
1. **Language Specification**: Read the comprehensive [Language Specification](./SPEC.md) to learn about Zirco's syntax, type system, and semantics.
420419

421420
2. **Examples**: Explore the `examples/` directory to see more complex Zirco programs:
422-
423421
- `hello_world/` - Basic program structure
424422
- `fibonacci/` - Recursion and conditionals
425423
- `struct_construction/` - Working with structs
@@ -428,14 +426,12 @@ Now that you have Zirco up and running, here's what you can explore next:
428426
- `global_variables/` - Global variable usage
429427

430428
3. **Contributing**: If you'd like to contribute to Zirco, check out [CONTRIBUTING.md](../.github/CONTRIBUTING.md) for guidelines on:
431-
432429
- Setting up a development environment
433430
- Running tests and linters
434431
- Code style requirements
435432
- Submitting pull requests
436433

437434
4. **Compiler Internals**: Learn about the compiler pipeline:
438-
439435
- **Lexer** (`zrc_parser`) - Tokenization
440436
- **Parser** (`zrc_parser`) - AST generation using LALRPOP
441437
- **Type Checker** (`zrc_typeck`) - Semantic analysis
@@ -452,21 +448,21 @@ Now that you have Zirco up and running, here's what you can explore next:
452448

453449
⚠️ **Zirco is experimental and unstable.** There are **NO STABILITY GUARANTEES** on the current version. This means:
454450

455-
- Internal compiler APIs may change without notice
456-
- Zirco code may fail to build on different `zrc` versions
457-
- Language semantics may change
458-
- This is not recommended for production use
451+
- Internal compiler APIs may change without notice
452+
- Zirco code may fail to build on different `zrc` versions
453+
- Language semantics may change
454+
- This is not recommended for production use
459455

460456
Zirco is a learning project and reference implementation for compiler design. Use it for education, experimentation, and fun!
461457

462458
### Platform Support
463459

464460
While Zirco is primarily developed and tested on Linux and WSL, it should work on:
465461

466-
- ✅ Linux (Ubuntu, Debian, Fedora, Arch, etc.)
467-
- ✅ WSL (Windows Subsystem for Linux)
468-
- ✅ macOS (with some environment variable configuration)
469-
- ⚠️ Windows (recommended to use WSL for best experience)
462+
- ✅ Linux (Ubuntu, Debian, Fedora, Arch, etc.)
463+
- ✅ WSL (Windows Subsystem for Linux)
464+
- ✅ macOS (with some environment variable configuration)
465+
- ⚠️ Windows (recommended to use WSL for best experience)
470466

471467
The compiler can target any platform supported by LLVM through the `--target` flag.
472468

examples/common.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ $(OUTDIR)/run: libzr $(ZR_OUTPUTS)
3939
$(OUTDIR)/%.o: %.zr
4040
$(Q)mkdir -p $(OUTDIR)
4141
$(ECHO) " ZRC $<"
42-
$(Q)$(ZRC) --emit object $(ZRFLAGS) -o $@ $<
42+
$(Q)$(ZRC) $(ZRFLAGS) -o $@ $<
4343

4444
.PHONY: clean
4545
clean:

libzr/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ all-opt: all
4040

4141
$(OUTDIR)/%.o: $(SRCDIR)/%.zr
4242
$(ECHO) " ZRC $<"
43-
$(Q)$(ZRC) --emit object $(ZRFLAGS) -o $@ $<
43+
$(Q)$(ZRC) $(ZRFLAGS) -o $@ $<
4444

4545
$(OUTDIR)/%.o: $(SRCDIR)/%.c
4646
$(ECHO) " CC $<"

0 commit comments

Comments
 (0)