initial working version of the builder

This commit is contained in:
Stefan Stefanov 2024-01-18 17:40:11 +02:00
parent 51ec473ee6
commit b7e340b562
7 changed files with 124 additions and 10 deletions

View file

@ -5,6 +5,9 @@ build: clean
run: run:
./bin/odin_runner.exe ./bin/odin_runner.exe
check:
odin check ./src/
clean: clean:
rm -rf ./bin/odin_runner.* rm -rf ./bin/odin_runner.*

View file

@ -2,6 +2,7 @@
"defaults": { "defaults": {
"collections": [], "collections": [],
"flags": [], "flags": [],
"source": "./src/",
"output_dir": "./bin/", "output_dir": "./bin/",
"binary_name": "binary_name.bin" "binary_name": "binary_name.bin"
}, },
@ -17,6 +18,7 @@
"flags": [ "flags": [
"-o:speed", "-o:speed",
], ],
"source": "./src/",
"output_dir": "./bin/release/", "output_dir": "./bin/release/",
"binary_name": "binary_name_release.bin" "binary_name": "binary_name_release.bin"
} }
@ -32,6 +34,7 @@
"flags": [ "flags": [
"-debug", "-debug",
], ],
"source": "./src/",
"output_dir": "./bin/debug/", "output_dir": "./bin/debug/",
"binary_name": "binary_name_debug.bin" "binary_name": "binary_name_debug.bin"
} }

BIN
src.bin Executable file

Binary file not shown.

View file

@ -4,30 +4,51 @@ import "core:fmt"
import "core:log" import "core:log"
import "core:os" import "core:os"
ECommand :: enum { Command :: enum {
TEST,
BUILD, BUILD,
CHECK, CHECK,
CLEAN, CLEAN,
} }
TEST_CMD :: "test"
BUILD_CMD :: "build" BUILD_CMD :: "build"
CHECK_CMD :: "check" CHECK_CMD :: "check"
CLEAN_CMD :: "clean" CLEAN_CMD :: "clean"
parse_commands :: proc() { parse_commands :: proc() -> (command: Command, target: TargetName) {
command : ECommand
args := os.args args := os.args
binary_name := args[0] binary_name := args[0]
command_string := args[1] command_string := len(args) > 1 ? args[1] : "build"
log.infof("args: %v", args) 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 command = .BUILD
} } else if command_string == CHECK_CMD {
if command_string == CHECK_CMD {
command = .CHECK command = .CHECK
} } else if command_string == CLEAN_CMD {
if command_string == CLEAN_CMD {
command = .CLEAN 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 ""
} }

80
src/command_executor.odin Normal file
View file

@ -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
}

View file

@ -13,6 +13,7 @@ TargetName :: distinct string
DEFAULT_TARGET_NAME :: "defaults" DEFAULT_TARGET_NAME :: "defaults"
CONFIGURATIONS_KEY :: "configurations" CONFIGURATIONS_KEY :: "configurations"
FLAGS_KEY :: "flags" FLAGS_KEY :: "flags"
SOURCE_KEY :: "source"
OUTPUT_DIR_KEY :: "output_dir" OUTPUT_DIR_KEY :: "output_dir"
BINARY_NAME_KEY :: "binary_name" BINARY_NAME_KEY :: "binary_name"
COLLECTION_NAME_KEY :: "name" COLLECTION_NAME_KEY :: "name"
@ -26,6 +27,7 @@ Config :: struct {
output_dir: Path, output_dir: Path,
binary_name: string, binary_name: string,
configuration_name: TargetName, configuration_name: TargetName,
source: Path,
} }
ConfigurationTargets :: distinct map[TargetName]Config 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) output_dir, o_ok := target_obj[OUTPUT_DIR_KEY].(json.String)
if o_ok {config.output_dir = Path(output_dir)} if o_ok {config.output_dir = Path(output_dir)}

View file

@ -1,11 +1,13 @@
package main package main
import "core:log" import "core:log"
import c "core:c/libc"
main :: proc() { main :: proc() {
context.logger = log.create_console_logger() context.logger = log.create_console_logger()
parse_commands() command, target := parse_commands()
targets := parse_config("./odin_runner.json") targets := parse_config("./odin_runner.json")
log.debug(targets) log.debug(targets)
execute_command(command, target, targets)
} }