浏览代码

add hotreload support for windows

MarkosTh09 1 年之前
父节点
当前提交
88703e1ebc
共有 5 个文件被更改,包括 158 次插入21 次删除
  1. 1 0
      .gitignore
  2. 38 0
      src/hotreload_windows.c
  3. 55 5
      src/nob_win64_mingw.c
  4. 54 12
      src/nob_win64_msvc.c
  5. 10 4
      src/plug.c

+ 1 - 0
.gitignore

@@ -14,3 +14,4 @@ nob
 nob.old
 nob.exe
 nob.exe.old
+nob.obj

+ 38 - 0
src/hotreload_windows.c

@@ -0,0 +1,38 @@
+#include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#define NOUSER
+#include <windows.h>
+
+#include <raylib.h>
+#include "hotreload.h"
+
+static const char *libplug_file_name = "libplug.dll";
+static void *libplug = NULL;
+
+#define PLUG(name, ...) name##_t *name = NULL;
+LIST_OF_PLUGS
+#undef PLUG
+
+bool reload_libplug(void)
+{
+    if (libplug != NULL) FreeLibrary(libplug);
+
+    libplug = LoadLibrary(libplug_file_name);
+    if (libplug == NULL) {
+        TraceLog(LOG_ERROR, "HOTRELOAD: could not load %s: %s", libplug_file_name, GetLastError());
+        return false;
+    }
+
+    #define PLUG(name, ...) \
+        name = GetProcAddress(libplug, #name); \
+        if (name == NULL) { \
+            TraceLog(LOG_ERROR, "HOTRELOAD: could not find %s symbol in %s: %s", \
+                     #name, libplug_file_name, GetLastError()); \
+            return false; \
+        }
+    LIST_OF_PLUGS
+    #undef PLUG
+
+    return true;
+}

+ 55 - 5
src/nob_win64_mingw.c

@@ -6,9 +6,6 @@ bool build_musializer(void)
     Nob_Cmd cmd = {0};
     Nob_Procs procs = {0};
 
-#ifdef MUSIALIZER_HOTRELOAD
-#error "TODO: hotreloading is not supported on TARGET_WIN64_MINGW yet"
-#else
     cmd.count = 0;
     #ifdef _WIN32
         // On windows, mingw doesn't have the `x86_64-w64-mingw32-` prefix for windres.
@@ -21,7 +18,47 @@ bool build_musializer(void)
         nob_cmd_append(&cmd, "-O", "coff");
         nob_cmd_append(&cmd, "-o", "./build/musializer.res");
     if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
+#ifdef MUSIALIZER_HOTRELOAD
+    procs.count = 0;
+            cmd.count = 0;
+                nob_cmd_append(&cmd, "x86_64-w64-mingw32-gcc");
+                nob_cmd_append(&cmd, "-mwindows", "-Wall", "-Wextra", "-ggdb");
+                nob_cmd_append(&cmd, "-I./build/");
+                nob_cmd_append(&cmd, "-I./raylib/raylib-"RAYLIB_VERSION"/src/");
+                nob_cmd_append(&cmd, "-fPIC", "-shared");
+                nob_cmd_append(&cmd, "-static-libgcc");
+                nob_cmd_append(&cmd, "-o", "./build/libplug.dll");
+                nob_cmd_append(&cmd,
+                    "./src/plug.c",
+                    "./src/ffmpeg_windows.c");
+                nob_cmd_append(&cmd,
+                    "-L./build",
+                    "-l:raylib.dll");
+                nob_cmd_append(&cmd, "-lwinmm", "-lgdi32");
+            nob_da_append(&procs, nob_cmd_run_async(cmd));
 
+            cmd.count = 0;
+                nob_cmd_append(&cmd, "x86_64-w64-mingw32-gcc");
+                nob_cmd_append(&cmd, "-mwindows", "-Wall", "-Wextra", "-ggdb");
+                nob_cmd_append(&cmd, "-I./build/");
+                nob_cmd_append(&cmd, "-I./raylib/raylib-"RAYLIB_VERSION"/src/");
+                nob_cmd_append(&cmd, "-o", "./build/musializer");
+                nob_cmd_append(&cmd,
+                    "./src/musializer.c",
+                    "./src/hotreload_windows.c");
+                nob_cmd_append(&cmd,
+                    "-Wl,-rpath=./build/",
+                    "-Wl,-rpath=./",
+                    nob_temp_sprintf("-Wl,-rpath=./build/raylib/%s", MUSIALIZER_TARGET_NAME),
+                    // NOTE: just in case somebody wants to run musializer from within the ./build/ folder
+                    nob_temp_sprintf("-Wl,-rpath=./raylib/%s", MUSIALIZER_TARGET_NAME));
+                nob_cmd_append(&cmd,
+                    "-L./build",
+                    "-l:raylib.dll");
+                nob_cmd_append(&cmd, "-lwinmm", "-lgdi32");
+            nob_da_append(&procs, nob_cmd_run_async(cmd));
+        if (!nob_procs_wait(procs)) nob_return_defer(false);
+#else
     cmd.count = 0;
         nob_cmd_append(&cmd, "x86_64-w64-mingw32-gcc");
         nob_cmd_append(&cmd, "-mwindows", "-Wall", "-Wextra", "-ggdb");
@@ -95,7 +132,7 @@ bool build_raylib()
     const char *libraylib_path = nob_temp_sprintf("%s/libraylib.a", build_path);
 
     if (nob_needs_rebuild(libraylib_path, object_files.items, object_files.count)) {
-        nob_cmd_append(&cmd, "ar", "-crs", libraylib_path);
+        nob_cmd_append(&cmd, "x86_64-w64-mingw32-ar", "-crs", libraylib_path);
         for (size_t i = 0; i < NOB_ARRAY_LEN(raylib_modules); ++i) {
             const char *input_path = nob_temp_sprintf("%s/%s.o", build_path, raylib_modules[i]);
             nob_cmd_append(&cmd, input_path);
@@ -103,7 +140,20 @@ bool build_raylib()
         if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
     }
 #else
-#error "TODO: dynamic raylib is not supported for TARGET_WIN64_MINGW"
+    // it cannot load the raylib dll if it not in the same folder as the executable
+    const char *libraylib_path = "./build/raylib.dll";
+
+    if (nob_needs_rebuild(libraylib_path, object_files.items, object_files.count)) {
+        nob_cmd_append(&cmd, "x86_64-w64-mingw32-gcc");
+        nob_cmd_append(&cmd, "-shared");
+        nob_cmd_append(&cmd, "-o", libraylib_path);
+        for (size_t i = 0; i < NOB_ARRAY_LEN(raylib_modules); ++i) {
+            const char *input_path = nob_temp_sprintf("%s/%s.o", build_path, raylib_modules[i]);
+            nob_cmd_append(&cmd, input_path);
+        }
+        nob_cmd_append(&cmd, "-lwinmm", "-lgdi32");
+        if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
+    }
 #endif // MUSIALIZER_HOTRELOAD
 
 defer:

+ 54 - 12
src/nob_win64_msvc.c

@@ -7,16 +7,49 @@ bool build_musializer(void)
     Nob_Cmd cmd = {0};
     Nob_Procs procs = {0};
 
-#ifdef MUSIALIZER_HOTRELOAD
-    nob_log(NOB_ERROR, "TODO: hotreloading is not supported on %s yet", NOB_ARRAY_GET(target_names, config.target));
-    nob_return_defer(false);
-#else
     cmd.count = 0;
         nob_cmd_append(&cmd, "rc");
         nob_cmd_append(&cmd, "/fo", "./build/musializer.res");
         nob_cmd_append(&cmd, "./src/musializer.rc");
         // NOTE: Do not change the order of commandline arguments to rc. Their argparser is weird.
     if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
+#ifdef MUSIALIZER_HOTRELOAD
+    procs.count = 0;
+        cmd.count = 0;
+            nob_cmd_append(&cmd, "cl.exe");
+            nob_cmd_append(&cmd, "/LD");
+            nob_cmd_append(&cmd, "/Fobuild\\", "/Fe./build/libplug.dll");
+            nob_cmd_append(&cmd, "/I", "./build/");
+            nob_cmd_append(&cmd, "/I", "./raylib/raylib-"RAYLIB_VERSION"/src/");
+            nob_cmd_append(&cmd,
+                "src/plug.c",
+                "src/ffmpeg_windows.c");
+            nob_cmd_append(&cmd,
+                "/link",
+                nob_temp_sprintf("/LIBPATH:build/raylib/%s", MUSIALIZER_TARGET_NAME),
+                "raylib.lib");
+            nob_cmd_append(&cmd, "Winmm.lib", "gdi32.lib", "User32.lib", "Shell32.lib");
+        nob_da_append(&procs, nob_cmd_run_async(cmd));
+            
+        cmd.count = 0;
+            nob_cmd_append(&cmd, "cl.exe");
+            nob_cmd_append(&cmd, "/I", "./build/");
+            nob_cmd_append(&cmd, "/I", "./raylib/raylib-"RAYLIB_VERSION"/src/");
+            nob_cmd_append(&cmd, "/Fobuild\\", "/Febuild\\musializer.exe");
+            nob_cmd_append(&cmd,
+                "./src/musializer.c",
+                "./src/hotreload_windows.c",
+                );
+            nob_cmd_append(&cmd,
+                "/link",
+                "/SUBSYSTEM:WINDOWS",
+                "/entry:mainCRTStartup",
+                nob_temp_sprintf("/LIBPATH:build/raylib/%s", MUSIALIZER_TARGET_NAME),
+                "raylib.lib");
+            nob_cmd_append(&cmd, "Winmm.lib", "gdi32.lib", "User32.lib", "Shell32.lib", "./build/musializer.res");
+        nob_da_append(&procs, nob_cmd_run_async(cmd));
+    if (!nob_procs_wait(procs)) nob_return_defer(false);
+#else
     cmd.count = 0;
         nob_cmd_append(&cmd, "cl.exe");
         nob_cmd_append(&cmd, "/I", "./build/");
@@ -25,9 +58,7 @@ bool build_musializer(void)
         nob_cmd_append(&cmd,
             "./src/musializer.c",
             "./src/plug.c",
-            "./src/ffmpeg_windows.c"
-            // TODO: building resource file is not implemented for TARGET_WIN64_MSVC
-            );
+            "./src/ffmpeg_windows.c");
         nob_cmd_append(&cmd,
             "/link",
             "/SUBSYSTEM:WINDOWS",
@@ -73,6 +104,9 @@ bool build_raylib(void)
         if (nob_needs_rebuild(output_path, &input_path, 1)) {
             cmd.count = 0;
             nob_cmd_append(&cmd, "cl.exe", "/DPLATFORM_DESKTOP", "/DSUPPORT_FILEFORMAT_FLAC=1");
+            #ifdef MUSIALIZER_HOTRELOAD
+                nob_cmd_append(&cmd, "/DBUILD_LIBTYPE_SHARED");
+            #endif
             nob_cmd_append(&cmd, "/I", "./raylib/raylib-"RAYLIB_VERSION"/src/external/glfw/include");
             nob_cmd_append(&cmd, "/c", input_path);
             nob_cmd_append(&cmd, nob_temp_sprintf("/Fo%s", output_path));
@@ -83,7 +117,6 @@ bool build_raylib(void)
     cmd.count = 0;
 
     if (!nob_procs_wait(procs)) nob_return_defer(false);
-
 #ifndef MUSIALIZER_HOTRELOAD
     const char *libraylib_path = nob_temp_sprintf("%s/raylib.lib", build_path);
     if (nob_needs_rebuild(libraylib_path, object_files.items, object_files.count)) {
@@ -96,10 +129,19 @@ bool build_raylib(void)
         if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
     }
 #else
-    nob_log(NOB_WARNING, "TODO: dynamic raylib for %s is not supported yet", NOB_ARRAY_GET(target_names, config.target));
-    nob_return_defer(false);
+    if (nob_needs_rebuild("./build/raylib.dll", object_files.items, object_files.count)) {
+        nob_cmd_append(&cmd, "link.exe", "/DLL");
+        for (size_t i = 0; i < NOB_ARRAY_LEN(raylib_modules); ++i) {
+            const char *input_path = nob_temp_sprintf("%s/%s.obj", build_path, raylib_modules[i]);
+            nob_cmd_append(&cmd, input_path);
+        }
+        nob_cmd_append(&cmd, "Winmm.lib", "gdi32.lib", "User32.lib", "Shell32.lib");
+        nob_cmd_append(&cmd, nob_temp_sprintf("/IMPLIB:%s/raylib.lib", build_path));
+        nob_cmd_append(&cmd, "/OUT:./build/raylib.dll");
+        if (!nob_cmd_run_sync(cmd)) nob_return_defer(false);
+    }
 #endif // MUSIALIZER_HOTRELOAD
-
+    
 defer:
     nob_cmd_free(cmd);
     nob_da_free(object_files);
@@ -115,4 +157,4 @@ bool build_dist(void)
     nob_log(NOB_ERROR, "TODO: Creating distro for MSVC build is not implemented yet");
     return false;
 #endif // MUSIALIZER_HOTRELOAD
-}
+}

+ 10 - 4
src/plug.c

@@ -110,6 +110,12 @@ void *plug_load_resource(const char *file_path, size_t *size)
 #    define subcc(a, b) ((a)-(b))
 #endif
 
+#ifdef _WIN32
+#define MUSIALIZER_PLUG __declspec(dllexport)
+#else
+#define MUSIALIZER_PLUG
+#endif
+
 typedef struct {
     char *file_path;
     Music music;
@@ -1726,7 +1732,7 @@ static void rendering_screen(void)
     }
 }
 
-void plug_init(void)
+MUSIALIZER_PLUG void plug_init(void)
 {
     p = malloc(sizeof(*p));
     assert(p != NULL && "Buy more RAM lol");
@@ -1762,7 +1768,7 @@ void plug_init(void)
     SetMasterVolume(0.5);
 }
 
-Plug *plug_pre_reload(void)
+MUSIALIZER_PLUG Plug *plug_pre_reload(void)
 {
     for (size_t i = 0; i < p->tracks.count; ++i) {
         Track *it = &p->tracks.items[i];
@@ -1772,7 +1778,7 @@ Plug *plug_pre_reload(void)
     return p;
 }
 
-void plug_post_reload(Plug *pp)
+MUSIALIZER_PLUG void plug_post_reload(Plug *pp)
 {
     p = pp;
     for (size_t i = 0; i < p->tracks.count; ++i) {
@@ -1789,7 +1795,7 @@ void plug_post_reload(Plug *pp)
     p->circle_power_location = GetShaderLocation(p->circle, "power");
 }
 
-void plug_update(void)
+MUSIALIZER_PLUG void plug_update(void)
 {
     BeginDrawing();
     ClearBackground(COLOR_BACKGROUND);