diff --git a/External/tely b/External/tely index a131934..798d1a7 160000 --- a/External/tely +++ b/External/tely @@ -1 +1 @@ -Subproject commit a131934ffcc917dda53e0084ff7c3a136b6250ec +Subproject commit 798d1a7d5d98801161992259e24e4aa0c926c14f diff --git a/build.bat b/build.bat index 902dee7..23daa00 100644 --- a/build.bat +++ b/build.bat @@ -103,7 +103,7 @@ set msvc_sprite_packer_cmd=cl %common_compile_flags% %code_dir%\feely_pona_s powershell -Command "$duration = Measure-Command {%msvc_sprite_packer_cmd% | Out-Default}; Write-Host 'msvc (sprite packer):' $duration.TotalSeconds 'seconds'" powershell -Command "$duration = Measure-Command {%msvc_no_dll_cmd% | Out-Default}; Write-Host 'msvc (no-dll):' $duration.TotalSeconds 'seconds'" -REM cl /nologo /Z7 %code_dir%\feely_pona_build.cpp +cl /nologo /Z7 %code_dir%\feely_pona_build.cpp popd exit /B 1 diff --git a/feely_pona_build.cpp b/feely_pona_build.cpp index ebfcd6b..6edb088 100644 --- a/feely_pona_build.cpp +++ b/feely_pona_build.cpp @@ -1,45 +1,78 @@ // #include +#include + #define DQN_IMPLEMENTATION #include "External/tely/External/dqn/dqn.h" -struct Dqn_OSRunCommandAsyncResult +struct Dqn_OSExecuteAsyncHandle { void *process; }; -struct Dqn_OSRunCommandResult +struct Dqn_OSExecuteResult { uint32_t os_error_code; uint32_t exit_code; }; -Dqn_OSRunCommandResult Dqn_OS_RunCommandWait(Dqn_OSRunCommandAsyncResult run_cmd) +struct Dqn_CPPBuildCompileFile { - Dqn_OSRunCommandResult result = {}; - DWORD exec_result = WaitForSingleObject(run_cmd.process, INFINITE); + Dqn_Slice flags; + Dqn_String8 path; +}; + +struct Dqn_CPPBuildContext +{ + Dqn_Slice compile_files; + Dqn_Slice compile_flags; + Dqn_Slice include_dirs; + Dqn_Slice link_flags; + Dqn_String8 build_dir; +}; + +enum Dqn_CPPBuildStatus +{ + Dqn_CPPBuildStatus_Ok, + Dqn_CPPBuildStatus_BuildDirectoryFailedToBeMade, +}; + +struct Dqn_CPPBuildAsyncResult +{ + Dqn_CPPBuildStatus status; + Dqn_OSExecuteAsyncHandle async_handle; +}; + +Dqn_OSExecuteResult Dqn_OS_ExecuteWait(Dqn_OSExecuteAsyncHandle handle) +{ + Dqn_OSExecuteResult result = {}; + if (!handle.process) + return result; + + DWORD exec_result = WaitForSingleObject(handle.process, INFINITE); if (exec_result == WAIT_FAILED) { result.os_error_code = GetLastError(); return result; } DWORD exit_status; - if (!GetExitCodeProcess(run_cmd.process, &exit_status)) { + if (!GetExitCodeProcess(handle.process, &exit_status)) { result.os_error_code = GetLastError(); return result; } result.exit_code = exit_status; - CloseHandle(run_cmd.process); + CloseHandle(handle.process); return result; } -Dqn_OSRunCommandAsyncResult Dqn_OS_RunCommandAsync(Dqn_String8 cmd) +Dqn_OSExecuteAsyncHandle Dqn_OS_ExecuteAsync(Dqn_String8 cmd, Dqn_String8 working_dir) { - Dqn_OSRunCommandAsyncResult result = {}; + Dqn_OSExecuteAsyncHandle result = {}; #if defined(DQN_OS_WIN32) - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_String16 cmd16 = Dqn_Win_String8ToString16(scratch.arena, cmd); + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String16 cmd16 = Dqn_Win_String8ToString16(scratch.arena, cmd); + Dqn_String16 working_dir16 = Dqn_Win_String8ToString16(scratch.arena, working_dir); PROCESS_INFORMATION proc_info = {}; STARTUPINFOW startup_info = {}; @@ -48,82 +81,353 @@ Dqn_OSRunCommandAsyncResult Dqn_OS_RunCommandAsync(Dqn_String8 cmd) startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startup_info.dwFlags |= STARTF_USESTDHANDLES; - BOOL create_result = CreateProcessW(nullptr, cmd16.data, nullptr, nullptr, true, 0, nullptr, nullptr, &startup_info, &proc_info); + BOOL create_result = CreateProcessW(nullptr, cmd16.data, nullptr, nullptr, true, 0, nullptr, working_dir16.data, &startup_info, &proc_info); if (!create_result) return result; CloseHandle(proc_info.hThread); result.process = proc_info.hProcess; #else - pid_t cpid = fork(); - if (cpid < 0) { - nob_log(NOB_ERROR, "Could not fork child process: %s", strerror(errno)); - return NOB_INVALID_PROC; + pid_t child_pid = fork(); + if (child_pid < 0) { + result.os_error_code = errno; + return result; } - if (cpid == 0) { - // NOTE: This leaks a bit of memory in the child process. - // But do we actually care? It's a one off leak anyway... - Nob_Cmd cmd_null = {0}; - nob_da_append_many(&cmd_null, cmd.items, cmd.count); - nob_cmd_append(&cmd_null, NULL); + if (child_pid == 0) { + if (working_dir.size) { + if (chdir(working_dir.data) == -1) { + result.os_error_code = errno; + return result; + } + } if (execvp(cmd.items[0], (char * const*) cmd_null.items) < 0) { - nob_log(NOB_ERROR, "Could not exec child process: %s", strerror(errno)); - exit(1); + result.os_error_code = errno; + return result; } - NOB_ASSERT(0 && "unreachable"); + DQN_INVALID_CODE_PATH; } - return cpid; + result.process = DQN_CAST(void *)child_pid; #endif return result; } +Dqn_OSExecuteResult Dqn_OS_Execute(Dqn_String8 cmd, Dqn_String8 working_dir) +{ + Dqn_OSExecuteAsyncHandle async_handle = Dqn_OS_ExecuteAsync(cmd, working_dir); + Dqn_OSExecuteResult result = Dqn_OS_ExecuteWait(async_handle); + return result; +} + +Dqn_String8 Dqn_CPPBuildContext_ToCommandLine(Dqn_CPPBuildContext build_context, Dqn_Allocator allocator) +{ + // NOTE: Check if object files are newer than the source files ================================= + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(allocator.user_context); + Dqn_Slice dirtied_compile_files = Dqn_Slice_Alloc(scratch.arena, build_context.compile_files.size, Dqn_ZeroMem_Yes); + dirtied_compile_files.size = 0; + DQN_FOR_UINDEX (index, build_context.compile_files.size) { + Dqn_CPPBuildCompileFile file = build_context.compile_files.data[index]; + Dqn_String8 file_stem = Dqn_String8_FileNameNoExtension(file.path); + + Dqn_String8 obj_file = {}; + if (build_context.build_dir.size) + obj_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.obj", DQN_STRING_FMT(build_context.build_dir), DQN_STRING_FMT(file_stem)); + else + obj_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s.obj", DQN_STRING_FMT(file_stem)); + + Dqn_FsInfo file_info = Dqn_Fs_GetInfo(file.path); + Dqn_FsInfo obj_file_info = Dqn_Fs_GetInfo(obj_file); + if (obj_file_info.last_write_time_in_s >= file_info.last_write_time_in_s) + continue; + + dirtied_compile_files.data[dirtied_compile_files.size++] = file; + } + + Dqn_String8 result = {}; + if (dirtied_compile_files.size <= 0) + return result; + + // NOTE: Build the command line invocation ===================================================== + Dqn_String8Builder builder = {}; + builder.allocator = allocator; + DQN_FOR_UINDEX (index, build_context.compile_flags.size) { + Dqn_String8 flag = build_context.compile_flags.data[index]; + if (index) + Dqn_String8Builder_AppendF(&builder, " "); + Dqn_String8Builder_AppendRef(&builder, flag); + } + + DQN_FOR_UINDEX (index, build_context.include_dirs.size) { + Dqn_String8 include_dir = build_context.include_dirs.data[index]; + if (builder.count) + Dqn_String8Builder_AppendF(&builder, " "); + Dqn_String8Builder_AppendF(&builder, "/I %.*s", DQN_STRING_FMT(include_dir)); + } + + DQN_FOR_UINDEX (index, dirtied_compile_files.size) { + Dqn_CPPBuildCompileFile file = dirtied_compile_files.data[index]; + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(allocator.user_context); + Dqn_String8 obj_file = {}; + if (builder.count) + Dqn_String8Builder_AppendF(&builder, " "); + DQN_FOR_UINDEX (flag_index, file.flags.size) { + Dqn_String8 flag = file.flags.data[flag_index]; + Dqn_String8Builder_AppendF(&builder, "%s%.*s", flag_index ? " " : "", DQN_STRING_FMT(flag)); + } + if (file.flags.size) + Dqn_String8Builder_AppendF(&builder, " "); + Dqn_String8Builder_AppendRef(&builder, file.path); + } + + DQN_FOR_UINDEX (index, build_context.link_flags.size) { + Dqn_String8 file = build_context.link_flags.data[index]; + if (builder.count) + Dqn_String8Builder_AppendF(&builder, " "); + Dqn_String8Builder_AppendRef(&builder, file); + } + + result = Dqn_String8Builder_Build(&builder, allocator); + return result; +} + +Dqn_CPPBuildAsyncResult Dqn_CPPBuild_Async(Dqn_CPPBuildContext build_context) +{ + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 cmd = Dqn_CPPBuildContext_ToCommandLine(build_context, scratch.allocator); + Dqn_CPPBuildAsyncResult result = {}; + if (!cmd.size) + return result; + + if (!Dqn_Fs_MakeDir(build_context.build_dir)) { + result.status = Dqn_CPPBuildStatus_BuildDirectoryFailedToBeMade; + return result; + } + + result.async_handle = Dqn_OS_ExecuteAsync(cmd, build_context.build_dir); + return result; +} + +void Dqn_CPPBuild_ExecuteOrAbort(Dqn_CPPBuildContext build_context) +{ + Dqn_CPPBuildAsyncResult build_result = Dqn_CPPBuild_Async(build_context); + if (build_result.status == Dqn_CPPBuildStatus_BuildDirectoryFailedToBeMade) { + Dqn_Log_ErrorF("Failed to make build dir '%.*s'", DQN_STRING_FMT(build_context.build_dir)); + exit(-1); + } + + Dqn_OSExecuteResult exec_result = Dqn_OS_ExecuteWait(build_result.async_handle); + if (exec_result.os_error_code) { + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_WinError error = Dqn_Win_LastError(scratch.arena); + Dqn_Log_ErrorF("Build command could not be executed, error returned was (%d): %.*s", error.code, DQN_STRING_FMT(error.msg)); + exit(-1); + } + + if (exec_result.exit_code) + exit(exec_result.exit_code); +} + int main() { Dqn_Library_Init(); - Dqn_String8 build_dir = DQN_STRING8("./Build"); - if (!Dqn_Fs_MakeDir(build_dir)) { - Dqn_Log_ErrorF("Failed to make build dir '%.*s'", DQN_STRING_FMT(build_dir)); - return -1; + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_String8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); + Dqn_String8 const build_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Build", DQN_STRING_FMT(exe_dir)); + Dqn_String8 const tely_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely", DQN_STRING_FMT(exe_dir)); + + Dqn_Slice common_compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { + DQN_STRING8("cl"), + DQN_STRING8("/W4"), + DQN_STRING8("/Z7"), + DQN_STRING8("/MT"), + DQN_STRING8("/EHsc"), + DQN_STRING8("/nologo"), + }); + + Dqn_Slice common_link_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { + DQN_STRING8("/link"), + DQN_STRING8("/incremental:no"), + }); + + // NOTE: Assets ================================================================================ + uint64_t robocopy_timings[2] = {}; + { + robocopy_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { robocopy_timings[1] = Dqn_OS_PerfCounterNow(); }; + Dqn_String8 robocopy_cmd = Dqn_String8_InitF(scratch.allocator, "robocopy /MIR /NJH /NJS /NDL /NP %.*s\\Data %.*s\\Data", DQN_STRING_FMT(exe_dir), DQN_STRING_FMT(build_dir)); + Dqn_OS_Execute(robocopy_cmd, /*working_dir*/ {}); } - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_String8 exe_dir = Dqn_OS_EXEDir(scratch.arena); - Dqn_String8Builder raylib_cmd_builder = {}; - raylib_cmd_builder.allocator = scratch.allocator; + // NOTE: Raylib ================================================================================ + Dqn_CPPBuildContext raylib_build_context = {}; + Dqn_String8 const raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely/external/raylib", DQN_STRING_FMT(exe_dir)); - Dqn_String8 raylib_files[] = { - DQN_STRING8("rcore.c"), - DQN_STRING8("utils.c"), - DQN_STRING8("raudio.c"), - DQN_STRING8("rmodels.c"), - DQN_STRING8("rtext.c"), - DQN_STRING8("rtextures.c"), - DQN_STRING8("rshapes.c"), - DQN_STRING8("rglfw.c"), - }; + uint64_t raylib_timings[2] = {}; + { + raylib_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { raylib_timings[1] = Dqn_OS_PerfCounterNow(); }; - Dqn_String8 raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely/external/raylib", DQN_STRING_FMT(exe_dir)); - Dqn_String8 raylib_include_dirs[] = { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STRING_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/external/glfw/include", DQN_STRING_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/glfw/deps/mingw", DQN_STRING_FMT(raylib_dir)), - }; + raylib_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rcore.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/utils.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/raudio.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rmodels.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtext.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtextures.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STRING_FMT(raylib_dir))}, + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STRING_FMT(raylib_dir))}, + }); - Dqn_String8 compile_flags = DQN_STRING8("/W4 /Z7 /MT /EHsc /nologo"); - Dqn_String8 link_flags = DQN_STRING8("/link /incremental:no"); + raylib_build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STRING_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/external/glfw/include", DQN_STRING_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/glfw/deps/mingw", DQN_STRING_FMT(raylib_dir)), + }); - Dqn_String8Builder_AppendF(&raylib_cmd_builder, "cl %.*s /w /c /D _DEFAULT_SOURCE /D PLATFORM_DESKTOP", DQN_STRING_FMT(compile_flags)); - for (Dqn_String8 include_dir : raylib_include_dirs) - Dqn_String8Builder_AppendF(&raylib_cmd_builder, " /I %.*s", DQN_STRING_FMT(include_dir)); + raylib_build_context.compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { + DQN_STRING8("cl"), + DQN_STRING8("/w"), + DQN_STRING8("/c"), + DQN_STRING8("/D _DEFAULT_SOURCE"), + DQN_STRING8("/D PLATFORM_DESKTOP"), + DQN_STRING8("/W4"), + DQN_STRING8("/Z7"), + DQN_STRING8("/MT"), + DQN_STRING8("/EHsc"), + DQN_STRING8("/nologo"), + }); - for (Dqn_String8 file_name : raylib_files) - Dqn_String8Builder_AppendRef(&raylib_cmd_builder, Dqn_FsPath_ConvertF(scratch.arena, " %.*s/%.*s", DQN_STRING_FMT(raylib_dir), DQN_STRING_FMT(file_name))); + raylib_build_context.link_flags = common_link_flags; + raylib_build_context.build_dir = build_dir; - Dqn_String8 cmd = Dqn_String8Builder_Build(&raylib_cmd_builder, scratch.allocator); - Dqn_OSRunCommandAsyncResult run_result = Dqn_OS_RunCommandAsync(cmd); - Dqn_OS_RunCommandWait(run_result); + Dqn_CPPBuild_ExecuteOrAbort(raylib_build_context); + } + + // NOTE: Feely Pona Sprite Packer ============================================================== + uint64_t feely_pona_sprite_packer_timings[2] = {}; + { + feely_pona_sprite_packer_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { feely_pona_sprite_packer_timings[1] = Dqn_OS_PerfCounterNow(); }; + + Dqn_String8 code_dir = exe_dir; + Dqn_CPPBuildContext build_context = {}; + build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.h", DQN_STRING_FMT(code_dir)) }, + }); + + build_context.compile_flags = common_compile_flags; + build_context.link_flags = common_link_flags; + build_context.build_dir = build_dir; + + Dqn_CPPBuild_ExecuteOrAbort(build_context); + } + + // NOTE: Feely Pona No DLL ===================================================================== + uint64_t feely_pona_no_dll_timings[2] = {}; + Dqn_CPPBuildContext feely_pona_no_dll_build_context = {}; + { + feely_pona_no_dll_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { feely_pona_no_dll_timings[1] = Dqn_OS_PerfCounterNow(); }; + + Dqn_String8 code_dir = exe_dir; + feely_pona_no_dll_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_CPPBuildCompileFile{ + {Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")})}, + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_nodll.h", DQN_STRING_FMT(code_dir)) + }, + }); + + feely_pona_no_dll_build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STRING_FMT(raylib_dir)), + }); + + feely_pona_no_dll_build_context.compile_flags = common_compile_flags; + + // NOTE: Link to raylib object files and windows libs ====================================== + Dqn_List link_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_link_flags); + { + for (Dqn_CPPBuildCompileFile file : raylib_build_context.compile_files) { + Dqn_String8 file_stem = Dqn_String8_FileNameNoExtension(file.path); + Dqn_String8 obj_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.obj", DQN_STRING_FMT(raylib_build_context.build_dir), DQN_STRING_FMT(file_stem)); + Dqn_List_Add(&link_flags, obj_file); + } + Dqn_List_Add(&link_flags, DQN_STRING8("gdi32.lib")); + Dqn_List_Add(&link_flags, DQN_STRING8("opengl32.lib")); + Dqn_List_Add(&link_flags, DQN_STRING8("winmm.lib")); + Dqn_List_Add(&link_flags, DQN_STRING8("user32.lib")); + Dqn_List_Add(&link_flags, DQN_STRING8("shell32.lib")); + } + + feely_pona_no_dll_build_context.link_flags = Dqn_List_ToSliceCopy(&link_flags, scratch.arena); + feely_pona_no_dll_build_context.build_dir = build_dir; + + Dqn_CPPBuild_ExecuteOrAbort(feely_pona_no_dll_build_context); + } + + // NOTE: Feely Pona DLL ======================================================================== + uint64_t feely_pona_dll_timings[2] = {}; + { + feely_pona_dll_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { feely_pona_dll_timings[1] = Dqn_OS_PerfCounterNow(); }; + + Dqn_String8 code_dir = exe_dir; + Dqn_CPPBuildContext build_context = {}; + build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_CPPBuildCompileFile{ + {Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")})}, + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STRING_FMT(code_dir)) + }, + }); + + Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags); + Dqn_List_Add(&compile_flags, DQN_STRING8("/LD")); + Dqn_List_Add(&compile_flags, DQN_STRING8("/Fotely_dll_msvc")); + Dqn_List_Add(&compile_flags, DQN_STRING8("/Fetely_dll_msvc")); + + build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); + build_context.link_flags = feely_pona_no_dll_build_context.link_flags; + build_context.build_dir = build_dir; + + Dqn_CPPBuild_ExecuteOrAbort(build_context); + } + + // NOTE: Feely Pona platform =================================================================== + uint64_t feely_pona_platform_timings[2] = {}; + { + feely_pona_platform_timings[0] = Dqn_OS_PerfCounterNow(); + DQN_DEFER { feely_pona_platform_timings[1] = Dqn_OS_PerfCounterNow(); }; + + Dqn_String8 code_dir = exe_dir; + Dqn_CPPBuildContext build_context = {}; + build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_CPPBuildCompileFile{ + {Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")})}, + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/tely_platform_raylib_unity.h", DQN_STRING_FMT(tely_dir)) + }, + }); + + build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, { + raylib_dir, + }); + + Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags); + Dqn_List_Add(&compile_flags, DQN_STRING8("/Fofeely_pona_msvc")); + Dqn_List_Add(&compile_flags, DQN_STRING8("/Fefeely_pona_msvc")); + build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); + build_context.link_flags = feely_pona_no_dll_build_context.link_flags; + build_context.build_dir = build_dir; + + Dqn_CPPBuild_ExecuteOrAbort(build_context); + } + + Dqn_Print_StdLnF(Dqn_PrintStd_Out, ""); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "robocopy: %.2fms", Dqn_OS_PerfCounterMs(robocopy_timings[0], robocopy_timings[1])); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "raylib: %.2fms", Dqn_OS_PerfCounterMs(raylib_timings[0], raylib_timings[1])); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "feely pona sprite packer: %.2fms", Dqn_OS_PerfCounterMs(feely_pona_sprite_packer_timings[0], feely_pona_sprite_packer_timings[1])); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "feely pona (no dll): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_no_dll_timings[0], feely_pona_no_dll_timings[1])); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "feely pona (dll): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_dll_timings[0], feely_pona_dll_timings[1])); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "feely pona (platform): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_platform_timings[0], feely_pona_platform_timings[1])); return 0; } diff --git a/project.rdbg b/project.rdbg index e92225e..1a23184 100644 Binary files a/project.rdbg and b/project.rdbg differ