commit 51ec473ee61f884831e43175a825b65ed0d394b7 Author: Stefan Stefanov Date: Thu Jan 18 16:38:37 2024 +0200 working parsing of json and stub for parsing commands diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5198d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# build and editor ignores +.vscode/ +bin/ + +# Build artefacts +*.exe +*.pdb +*.dSYM diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..14ed2cf --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +build: clean + mkdir -p ./bin/ + odin build ./src/ -out:bin/odin_runner.exe -debug + +run: + ./bin/odin_runner.exe + +clean: + rm -rf ./bin/odin_runner.* + +nuke: + rm -rf ./bin diff --git a/odin_runner.json b/odin_runner.json new file mode 100644 index 0000000..e5c4cf7 --- /dev/null +++ b/odin_runner.json @@ -0,0 +1,40 @@ +{ + "defaults": { + "collections": [], + "flags": [], + "output_dir": "./bin/", + "binary_name": "binary_name.bin" + }, + "configurations": [ + { + "release": { + "collections": [ + { + "name": "shared", + "path": "./src/" + } + ], + "flags": [ + "-o:speed", + ], + "output_dir": "./bin/release/", + "binary_name": "binary_name_release.bin" + } + }, + { + "debug": { + "collections": [ + { + "name": "shared", + "path": "./src/" + } + ], + "flags": [ + "-debug", + ], + "output_dir": "./bin/debug/", + "binary_name": "binary_name_debug.bin" + } + } + ], +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..09fc8fb --- /dev/null +++ b/readme.md @@ -0,0 +1,11 @@ +# Why? +Because I can. + +# How to use +Usage: + * `odin_runner` - Run the default command with the defautl configuration (i.e. build with the defaults) + * `odin_runner build` - Same as above + * `odin_runner build debug` - Same as above but with an explicit configuration (`debug`) + * `odin_runner check` - Runs odin check with the defaults + * `odin_runner check debug` - Same as above but with an explicit configuration (`debug`) + * `odin_runner clean debug` - Cleans up build artefacts in the build directory of an explicit configuration (`debug`) diff --git a/src/argument_parser.odin b/src/argument_parser.odin new file mode 100644 index 0000000..f9f9ae5 --- /dev/null +++ b/src/argument_parser.odin @@ -0,0 +1,33 @@ +package main + +import "core:fmt" +import "core:log" +import "core:os" + +ECommand :: enum { + BUILD, + CHECK, + CLEAN, +} + +BUILD_CMD :: "build" +CHECK_CMD :: "check" +CLEAN_CMD :: "clean" + +parse_commands :: proc() { + command : ECommand + args := os.args + binary_name := args[0] + command_string := args[1] + log.infof("args: %v", args) + + if command_string == BUILD_CMD { + command = .BUILD + } + if command_string == CHECK_CMD { + command = .CHECK + } + if command_string == CLEAN_CMD { + command = .CLEAN + } +} diff --git a/src/config_parser.odin b/src/config_parser.odin new file mode 100644 index 0000000..38fbebe --- /dev/null +++ b/src/config_parser.odin @@ -0,0 +1,114 @@ +package main + +import "core:encoding/json" +import "core:fmt" +import "core:log" +import "core:os" +import "core:strings" + +Path :: distinct string // a unix like path (absolute or relative) +CollectionName :: distinct string +TargetName :: distinct string + +DEFAULT_TARGET_NAME :: "defaults" +CONFIGURATIONS_KEY :: "configurations" +FLAGS_KEY :: "flags" +OUTPUT_DIR_KEY :: "output_dir" +BINARY_NAME_KEY :: "binary_name" +COLLECTION_NAME_KEY :: "name" +COLLECTION_PATH_KEY :: "path" + +// A single config object should hold the configuration for a single target +// i.e. "Release", "Debug", etc... +Config :: struct { + collections: map[CollectionName]Path, + flags: [dynamic]string, + output_dir: Path, + binary_name: string, + configuration_name: TargetName, +} + +ConfigurationTargets :: distinct map[TargetName]Config + +parse_config :: proc( + config_path: string, + allocator := context.allocator, +) -> ( + configs: ConfigurationTargets, +) { + log.infof("Parsing config file: %s", config_path) + + ok: bool + settings_json_bytes: []byte + settings_json_bytes, ok = os.read_entire_file(config_path, allocator);if !ok { + log.errorf("Couldn't read settings file: %s", config_path) + return + } + + parsed_json_data, parse_err := json.parse(settings_json_bytes);if parse_err != nil { + log.errorf("Failed to parse json data: %v", parse_err) + return + } + + root, rok := parsed_json_data.(json.Object);if !rok { + log.errorf("Empty json!") + return + } + + defaults_target: json.Object + defaults_target, ok = root[DEFAULT_TARGET_NAME].(json.Object) + if !ok {log.info("No default target in config.")} + + configs = make(ConfigurationTargets) + configurations_object, conf_ok := root[CONFIGURATIONS_KEY].(json.Array) + if conf_ok { + for conf_obj in configurations_object { + // log.debugf("Found custom target: %v", conf_obj) + // k: json.String; v: json.Object; conf: json.Object + conf := conf_obj.(json.Object) + for k, v in conf { + conf_name := k + conf_obj_target := v.(json.Object) + configs[TargetName(conf_name)] = parse_target_config(TargetName(conf_name), conf_obj_target) + } + } + } else {log.info("No custom targets in config.")} + + // parse the default target configuration + configs[DEFAULT_TARGET_NAME] = parse_target_config(DEFAULT_TARGET_NAME, defaults_target) + + return +} + +parse_target_config :: proc(name: TargetName, target_obj: json.Object) -> (config: Config) { + log.infof("Parsing custom target: %s", name) + config.configuration_name = name + + collections_arr, c_ok := target_obj["collections"].(json.Array) + if c_ok { + for collection in collections_arr { + collection_obj, cc_ok := collection.(json.Object);if cc_ok { + name := collection_obj[COLLECTION_NAME_KEY].(json.String) + path := collection_obj[COLLECTION_PATH_KEY].(json.String) + config.collections[CollectionName(name)] = Path(path) + } + } + } + + flags_arr, f_ok := target_obj[FLAGS_KEY].(json.Array) + if f_ok { + for flag in flags_arr { + flag, ff_ok := flag.(json.String);if ff_ok { + append(&config.flags, string(flag)) + } + } + } + + output_dir, o_ok := target_obj[OUTPUT_DIR_KEY].(json.String) + if o_ok {config.output_dir = Path(output_dir)} + + binary_name, b_ok := target_obj[BINARY_NAME_KEY].(json.String) + if b_ok {config.binary_name = binary_name} + + return +} diff --git a/src/main.odin b/src/main.odin new file mode 100644 index 0000000..e6d144b --- /dev/null +++ b/src/main.odin @@ -0,0 +1,11 @@ +package main + +import "core:log" + +main :: proc() { + context.logger = log.create_console_logger() + + parse_commands() + targets := parse_config("./odin_runner.json") + log.debug(targets) +}