hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

main.ha (4469B)


      1 // SPDX-License-Identifier: GPL-3.0-only
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use cmd::hare::build;
      5 use fmt;
      6 use fs;
      7 use getopt;
      8 use hare::module;
      9 use hare::parse;
     10 use io;
     11 use os;
     12 use os::exec;
     13 use path;
     14 use strconv;
     15 
     16 def VERSION: str = "unknown";
     17 def HAREPATH: str = ".";
     18 
     19 const help: []getopt::help = [
     20 	"compile, run, and test Hare programs",
     21 	"<subcommand>",
     22 	"args...",
     23 	("build", [
     24 		"compiles a Hare program or module",
     25 		// XXX: once cross-compiling to different targets (linux,
     26 		// freebsd, etc) is supported, we can probably merge -F with it
     27 		('F', "build for freestanding environment"),
     28 		('q', "build silently"),
     29 		('v', "print executed commands (specify twice to print arguments)"),
     30 		('a', "arch", "set target architecture"),
     31 		('D', "ident[:type]=value", "define a constant"),
     32 		('j', "jobs", "set parallelism for build"),
     33 		('L', "libdir", "add directory to linker library search path"),
     34 		('l', "libname", "link with a system library"),
     35 		('N', "namespace", "override namespace for module"),
     36 		('o', "path", "set output file name"),
     37 		('R', "build in release mode"),
     38 		('T', "tagset", "set/unset build tags"),
     39 		('t', "type", "build type (s/o/bin)"),
     40 		"[path]"
     41 	]: []getopt::help),
     42 	("cache", [
     43 		"manages the build cache",
     44 		('c', "clears the cache"),
     45 	]: []getopt::help),
     46 	("deps", [
     47 		"prints dependency information for a Hare program",
     48 		('d', "print dot syntax for use with graphviz"),
     49 		('T', "tagset", "set/unset build tags"),
     50 		"[path|module]",
     51 	]: []getopt::help),
     52 	("run", [
     53 		"compiles and runs a Hare program or module",
     54 		('q', "build silently"),
     55 		('v', "print executed commands (specify twice to print arguments)"),
     56 		('a', "arch", "set target architecture"),
     57 		('D', "ident[:type]=value", "define a constant"),
     58 		('j', "jobs", "set parallelism for build"),
     59 		('L', "libdir", "add directory to linker library search path"),
     60 		('l', "libname", "link with a system library"),
     61 		('R', "build in release mode"),
     62 		('T', "tagset", "set/unset build tags"),
     63 		"[path [args...]]",
     64 	]: []getopt::help),
     65 	("test", [
     66 		"compiles and runs tests for Hare code",
     67 		('q', "build silently"),
     68 		('v', "print executed commands (specify twice to print arguments)"),
     69 		('a', "arch", "set target architecture"),
     70 		('D', "ident[:type]=value", "define a constant"),
     71 		('j', "jobs", "set parallelism for build"),
     72 		('L', "libdir", "add directory to linker library search path"),
     73 		('l', "libname", "link with a system library"),
     74 		('o', "path", "set output file name"),
     75 		('R', "build in release mode"),
     76 		('T', "tagset", "set/unset build tags"),
     77 		"[path]"
     78 	]: []getopt::help),
     79 	("version", [
     80 		"provides version information for the Hare environment",
     81 		('v', "print build parameters"),
     82 	]: []getopt::help),
     83 ];
     84 
     85 export fn main() void = {
     86 	const cmd = getopt::parse(os::args, help...);
     87 	defer getopt::finish(&cmd);
     88 	match (cmd.subcmd) {
     89 	case void =>
     90 		getopt::printusage(os::stderr, os::args[0], help...)!;
     91 		os::exit(os::status::FAILURE);
     92 	case let subcmd: (str, *getopt::command) =>
     93 		const task = switch (subcmd.0) {
     94 		case "build", "run", "test" =>
     95 			yield &build;
     96 		case "cache" =>
     97 			yield &cache;
     98 		case "deps" =>
     99 			yield &deps;
    100 		case "version" =>
    101 			yield &version;
    102 		case => abort();
    103 		};
    104 		match (task(subcmd.0, subcmd.1)) {
    105 		case void => void;
    106 		case let e: exec::error =>
    107 			fmt::fatal("Error:", exec::strerror(e));
    108 		case let e: fs::error =>
    109 			fmt::fatal("Error:", fs::strerror(e));
    110 		case let e: io::error =>
    111 			fmt::fatal("Error:", io::strerror(e));
    112 		case let e: module::error =>
    113 			fmt::fatal("Error:", module::strerror(e));
    114 		case let e: path::error =>
    115 			fmt::fatal("Error:", path::strerror(e));
    116 		case let e: parse::error =>
    117 			fmt::fatal("Error:", parse::strerror(e));
    118 		case let e: strconv::error =>
    119 			fmt::fatal("Error:", strconv::strerror(e));
    120 		case let e: unknown_arch =>
    121 			fmt::fatalf("Error: Unknown arch: {}", e);
    122 		case let e: build::unknown_platform =>
    123 			fmt::fatalf("Error: Unknown platform: {}", e);
    124 		case unknown_output =>
    125 			fmt::fatal("Error: Can't guess output in root directory");
    126 		case let e: unknown_type =>
    127 			fmt::fatalf("Error: Unknown build type: {}", e);
    128 		case let e: output_exists =>
    129 			fmt::fatalf("Error: Output path '{}' already exists, but isn't an executable file",
    130 				e);
    131 		case let e: output_failed =>
    132 			fmt::fatalf("Error: Could not open output '{}': {}",
    133 				e.0, fs::strerror(e.1));
    134 		case let e: invalid_namespace =>
    135 			fmt::fatalf("Error: Invalid namespace: {}", e);
    136 		};
    137 	};
    138 };