diff --git a/Makefile b/Makefile index 14ed2cf..7b76a03 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ build: clean run: ./bin/odin_runner.exe +check: + odin check ./src/ + clean: rm -rf ./bin/odin_runner.* diff --git a/odin_runner.json b/odin_runner.json index e5c4cf7..263a324 100644 --- a/odin_runner.json +++ b/odin_runner.json @@ -2,6 +2,7 @@ "defaults": { "collections": [], "flags": [], + "source": "./src/", "output_dir": "./bin/", "binary_name": "binary_name.bin" }, @@ -17,6 +18,7 @@ "flags": [ "-o:speed", ], + "source": "./src/", "output_dir": "./bin/release/", "binary_name": "binary_name_release.bin" } @@ -32,6 +34,7 @@ "flags": [ "-debug", ], + "source": "./src/", "output_dir": "./bin/debug/", "binary_name": "binary_name_debug.bin" } diff --git a/src.bin b/src.bin new file mode 100755 index 0000000..9885ffb Binary files /dev/null and b/src.bin differ diff --git a/src/argument_parser.odin b/src/argument_parser.odin index f9f9ae5..ab79560 100644 --- a/src/argument_parser.odin +++ b/src/argument_parser.odin @@ -4,30 +4,51 @@ import "core:fmt" import "core:log" import "core:os" -ECommand :: enum { +Command :: enum { + TEST, BUILD, CHECK, CLEAN, } +TEST_CMD :: "test" BUILD_CMD :: "build" CHECK_CMD :: "check" CLEAN_CMD :: "clean" -parse_commands :: proc() { - command : ECommand +parse_commands :: proc() -> (command: Command, target: TargetName) { args := os.args binary_name := args[0] - command_string := args[1] + command_string := len(args) > 1 ? args[1] : "build" log.infof("args: %v", args) - if command_string == BUILD_CMD { + if command_string == TEST_CMD { + command = .TEST + } else if command_string == BUILD_CMD { command = .BUILD - } - if command_string == CHECK_CMD { + } else if command_string == CHECK_CMD { command = .CHECK - } - if command_string == CLEAN_CMD { + } else if command_string == CLEAN_CMD { command = .CLEAN + } else {log.errorf("Unsupported command: %s", command_string);os.exit(1)} + + if len(args) > 2 { + target = TargetName(args[2]) } + return +} + +command_to_string :: proc(command: Command) -> string { + switch command { + case .TEST: + {return "test"} + case .BUILD: + {return "build"} + case .CLEAN: + {return "clean"} + case .CHECK: + {return "check"} + } + + return "" } diff --git a/src/command_executor.odin b/src/command_executor.odin new file mode 100644 index 0000000..7c9c3f9 --- /dev/null +++ b/src/command_executor.odin @@ -0,0 +1,80 @@ +package main + +import c "core:c/libc" +import "core:log" +import "core:os" +import "core:strings" + +ExecutionError :: enum { + None, + ErrorDuringCommandExecution, +} + +execute_command :: proc( + command: Command, + target_name: TargetName, + configuration: ConfigurationTargets, +) -> ( + error: ExecutionError, +) { + target_config, found_target_in_config := configuration[target_name] + if !found_target_in_config && target_name != "" { + log.errorf("No such target in config: %s", target_name) + os.exit(1) + } + + compile_flags: string + sb := strings.builder_make() + defer strings.builder_destroy(&sb) + + // Append the command + strings.write_string(&sb, "odin ") + strings.write_string(&sb, command_to_string(command)) + strings.write_byte(&sb, ' ') + + if def_config, ok := configuration[DEFAULT_TARGET_NAME]; ok && !found_target_in_config { + strings.write_string(&sb, string(def_config.source)) + } else if found_target_in_config { + strings.write_string(&sb, string(target_config.source)) + } + + // Add the collections to the compile flags + if def_config, ok := configuration[DEFAULT_TARGET_NAME]; ok { + for collectionName, collectionPath in def_config.collections { + strings.write_string(&sb, " -collection:") + strings.write_string(&sb, string(collectionName)) + strings.write_string(&sb, "=") + strings.write_string(&sb, string(collectionPath)) + } + } + if found_target_in_config { + for collectionName, collectionPath in target_config.collections { + strings.write_string(&sb, " -collection:") + strings.write_string(&sb, string(collectionName)) + strings.write_string(&sb, "=") + strings.write_string(&sb, string(collectionPath)) + } + } + + // Add the other type of flags + if def_config, ok := configuration[DEFAULT_TARGET_NAME]; ok { + for flag in def_config.flags { + strings.write_byte(&sb, ' ') + strings.write_string(&sb, flag) + } + } + if found_target_in_config { + for flag in target_config.flags { + strings.write_byte(&sb, ' ') + strings.write_string(&sb, flag) + } + } + + compile_flags = strings.to_string(sb) + + log.infof("Calling command:\n\t'%s'", compile_flags) + ccommand, err := strings.clone_to_cstring(compile_flags) + c.system(ccommand) + + return +} diff --git a/src/config_parser.odin b/src/config_parser.odin index 38fbebe..e562eec 100644 --- a/src/config_parser.odin +++ b/src/config_parser.odin @@ -13,6 +13,7 @@ TargetName :: distinct string DEFAULT_TARGET_NAME :: "defaults" CONFIGURATIONS_KEY :: "configurations" FLAGS_KEY :: "flags" +SOURCE_KEY :: "source" OUTPUT_DIR_KEY :: "output_dir" BINARY_NAME_KEY :: "binary_name" COLLECTION_NAME_KEY :: "name" @@ -26,6 +27,7 @@ Config :: struct { output_dir: Path, binary_name: string, configuration_name: TargetName, + source: Path, } ConfigurationTargets :: distinct map[TargetName]Config @@ -104,6 +106,9 @@ parse_target_config :: proc(name: TargetName, target_obj: json.Object) -> (confi } } + source, s_ok := target_obj[SOURCE_KEY].(json.String) + if s_ok {config.source = Path(source)} + output_dir, o_ok := target_obj[OUTPUT_DIR_KEY].(json.String) if o_ok {config.output_dir = Path(output_dir)} diff --git a/src/main.odin b/src/main.odin index e6d144b..56df7f2 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,11 +1,13 @@ package main import "core:log" +import c "core:c/libc" main :: proc() { context.logger = log.create_console_logger() - parse_commands() + command, target := parse_commands() targets := parse_config("./odin_runner.json") log.debug(targets) + execute_command(command, target, targets) }