Finally working hot reload again
This commit is contained in:
parent
8b8ab8c6bc
commit
33cffe95a2
@ -1,2 +1,2 @@
|
|||||||
vim.opt_global.makeprg = "./build_hot_reload.sh"
|
vim.opt_global.makeprg = "./build.sh"
|
||||||
vim.opt.errorformat = "%f(%l:%c)\\ %m"
|
vim.opt.errorformat = "%f(%l:%c)\\ %m"
|
||||||
|
@ -199,11 +199,15 @@ setup_emsdk_env :: proc() {
|
|||||||
set_env("EMSDK", absolute_path("./libs/emsdk"))
|
set_env("EMSDK", absolute_path("./libs/emsdk"))
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_bin_dir :: proc(path: string, files_to_copy: []string) {
|
setup_bin_dir :: proc(opts: Options, path: string, files_to_copy: []string) {
|
||||||
mkdir_all(path)
|
mkdir_all(path)
|
||||||
|
|
||||||
for file in files_to_copy {
|
for file in files_to_copy {
|
||||||
copy_file(file, temp_path_join(path, filepath.base(file)))
|
dst := temp_path_join(path, filepath.base(file))
|
||||||
|
|
||||||
|
if !os.is_file(dst) || opts.force {
|
||||||
|
copy_file(file, dst)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +216,7 @@ main :: proc() {
|
|||||||
opts := Options {
|
opts := Options {
|
||||||
tracy = true,
|
tracy = true,
|
||||||
debug = true,
|
debug = true,
|
||||||
run = true,
|
optimize = true,
|
||||||
}
|
}
|
||||||
flags.parse_or_exit(&opts, os.args, .Unix, context.temp_allocator)
|
flags.parse_or_exit(&opts, os.args, .Unix, context.temp_allocator)
|
||||||
if opts.variant == .Web {
|
if opts.variant == .Web {
|
||||||
@ -230,10 +234,10 @@ main :: proc() {
|
|||||||
|
|
||||||
switch opts.variant {
|
switch opts.variant {
|
||||||
case .Hot_Reload:
|
case .Hot_Reload:
|
||||||
setup_bin_dir("./build/hotreload", shared_dep_paths)
|
setup_bin_dir(opts, "./build/hotreload", shared_dep_paths)
|
||||||
|
|
||||||
is_main_built := os.is_file("./build/hotreload/game.bin")
|
is_running := process_exists("game.bin")
|
||||||
if !is_main_built || opts.force {
|
if !is_running {
|
||||||
run_cmd(
|
run_cmd(
|
||||||
temp_concat(
|
temp_concat(
|
||||||
[]string {
|
[]string {
|
||||||
@ -244,13 +248,13 @@ main :: proc() {
|
|||||||
},
|
},
|
||||||
debug_flag,
|
debug_flag,
|
||||||
tracy_flag,
|
tracy_flag,
|
||||||
optimize_flag,
|
|
||||||
COMMON_FLAGS,
|
COMMON_FLAGS,
|
||||||
),
|
),
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
build_game_cmd := temp_concat(
|
build_game_cmd := run_cmd(
|
||||||
|
temp_concat(
|
||||||
[]string {
|
[]string {
|
||||||
"odin",
|
"odin",
|
||||||
"build",
|
"build",
|
||||||
@ -264,52 +268,12 @@ main :: proc() {
|
|||||||
debug_flag,
|
debug_flag,
|
||||||
optimize_flag,
|
optimize_flag,
|
||||||
COMMON_FLAGS,
|
COMMON_FLAGS,
|
||||||
|
),
|
||||||
|
"",
|
||||||
)
|
)
|
||||||
build_game_lib :: proc(build_cmd: []string) {
|
|
||||||
run_cmd(build_cmd, "")
|
|
||||||
rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so")
|
rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so")
|
||||||
}
|
|
||||||
build_game_lib(build_game_cmd)
|
|
||||||
|
|
||||||
if opts.run && !process_exists("game.bin") {
|
|
||||||
Watcher_Context :: struct {
|
|
||||||
run: bool,
|
|
||||||
build_game_cmd: []string,
|
|
||||||
}
|
|
||||||
watcher_ctx := Watcher_Context {
|
|
||||||
run = true,
|
|
||||||
build_game_cmd = build_game_cmd,
|
|
||||||
}
|
|
||||||
thread_ctx := context
|
|
||||||
thread_ctx.user_ptr = &watcher_ctx
|
|
||||||
thrd := thread.create_and_start(proc() {
|
|
||||||
watcher_ctx := (cast(^Watcher_Context)context.user_ptr)
|
|
||||||
input := os.to_reader(os.stdin)
|
|
||||||
|
|
||||||
buf: [1024]u8
|
|
||||||
for {
|
|
||||||
n, err := io.read(input, buf[:])
|
|
||||||
|
|
||||||
for cmd in buf[0:n] {
|
|
||||||
switch cmd {
|
|
||||||
case 'r', 'R':
|
|
||||||
build_game_lib(watcher_ctx.build_game_cmd)
|
|
||||||
case:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == .EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_error(err)
|
|
||||||
}
|
|
||||||
}, thread_ctx)
|
|
||||||
|
|
||||||
run_cmd({"./build/hotreload/game.bin"}, "")
|
|
||||||
}
|
|
||||||
case .Desktop:
|
case .Desktop:
|
||||||
setup_bin_dir("./build/desktop", shared_dep_paths)
|
setup_bin_dir(opts, "./build/desktop", shared_dep_paths)
|
||||||
|
|
||||||
cmd := slice.concatenate(
|
cmd := slice.concatenate(
|
||||||
[][]string {
|
[][]string {
|
||||||
|
@ -20,9 +20,11 @@ Run_Error :: union #shared_nil {
|
|||||||
os.Error,
|
os.Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
run_cmd_internal :: proc(
|
run_cmd_internal :: proc(
|
||||||
cmd: []string,
|
cmd: []string,
|
||||||
cwd: string,
|
cwd: string,
|
||||||
|
capture: bool,
|
||||||
loc := #caller_location,
|
loc := #caller_location,
|
||||||
) -> (
|
) -> (
|
||||||
result: string,
|
result: string,
|
||||||
@ -70,7 +72,9 @@ run_cmd_internal :: proc(
|
|||||||
buf: [1024]u8
|
buf: [1024]u8
|
||||||
if has_data {
|
if has_data {
|
||||||
n = handle_error1(os.read(r, buf[:]))
|
n = handle_error1(os.read(r, buf[:]))
|
||||||
|
if capture {
|
||||||
strings.write_bytes(&b, buf[0:n])
|
strings.write_bytes(&b, buf[0:n])
|
||||||
|
}
|
||||||
handle_error1(os.write(os.stderr, buf[0:n]))
|
handle_error1(os.write(os.stderr, buf[0:n]))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,10 +110,11 @@ run_cmd_internal :: proc(
|
|||||||
run_cmd :: proc(
|
run_cmd :: proc(
|
||||||
cmd: []string,
|
cmd: []string,
|
||||||
cwd: string,
|
cwd: string,
|
||||||
|
capture := true,
|
||||||
expr := #caller_expression,
|
expr := #caller_expression,
|
||||||
loc := #caller_location,
|
loc := #caller_location,
|
||||||
) -> string {
|
) -> string {
|
||||||
result, err := run_cmd_internal(cmd, cwd, loc)
|
result, err := run_cmd_internal(cmd, cwd, capture, loc)
|
||||||
handle_error(err, "", expr, loc)
|
handle_error(err, "", expr, loc)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -577,8 +577,6 @@ get_convex :: proc(assetman: ^Asset_Manager, path: cstring) -> (result: Loaded_C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debugf("num verts: %v", len(vertices))
|
|
||||||
|
|
||||||
center := (max_pos + min_pos) * 0.5
|
center := (max_pos + min_pos) * 0.5
|
||||||
extent := (max_pos - min_pos) * 0.5
|
extent := (max_pos - min_pos) * 0.5
|
||||||
|
|
||||||
|
@ -1302,6 +1302,7 @@ game_init :: proc() {
|
|||||||
g_mem.ui_context.default_style.font_size = 20
|
g_mem.ui_context.default_style.font_size = 20
|
||||||
g_mem.ui_context.text_size = ui.rl_measure_text_2d
|
g_mem.ui_context.text_size = ui.rl_measure_text_2d
|
||||||
|
|
||||||
|
log.debugf("game_init")
|
||||||
game_hot_reloaded(g_mem)
|
game_hot_reloaded(g_mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1340,6 +1341,7 @@ game_hot_reloaded :: proc(mem: rawptr) {
|
|||||||
ui.rl_init()
|
ui.rl_init()
|
||||||
|
|
||||||
g_mem.runtime_world.orbit_camera.distance = 4
|
g_mem.runtime_world.orbit_camera.distance = 4
|
||||||
|
log.debugf("hot reloaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(export)
|
@(export)
|
||||||
|
@ -52,8 +52,14 @@ Game_API :: struct {
|
|||||||
api_version: int,
|
api_version: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) {
|
load_game_api :: proc(bin_dir: string, api_version: int) -> (api: Game_API, ok: bool) {
|
||||||
mod_time, mod_time_error := os.last_write_time_by_name("game" + DLL_EXT)
|
// NOTE: this needs to be a relative path for Linux to work.
|
||||||
|
game_dll_name := fmt.tprintf("game_{0}" + DLL_EXT, api_version)
|
||||||
|
game_dll_path := filepath.join({bin_dir, game_dll_name}, context.temp_allocator)
|
||||||
|
|
||||||
|
mod_time, mod_time_error := os.last_write_time_by_name(
|
||||||
|
filepath.join({bin_dir, "game" + DLL_EXT}, context.temp_allocator),
|
||||||
|
)
|
||||||
if mod_time_error != os.ERROR_NONE {
|
if mod_time_error != os.ERROR_NONE {
|
||||||
fmt.printfln(
|
fmt.printfln(
|
||||||
"Failed getting last write time of game" + DLL_EXT + ", error code: {1}",
|
"Failed getting last write time of game" + DLL_EXT + ", error code: {1}",
|
||||||
@ -62,14 +68,9 @@ load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: this needs to be a relative path for Linux to work.
|
|
||||||
game_dll_name := fmt.tprintf("game_{0}" + DLL_EXT, api_version)
|
|
||||||
bin_dir := filepath.dir(os.args[0], context.temp_allocator)
|
|
||||||
|
|
||||||
copy_dll(bin_dir, game_dll_name) or_return
|
copy_dll(bin_dir, game_dll_name) or_return
|
||||||
|
|
||||||
game_dll_path := filepath.join({bin_dir, game_dll_name}, context.temp_allocator)
|
|
||||||
|
|
||||||
// This proc matches the names of the fields in Game_API to symbols in the
|
// This proc matches the names of the fields in Game_API to symbols in the
|
||||||
// game DLL. It actually looks for symbols starting with `game_`, which is
|
// game DLL. It actually looks for symbols starting with `game_`, which is
|
||||||
// why the argument `"game_"` is there.
|
// why the argument `"game_"` is there.
|
||||||
@ -85,15 +86,13 @@ load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
unload_game_api :: proc(api: ^Game_API) {
|
unload_game_api :: proc(bin_dir: string, api: ^Game_API) {
|
||||||
if api.lib != nil {
|
if api.lib != nil {
|
||||||
if !dynlib.unload_library(api.lib) {
|
if !dynlib.unload_library(api.lib) {
|
||||||
fmt.printfln("Failed unloading lib: {0}", dynlib.last_error())
|
fmt.printfln("Failed unloading lib: {0}", dynlib.last_error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bin_dir := filepath.dir(os.args[0], context.temp_allocator)
|
|
||||||
|
|
||||||
game_dll_path := filepath.join(
|
game_dll_path := filepath.join(
|
||||||
{bin_dir, fmt.tprintf("game_{0}" + DLL_EXT, api.api_version)},
|
{bin_dir, fmt.tprintf("game_{0}" + DLL_EXT, api.api_version)},
|
||||||
context.temp_allocator,
|
context.temp_allocator,
|
||||||
@ -137,7 +136,7 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
game_api_version := 0
|
game_api_version := 0
|
||||||
game_api, game_api_ok := load_game_api(game_api_version)
|
game_api, game_api_ok := load_game_api(bin_dir, game_api_version)
|
||||||
|
|
||||||
if !game_api_ok {
|
if !game_api_ok {
|
||||||
fmt.println("Failed to load Game API")
|
fmt.println("Failed to load Game API")
|
||||||
@ -165,7 +164,7 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if reload {
|
if reload {
|
||||||
new_game_api, new_game_api_ok := load_game_api(game_api_version)
|
new_game_api, new_game_api_ok := load_game_api(bin_dir, game_api_version)
|
||||||
|
|
||||||
if new_game_api_ok {
|
if new_game_api_ok {
|
||||||
force_restart =
|
force_restart =
|
||||||
@ -194,11 +193,11 @@ main :: proc() {
|
|||||||
reset_tracking_allocator(&tracking_allocator)
|
reset_tracking_allocator(&tracking_allocator)
|
||||||
|
|
||||||
for &g in old_game_apis {
|
for &g in old_game_apis {
|
||||||
unload_game_api(&g)
|
unload_game_api(bin_dir, &g)
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(&old_game_apis)
|
clear(&old_game_apis)
|
||||||
unload_game_api(&game_api)
|
unload_game_api(bin_dir, &game_api)
|
||||||
game_api = new_game_api
|
game_api = new_game_api
|
||||||
game_api.init()
|
game_api.init()
|
||||||
}
|
}
|
||||||
@ -232,13 +231,13 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for &g in old_game_apis {
|
for &g in old_game_apis {
|
||||||
unload_game_api(&g)
|
unload_game_api(bin_dir, &g)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(old_game_apis)
|
delete(old_game_apis)
|
||||||
|
|
||||||
game_api.shutdown_window()
|
game_api.shutdown_window()
|
||||||
unload_game_api(&game_api)
|
unload_game_api(bin_dir, &game_api)
|
||||||
mem.tracking_allocator_destroy(&tracking_allocator)
|
mem.tracking_allocator_destroy(&tracking_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user