(args: &Args)
| 200 | other => Err(CliError::Usage(format!( |
| 201 | "unknown mode `{other}`; expected `hosted`, `freestanding`, or `kernel`" |
| 202 | ))), |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | // --- build --- |
| 207 | |
| 208 | fn cmd_build(args: &Args) -> Result<ExitCode, CliError> { |
| 209 | let input = require_single_input(args)?; |
| 210 | let (fs, config) = config_for_cli_input(input, args.mode)?; |
| 211 | let engine = SessionEngine::new(&fs); |
| 212 | let outcome = engine.build_config(&config).map_err(map_session_error)?; |
| 213 | |
| 214 | if let Some(output_path) = args.output.as_deref() { |
| 215 | fs::write(output_path, linked_elf_bytes(&outcome))?; |
| 216 | eprintln!("fsc: wrote linked ELF to `{output_path}`"); |
| 217 | } |
| 218 | print_build_summary(&outcome); |
| 219 | Ok(ExitCode::SUCCESS) |
| 220 | } |
| 221 | |
| 222 | // --- link --- |
| 223 | |
| 224 | fn cmd_link(args: &Args) -> Result<ExitCode, CliError> { |
| 225 | if args.inputs.is_empty() { |
| 226 | return Err(CliError::Usage( |
| 227 | "`link` requires at least one input file\n\nRun `fsc help` for usage.".to_owned(), |
| 228 | )); |
| 229 | } |
| 230 | |
| 231 | if args.inputs.len() == 1 && has_extension(&args.inputs[0], "build") { |
| 232 | let (fs, config) = config_for_cli_input(&args.inputs[0], args.mode)?; |
| 233 | let engine = SessionEngine::new(&fs); |
| 234 | let outcome = engine.build_config(&config).map_err(map_session_error)?; |
| 235 | let elf_bytes = linked_elf_bytes(&outcome); |
| 236 | let output_path = args.output.as_deref().unwrap_or("out.elf"); |
| 237 | fs::write(output_path, &elf_bytes)?; |
| 238 | eprintln!("fsc: wrote linked ELF to `{output_path}`"); |
| 239 | return Ok(ExitCode::SUCCESS); |
| 240 | } |
| 241 | |
| 242 | let first = args.first_input().expect("inputs checked above"); |
| 243 | let stem = source_stem(first, "linked"); |
| 244 | let mut manifest = BuildManifest::hosted(stem.clone(), ""); |
| 245 | manifest.target = args.mode; |
| 246 | manifest.root = BuildSource::path(stem.clone(), first); |
| 247 | if args.mode == TargetMode::Kernel { |
| 248 | manifest.import_closure = ImportClosurePolicy::Enabled { |
| 249 | mangle_symbols: false, |
| 250 | }; |
| 251 | } |
| 252 | if args.inputs.len() > 1 { |
| 253 | return Err(CliError::Usage( |
| 254 | "multiple HLL inputs are no longer linked positionally; use a .build root with \ |
| 255 | import(...) dependencies" |
| 256 | .to_owned(), |
| 257 | )); |
| 258 | } |
| 259 |
no test coverage detected