Skip to content

Commit 5cf129f

Browse files
committed
Decouple btest from codegens by introducing -nobuild flag
1 parent f77509f commit 5cf129f

2 files changed

Lines changed: 133 additions & 108 deletions

File tree

src/b.rs

Lines changed: 113 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
11911191
let target_name = flag_str(c!("t"), default_target_name, c!("Compilation target. Pass \"list\" to get the list of available targets."));
11921192
let output_path = flag_str(c!("o"), ptr::null(), c!("Output path"));
11931193
let run = flag_bool(c!("run"), false, c!("Run the compiled program (if applicable for the target)"));
1194+
let nobuild = flag_bool(c!("nobuild"), false, strdup(temp_sprintf(c!("Skip the build step. Useful in conjunction with the -%s flag when you already have a build program and just want to run it on the specified target without rebuilding it."), flag_name(run)))); // memory leak
11941195
let help = flag_bool(c!("help"), false, c!("Print this help message"));
11951196
let linker = flag_list(c!("L"), c!("Append a flag to the linker of the target platform"));
11961197
let nostdlib = flag_bool(c!("nostdlib"), false, c!("Do not link with standard libraries like libb and/or libc on some platforms"));
@@ -1256,62 +1257,64 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
12561257
c.target = target;
12571258
c.historical = *historical;
12581259

1259-
if !*nostdlib {
1260-
// TODO: should be probably a list libb paths which we sequentually probe to find which one exists.
1261-
// And of course we should also enable the user to append additional paths via the command line.
1262-
// Paths to potentially check by default:
1263-
// - Current working directory (like right now)
1264-
// - Directory where the b executable resides
1265-
// - Some system paths like /usr/include/libb on Linux? (Not 100% sure about this one)
1266-
// - Some sort of instalation prefix? (Requires making build system more complicated)
1267-
//
1268-
// - rexim (2025-06-12 20:56:08)
1269-
let libb_path = c!("./libb");
1270-
if !file_exists(libb_path)? {
1271-
log(Log_Level::ERROR, c!("No standard library path %s found. Please run the compiler from the same folder where %s is located. Or if you don't want to use the standard library pass the -%s flag."), libb_path, libb_path, flag_name(nostdlib));
1272-
return None;
1260+
if !*nobuild {
1261+
if !*nostdlib {
1262+
// TODO: should be probably a list libb paths which we sequentually probe to find which one exists.
1263+
// And of course we should also enable the user to append additional paths via the command line.
1264+
// Paths to potentially check by default:
1265+
// - Current working directory (like right now)
1266+
// - Directory where the b executable resides
1267+
// - Some system paths like /usr/include/libb on Linux? (Not 100% sure about this one)
1268+
// - Some sort of instalation prefix? (Requires making build system more complicated)
1269+
//
1270+
// - rexim (2025-06-12 20:56:08)
1271+
let libb_path = c!("./libb");
1272+
if !file_exists(libb_path)? {
1273+
log(Log_Level::ERROR, c!("No standard library path %s found. Please run the compiler from the same folder where %s is located. Or if you don't want to use the standard library pass the -%s flag."), libb_path, libb_path, flag_name(nostdlib));
1274+
return None;
1275+
}
1276+
include_path_if_exists(&mut input_paths, arena::sprintf(&mut c.arena, c!("%s/all.b"), libb_path));
1277+
include_path_if_exists(&mut input_paths, arena::sprintf(&mut c.arena, c!("%s/%s.b"), libb_path, *target_name));
12731278
}
1274-
include_path_if_exists(&mut input_paths, arena::sprintf(&mut c.arena, c!("%s/all.b"), libb_path));
1275-
include_path_if_exists(&mut input_paths, arena::sprintf(&mut c.arena, c!("%s/%s.b"), libb_path, *target_name));
1276-
}
12771279

1278-
let mut sb: String_Builder = zeroed();
1279-
for i in 0..input_paths.count {
1280-
let input_path = *input_paths.items.add(i);
1281-
if i > 0 { sb_appendf(&mut sb, c!(", ")); }
1282-
sb_appendf(&mut sb, c!("%s"), input_path);
1283-
}
1284-
da_append(&mut sb, 0);
1285-
log(Log_Level::INFO, c!("compiling files %s"), sb.items);
1280+
let mut sb: String_Builder = zeroed();
1281+
for i in 0..input_paths.count {
1282+
let input_path = *input_paths.items.add(i);
1283+
if i > 0 { sb_appendf(&mut sb, c!(", ")); }
1284+
sb_appendf(&mut sb, c!("%s"), input_path);
1285+
}
1286+
da_append(&mut sb, 0);
1287+
log(Log_Level::INFO, c!("compiling files %s"), sb.items);
12861288

1287-
let mut input: String_Builder = zeroed();
1289+
let mut input: String_Builder = zeroed();
12881290

1289-
scope_push(&mut c.vars); // begin global scope
1291+
scope_push(&mut c.vars); // begin global scope
12901292

1291-
for i in 0..input_paths.count {
1292-
let input_path = *input_paths.items.add(i);
1293+
for i in 0..input_paths.count {
1294+
let input_path = *input_paths.items.add(i);
12931295

1294-
input.count = 0;
1295-
read_entire_file(input_path, &mut input)?;
1296+
input.count = 0;
1297+
read_entire_file(input_path, &mut input)?;
12961298

1297-
let mut l: Lexer = lexer::new(input_path, input.items, input.items.add(input.count), *historical);
1299+
let mut l: Lexer = lexer::new(input_path, input.items, input.items.add(input.count), *historical);
12981300

1299-
compile_program(&mut l, &mut c)?;
1300-
}
1301+
compile_program(&mut l, &mut c)?;
1302+
}
13011303

1302-
for i in 0..c.used_funcs.count {
1303-
let used_global = *c.used_funcs.items.add(i);
1304+
for i in 0..c.used_funcs.count {
1305+
let used_global = *c.used_funcs.items.add(i);
13041306

1305-
if find_var_deep(&mut c.vars, used_global.name).is_null() {
1306-
diagf!(used_global.loc, c!("ERROR: could not find name `%s`\n"), used_global.name);
1307-
bump_error_count(&mut c);
1307+
if find_var_deep(&mut c.vars, used_global.name).is_null() {
1308+
diagf!(used_global.loc, c!("ERROR: could not find name `%s`\n"), used_global.name);
1309+
bump_error_count(&mut c);
1310+
}
13081311
}
1309-
}
13101312

1311-
scope_pop(&mut c.vars); // end global scope
1313+
scope_pop(&mut c.vars); // end global scope
13121314

1313-
if c.error_count > 0 {
1314-
return None
1315+
if c.error_count > 0 {
1316+
return None
1317+
}
13151318
}
13161319

13171320
let mut output: String_Builder = zeroed();
@@ -1321,6 +1324,9 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13211324
dump_program(&mut output, &c.program);
13221325
da_append(&mut output, 0);
13231326
printf(c!("%s"), output.items);
1327+
if *nobuild {
1328+
printf(c!("You provided -%s along with -%s. So this is your IR dump of a program that was never built. Enjoy!\n"), flag_name(ir), flag_name(nobuild));
1329+
}
13241330
return Some(())
13251331
}
13261332

@@ -1350,72 +1356,84 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13501356

13511357
match target {
13521358
Target::Gas_AArch64_Linux => {
1353-
codegen::gas_aarch64::generate_program(
1354-
// Inputs
1355-
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Linux, *nostdlib, *debug,
1356-
// Temporaries
1357-
&mut output, &mut cmd,
1358-
)?;
1359+
if !*nobuild {
1360+
codegen::gas_aarch64::generate_program(
1361+
// Inputs
1362+
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Linux, *nostdlib, *debug,
1363+
// Temporaries
1364+
&mut output, &mut cmd,
1365+
)?;
1366+
}
13591367

13601368
if *run {
13611369
codegen::gas_aarch64::run_program(&mut cmd, program_path, da_slice(run_args), None, Os::Linux)?;
13621370
}
13631371
}
13641372
Target::Gas_AArch64_Darwin => {
1365-
codegen::gas_aarch64::generate_program(
1366-
// Inputs
1367-
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Darwin, *nostdlib, *debug,
1368-
// Temporaries
1369-
&mut output, &mut cmd,
1370-
)?;
1373+
if !*nobuild {
1374+
codegen::gas_aarch64::generate_program(
1375+
// Inputs
1376+
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Darwin, *nostdlib, *debug,
1377+
// Temporaries
1378+
&mut output, &mut cmd,
1379+
)?;
1380+
}
13711381

13721382
if *run {
13731383
codegen::gas_aarch64::run_program(&mut cmd, program_path, da_slice(run_args), None, Os::Darwin)?;
13741384
}
13751385
}
13761386
Target::Gas_x86_64_Linux => {
1377-
codegen::gas_x86_64::generate_program(
1378-
// Inputs
1379-
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Linux, *nostdlib, *debug,
1380-
// Temporaries
1381-
&mut output, &mut cmd,
1382-
)?;
1387+
if !*nobuild {
1388+
codegen::gas_x86_64::generate_program(
1389+
// Inputs
1390+
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Linux, *nostdlib, *debug,
1391+
// Temporaries
1392+
&mut output, &mut cmd,
1393+
)?;
1394+
}
13831395

13841396
if *run {
13851397
codegen::gas_x86_64::run_program(&mut cmd, program_path, da_slice(run_args), None, Os::Linux)?
13861398
}
13871399
}
13881400
Target::Gas_x86_64_Windows => {
1389-
codegen::gas_x86_64::generate_program(
1390-
// Inputs
1391-
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Windows, *nostdlib, *debug,
1392-
// Temporaries
1393-
&mut output, &mut cmd,
1394-
)?;
1401+
if !*nobuild {
1402+
codegen::gas_x86_64::generate_program(
1403+
// Inputs
1404+
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Windows, *nostdlib, *debug,
1405+
// Temporaries
1406+
&mut output, &mut cmd,
1407+
)?;
1408+
}
13951409

13961410
if *run {
13971411
codegen::gas_x86_64::run_program(&mut cmd, program_path, da_slice(run_args), None, Os::Windows)?;
13981412
}
13991413
},
14001414
Target::Gas_x86_64_Darwin => {
1401-
codegen::gas_x86_64::generate_program(
1402-
// Inputs
1403-
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Darwin, *nostdlib, *debug,
1404-
// Temporaries
1405-
&mut output, &mut cmd,
1406-
)?;
1415+
if !*nobuild {
1416+
codegen::gas_x86_64::generate_program(
1417+
// Inputs
1418+
&c.program, program_path, garbage_base, da_slice(*linker), targets::Os::Darwin, *nostdlib, *debug,
1419+
// Temporaries
1420+
&mut output, &mut cmd,
1421+
)?;
1422+
}
14071423

14081424
if *run {
14091425
codegen::gas_x86_64::run_program(&mut cmd, program_path, da_slice(run_args), None, Os::Darwin)?;
14101426
}
14111427
}
14121428
Target::Uxn => {
1413-
codegen::uxn::generate_program(
1414-
// Inputs
1415-
&c.program, program_path, garbage_base, da_slice(*linker), *debug,
1416-
// Temporaries
1417-
&mut output, &mut cmd,
1418-
)?;
1429+
if !*nobuild {
1430+
codegen::uxn::generate_program(
1431+
// Inputs
1432+
&c.program, program_path, garbage_base, da_slice(*linker), *debug,
1433+
// Temporaries
1434+
&mut output, &mut cmd,
1435+
)?;
1436+
}
14191437

14201438
if *run {
14211439
codegen::uxn::run_program(&mut cmd, c!("uxnemu"), program_path, da_slice(run_args), None)?;
@@ -1424,24 +1442,28 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14241442
Target::Mos6502_Posix => {
14251443
let config = codegen::mos6502::parse_config_from_link_flags(da_slice(*linker))?;
14261444

1427-
codegen::mos6502::generate_program(
1428-
// Inputs
1429-
&c.program, program_path, garbage_base, config, *debug,
1430-
// Temporaries
1431-
&mut output, &mut cmd,
1432-
)?;
1445+
if !*nobuild {
1446+
codegen::mos6502::generate_program(
1447+
// Inputs
1448+
&c.program, program_path, garbage_base, config, *debug,
1449+
// Temporaries
1450+
&mut output, &mut cmd,
1451+
)?;
1452+
}
14331453

14341454
if *run {
14351455
codegen::mos6502::run_program(&mut cmd, config, program_path, da_slice(run_args), None)?;
14361456
}
14371457
}
14381458
Target::ILasm_Mono => {
1439-
codegen::ilasm_mono::generate_program(
1440-
// Inputs
1441-
&c.program, program_path, garbage_base, da_slice(*linker), *debug,
1442-
// Temporaries
1443-
&mut output, &mut cmd,
1444-
)?;
1459+
if !*nobuild {
1460+
codegen::ilasm_mono::generate_program(
1461+
// Inputs
1462+
&c.program, program_path, garbage_base, da_slice(*linker), *debug,
1463+
// Temporaries
1464+
&mut output, &mut cmd,
1465+
)?;
1466+
}
14451467

14461468
if *run {
14471469
codegen::ilasm_mono::run_program(&mut cmd, program_path, da_slice(run_args), None)?;

src/btest.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ pub mod flag;
1313
pub mod glob;
1414
pub mod jim;
1515
pub mod jimp;
16-
pub mod lexer;
17-
pub mod codegen;
18-
pub mod ir;
1916

2017
use core::ffi::*;
2118
use core::cmp;
@@ -24,7 +21,6 @@ use core::ptr;
2421
use crust::libc::*;
2522
use nob::*;
2623
use targets::*;
27-
use codegen::mos6502::{Config, DEFAULT_LOAD_OFFSET};
2824
use flag::*;
2925
use glob::*;
3026
use jim::*;
@@ -156,25 +152,32 @@ pub unsafe fn execute_test(
156152
if !cmd_run_sync_and_reset(cmd) {
157153
return Some(Outcome::BuildFail);
158154
}
159-
let run_result = match target {
160-
Target::Gas_AArch64_Linux => codegen::gas_aarch64::run_program(cmd, program_path, &[], Some(stdout_path), Os::Linux),
161-
Target::Gas_AArch64_Darwin => codegen::gas_aarch64::run_program(cmd, program_path, &[], Some(stdout_path), Os::Darwin),
162-
Target::Gas_x86_64_Linux => codegen::gas_x86_64::run_program(cmd, program_path, &[], Some(stdout_path), Os::Linux),
163-
Target::Gas_x86_64_Windows => codegen::gas_x86_64::run_program(cmd, program_path, &[], Some(stdout_path), Os::Windows),
164-
Target::Gas_x86_64_Darwin => codegen::gas_x86_64::run_program(cmd, program_path, &[], Some(stdout_path), Os::Darwin),
165-
Target::Uxn => codegen::uxn::run_program(cmd, c!("uxncli"), program_path, &[], Some(stdout_path)),
166-
Target::Mos6502_Posix => codegen::mos6502::run_program(cmd, Config {
167-
load_offset: DEFAULT_LOAD_OFFSET
168-
}, program_path, &[], Some(stdout_path)),
169-
Target::ILasm_Mono => codegen::ilasm_mono::run_program(cmd, program_path, &[], Some(stdout_path)),
170-
};
155+
156+
cmd_append! {
157+
cmd,
158+
if cfg!(target_os = "windows") {
159+
c!("./build/b.exe")
160+
} else {
161+
c!("./build/b")
162+
},
163+
input_path,
164+
c!("-t"), target.name(),
165+
c!("-o"), program_path,
166+
c!("-q"),
167+
c!("-nobuild"),
168+
c!("-run"),
169+
}
170+
let mut fdout = fd_open_for_write(stdout_path);
171+
let mut redirect: Cmd_Redirect = zeroed();
172+
redirect.fdout = &mut fdout;
173+
let run_ok = cmd_run_sync_redirect_and_reset(cmd, redirect);
171174

172175
(*sb).count = 0;
173176
read_entire_file(stdout_path, sb)?; // Should always succeed, but may fail if stdout_path is a directory for instance.
174177
da_append(sb, 0); // NULL-terminating the stdout
175178
printf(c!("%s"), (*sb).items); // Forward stdout for diagnostic purposes
176179

177-
if run_result.is_none() {
180+
if !run_ok {
178181
Some(Outcome::RunFail)
179182
} else {
180183
Some(Outcome::RunSuccess{stdout: strdup((*sb).items)}) // TODO: memory leak

0 commit comments

Comments
 (0)