| ... | ... | @@ -26,15 +26,11 @@ const usage = |
| 26 | 26 | \\ |
| 27 | 27 | \\Commands: |
| 28 | 28 | \\ |
| 29 | | \\ build Build project from build.zig |
| 30 | 29 | \\ build-exe [source] Create executable from source or object files |
| 31 | 30 | \\ build-lib [source] Create library from source or object files |
| 32 | 31 | \\ build-obj [source] Create object from source or assembly |
| 33 | 32 | \\ fmt [source] Parse file and render in canonical zig format |
| 34 | | \\ run [source] Create executable and run immediately |
| 35 | 33 | \\ targets List available compilation targets |
| 36 | | \\ test [source] Create and run a test build |
| 37 | | \\ translate-c [source] Convert c code to zig code |
| 38 | 34 | \\ version Print version number and exit |
| 39 | 35 | \\ zen Print zen of zig and exit |
| 40 | 36 | \\ |
| ... | ... | @@ -47,7 +43,7 @@ const Command = struct { |
| 47 | 43 | }; |
| 48 | 44 | |
| 49 | 45 | pub fn main() !void { |
| 50 | | var allocator = std.heap.c_allocator; |
| 46 | const allocator = std.heap.c_allocator; |
| 51 | 47 | |
| 52 | 48 | var stdout_file = try std.io.getStdOut(); |
| 53 | 49 | var stdout_out_stream = std.io.FileOutStream.init(&stdout_file); |
| ... | ... | @@ -58,18 +54,16 @@ pub fn main() !void { |
| 58 | 54 | stderr = &stderr_out_stream.stream; |
| 59 | 55 | |
| 60 | 56 | const args = try os.argsAlloc(allocator); |
| 61 | | defer os.argsFree(allocator, args); |
| 57 | // TODO I'm getting unreachable code here, which shouldn't happen |
| 58 | //defer os.argsFree(allocator, args); |
| 62 | 59 | |
| 63 | 60 | if (args.len <= 1) { |
| 61 | try stderr.write("expected command argument\n\n"); |
| 64 | 62 | try stderr.write(usage); |
| 65 | 63 | os.exit(1); |
| 66 | 64 | } |
| 67 | 65 | |
| 68 | 66 | const commands = []Command{ |
| 69 | | Command{ |
| 70 | | .name = "build", |
| 71 | | .exec = cmdBuild, |
| 72 | | }, |
| 73 | 67 | Command{ |
| 74 | 68 | .name = "build-exe", |
| 75 | 69 | .exec = cmdBuildExe, |
| ... | ... | @@ -86,22 +80,10 @@ pub fn main() !void { |
| 86 | 80 | .name = "fmt", |
| 87 | 81 | .exec = cmdFmt, |
| 88 | 82 | }, |
| 89 | | Command{ |
| 90 | | .name = "run", |
| 91 | | .exec = cmdRun, |
| 92 | | }, |
| 93 | 83 | Command{ |
| 94 | 84 | .name = "targets", |
| 95 | 85 | .exec = cmdTargets, |
| 96 | 86 | }, |
| 97 | | Command{ |
| 98 | | .name = "test", |
| 99 | | .exec = cmdTest, |
| 100 | | }, |
| 101 | | Command{ |
| 102 | | .name = "translate-c", |
| 103 | | .exec = cmdTranslateC, |
| 104 | | }, |
| 105 | 87 | Command{ |
| 106 | 88 | .name = "version", |
| 107 | 89 | .exec = cmdVersion, |
| ... | ... | @@ -124,177 +106,15 @@ pub fn main() !void { |
| 124 | 106 | |
| 125 | 107 | for (commands) |command| { |
| 126 | 108 | if (mem.eql(u8, command.name, args[1])) { |
| 127 | | try command.exec(allocator, args[2..]); |
| 128 | | return; |
| 109 | return command.exec(allocator, args[2..]); |
| 129 | 110 | } |
| 130 | 111 | } |
| 131 | 112 | |
| 132 | 113 | try stderr.print("unknown command: {}\n\n", args[1]); |
| 133 | 114 | try stderr.write(usage); |
| 115 | os.exit(1); |
| 134 | 116 | } |
| 135 | 117 | |
| 136 | | // cmd:build /////////////////////////////////////////////////////////////////////////////////////// |
| 137 | | |
| 138 | | const usage_build = |
| 139 | | \\usage: zig build <options> |
| 140 | | \\ |
| 141 | | \\General Options: |
| 142 | | \\ --help Print this help and exit |
| 143 | | \\ --init Generate a build.zig template |
| 144 | | \\ --build-file [file] Override path to build.zig |
| 145 | | \\ --cache-dir [path] Override path to cache directory |
| 146 | | \\ --verbose Print commands before executing them |
| 147 | | \\ --prefix [path] Override default install prefix |
| 148 | | \\ |
| 149 | | \\Project-Specific Options: |
| 150 | | \\ |
| 151 | | \\ Project-specific options become available when the build file is found. |
| 152 | | \\ |
| 153 | | \\Advanced Options: |
| 154 | | \\ --build-file [file] Override path to build.zig |
| 155 | | \\ --cache-dir [path] Override path to cache directory |
| 156 | | \\ --verbose-tokenize Enable compiler debug output for tokenization |
| 157 | | \\ --verbose-ast Enable compiler debug output for parsing into an AST |
| 158 | | \\ --verbose-link Enable compiler debug output for linking |
| 159 | | \\ --verbose-ir Enable compiler debug output for Zig IR |
| 160 | | \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR |
| 161 | | \\ --verbose-cimport Enable compiler debug output for C imports |
| 162 | | \\ |
| 163 | | \\ |
| 164 | | ; |
| 165 | | |
| 166 | | const args_build_spec = []Flag{ |
| 167 | | Flag.Bool("--help"), |
| 168 | | Flag.Bool("--init"), |
| 169 | | Flag.Arg1("--build-file"), |
| 170 | | Flag.Arg1("--cache-dir"), |
| 171 | | Flag.Bool("--verbose"), |
| 172 | | Flag.Arg1("--prefix"), |
| 173 | | |
| 174 | | Flag.Arg1("--build-file"), |
| 175 | | Flag.Arg1("--cache-dir"), |
| 176 | | Flag.Bool("--verbose-tokenize"), |
| 177 | | Flag.Bool("--verbose-ast"), |
| 178 | | Flag.Bool("--verbose-link"), |
| 179 | | Flag.Bool("--verbose-ir"), |
| 180 | | Flag.Bool("--verbose-llvm-ir"), |
| 181 | | Flag.Bool("--verbose-cimport"), |
| 182 | | }; |
| 183 | | |
| 184 | | const missing_build_file = |
| 185 | | \\No 'build.zig' file found. |
| 186 | | \\ |
| 187 | | \\Initialize a 'build.zig' template file with `zig build --init`, |
| 188 | | \\or build an executable directly with `zig build-exe $FILENAME.zig`. |
| 189 | | \\ |
| 190 | | \\See: `zig build --help` or `zig help` for more options. |
| 191 | | \\ |
| 192 | | ; |
| 193 | | |
| 194 | | fn cmdBuild(allocator: *Allocator, args: []const []const u8) !void { |
| 195 | | var flags = try Args.parse(allocator, args_build_spec, args); |
| 196 | | defer flags.deinit(); |
| 197 | | |
| 198 | | if (flags.present("help")) { |
| 199 | | try stderr.write(usage_build); |
| 200 | | os.exit(0); |
| 201 | | } |
| 202 | | |
| 203 | | const zig_lib_dir = try introspect.resolveZigLibDir(allocator); |
| 204 | | defer allocator.free(zig_lib_dir); |
| 205 | | |
| 206 | | const zig_std_dir = try os.path.join(allocator, zig_lib_dir, "std"); |
| 207 | | defer allocator.free(zig_std_dir); |
| 208 | | |
| 209 | | const special_dir = try os.path.join(allocator, zig_std_dir, "special"); |
| 210 | | defer allocator.free(special_dir); |
| 211 | | |
| 212 | | const build_runner_path = try os.path.join(allocator, special_dir, "build_runner.zig"); |
| 213 | | defer allocator.free(build_runner_path); |
| 214 | | |
| 215 | | const build_file = flags.single("build-file") orelse "build.zig"; |
| 216 | | const build_file_abs = try os.path.resolve(allocator, ".", build_file); |
| 217 | | defer allocator.free(build_file_abs); |
| 218 | | |
| 219 | | const build_file_exists = os.File.access(allocator, build_file_abs, os.default_file_mode) catch false; |
| 220 | | |
| 221 | | if (flags.present("init")) { |
| 222 | | if (build_file_exists) { |
| 223 | | try stderr.print("build.zig already exists\n"); |
| 224 | | os.exit(1); |
| 225 | | } |
| 226 | | |
| 227 | | // need a new scope for proper defer scope finalization on exit |
| 228 | | { |
| 229 | | const build_template_path = try os.path.join(allocator, special_dir, "build_file_template.zig"); |
| 230 | | defer allocator.free(build_template_path); |
| 231 | | |
| 232 | | try os.copyFile(allocator, build_template_path, build_file_abs); |
| 233 | | try stderr.print("wrote build.zig template\n"); |
| 234 | | } |
| 235 | | |
| 236 | | os.exit(0); |
| 237 | | } |
| 238 | | |
| 239 | | if (!build_file_exists) { |
| 240 | | try stderr.write(missing_build_file); |
| 241 | | os.exit(1); |
| 242 | | } |
| 243 | | |
| 244 | | // TODO: Invoke build.zig entrypoint directly? |
| 245 | | var zig_exe_path = try os.selfExePath(allocator); |
| 246 | | defer allocator.free(zig_exe_path); |
| 247 | | |
| 248 | | var build_args = ArrayList([]const u8).init(allocator); |
| 249 | | defer build_args.deinit(); |
| 250 | | |
| 251 | | const build_file_basename = os.path.basename(build_file_abs); |
| 252 | | const build_file_dirname = os.path.dirname(build_file_abs) orelse "."; |
| 253 | | |
| 254 | | var full_cache_dir: []u8 = undefined; |
| 255 | | if (flags.single("cache-dir")) |cache_dir| { |
| 256 | | full_cache_dir = try os.path.resolve(allocator, ".", cache_dir, full_cache_dir); |
| 257 | | } else { |
| 258 | | full_cache_dir = try os.path.join(allocator, build_file_dirname, "zig-cache"); |
| 259 | | } |
| 260 | | defer allocator.free(full_cache_dir); |
| 261 | | |
| 262 | | const path_to_build_exe = try os.path.join(allocator, full_cache_dir, "build"); |
| 263 | | defer allocator.free(path_to_build_exe); |
| 264 | | |
| 265 | | try build_args.append(path_to_build_exe); |
| 266 | | try build_args.append(zig_exe_path); |
| 267 | | try build_args.append(build_file_dirname); |
| 268 | | try build_args.append(full_cache_dir); |
| 269 | | |
| 270 | | var proc = try os.ChildProcess.init(build_args.toSliceConst(), allocator); |
| 271 | | defer proc.deinit(); |
| 272 | | |
| 273 | | var term = try proc.spawnAndWait(); |
| 274 | | switch (term) { |
| 275 | | os.ChildProcess.Term.Exited => |status| { |
| 276 | | if (status != 0) { |
| 277 | | try stderr.print("{} exited with status {}\n", build_args.at(0), status); |
| 278 | | os.exit(1); |
| 279 | | } |
| 280 | | }, |
| 281 | | os.ChildProcess.Term.Signal => |signal| { |
| 282 | | try stderr.print("{} killed by signal {}\n", build_args.at(0), signal); |
| 283 | | os.exit(1); |
| 284 | | }, |
| 285 | | os.ChildProcess.Term.Stopped => |signal| { |
| 286 | | try stderr.print("{} stopped by signal {}\n", build_args.at(0), signal); |
| 287 | | os.exit(1); |
| 288 | | }, |
| 289 | | os.ChildProcess.Term.Unknown => |status| { |
| 290 | | try stderr.print("{} encountered unknown failure {}\n", build_args.at(0), status); |
| 291 | | os.exit(1); |
| 292 | | }, |
| 293 | | } |
| 294 | | } |
| 295 | | |
| 296 | | // cmd:build-exe /////////////////////////////////////////////////////////////////////////////////// |
| 297 | | |
| 298 | 118 | const usage_build_generic = |
| 299 | 119 | \\usage: zig build-exe <options> [file] |
| 300 | 120 | \\ zig build-lib <options> [file] |
| ... | ... | @@ -315,8 +135,11 @@ const usage_build_generic = |
| 315 | 135 | \\ --output-h [file] Override generated header file path |
| 316 | 136 | \\ --pkg-begin [name] [path] Make package available to import and push current pkg |
| 317 | 137 | \\ --pkg-end Pop current pkg |
| 318 | | \\ --release-fast Build with optimizations on and safety off |
| 319 | | \\ --release-safe Build with optimizations on and safety on |
| 138 | \\ --mode [mode] Set the build mode |
| 139 | \\ debug (default) optimizations off, safety on |
| 140 | \\ release-fast optimizations on, safety off |
| 141 | \\ release-safe optimizations on, safety on |
| 142 | \\ release-small optimize for small binary, safety off |
| 320 | 143 | \\ --static Output will be statically linked |
| 321 | 144 | \\ --strip Exclude debug symbols |
| 322 | 145 | \\ --target-arch [name] Specify target architecture |
| ... | ... | @@ -367,6 +190,12 @@ const args_build_generic = []Flag{ |
| 367 | 190 | "off", |
| 368 | 191 | "on", |
| 369 | 192 | }), |
| 193 | Flag.Option("--mode", []const []const u8{ |
| 194 | "debug", |
| 195 | "release-fast", |
| 196 | "release-safe", |
| 197 | "release-small", |
| 198 | }), |
| 370 | 199 | |
| 371 | 200 | Flag.ArgMergeN("--assembly", 1), |
| 372 | 201 | Flag.Arg1("--cache-dir"), |
| ... | ... | @@ -383,8 +212,6 @@ const args_build_generic = []Flag{ |
| 383 | 212 | // NOTE: Parsed manually after initial check |
| 384 | 213 | Flag.ArgN("--pkg-begin", 2), |
| 385 | 214 | Flag.Bool("--pkg-end"), |
| 386 | | Flag.Bool("--release-fast"), |
| 387 | | Flag.Bool("--release-safe"), |
| 388 | 215 | Flag.Bool("--static"), |
| 389 | 216 | Flag.Bool("--strip"), |
| 390 | 217 | Flag.Arg1("--target-arch"), |
| ... | ... | @@ -431,16 +258,25 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 431 | 258 | defer flags.deinit(); |
| 432 | 259 | |
| 433 | 260 | if (flags.present("help")) { |
| 434 | | try stderr.write(usage_build_generic); |
| 261 | try stdout.write(usage_build_generic); |
| 435 | 262 | os.exit(0); |
| 436 | 263 | } |
| 437 | 264 | |
| 438 | | var build_mode = builtin.Mode.Debug; |
| 439 | | if (flags.present("release-fast")) { |
| 440 | | build_mode = builtin.Mode.ReleaseFast; |
| 441 | | } else if (flags.present("release-safe")) { |
| 442 | | build_mode = builtin.Mode.ReleaseSafe; |
| 443 | | } |
| 265 | const build_mode = blk: { |
| 266 | if (flags.single("mode")) |mode_flag| { |
| 267 | if (mem.eql(u8, mode_flag, "debug")) { |
| 268 | break :blk builtin.Mode.Debug; |
| 269 | } else if (mem.eql(u8, mode_flag, "release-fast")) { |
| 270 | break :blk builtin.Mode.ReleaseFast; |
| 271 | } else if (mem.eql(u8, mode_flag, "release-safe")) { |
| 272 | break :blk builtin.Mode.ReleaseSafe; |
| 273 | } else if (mem.eql(u8, mode_flag, "release-small")) { |
| 274 | break :blk builtin.Mode.ReleaseSmall; |
| 275 | } else unreachable; |
| 276 | } else { |
| 277 | break :blk builtin.Mode.Debug; |
| 278 | } |
| 279 | }; |
| 444 | 280 | |
| 445 | 281 | const color = blk: { |
| 446 | 282 | if (flags.single("color")) |color_flag| { |
| ... | ... | @@ -456,20 +292,21 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 456 | 292 | } |
| 457 | 293 | }; |
| 458 | 294 | |
| 459 | | var emit_type = Module.Emit.Binary; |
| 460 | | if (flags.single("emit")) |emit_flag| { |
| 461 | | if (mem.eql(u8, emit_flag, "asm")) { |
| 462 | | emit_type = Module.Emit.Assembly; |
| 463 | | } else if (mem.eql(u8, emit_flag, "bin")) { |
| 464 | | emit_type = Module.Emit.Binary; |
| 465 | | } else if (mem.eql(u8, emit_flag, "llvm-ir")) { |
| 466 | | emit_type = Module.Emit.LlvmIr; |
| 295 | const emit_type = blk: { |
| 296 | if (flags.single("emit")) |emit_flag| { |
| 297 | if (mem.eql(u8, emit_flag, "asm")) { |
| 298 | break :blk Module.Emit.Assembly; |
| 299 | } else if (mem.eql(u8, emit_flag, "bin")) { |
| 300 | break :blk Module.Emit.Binary; |
| 301 | } else if (mem.eql(u8, emit_flag, "llvm-ir")) { |
| 302 | break :blk Module.Emit.LlvmIr; |
| 303 | } else unreachable; |
| 467 | 304 | } else { |
| 468 | | unreachable; |
| 305 | break :blk Module.Emit.Binary; |
| 469 | 306 | } |
| 470 | | } |
| 307 | }; |
| 471 | 308 | |
| 472 | | var cur_pkg = try Module.CliPkg.init(allocator, "", "", null); // TODO: Need a path, name? |
| 309 | var cur_pkg = try CliPkg.init(allocator, "", "", null); |
| 473 | 310 | defer cur_pkg.deinit(); |
| 474 | 311 | |
| 475 | 312 | var i: usize = 0; |
| ... | ... | @@ -482,15 +319,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 482 | 319 | i += 1; |
| 483 | 320 | const new_pkg_path = args[i]; |
| 484 | 321 | |
| 485 | | var new_cur_pkg = try Module.CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); |
| 322 | var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); |
| 486 | 323 | try cur_pkg.children.append(new_cur_pkg); |
| 487 | 324 | cur_pkg = new_cur_pkg; |
| 488 | 325 | } else if (mem.eql(u8, "--pkg-end", arg_name)) { |
| 489 | | if (cur_pkg.parent == null) { |
| 326 | if (cur_pkg.parent) |parent| { |
| 327 | cur_pkg = parent; |
| 328 | } else { |
| 490 | 329 | try stderr.print("encountered --pkg-end with no matching --pkg-begin\n"); |
| 491 | 330 | os.exit(1); |
| 492 | 331 | } |
| 493 | | cur_pkg = cur_pkg.parent.?; |
| 494 | 332 | } |
| 495 | 333 | } |
| 496 | 334 | |
| ... | ... | @@ -499,43 +337,42 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 499 | 337 | os.exit(1); |
| 500 | 338 | } |
| 501 | 339 | |
| 502 | | var in_file: ?[]const u8 = undefined; |
| 503 | | switch (flags.positionals.len) { |
| 504 | | 0 => { |
| 505 | | try stderr.write("--name [name] not provided and unable to infer\n"); |
| 506 | | os.exit(1); |
| 507 | | }, |
| 508 | | 1 => { |
| 509 | | in_file = flags.positionals.at(0); |
| 510 | | }, |
| 340 | const provided_name = flags.single("name"); |
| 341 | const root_source_file = switch (flags.positionals.len) { |
| 342 | 0 => null, |
| 343 | 1 => flags.positionals.at(0), |
| 511 | 344 | else => { |
| 512 | | try stderr.write("only one zig input file is accepted during build\n"); |
| 345 | try stderr.print("unexpected extra parameter: {}\n", flags.positionals.at(1)); |
| 513 | 346 | os.exit(1); |
| 514 | 347 | }, |
| 515 | | } |
| 348 | }; |
| 516 | 349 | |
| 517 | | const basename = os.path.basename(in_file.?); |
| 518 | | var it = mem.split(basename, "."); |
| 519 | | const root_name = it.next() orelse { |
| 520 | | try stderr.write("file name cannot be empty\n"); |
| 521 | | os.exit(1); |
| 350 | const root_name = if (provided_name) |n| n else blk: { |
| 351 | if (root_source_file) |file| { |
| 352 | const basename = os.path.basename(file); |
| 353 | var it = mem.split(basename, "."); |
| 354 | break :blk it.next() orelse basename; |
| 355 | } else { |
| 356 | try stderr.write("--name [name] not provided and unable to infer\n"); |
| 357 | os.exit(1); |
| 358 | } |
| 522 | 359 | }; |
| 523 | 360 | |
| 524 | | const asm_a = flags.many("assembly"); |
| 525 | | const obj_a = flags.many("object"); |
| 526 | | if (in_file == null and (obj_a == null or obj_a.?.len == 0) and (asm_a == null or asm_a.?.len == 0)) { |
| 361 | const assembly_files = flags.many("assembly"); |
| 362 | const link_objects = flags.many("object"); |
| 363 | if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) { |
| 527 | 364 | try stderr.write("Expected source file argument or at least one --object or --assembly argument\n"); |
| 528 | 365 | os.exit(1); |
| 529 | 366 | } |
| 530 | 367 | |
| 531 | | if (out_type == Module.Kind.Obj and (obj_a != null and obj_a.?.len != 0)) { |
| 368 | if (out_type == Module.Kind.Obj and link_objects.len != 0) { |
| 532 | 369 | try stderr.write("When building an object file, --object arguments are invalid\n"); |
| 533 | 370 | os.exit(1); |
| 534 | 371 | } |
| 535 | 372 | |
| 536 | | const zig_root_source_file = in_file; |
| 537 | | |
| 538 | | const full_cache_dir = os.path.resolve(allocator, ".", flags.single("cache-dir") orelse "zig-cache"[0..]) catch { |
| 373 | const rel_cache_dir = flags.single("cache-dir") orelse "zig-cache"[0..]; |
| 374 | const full_cache_dir = os.path.resolve(allocator, ".", rel_cache_dir) catch { |
| 375 | try stderr.print("invalid cache dir: {}\n", rel_cache_dir); |
| 539 | 376 | os.exit(1); |
| 540 | 377 | }; |
| 541 | 378 | defer allocator.free(full_cache_dir); |
| ... | ... | @@ -546,7 +383,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 546 | 383 | var module = try Module.create( |
| 547 | 384 | allocator, |
| 548 | 385 | root_name, |
| 549 | | zig_root_source_file, |
| 386 | root_source_file, |
| 550 | 387 | Target.Native, |
| 551 | 388 | out_type, |
| 552 | 389 | build_mode, |
| ... | ... | @@ -561,24 +398,21 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 561 | 398 | |
| 562 | 399 | module.is_test = false; |
| 563 | 400 | |
| 564 | | if (flags.single("linker-script")) |linker_script| { |
| 565 | | module.linker_script = linker_script; |
| 566 | | } |
| 567 | | |
| 401 | module.linker_script = flags.single("linker-script"); |
| 568 | 402 | module.each_lib_rpath = flags.present("each-lib-rpath"); |
| 569 | 403 | |
| 570 | 404 | var clang_argv_buf = ArrayList([]const u8).init(allocator); |
| 571 | 405 | defer clang_argv_buf.deinit(); |
| 572 | | if (flags.many("mllvm")) |mllvm_flags| { |
| 573 | | for (mllvm_flags) |mllvm| { |
| 574 | | try clang_argv_buf.append("-mllvm"); |
| 575 | | try clang_argv_buf.append(mllvm); |
| 576 | | } |
| 577 | 406 | |
| 578 | | module.llvm_argv = mllvm_flags; |
| 579 | | module.clang_argv = clang_argv_buf.toSliceConst(); |
| 407 | const mllvm_flags = flags.many("mllvm"); |
| 408 | for (mllvm_flags) |mllvm| { |
| 409 | try clang_argv_buf.append("-mllvm"); |
| 410 | try clang_argv_buf.append(mllvm); |
| 580 | 411 | } |
| 581 | 412 | |
| 413 | module.llvm_argv = mllvm_flags; |
| 414 | module.clang_argv = clang_argv_buf.toSliceConst(); |
| 415 | |
| 582 | 416 | module.strip = flags.present("strip"); |
| 583 | 417 | module.is_static = flags.present("static"); |
| 584 | 418 | |
| ... | ... | @@ -610,18 +444,9 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 610 | 444 | module.verbose_cimport = flags.present("verbose-cimport"); |
| 611 | 445 | |
| 612 | 446 | module.err_color = color; |
| 613 | | |
| 614 | | if (flags.many("library-path")) |lib_dirs| { |
| 615 | | module.lib_dirs = lib_dirs; |
| 616 | | } |
| 617 | | |
| 618 | | if (flags.many("framework")) |frameworks| { |
| 619 | | module.darwin_frameworks = frameworks; |
| 620 | | } |
| 621 | | |
| 622 | | if (flags.many("rpath")) |rpath_list| { |
| 623 | | module.rpath_list = rpath_list; |
| 624 | | } |
| 447 | module.lib_dirs = flags.many("library-path"); |
| 448 | module.darwin_frameworks = flags.many("framework"); |
| 449 | module.rpath_list = flags.many("rpath"); |
| 625 | 450 | |
| 626 | 451 | if (flags.single("output-h")) |output_h| { |
| 627 | 452 | module.out_h_path = output_h; |
| ... | ... | @@ -644,41 +469,25 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 644 | 469 | } |
| 645 | 470 | |
| 646 | 471 | module.emit_file_type = emit_type; |
| 647 | | if (flags.many("object")) |objects| { |
| 648 | | module.link_objects = objects; |
| 649 | | } |
| 650 | | if (flags.many("assembly")) |assembly_files| { |
| 651 | | module.assembly_files = assembly_files; |
| 652 | | } |
| 472 | module.link_objects = link_objects; |
| 473 | module.assembly_files = assembly_files; |
| 653 | 474 | |
| 654 | 475 | try module.build(); |
| 655 | | try module.link(flags.single("out-file") orelse null); |
| 656 | | |
| 657 | | if (flags.present("print-timing-info")) { |
| 658 | | // codegen_print_timing_info(g, stderr); |
| 659 | | } |
| 660 | | |
| 661 | | try stderr.print("building {}: {}\n", @tagName(out_type), in_file); |
| 476 | try module.link(flags.single("out-file")); |
| 662 | 477 | } |
| 663 | 478 | |
| 664 | 479 | fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void { |
| 665 | | try buildOutputType(allocator, args, Module.Kind.Exe); |
| 480 | return buildOutputType(allocator, args, Module.Kind.Exe); |
| 666 | 481 | } |
| 667 | 482 | |
| 668 | | // cmd:build-lib /////////////////////////////////////////////////////////////////////////////////// |
| 669 | | |
| 670 | 483 | fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void { |
| 671 | | try buildOutputType(allocator, args, Module.Kind.Lib); |
| 484 | return buildOutputType(allocator, args, Module.Kind.Lib); |
| 672 | 485 | } |
| 673 | 486 | |
| 674 | | // cmd:build-obj /////////////////////////////////////////////////////////////////////////////////// |
| 675 | | |
| 676 | 487 | fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void { |
| 677 | | try buildOutputType(allocator, args, Module.Kind.Obj); |
| 488 | return buildOutputType(allocator, args, Module.Kind.Obj); |
| 678 | 489 | } |
| 679 | 490 | |
| 680 | | // cmd:fmt ///////////////////////////////////////////////////////////////////////////////////////// |
| 681 | | |
| 682 | 491 | const usage_fmt = |
| 683 | 492 | \\usage: zig fmt [file]... |
| 684 | 493 | \\ |
| ... | ... | @@ -735,7 +544,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 735 | 544 | defer flags.deinit(); |
| 736 | 545 | |
| 737 | 546 | if (flags.present("help")) { |
| 738 | | try stderr.write(usage_fmt); |
| 547 | try stdout.write(usage_fmt); |
| 739 | 548 | os.exit(0); |
| 740 | 549 | } |
| 741 | 550 | |
| ... | ... | @@ -863,162 +672,16 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void { |
| 863 | 672 | } |
| 864 | 673 | } |
| 865 | 674 | |
| 866 | | // cmd:version ///////////////////////////////////////////////////////////////////////////////////// |
| 867 | | |
| 868 | 675 | fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { |
| 869 | 676 | try stdout.print("{}\n", std.cstr.toSliceConst(c.ZIG_VERSION_STRING)); |
| 870 | 677 | } |
| 871 | 678 | |
| 872 | | // cmd:test //////////////////////////////////////////////////////////////////////////////////////// |
| 873 | | |
| 874 | | const usage_test = |
| 875 | | \\usage: zig test [file]... |
| 876 | | \\ |
| 877 | | \\Options: |
| 878 | | \\ --help Print this help and exit |
| 879 | | \\ |
| 880 | | \\ |
| 881 | | ; |
| 882 | | |
| 883 | 679 | const args_test_spec = []Flag{Flag.Bool("--help")}; |
| 884 | 680 | |
| 885 | | fn cmdTest(allocator: *Allocator, args: []const []const u8) !void { |
| 886 | | var flags = try Args.parse(allocator, args_build_spec, args); |
| 887 | | defer flags.deinit(); |
| 888 | | |
| 889 | | if (flags.present("help")) { |
| 890 | | try stderr.write(usage_test); |
| 891 | | os.exit(0); |
| 892 | | } |
| 893 | | |
| 894 | | if (flags.positionals.len != 1) { |
| 895 | | try stderr.write("expected exactly one zig source file\n"); |
| 896 | | os.exit(1); |
| 897 | | } |
| 898 | | |
| 899 | | // compile the test program into the cache and run |
| 900 | | |
| 901 | | // NOTE: May be overlap with buildOutput, take the shared part out. |
| 902 | | try stderr.print("testing file {}\n", flags.positionals.at(0)); |
| 903 | | } |
| 904 | | |
| 905 | | // cmd:run ///////////////////////////////////////////////////////////////////////////////////////// |
| 906 | | |
| 907 | | // Run should be simple and not expose the full set of arguments provided by build-exe. If specific |
| 908 | | // build requirements are need, the user should `build-exe` then `run` manually. |
| 909 | | const usage_run = |
| 910 | | \\usage: zig run [file] -- <runtime args> |
| 911 | | \\ |
| 912 | | \\Options: |
| 913 | | \\ --help Print this help and exit |
| 914 | | \\ |
| 915 | | \\ |
| 916 | | ; |
| 917 | | |
| 918 | | const args_run_spec = []Flag{Flag.Bool("--help")}; |
| 919 | | |
| 920 | | fn cmdRun(allocator: *Allocator, args: []const []const u8) !void { |
| 921 | | var compile_args = args; |
| 922 | | var runtime_args: []const []const u8 = []const []const u8{}; |
| 923 | | |
| 924 | | for (args) |argv, i| { |
| 925 | | if (mem.eql(u8, argv, "--")) { |
| 926 | | compile_args = args[0..i]; |
| 927 | | runtime_args = args[i + 1 ..]; |
| 928 | | break; |
| 929 | | } |
| 930 | | } |
| 931 | | var flags = try Args.parse(allocator, args_run_spec, compile_args); |
| 932 | | defer flags.deinit(); |
| 933 | | |
| 934 | | if (flags.present("help")) { |
| 935 | | try stderr.write(usage_run); |
| 936 | | os.exit(0); |
| 937 | | } |
| 938 | | |
| 939 | | if (flags.positionals.len != 1) { |
| 940 | | try stderr.write("expected exactly one zig source file\n"); |
| 941 | | os.exit(1); |
| 942 | | } |
| 943 | | |
| 944 | | try stderr.print("runtime args:\n"); |
| 945 | | for (runtime_args) |cargs| { |
| 946 | | try stderr.print("{}\n", cargs); |
| 947 | | } |
| 948 | | } |
| 949 | | |
| 950 | | // cmd:translate-c ///////////////////////////////////////////////////////////////////////////////// |
| 951 | | |
| 952 | | const usage_translate_c = |
| 953 | | \\usage: zig translate-c [file] |
| 954 | | \\ |
| 955 | | \\Options: |
| 956 | | \\ --help Print this help and exit |
| 957 | | \\ --enable-timing-info Print timing diagnostics |
| 958 | | \\ --output [path] Output file to write generated zig file (default: stdout) |
| 959 | | \\ |
| 960 | | \\ |
| 961 | | ; |
| 962 | | |
| 963 | | const args_translate_c_spec = []Flag{ |
| 964 | | Flag.Bool("--help"), |
| 965 | | Flag.Bool("--enable-timing-info"), |
| 966 | | Flag.Arg1("--libc-include-dir"), |
| 967 | | Flag.Arg1("--output"), |
| 968 | | }; |
| 969 | | |
| 970 | | fn cmdTranslateC(allocator: *Allocator, args: []const []const u8) !void { |
| 971 | | var flags = try Args.parse(allocator, args_translate_c_spec, args); |
| 972 | | defer flags.deinit(); |
| 973 | | |
| 974 | | if (flags.present("help")) { |
| 975 | | try stderr.write(usage_translate_c); |
| 976 | | os.exit(0); |
| 977 | | } |
| 978 | | |
| 979 | | if (flags.positionals.len != 1) { |
| 980 | | try stderr.write("expected exactly one c source file\n"); |
| 981 | | os.exit(1); |
| 982 | | } |
| 983 | | |
| 984 | | // set up codegen |
| 985 | | |
| 986 | | const zig_root_source_file = null; |
| 987 | | |
| 988 | | // NOTE: translate-c shouldn't require setting up the full codegen instance as it does in |
| 989 | | // the C++ compiler. |
| 990 | | |
| 991 | | // codegen_create(g); |
| 992 | | // codegen_set_out_name(g, null); |
| 993 | | // codegen_translate_c(g, flags.positional.at(0)) |
| 994 | | |
| 995 | | var output_stream = stdout; |
| 996 | | if (flags.single("output")) |output_file| { |
| 997 | | var file = try os.File.openWrite(allocator, output_file); |
| 998 | | defer file.close(); |
| 999 | | |
| 1000 | | var file_stream = io.FileOutStream.init(&file); |
| 1001 | | // TODO: Not being set correctly, still stdout |
| 1002 | | output_stream = &file_stream.stream; |
| 1003 | | } |
| 1004 | | |
| 1005 | | // ast_render(g, output_stream, g->root_import->root, 4); |
| 1006 | | try output_stream.write("pub const example = 10;\n"); |
| 1007 | | |
| 1008 | | if (flags.present("enable-timing-info")) { |
| 1009 | | // codegen_print_timing_info(g, stdout); |
| 1010 | | try stderr.write("printing timing info for translate-c\n"); |
| 1011 | | } |
| 1012 | | } |
| 1013 | | |
| 1014 | | // cmd:help //////////////////////////////////////////////////////////////////////////////////////// |
| 1015 | | |
| 1016 | 681 | fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { |
| 1017 | | try stderr.write(usage); |
| 682 | try stdout.write(usage); |
| 1018 | 683 | } |
| 1019 | 684 | |
| 1020 | | // cmd:zen ///////////////////////////////////////////////////////////////////////////////////////// |
| 1021 | | |
| 1022 | 685 | const info_zen = |
| 1023 | 686 | \\ |
| 1024 | 687 | \\ * Communicate intent precisely. |
| ... | ... | @@ -1040,8 +703,6 @@ fn cmdZen(allocator: *Allocator, args: []const []const u8) !void { |
| 1040 | 703 | try stdout.write(info_zen); |
| 1041 | 704 | } |
| 1042 | 705 | |
| 1043 | | // cmd:internal //////////////////////////////////////////////////////////////////////////////////// |
| 1044 | | |
| 1045 | 706 | const usage_internal = |
| 1046 | 707 | \\usage: zig internal [subcommand] |
| 1047 | 708 | \\ |
| ... | ... | @@ -1095,3 +756,28 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void { |
| 1095 | 756 | std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB), |
| 1096 | 757 | ); |
| 1097 | 758 | } |
| 759 | |
| 760 | const CliPkg = struct { |
| 761 | name: []const u8, |
| 762 | path: []const u8, |
| 763 | children: ArrayList(*CliPkg), |
| 764 | parent: ?*CliPkg, |
| 765 | |
| 766 | pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg { |
| 767 | var pkg = try allocator.create(CliPkg{ |
| 768 | .name = name, |
| 769 | .path = path, |
| 770 | .children = ArrayList(*CliPkg).init(allocator), |
| 771 | .parent = parent, |
| 772 | }); |
| 773 | return pkg; |
| 774 | } |
| 775 | |
| 776 | pub fn deinit(self: *CliPkg) void { |
| 777 | for (self.children.toSliceConst()) |child| { |
| 778 | child.deinit(); |
| 779 | } |
| 780 | self.children.deinit(); |
| 781 | } |
| 782 | }; |
| 783 | |