1
1
const std = @import ("std" );
2
+ const Build = std .Build ;
3
+ const LazyPath = Build .LazyPath ;
4
+ const ResolvedTarget = Build .ResolvedTarget ;
5
+
2
6
const TestSuiteConfig = @import ("src/testconfig.zig" ).TestSuiteConfig ;
3
7
4
8
const samples = [_ ][]const u8 {
5
9
"math" ,
10
+ "hello-world" ,
6
11
};
7
12
8
- const avr_target = std.zig.CrossTarget {
13
+ const avr_target_query = std.Target.Query {
9
14
.cpu_arch = .avr ,
10
15
.cpu_model = .{ .explicit = & std .Target .avr .cpu .atmega328p },
11
16
.os_tag = .freestanding ,
@@ -15,7 +20,7 @@ const avr_target = std.zig.CrossTarget{
15
20
// Although this function looks imperative, note that its job is to
16
21
// declaratively construct a build graph that will be executed by an external
17
22
// runner.
18
- pub fn build (b : * std. Build ) ! void {
23
+ pub fn build (b : * Build ) ! void {
19
24
// Targets
20
25
const test_step = b .step ("test" , "Run test suite" );
21
26
const run_step = b .step ("run" , "Run the app" );
@@ -36,31 +41,35 @@ pub fn build(b: *std.Build) !void {
36
41
// Modules
37
42
38
43
const isa_module = b .createModule (.{
39
- .source_file = .{ . path = "src/shared/isa.zig" } ,
44
+ .root_source_file = b . path ( "src/shared/isa.zig" ) ,
40
45
});
41
46
const isa_tables_module = b .createModule (.{
42
- .source_file = generateIsaTables (b , isa_module ),
43
- .dependencies = &.{
47
+ .root_source_file = generateIsaTables (b , isa_module ),
48
+ .imports = &.{
44
49
.{ .name = "isa" , .module = isa_module },
45
50
},
46
51
});
47
52
const aviron_module = b .addModule ("aviron" , .{
48
- .source_file = .{ . path = "src/lib/aviron.zig" } ,
49
- .dependencies = &.{
53
+ .root_source_file = b . path ( "src/lib/aviron.zig" ) ,
54
+ .imports = &.{
50
55
.{ .name = "autogen-tables" , .module = isa_tables_module },
51
56
.{ .name = "isa" , .module = isa_module },
52
57
},
53
58
});
54
59
60
+ const testsuite_module = b .addModule ("aviron-testsuite" , .{
61
+ .root_source_file = b .path ("src/libtestsuite/lib.zig" ),
62
+ });
63
+
55
64
// Main emulator executable
56
65
const aviron_exe = b .addExecutable (.{
57
66
.name = "aviron" ,
58
- .root_source_file = .{ . path = "src/main.zig" } ,
67
+ .root_source_file = b . path ( "src/main.zig" ) ,
59
68
.target = target ,
60
69
.optimize = optimize ,
61
70
});
62
- aviron_exe .addModule ("args" , args_module );
63
- aviron_exe .addModule ("aviron" , aviron_module );
71
+ aviron_exe .root_module . addImport ("args" , args_module );
72
+ aviron_exe .root_module . addImport ("aviron" , aviron_module );
64
73
b .installArtifact (aviron_exe );
65
74
66
75
const run_cmd = b .addRunArtifact (aviron_exe );
@@ -70,17 +79,20 @@ pub fn build(b: *std.Build) !void {
70
79
}
71
80
run_step .dependOn (& run_cmd .step );
72
81
82
+ const avr_target = b .resolveTargetQuery (avr_target_query );
83
+
73
84
// Samples
74
85
for (samples ) | sample_name | {
75
86
const sample = b .addExecutable (.{
76
87
.name = sample_name ,
77
- .root_source_file = .{ . path = b .fmt ("samples/{s}.zig" , .{sample_name }) } ,
88
+ .root_source_file = b . path ( b .fmt ("samples/{s}.zig" , .{sample_name })) ,
78
89
.target = avr_target ,
79
90
.optimize = .ReleaseSmall ,
91
+ .strip = false ,
80
92
});
81
93
sample .bundle_compiler_rt = false ;
82
- sample .setLinkerScriptPath ( std.build.FileSource { . path = "linker.ld" } );
83
- sample .strip = false ;
94
+ sample .setLinkerScript ( b . path ( "linker.ld" ) );
95
+ sample .root_module . addImport ( "testsuite" , testsuite_module ) ;
84
96
85
97
// install to the prefix:
86
98
const install_elf_sample = b .addInstallFile (sample .getEmittedBin (), b .fmt ("samples/{s}.elf" , .{sample_name }));
@@ -89,40 +101,43 @@ pub fn build(b: *std.Build) !void {
89
101
90
102
// Test suite:
91
103
92
- try addTestSuite (b , test_step , debug_testsuite_step , target , optimize , args_module , aviron_module );
104
+ try addTestSuite (b , test_step , debug_testsuite_step , target , avr_target , optimize , args_module , aviron_module );
93
105
94
106
try addTestSuiteUpdate (b , update_testsuite_step );
95
107
}
96
108
97
109
fn addTestSuite (
98
- b : * std.Build ,
99
- test_step : * std.Build.Step ,
100
- debug_step : * std.Build.Step ,
101
- target : std.zig.CrossTarget ,
110
+ b : * Build ,
111
+ test_step : * Build.Step ,
112
+ debug_step : * Build.Step ,
113
+ host_target : ResolvedTarget ,
114
+ avr_target : ResolvedTarget ,
102
115
optimize : std.builtin.OptimizeMode ,
103
- args_module : * std.build .Module ,
104
- aviron_module : * std.build .Module ,
116
+ args_module : * Build .Module ,
117
+ aviron_module : * Build .Module ,
105
118
) ! void {
106
119
const unit_tests = b .addTest (.{
107
- .root_source_file = .{ . path = "src/main.zig" } ,
108
- .target = target ,
120
+ .root_source_file = b . path ( "src/main.zig" ) ,
121
+ .target = host_target ,
109
122
.optimize = optimize ,
110
123
});
111
124
test_step .dependOn (& b .addRunArtifact (unit_tests ).step );
112
125
113
126
const testrunner_exe = b .addExecutable (.{
114
127
.name = "aviron-test-runner" ,
115
- .root_source_file = .{ . path = "src/testrunner.zig" } ,
116
- .target = target ,
128
+ .root_source_file = b . path ( "src/testrunner.zig" ) ,
129
+ .target = host_target ,
117
130
.optimize = optimize ,
118
131
});
119
- testrunner_exe .addModule ("args" , args_module );
120
- testrunner_exe .addModule ("aviron" , aviron_module );
132
+ testrunner_exe .root_module . addImport ("args" , args_module );
133
+ testrunner_exe .root_module . addImport ("aviron" , aviron_module );
121
134
122
135
debug_step .dependOn (& b .addInstallArtifact (testrunner_exe , .{}).step );
123
136
124
137
{
125
- var walkdir = try b .build_root .handle .openIterableDir ("testsuite" , .{});
138
+ var walkdir = try b .build_root .handle .openDir ("testsuite" , .{
139
+ .iterate = true ,
140
+ });
126
141
defer walkdir .close ();
127
142
128
143
var walker = try walkdir .walk (b .allocator );
@@ -132,6 +147,11 @@ fn addTestSuite(
132
147
if (entry .kind != .file )
133
148
continue ;
134
149
150
+ if (std .mem .eql (u8 , entry .path , "dummy.zig" )) {
151
+ // This file is not interesting to test.
152
+ continue ;
153
+ }
154
+
135
155
const FileAction = union (enum ) {
136
156
compile ,
137
157
load ,
@@ -162,7 +182,7 @@ fn addTestSuite(
162
182
} else .unknown ;
163
183
164
184
const ConfigAndExe = struct {
165
- binary : std.Build. LazyPath ,
185
+ binary : LazyPath ,
166
186
config : TestSuiteConfig ,
167
187
};
168
188
@@ -177,26 +197,58 @@ fn addTestSuite(
177
197
const config = try parseTestSuiteConfig (b , file );
178
198
179
199
const custom_target = if (config .cpu ) | cpu |
180
- std .zig . CrossTarget .parse (.{
200
+ b . resolveTargetQuery ( std .Target . Query .parse (.{
181
201
.arch_os_abi = "avr-freestanding-eabi" ,
182
202
.cpu_features = cpu ,
183
- }) catch @panic (cpu )
203
+ }) catch @panic (cpu ))
184
204
else
185
205
avr_target ;
186
206
207
+ const file_ext = std .fs .path .extension (entry .path );
208
+ const is_zig_test = std .mem .eql (u8 , file_ext , ".zig" );
209
+ const is_c_test = std .mem .eql (u8 , file_ext , ".c" );
210
+ const is_asm_test = std .mem .eql (u8 , file_ext , ".S" );
211
+
212
+ std .debug .assert (is_zig_test or is_c_test or is_asm_test );
213
+
214
+ const source_file = b .path (b .fmt ("testsuite/{s}" , .{entry .path }));
215
+ const root_file = if (is_zig_test )
216
+ source_file
217
+ else
218
+ b .path ("testsuite/dummy.zig" );
219
+
187
220
const test_payload = b .addExecutable (.{
188
221
.name = std .fs .path .stem (entry .basename ),
189
- .root_source_file = .{ .path = b .fmt ("testsuite/{s}" , .{entry .path }) },
190
222
.target = custom_target ,
191
223
.optimize = config .optimize ,
224
+ .strip = false ,
225
+ .root_source_file = if (is_zig_test ) root_file else null ,
226
+ .link_libc = false ,
192
227
});
228
+ test_payload .want_lto = false ; // AVR has no LTO support!
229
+ test_payload .verbose_link = true ;
230
+ test_payload .verbose_cc = true ;
193
231
test_payload .bundle_compiler_rt = false ;
194
- test_payload .addIncludePath (.{ .path = "testsuite" });
195
- test_payload .setLinkerScriptPath (std.build.FileSource { .path = "linker.ld" });
196
- test_payload .addAnonymousModule ("testsuite" , .{
197
- .source_file = .{ .path = "src/libtestsuite/lib.zig" },
198
- });
199
- test_payload .strip = false ;
232
+
233
+ test_payload .setLinkerScript (b .path ("linker.ld" ));
234
+
235
+ if (is_c_test or is_asm_test ) {
236
+ test_payload .addIncludePath (b .path ("testsuite" ));
237
+ }
238
+ if (is_c_test ) {
239
+ test_payload .addCSourceFile (.{
240
+ .file = source_file ,
241
+ .flags = &.{},
242
+ });
243
+ }
244
+ if (is_asm_test ) {
245
+ test_payload .addAssemblyFile (source_file );
246
+ }
247
+ if (is_zig_test ) {
248
+ test_payload .root_module .addAnonymousImport ("testsuite" , .{
249
+ .root_source_file = b .path ("src/libtestsuite/lib.zig" ),
250
+ });
251
+ }
200
252
201
253
debug_step .dependOn (& b .addInstallFile (
202
254
test_payload .getEmittedBin (),
@@ -219,7 +271,7 @@ fn addTestSuite(
219
271
} else | _ | @panic (config_path );
220
272
221
273
break :blk ConfigAndExe {
222
- .binary = .{ . path = b .fmt ("testsuite/{s}" , .{entry .path }) } ,
274
+ .binary = b . path ( b .fmt ("testsuite/{s}" , .{entry .path })) ,
223
275
.config = config ,
224
276
};
225
277
},
@@ -229,7 +281,7 @@ fn addTestSuite(
229
281
230
282
const test_run = b .addRunArtifact (testrunner_exe );
231
283
test_run .addArg ("--config" );
232
- test_run .addFileArg (write_file .files . items [ 0 ]. getPath ( ));
284
+ test_run .addFileArg (write_file .getDirectory (). path ( b , "config.json" ));
233
285
test_run .addArg ("--name" );
234
286
test_run .addArg (entry .path );
235
287
@@ -242,16 +294,20 @@ fn addTestSuite(
242
294
}
243
295
}
244
296
245
- fn addTestSuiteUpdate (b : * std.Build , invoke_step : * std.Build.Step ) ! void {
246
- const avr_gcc = if (b .findProgram (&.{"avr-gcc" }, &.{})) | path | std.build.LazyPath {
297
+ fn addTestSuiteUpdate (
298
+ b : * Build ,
299
+ invoke_step : * Build.Step ,
300
+ ) ! void {
301
+ const avr_gcc = if (b .findProgram (&.{"avr-gcc" }, &.{})) | path | LazyPath {
247
302
.cwd_relative = path ,
248
303
} else | _ | b .addExecutable (.{
249
304
.name = "no-avr-gcc" ,
250
- .root_source_file = .{ .path = "tools/no-avr-gcc.zig" },
305
+ .target = b .graph .host ,
306
+ .root_source_file = b .path ("tools/no-avr-gcc.zig" ),
251
307
}).getEmittedBin ();
252
308
253
309
{
254
- var walkdir = try b .build_root .handle .openIterableDir ("testsuite.avr-gcc" , .{});
310
+ var walkdir = try b .build_root .handle .openDir ("testsuite.avr-gcc" , .{ . iterate = true });
255
311
defer walkdir .close ();
256
312
257
313
var walker = try walkdir .walk (b .allocator );
@@ -295,11 +351,12 @@ fn addTestSuiteUpdate(b: *std.Build, invoke_step: *std.Build.Step) !void {
295
351
296
352
const config = try parseTestSuiteConfig (b , file );
297
353
298
- const gcc_invocation = std . Build .Step .Run .create (b , "run avr-gcc" );
354
+ const gcc_invocation = Build .Step .Run .create (b , "run avr-gcc" );
299
355
gcc_invocation .addFileArg (avr_gcc );
300
356
gcc_invocation .addArg ("-o" );
301
357
gcc_invocation .addArg (b .fmt ("testsuite/{s}/{s}.elf" , .{ std .fs .path .dirname (entry .path ).? , std .fs .path .stem (entry .basename ) }));
302
- gcc_invocation .addArg (b .fmt ("-mmcu={s}" , .{config .cpu orelse avr_target .cpu_model .explicit .llvm_name orelse @panic ("Unknown MCU!" )}));
358
+ gcc_invocation .addArg (b .fmt ("-mmcu={s}" , .{config .cpu orelse @panic ("Uknown MCU!" )}));
359
+ //avr_target.cpu_model.explicit.llvm_name orelse @panic("Unknown MCU!")}));
303
360
for (config .gcc_flags ) | opt | {
304
361
gcc_invocation .addArg (opt );
305
362
}
@@ -310,7 +367,7 @@ fn addTestSuiteUpdate(b: *std.Build, invoke_step: *std.Build.Step) !void {
310
367
const write_file = b .addWriteFile ("config.json" , config .toString (b ));
311
368
312
369
const copy_file = b .addSystemCommand (&.{"cp" }); // todo make this cross-platform!
313
- copy_file .addFileArg (write_file .files . items [ 0 ]. getPath ( ));
370
+ copy_file .addFileArg (write_file .getDirectory (). path ( b , "config.json" ));
314
371
copy_file .addArg (b .fmt ("testsuite/{s}/{s}.elf.json" , .{ std .fs .path .dirname (entry .path ).? , std .fs .path .stem (entry .basename ) }));
315
372
316
373
invoke_step .dependOn (& gcc_invocation .step );
@@ -321,7 +378,7 @@ fn addTestSuiteUpdate(b: *std.Build, invoke_step: *std.Build.Step) !void {
321
378
}
322
379
}
323
380
324
- fn parseTestSuiteConfig (b : * std. Build , file : std.fs.File ) ! TestSuiteConfig {
381
+ fn parseTestSuiteConfig (b : * Build , file : std.fs.File ) ! TestSuiteConfig {
325
382
var code = std .ArrayList (u8 ).init (b .allocator );
326
383
defer code .deinit ();
327
384
@@ -355,14 +412,14 @@ fn parseTestSuiteConfig(b: *std.Build, file: std.fs.File) !TestSuiteConfig {
355
412
);
356
413
}
357
414
358
- fn generateIsaTables (b : * std. Build , isa_mod : * std. Build.Module ) std.Build. LazyPath {
415
+ fn generateIsaTables (b : * Build , isa_mod : * Build.Module ) LazyPath {
359
416
const generate_tables_exe = b .addExecutable (.{
360
417
.name = "aviron-generate-tables" ,
361
- .root_source_file = .{ . path = "tools/generate-tables.zig" } ,
362
- .target = .{} ,
418
+ .root_source_file = b . path ( "tools/generate-tables.zig" ) ,
419
+ .target = b . graph . host ,
363
420
.optimize = .Debug ,
364
421
});
365
- generate_tables_exe .addModule ("isa" , isa_mod );
422
+ generate_tables_exe .root_module . addImport ("isa" , isa_mod );
366
423
367
424
const run = b .addRunArtifact (generate_tables_exe );
368
425
0 commit comments