406 lines
8.5 KiB
Odin
406 lines
8.5 KiB
Odin
package builder
|
|
|
|
import "core:flags"
|
|
import "core:fmt"
|
|
import "core:io"
|
|
import "core:log"
|
|
import os "core:os/os2"
|
|
import "core:path/filepath"
|
|
import "core:slice"
|
|
import "core:strings"
|
|
import "core:thread"
|
|
|
|
Build_Variant :: enum {
|
|
Hot_Reload,
|
|
Desktop,
|
|
Web,
|
|
Assetcomp,
|
|
}
|
|
|
|
Options :: struct {
|
|
variant: Build_Variant `usage:"Variant of the build"`,
|
|
optimize: bool `args:"name=opt",usage:"Enable compiler optimizations"`,
|
|
debug: bool `usage:"Enable debug symbols"`,
|
|
force: bool `usage:"When enabled dependencies will be cleaned and rebuilt"`,
|
|
tracy: bool `usage:"Enable tracy profiler"`,
|
|
run: bool,
|
|
}
|
|
|
|
temp_concat :: proc(strs: ..[]string) -> []string {
|
|
result := slice.concatenate(strs, context.temp_allocator)
|
|
return result
|
|
}
|
|
|
|
temp_path_join :: proc(paths: ..string) -> string {
|
|
result, _ := filepath.join(paths, context.temp_allocator)
|
|
return result
|
|
}
|
|
|
|
when ODIN_OS == .Windows {
|
|
EXE_EXT :: ".exe"
|
|
DLL_EXT :: ".dll"
|
|
LIB_PREFIX :: ""
|
|
EMSCRIPTEN_SHELL_EXT :: ".bat"
|
|
} else when ODIN_OS == .Linux {
|
|
EXE_EXT :: ".bin"
|
|
DLL_EXT :: ".so"
|
|
LIB_PREFIX :: "lib"
|
|
EMSCRIPTEN_SHELL_EXT :: ""
|
|
} else when ODIN_OS == .Darwin {
|
|
EXE_EXT :: ".bin"
|
|
DLL_EXT :: ".dylib"
|
|
LIB_PREFIX :: "lib"
|
|
EMSCRIPTEN_SHELL_EXT :: ""
|
|
} else {
|
|
EXE_EXT :: ""
|
|
DLL_EXT :: ""
|
|
LIB_PREFIX :: ""
|
|
EMSCRIPTEN_SHELL_EXT :: ""
|
|
}
|
|
|
|
// Returns a list of shared dependencies that have to be copied to out dir
|
|
build_deps :: proc(opts: Options) -> []string {
|
|
log.infof("build_deps")
|
|
force := opts.force
|
|
shared := opts.variant == .Hot_Reload
|
|
|
|
out_libs := make([dynamic]string, 0, 3, context.temp_allocator)
|
|
|
|
// Raylib
|
|
{
|
|
|
|
if opts.variant == .Web {
|
|
cwd := "./libs/raylib/src"
|
|
|
|
build_mode := opts.debug ? "RAYLIB_BUILD_MODE=DEBUG" : "RAYLIB_BUILD_MODE=RELEASE"
|
|
|
|
if force {
|
|
run_cmd(temp_concat({"make", "clean", "PLATFORM=PLATFORM_WEB"}, {build_mode}), cwd)
|
|
}
|
|
|
|
run_cmd(temp_concat({"make", "PLATFORM=PLATFORM_WEB", "-j8"}, {build_mode}), cwd)
|
|
} else {
|
|
cwd := "./libs/raylib"
|
|
out_dir := shared ? "zig-out-shared" : "zig-out-static"
|
|
remove_all(fmt.tprintf("./libs/raylib/%s", out_dir))
|
|
if force {
|
|
remove_all("./libs/raylib/.zig-cache")
|
|
}
|
|
|
|
target := "native"
|
|
|
|
run_cmd(
|
|
{
|
|
"zig",
|
|
"build",
|
|
"-p",
|
|
out_dir,
|
|
fmt.tprintf("-Dshared=%v", shared),
|
|
fmt.tprintf("-Dtarget=%s", target),
|
|
},
|
|
cwd,
|
|
)
|
|
|
|
if shared {
|
|
append(
|
|
&out_libs,
|
|
temp_path_join(
|
|
"./libs/raylib/zig-out-shared/lib",
|
|
LIB_PREFIX + "raylib" + DLL_EXT,
|
|
),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Physfs
|
|
{
|
|
cwd := "./libs/physfs"
|
|
is_built := os.is_dir("./libs/physfs/build")
|
|
if force {
|
|
remove_all("./libs/physfs/build")
|
|
}
|
|
prepare_cmd := []string {
|
|
"cmake",
|
|
"-B",
|
|
"build",
|
|
fmt.tprintf("-DPHYSFS_BUILD_SHARED=%v", shared),
|
|
"-DCMAKE_BUILD_TYPE=MinSizeRel",
|
|
"./physfs",
|
|
}
|
|
build_cmd := []string{"cmake", "--build", "build", "--config", "MinSizeRel"}
|
|
if !is_built || force {
|
|
if opts.variant == .Web {
|
|
run_cmd(temp_concat({"emcmake" + EMSCRIPTEN_SHELL_EXT}, prepare_cmd), cwd)
|
|
run_cmd(temp_concat({"emmake" + EMSCRIPTEN_SHELL_EXT}, build_cmd), cwd)
|
|
} else {
|
|
run_cmd(prepare_cmd, cwd)
|
|
run_cmd(build_cmd, cwd)
|
|
}
|
|
}
|
|
|
|
if shared {
|
|
append(&out_libs, "./libs/physfs/build/libphysfs.so.1")
|
|
}
|
|
}
|
|
|
|
// Tracy
|
|
if opts.tracy {
|
|
assert(opts.variant != .Web)
|
|
|
|
cwd := "./libs/tracy"
|
|
|
|
when ODIN_OS == .Windows {
|
|
TRACY_NAME_SHARED :: "tracy.dll"
|
|
TRACY_NAME_STATIC :: "tracy.lib"
|
|
TRACY_FLAGS :: []string{"-lws2_32", "-ldbghelp"}
|
|
} else when ODIN_OS == .Linux {
|
|
TRACY_NAME_SHARED :: "tracy.so"
|
|
TRACY_NAME_STATIC :: "tracy.a"
|
|
TRACY_FLAGS :: []string{}
|
|
} else when ODIN_OS == .Darwin {
|
|
TRACY_NAME_SHARED :: "tracy.dynlib"
|
|
TRACY_NAME_STATIC :: "tracy.a"
|
|
TRACY_FLAGS :: []string{}
|
|
}
|
|
|
|
file_path := temp_path_join("./libs/tracy", shared ? TRACY_NAME_SHARED : TRACY_NAME_STATIC)
|
|
|
|
is_built := os.is_file(file_path)
|
|
if is_built && force {
|
|
remove_file(file_path)
|
|
}
|
|
|
|
if !is_built || force {
|
|
run_cmd(
|
|
temp_concat(
|
|
{
|
|
"zig",
|
|
"c++",
|
|
"-std=c++11",
|
|
"-DTRACY_ENABLE",
|
|
"-O2",
|
|
"vendor/tracy/public/TracyClient.cpp",
|
|
},
|
|
TRACY_FLAGS,
|
|
shared ? {"-shared", "-o", TRACY_NAME_SHARED} : {"-c", "-o", "tracy.o"},
|
|
),
|
|
cwd,
|
|
)
|
|
|
|
if !shared {
|
|
run_cmd({"zig", "ar", "rc", TRACY_NAME_STATIC, "tracy.o"}, cwd)
|
|
}
|
|
}
|
|
|
|
if shared {
|
|
append(&out_libs, "./libs/tracy/tracy" + DLL_EXT)
|
|
}
|
|
}
|
|
|
|
return out_libs[:]
|
|
}
|
|
|
|
COMMON_FLAGS :: []string {
|
|
"-collection:libs=./libs",
|
|
"-collection:common=./common",
|
|
"-collection:game=./game",
|
|
"-strict-style",
|
|
"-vet",
|
|
}
|
|
|
|
setup_emsdk_env :: proc() {
|
|
when ODIN_OS == .Windows {
|
|
PATH_ENV_DELIMITER :: ";"
|
|
} else {
|
|
PATH_ENV_DELIMITER :: ":"
|
|
}
|
|
|
|
PATHS :: [2]string{"./libs/emsdk/upstream/bin", "./libs/emsdk/upstream/emscripten"}
|
|
|
|
paths: [len(PATHS)]string
|
|
for path, i in PATHS {
|
|
paths[i] = absolute_path(path)
|
|
}
|
|
|
|
set_env(
|
|
"PATH",
|
|
strings.join(
|
|
{paths[0], paths[1], os.get_env("PATH", context.temp_allocator)},
|
|
PATH_ENV_DELIMITER,
|
|
context.temp_allocator,
|
|
),
|
|
)
|
|
|
|
set_env("EMSDK", absolute_path("./libs/emsdk"))
|
|
}
|
|
|
|
setup_bin_dir :: proc(opts: Options, path: string, files_to_copy: []string) {
|
|
mkdir_all(path)
|
|
|
|
for file in files_to_copy {
|
|
dst := temp_path_join(path, filepath.base(file))
|
|
|
|
if !os.is_file(dst) || opts.force {
|
|
copy_file(file, dst)
|
|
}
|
|
}
|
|
}
|
|
|
|
main :: proc() {
|
|
context.logger = log.create_console_logger()
|
|
opts := Options {
|
|
tracy = true,
|
|
debug = true,
|
|
optimize = true,
|
|
run = true,
|
|
}
|
|
flags.parse_or_exit(&opts, os.args, .Unix, context.temp_allocator)
|
|
if opts.variant == .Web {
|
|
log.warnf("tracy is not supported on Web")
|
|
opts.tracy = false
|
|
|
|
setup_emsdk_env()
|
|
}
|
|
|
|
tracy_flag: []string = opts.tracy ? {"-define:TRACY_ENABLE=true"} : {}
|
|
debug_flag: []string = opts.debug ? {"-debug"} : {}
|
|
optimize_flag: []string = opts.optimize ? {"-o:speed"} : {}
|
|
|
|
shared_dep_paths := build_deps(opts)
|
|
|
|
switch opts.variant {
|
|
case .Hot_Reload:
|
|
setup_bin_dir(opts, "./bin/hotreload", shared_dep_paths)
|
|
|
|
is_running := process_exists("game" + EXE_EXT)
|
|
if !is_running {
|
|
run_cmd(
|
|
temp_concat(
|
|
[]string {
|
|
"odin",
|
|
"build",
|
|
"main_hot_reload",
|
|
"-out:./bin/hotreload/game" + EXE_EXT,
|
|
},
|
|
debug_flag,
|
|
tracy_flag,
|
|
COMMON_FLAGS,
|
|
),
|
|
"",
|
|
)
|
|
}
|
|
build_game_cmd := run_cmd(
|
|
temp_concat(
|
|
[]string {
|
|
"odin",
|
|
"build",
|
|
"game",
|
|
"-define:NAME_STATIC_INIT=false",
|
|
"-define:RAYLIB_SHARED=true",
|
|
"-define:PHYSFS_SHARED=true",
|
|
"-define:DEV=true",
|
|
"-build-mode:dll",
|
|
"-out:./bin/hotreload/game_tmp" + DLL_EXT,
|
|
},
|
|
tracy_flag,
|
|
debug_flag,
|
|
optimize_flag,
|
|
COMMON_FLAGS,
|
|
),
|
|
"",
|
|
)
|
|
rename("./bin/hotreload/game_tmp" + DLL_EXT, "./bin/hotreload/game" + DLL_EXT)
|
|
|
|
if !is_running && opts.run {
|
|
run_cmd({"./bin/hotreload/game" + EXE_EXT}, "")
|
|
}
|
|
case .Desktop:
|
|
setup_bin_dir(opts, "./bin/desktop", shared_dep_paths)
|
|
|
|
cmd := slice.concatenate(
|
|
[][]string {
|
|
[]string{"odin", "build", "main_release", "-out:./bin/desktop/game" + EXE_EXT},
|
|
tracy_flag,
|
|
debug_flag,
|
|
optimize_flag,
|
|
COMMON_FLAGS,
|
|
},
|
|
context.temp_allocator,
|
|
)
|
|
run_cmd(cmd, "")
|
|
case .Web:
|
|
remove_all("./bin/web")
|
|
mkdir_all("./bin/web")
|
|
|
|
odin_root := run_cmd({"odin", "root"}, "")
|
|
|
|
cmd := slice.concatenate(
|
|
[][]string {
|
|
[]string {
|
|
"odin",
|
|
"build",
|
|
"main_web",
|
|
"-target:js_wasm32",
|
|
"-build-mode:obj",
|
|
"-out:bin/web/game.wasm.o",
|
|
},
|
|
COMMON_FLAGS,
|
|
debug_flag,
|
|
optimize_flag,
|
|
},
|
|
)
|
|
run_cmd(cmd, "")
|
|
|
|
wasm_debug_flag := opts.debug ? []string{"-g"} : []string{}
|
|
|
|
run_cmd(
|
|
temp_concat(
|
|
{
|
|
"emcc" + EMSCRIPTEN_SHELL_EXT,
|
|
"-o",
|
|
"bin/web/index.html",
|
|
"bin/web/game.wasm.o",
|
|
"libs/raylib/src/libraylib.web.a",
|
|
"libs/physfs/build/libphysfs.a",
|
|
"-sUSE_GLFW=3",
|
|
"-sWASM_BIGINT",
|
|
"-sWARN_ON_UNDEFINED_SYMBOLS=0",
|
|
"-sALLOW_MEMORY_GROWTH",
|
|
"-sASSERTIONS=2",
|
|
"--shell-file",
|
|
"main_web/index_template.html",
|
|
"--preload-file",
|
|
"assets",
|
|
},
|
|
wasm_debug_flag,
|
|
),
|
|
"",
|
|
)
|
|
remove_file("./bin/web/game.wasm.o")
|
|
|
|
copy_file(
|
|
filepath.join(
|
|
{odin_root, "core", "sys", "wasm", "js", "odin.js"},
|
|
context.temp_allocator,
|
|
),
|
|
"./bin/web/odin.js",
|
|
)
|
|
case .Assetcomp:
|
|
remove_all("./bin/assetcomp")
|
|
mkdir_all("./bin/assetcomp")
|
|
|
|
cmd := slice.concatenate(
|
|
[][]string {
|
|
[]string{"odin", "build", "assetcomp", "-out:./bin/assetcomp/assetcomp" + EXE_EXT},
|
|
// tracy_flag,
|
|
debug_flag,
|
|
optimize_flag,
|
|
COMMON_FLAGS,
|
|
},
|
|
context.temp_allocator,
|
|
)
|
|
run_cmd(cmd, "")
|
|
}
|
|
}
|