From 88d996af87c46c8051de82a17a2f2826dbca0422 Mon Sep 17 00:00:00 2001 From: doyle Date: Sat, 25 Nov 2023 18:28:55 +1100 Subject: [PATCH] build: Add flags for linux build --- External/tely | 2 +- feely_pona_build.cpp | 426 +++++++++++++++++++++++++------------------ 2 files changed, 253 insertions(+), 175 deletions(-) diff --git a/External/tely b/External/tely index 743d968..d13c0f1 160000 --- a/External/tely +++ b/External/tely @@ -1 +1 @@ -Subproject commit 743d9684bc7675b3059b8f4049abd5c27b2f646c +Subproject commit d13c0f1f1efc426bc2d4be79f46784be5952c426 diff --git a/feely_pona_build.cpp b/feely_pona_build.cpp index 19ea981..25b0e87 100644 --- a/feely_pona_build.cpp +++ b/feely_pona_build.cpp @@ -80,7 +80,7 @@ void RebuildProgramIfRequired(int argc, char const **argv) } #endif -#define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web|--fast-dev-build]") +#define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web|--fast-dev-build|--win|--linux]") int main(int argc, char const **argv) { Dqn_Library_Init(Dqn_LibraryOnInit_Nil); @@ -88,6 +88,8 @@ int main(int argc, char const **argv) bool dry_run = false; bool target_web = false; bool dev_fast_build = false; + bool windows_build = false; + bool linux_build = false; for (Dqn_isize arg_index = 1; arg_index < argc; arg_index++) { Dqn_Str8 arg = Dqn_Str8_InitCStr8(argv[arg_index]); if (arg == DQN_STR8("--help")) { @@ -99,6 +101,10 @@ int main(int argc, char const **argv) target_web = true; } else if (arg == DQN_STR8("--fast-dev-build")) { dev_fast_build = true; + } else if (arg == DQN_STR8("--linux")) { + linux_build = true; + } else if (arg == DQN_STR8("--win")) { + windows_build = true; } else { PRINT_HELP; return 0; @@ -111,50 +117,104 @@ int main(int argc, char const **argv) Dqn_Print_StdLnF(Dqn_PrintStd_Out, "-- Dqn_CPPBuild v0"); #endif - uint64_t build_timings[2] = {}; - build_timings[0] = Dqn_OS_PerfCounterNow(); - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_Str8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); - Dqn_Str8 const code_dir = exe_dir; - Dqn_Str8 const build_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Build", DQN_STR_FMT(exe_dir)); - Dqn_Str8 const tely_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely", DQN_STR_FMT(exe_dir)); + if (windows_build && linux_build) { + Dqn_Print_StdLnF(Dqn_PrintStd_Out, + "Both '--win' and '--linux' were specified but only one is supported at a time for this build program."); + return -1; + } - Dqn_Slice common_compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { - DQN_STR8("cl"), - DQN_STR8("/W4"), - DQN_STR8("/Z7"), - DQN_STR8("/MT"), - DQN_STR8("/EHsc"), - DQN_STR8("/nologo"), - }); + if (!windows_build && !linux_build) { + #if defined(DQN_OS_WIN32) + windows_build = true; + #else + linux_build = true; + #endif + } - Dqn_Slice common_link_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { - DQN_STR8("/link"), - DQN_STR8("/incremental:no"), - }); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Building for %s", windows_build ? "Windows" : "Linux"); + + uint64_t build_timings[2] = {}; + build_timings[0] = Dqn_OS_PerfCounterNow(); + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Str8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); + Dqn_Str8 const code_dir = exe_dir; + Dqn_Str8 const build_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Build", DQN_STR_FMT(exe_dir)); + Dqn_Str8 const tely_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely", DQN_STR_FMT(exe_dir)); + Dqn_CPPBuildFlagsStyle flags_style = windows_build ? Dqn_CPPBuildFlagsStyle_MSVC : Dqn_CPPBuildFlagsStyle_GCC; + + Dqn_FArray32 common_compile_flags = {}; + Dqn_FArray32 common_link_flags = {}; + if (windows_build) { + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("cl")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("/W4")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("/Z7")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("/MT")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("/EHsc")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("/nologo")); + + Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("/link")); + Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("/incremental:no")); + } else { + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("gcc")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-Wall")); + Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-g")); + + Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("-lm")); + } // NOTE: Assets ================================================================================ uint64_t robocopy_timings[2] = {}; { robocopy_timings[0] = Dqn_OS_PerfCounterNow(); DQN_DEFER { robocopy_timings[1] = Dqn_OS_PerfCounterNow(); }; - Dqn_Str8 robocopy_cmd[] = { - Dqn_Str8_InitF(scratch.allocator, "robocopy /NJH /NJS /NDL /NP %.*s\\Data\\Textures %.*s\\Data\\Textures atlas.*", DQN_STR_FMT(exe_dir), DQN_STR_FMT(build_dir)), - Dqn_Str8_InitF(scratch.allocator, "robocopy /MIR /NJH /NJS /NDL /NP %.*s\\Data\\Fonts %.*s\\Data\\Fonts", DQN_STR_FMT(exe_dir), DQN_STR_FMT(build_dir)), - Dqn_Str8_InitF(scratch.allocator, "robocopy /MIR /NJH /NJS /NDL /NP %.*s\\Data\\Audio %.*s\\Data\\Audio", DQN_STR_FMT(exe_dir), DQN_STR_FMT(build_dir)), + + Dqn_FArray32 common_copy_cmd_args = {}; + if (windows_build) { + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("robocopy")); + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("/NJH")); + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("/NDL")); + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("/NP")); + } else { + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("cp")); + Dqn_FArray_AddAssert(&common_copy_cmd_args, DQN_STR8("--recursive")); + } + + Dqn_FArray32 copy_textures_cmd = common_copy_cmd_args; + Dqn_FArray_AddAssert(©_textures_cmd, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures", DQN_STR_FMT(exe_dir))); + if (windows_build) { + Dqn_FArray_AddAssert(©_textures_cmd, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures atlas.*", DQN_STR_FMT(build_dir))); + } else { + Dqn_FArray_AddAssert(©_textures_cmd, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.*", DQN_STR_FMT(build_dir))); + } + + Dqn_FArray32 copy_fonts_cmd = common_copy_cmd_args; + Dqn_FArray_AddAssert(©_fonts_cmd, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(exe_dir))); + Dqn_FArray_AddAssert(©_fonts_cmd, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(build_dir))); + + Dqn_FArray32 copy_audio_cmd = common_copy_cmd_args; + Dqn_FArray_AddAssert(&common_copy_cmd_args, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(exe_dir))); + Dqn_FArray_AddAssert(&common_copy_cmd_args, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(build_dir))); + + Dqn_FArray32 *copy_cmd_list[] = { + ©_textures_cmd, + ©_fonts_cmd, + ©_audio_cmd, }; - for (Dqn_Str8 cmd : robocopy_cmd) { - if (dry_run) - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); - else - Dqn_OS_Exec(cmd, /*working_dir*/ {}); + for (Dqn_FArray32 *copy_cmd : copy_cmd_list) { + Dqn_Slice copy_cmd_slice = Dqn_FArray_Slice(copy_cmd); + if (dry_run) { + Dqn_Str8 rendered_line = Dqn_Slice_Str8Render(scratch.arena, copy_cmd_slice, DQN_STR8(" ")); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(rendered_line)); + } else { + Dqn_OS_Exec(copy_cmd_slice, /*working_dir*/ {}); + } } } // NOTE: Raylib ================================================================================ Dqn_Str8 const raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely/external/raylib", DQN_STR_FMT(exe_dir)); - Dqn_Slice const raylib_base_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + Dqn_Slice const raylib_base_files = Dqn_Slice_InitCArray(scratch.arena, { Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rcore.c", DQN_STR_FMT(raylib_dir)), Dqn_FsPath_ConvertF(scratch.arena, "%.*s/utils.c", DQN_STR_FMT(raylib_dir)), Dqn_FsPath_ConvertF(scratch.arena, "%.*s/raudio.c", DQN_STR_FMT(raylib_dir)), @@ -164,48 +224,57 @@ int main(int argc, char const **argv) Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STR_FMT(raylib_dir)), }); - Dqn_List raylib_pc_output_files = Dqn_List_Init(scratch.arena, 16); - uint64_t raylib_pc_timings[2] = {}; + Dqn_FArray32 raylib_pc_output_files = {}; + uint64_t raylib_pc_timings[2] = {}; { raylib_pc_timings[0] = Dqn_OS_PerfCounterNow(); DQN_DEFER { raylib_pc_timings[1] = Dqn_OS_PerfCounterNow(); }; // NOTE: Setup raylib build context ======================================================== + Dqn_FArray32 compile_flags = {}; Dqn_CPPBuildContext build_context = {}; { - build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, { + build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, { Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STR_FMT(raylib_dir)), Dqn_FsPath_ConvertF(scratch.arena, "%.*s/external/glfw/include", DQN_STR_FMT(raylib_dir)), Dqn_FsPath_ConvertF(scratch.arena, "%.*s/glfw/deps/mingw", DQN_STR_FMT(raylib_dir)), }); - build_context.compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, { - DQN_STR8("cl"), - DQN_STR8("/w"), - DQN_STR8("/c"), - DQN_STR8("/D _DEFAULT_SOURCE"), - DQN_STR8("/D PLATFORM_DESKTOP"), - DQN_STR8("/Z7"), - DQN_STR8("/MT"), - DQN_STR8("/EHsc"), - DQN_STR8("/nologo"), - }); - build_context.build_dir = build_dir; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; + if (windows_build) { + Dqn_FArray_Add(&compile_flags, DQN_STR8("cl")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/w")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/c")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/D _DEFAULT_SOURCE")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/D PLATFORM_DESKTOP")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/Z7")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/MT")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/EHsc")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("/nologo")); + } else { + Dqn_FArray_Add(&compile_flags, DQN_STR8("gcc")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("-c")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("-D _DEFAULT_SOURCE")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("-D PLATFORM_DESKTOP")); + Dqn_FArray_Add(&compile_flags, DQN_STR8("-g")); + } + + build_context.build_dir = build_dir; + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.flags_style = flags_style; } // NOTE: Compile each file separately with a custom output name ============================ for (Dqn_Str8 base_file : raylib_base_files) { Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(base_file); - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = base_file; - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_%.*s.obj", DQN_STR_FMT(file_stem)); - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - Dqn_List_Add(&raylib_pc_output_files, build_file.output_file_path); + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = base_file; + build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_%.*s.obj", DQN_STR_FMT(file_stem)); + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, {build_file}); + Dqn_FArray_AddAssert(&raylib_pc_output_files, build_file.output_file_path); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -217,11 +286,11 @@ int main(int argc, char const **argv) Dqn_CPPBuildCompileFile build_file = {}; build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STR_FMT(raylib_dir)); build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_rglfw.obj"); - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - Dqn_List_Add(&raylib_pc_output_files, build_file.output_file_path); + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, {build_file}); + Dqn_FArray_AddAssert(&raylib_pc_output_files, build_file.output_file_path); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -230,31 +299,33 @@ int main(int argc, char const **argv) } // NOTE: sokol_audio ================================================================================ - Dqn_Str8 sokol_audio_source_code_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol/sokol_audio.c", DQN_STR_FMT(tely_dir)); - uint64_t sokol_audio_pc_timings[2] = {}; - Dqn_List sokol_audio_pc_output_files = Dqn_List_Init(scratch.arena, 16); + Dqn_Str8 sokol_audio_source_code_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol/sokol_audio.c", DQN_STR_FMT(tely_dir)); + uint64_t sokol_audio_pc_timings[2] = {}; + Dqn_FArray32 sokol_audio_pc_output_files = {}; { sokol_audio_pc_timings[0] = Dqn_OS_PerfCounterNow(); DQN_DEFER { sokol_audio_pc_timings[1] = Dqn_OS_PerfCounterNow(); }; + Dqn_CPPBuildContext build_context = {}; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + build_context.flags_style = flags_style; + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { Dqn_CPPBuildCompileFile{ {}, // Args sokol_audio_source_code_file, }, }); - Dqn_List_Add(&sokol_audio_pc_output_files, DQN_STR8("sokol_audio.obj")); + Dqn_FArray_AddAssert(&sokol_audio_pc_output_files, DQN_STR8("sokol_audio.obj")); - Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 16, common_compile_flags); - Dqn_List_Add(&compile_flags, DQN_STR8("/c")); - build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/c")); + + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); build_context.build_dir = build_dir; if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -268,18 +339,18 @@ int main(int argc, char const **argv) DQN_DEFER { qoi_converter_timings[1] = Dqn_OS_PerfCounterNow(); }; Dqn_CPPBuildContext build_context = {}; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + build_context.flags_style = flags_style; + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/qoiconv.c", DQN_STR_FMT(code_dir)) }, }); - build_context.compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("cl"), DQN_STR8("-O2"), DQN_STR8("-MT"), DQN_STR8("/nologo")}); - build_context.link_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/link"), DQN_STR8("/incremental:no")}); - build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/stb", DQN_STR_FMT(tely_dir))}); + build_context.compile_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("cl"), DQN_STR8("-O2"), DQN_STR8("-MT"), DQN_STR8("/nologo")}); + build_context.link_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/link"), DQN_STR8("/incremental:no")}); + build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, {Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/stb", DQN_STR_FMT(tely_dir))}); build_context.build_dir = build_dir; if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -293,17 +364,17 @@ int main(int argc, char const **argv) DQN_DEFER { feely_pona_sprite_packer_timings[1] = Dqn_OS_PerfCounterNow(); }; Dqn_CPPBuildContext build_context = {}; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + build_context.flags_style = flags_style; + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.cpp", DQN_STR_FMT(code_dir)) }, }); - build_context.compile_flags = common_compile_flags; - build_context.link_flags = common_link_flags; + build_context.compile_flags = Dqn_FArray_Slice(&common_compile_flags); + build_context.link_flags = Dqn_FArray_Slice(&common_link_flags); build_context.build_dir = build_dir; if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -311,22 +382,18 @@ int main(int argc, char const **argv) } // NOTE: Feely Pona Link Flags ================================================================= - Dqn_Slice feely_pona_platform_link_flags = {}; + Dqn_FArray32 feely_pona_platform_link_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_ListIterator it = {}; Dqn_List_Iterate(&raylib_pc_output_files, &it, 0); ) - Dqn_List_Add(&link_flags, *it.data); - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(&sokol_audio_pc_output_files, &it, 0); ) - Dqn_List_Add(&link_flags, *it.data); - Dqn_List_Add(&link_flags, DQN_STR8("gdi32.lib")); - Dqn_List_Add(&link_flags, DQN_STR8("opengl32.lib")); - Dqn_List_Add(&link_flags, DQN_STR8("winmm.lib")); - Dqn_List_Add(&link_flags, DQN_STR8("user32.lib")); - Dqn_List_Add(&link_flags, DQN_STR8("shell32.lib")); + Dqn_FArray_AddArrayAssert(&feely_pona_platform_link_flags, raylib_pc_output_files.data, raylib_pc_output_files.size); + Dqn_FArray_AddArrayAssert(&feely_pona_platform_link_flags, sokol_audio_pc_output_files.data, sokol_audio_pc_output_files.size); + if (windows_build) { + Dqn_FArray_AddAssert(&feely_pona_platform_link_flags, DQN_STR8("gdi32.lib")); + Dqn_FArray_AddAssert(&feely_pona_platform_link_flags, DQN_STR8("opengl32.lib")); + Dqn_FArray_AddAssert(&feely_pona_platform_link_flags, DQN_STR8("winmm.lib")); + Dqn_FArray_AddAssert(&feely_pona_platform_link_flags, DQN_STR8("user32.lib")); + Dqn_FArray_AddAssert(&feely_pona_platform_link_flags, DQN_STR8("shell32.lib")); } - feely_pona_platform_link_flags = Dqn_List_ToSliceCopy(&link_flags, scratch.arena); } // NOTE: Feely Pona No DLL ===================================================================== @@ -338,24 +405,28 @@ int main(int argc, char const **argv) Dqn_CPPBuildCompileFile build_file = {}; build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry"); - build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")}); + if (windows_build) + build_file.flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); - Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 16, common_compile_flags); - Dqn_List_AddCArray(&compile_flags, { - DQN_STR8("/D TELY_WITH_PLATFORM"), - DQN_STR8("/D FEELY_PONA_IMPLEMENTATION"), - }); + Dqn_FArray32 compile_flags = common_compile_flags; + if (windows_build) { + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/D TELY_WITH_PLATFORM")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/D FEELY_PONA_IMPLEMENTATION")); + } else { + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-D TELY_WITH_PLATFORM")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-D FEELY_PONA_IMPLEMENTATION")); + } Dqn_CPPBuildContext feely_pona_no_dll_build_context = {}; - feely_pona_no_dll_build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - feely_pona_no_dll_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - feely_pona_no_dll_build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {raylib_dir}); - feely_pona_no_dll_build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); - feely_pona_no_dll_build_context.build_dir = build_dir; - feely_pona_no_dll_build_context.link_flags = feely_pona_platform_link_flags; + feely_pona_no_dll_build_context.flags_style = flags_style; + feely_pona_no_dll_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + feely_pona_no_dll_build_context.include_dirs = Dqn_Slice_Init(DQN_CAST(Dqn_Str8 *)&raylib_dir, 1); + feely_pona_no_dll_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + feely_pona_no_dll_build_context.build_dir = build_dir; + feely_pona_no_dll_build_context.link_flags = Dqn_FArray_Slice(&feely_pona_platform_link_flags); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild); @@ -364,33 +435,30 @@ int main(int argc, char const **argv) // NOTE: Feely Pona DLL ======================================================================== uint64_t feely_pona_dll_timings[2] = {}; - { + if (windows_build) { feely_pona_dll_timings[0] = Dqn_OS_PerfCounterNow(); DQN_DEFER { feely_pona_dll_timings[1] = Dqn_OS_PerfCounterNow(); }; Dqn_CPPBuildCompileFile build_file = {}; build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev_dll"); - build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")}); - - Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 16, common_compile_flags); - Dqn_List_AddCArray(&compile_flags, { - DQN_STR8("/LD"), - DQN_STR8("/D FEELY_PONA_IMPLEMENTATION"), - }); + build_file.flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/LD")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/D FEELY_PONA_IMPLEMENTATION")); if (!dev_fast_build) - Dqn_List_Add(&compile_flags, DQN_STR8("/analyze")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/analyze")); Dqn_CPPBuildContext build_context = {}; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); + build_context.flags_style = flags_style; + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); build_context.link_flags = {}; build_context.build_dir = build_dir; if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); @@ -399,31 +467,29 @@ int main(int argc, char const **argv) // NOTE: Feely Pona platform =================================================================== uint64_t feely_pona_platform_timings[2] = {}; - { + if (windows_build) { feely_pona_platform_timings[0] = Dqn_OS_PerfCounterNow(); DQN_DEFER { feely_pona_platform_timings[1] = Dqn_OS_PerfCounterNow(); }; Dqn_CPPBuildCompileFile build_file = {}; build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev", DQN_STR_FMT(code_dir)); - build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STR8("/Tp")}); + build_file.flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); - Dqn_List compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags); - Dqn_List_AddCArray(&compile_flags, { - DQN_STR8("/D TELY_WITH_PLATFORM"), - DQN_STR8("/D TELY_WITH_PLATFORM_DLL"), - }); + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/D TELY_WITH_PLATFORM")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("/D TELY_WITH_PLATFORM_DLL")); Dqn_CPPBuildContext build_context = {}; - build_context.compiler = Dqn_CPPBuildCompiler_MSVC; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); - build_context.link_flags = feely_pona_platform_link_flags; + build_context.flags_style = flags_style; + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.link_flags = Dqn_FArray_Slice(&feely_pona_platform_link_flags); build_context.build_dir = build_dir; - build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {raylib_dir}); + build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, {raylib_dir}); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/terry_cherry_dev.exe", DQN_STR_FMT(build_dir)); @@ -447,19 +513,15 @@ int main(int argc, char const **argv) Dqn_Str8 const raylib_emscripten_lib_name = DQN_STR8("raylib_emscripten.a"); bool debug_build = false; - Dqn_List build_specific_compile_flags = {}; + Dqn_FArray32 build_specific_compile_flags = {}; if (debug_build) { - build_specific_compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, { - DQN_STR8("-s"), DQN_STR8("ASSERTIONS=2"), - DQN_STR8("-s"), DQN_STR8("SAFE_HEAP=0"), - DQN_STR8("-s"), DQN_STR8("STACK_OVERFLOW_CHECK=2"), - DQN_STR8("--profiling-funcs"), // Expose function names in stack trace - DQN_STR8("-g"), // Debug symbols - }); + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("ASSERTIONS=2")}); + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("SAFE_HEAP=0")}); + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("STACK_OVERFLOW_CHECK=2")}); + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("--profiling-funcs")}); // Expose function names in stack trace + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-g")}); // Debug symbols } else { - build_specific_compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, { - DQN_STR8("-Os"), // Optimise for size - }); + Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-Os")}); // Optimise for size } // NOTE: Compile each raylib file separately with emcc ===================================== @@ -468,9 +530,9 @@ int main(int argc, char const **argv) DQN_DEFER { raylib_emscripten_timings[1] = Dqn_OS_PerfCounterNow(); }; // NOTE: Setup build context =========================================================== - Dqn_List emscripten_obj_files = Dqn_List_Init(scratch.arena, 16); + Dqn_FArray32 emscripten_obj_files = {}; Dqn_CPPBuildContext raylib_emscripten_build_context = {}; - raylib_emscripten_build_context.compiler = Dqn_CPPBuildCompiler_GCC; + raylib_emscripten_build_context.flags_style = flags_style; for (Dqn_Str8 base_file : raylib_base_files) { Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(base_file); @@ -480,7 +542,8 @@ int main(int argc, char const **argv) build_file.input_file_path = base_file; build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_%.*s_emscripten.o", DQN_STR_FMT(file_stem)); - Dqn_List compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, { + Dqn_FArray32 compile_flags = {}; + Dqn_FArray_AddCArrayAssert(&compile_flags, { DQN_STR8("cmd"), DQN_STR8("/C"), DQN_STR8("emcc.bat"), @@ -490,15 +553,15 @@ int main(int argc, char const **argv) DQN_STR8("-D PLATFORM_WEB"), DQN_STR8("-D GRAPHICS_API_OPENGL_ES2"), }); - Dqn_List_AddList(&compile_flags, build_specific_compile_flags); + Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - raylib_emscripten_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - raylib_emscripten_build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); - raylib_emscripten_build_context.build_dir = build_dir; - Dqn_List_Add(&emscripten_obj_files, build_file.output_file_path); + raylib_emscripten_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + raylib_emscripten_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + raylib_emscripten_build_context.build_dir = build_dir; + Dqn_FArray_AddAssert(&emscripten_obj_files, build_file.output_file_path); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(raylib_emscripten_build_context, Dqn_CPPBuildMode_CacheBuild); @@ -513,7 +576,7 @@ int main(int argc, char const **argv) build_file.input_file_path = base_file; build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "sokol_audio_emscripten.o"); - Dqn_List compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, { + Dqn_FArray32 compile_flags = Dqn_FArray_InitCArray({ DQN_STR8("cmd"), DQN_STR8("/C"), DQN_STR8("emcc.bat"), @@ -521,15 +584,15 @@ int main(int argc, char const **argv) DQN_STR8("-Wall"), DQN_STR8("-Os"), // Optimize for size }); - Dqn_List_AddList(&compile_flags, build_specific_compile_flags); + Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - raylib_emscripten_build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {build_file}); - raylib_emscripten_build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); - raylib_emscripten_build_context.build_dir = build_dir; - Dqn_List_Add(&emscripten_obj_files, build_file.output_file_path); + raylib_emscripten_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + raylib_emscripten_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + raylib_emscripten_build_context.build_dir = build_dir; + Dqn_FArray_AddAssert(&emscripten_obj_files, build_file.output_file_path); if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(raylib_emscripten_build_context, Dqn_CPPBuildMode_CacheBuild); @@ -538,18 +601,21 @@ int main(int argc, char const **argv) // NOTE: Build the wasm raylib+sokol_audio library ===================================== { - Dqn_Str8Builder builder = {}; - builder.allocator = scratch.allocator; - Dqn_Str8Builder_AppendF(&builder, "cmd /C emar.bat rcs %.*s", DQN_STR_FMT(raylib_emscripten_lib_name)); + Dqn_FArray32 cmd_args = Dqn_FArray_InitCArray({ + DQN_STR8("cmd"), + DQN_STR8("/C"), + DQN_STR8("emar.bat"), + DQN_STR8("rcs"), + raylib_emscripten_lib_name, + }); - for (Dqn_ListIterator it = {}; Dqn_List_Iterate(&emscripten_obj_files, &it, 0); ) - Dqn_Str8Builder_AppendF(&builder, " %.*s", DQN_STR_FMT(*it.data)); - - Dqn_Str8 cmd = Dqn_Str8Builder_Build(&builder, scratch.allocator); + Dqn_FArray_AddArrayAssert(&cmd_args, emscripten_obj_files.data, emscripten_obj_files.size); + Dqn_Slice cmd_slice = Dqn_FArray_Slice(&cmd_args); if (dry_run) { + Dqn_Str8 cmd = Dqn_Slice_Str8Render(scratch.arena, cmd_slice, DQN_STR8(" ") /*separator*/); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { - Dqn_OS_ExecOrAbort(cmd, build_dir); + Dqn_OS_ExecOrAbort(cmd_slice, build_dir); } } } @@ -604,12 +670,12 @@ int main(int argc, char const **argv) // NOTE: Compile with emcc ============================================================= Dqn_CPPBuildContext build_context = {}; build_context.compile_file_obj_suffix = DQN_CPP_BUILD_OBJ_SUFFIX_O; - build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, { + build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.cpp", DQN_STR_FMT(code_dir)) }, }); - Dqn_Str8 output_name = DQN_STR8("Terry_Cherry"); - Dqn_List compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, { + Dqn_Str8 output_name = DQN_STR8("Terry_Cherry"); + Dqn_FArray32 compile_flags = Dqn_FArray_InitCArray({ DQN_STR8("cmd"), DQN_STR8("/C"), DQN_STR8("emcc.bat"), DQN_STR8("-o"), Dqn_Str8_InitF(scratch.allocator, "%.*s.html", DQN_STR_FMT(output_name)), DQN_STR8("-Wall"), @@ -625,13 +691,13 @@ int main(int argc, char const **argv) DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"), }); - Dqn_List_AddList(&compile_flags, build_specific_compile_flags); + Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); build_context.build_dir = build_dir; if (dry_run) { - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); } else { Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); @@ -640,8 +706,10 @@ int main(int argc, char const **argv) // NOTE: Move the files to a directory Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name)); if (!Dqn_Fs_DirExists(folder_path)) { - Dqn_Str8 mkdir_cmd = Dqn_Str8_InitF(scratch.allocator, "mkdir %.*s", DQN_STR_FMT(folder_path)); - Dqn_OS_ExecOrAbort(mkdir_cmd, {}); + Dqn_FArray32 mkdir_cmd = {}; + Dqn_FArray_AddAssert(&mkdir_cmd, DQN_STR8("mkdir")); + Dqn_FArray_AddAssert(&mkdir_cmd, folder_path); + Dqn_OS_ExecOrAbort(Dqn_FArray_Slice(&mkdir_cmd), {}); } Dqn_Str8 const generated_file_extension[] = { @@ -654,11 +722,21 @@ int main(int argc, char const **argv) for (Dqn_Str8 file_ext : generated_file_extension) { Dqn_Str8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext)); Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext)); - Dqn_Str8 cmd = Dqn_Str8_InitF(scratch.allocator, "cmd /C move /Y %.*s %.*s", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path)); + + Dqn_FArray32 cmd_args = {}; + Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("cmd")); + Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("/C")); + Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("move")); + Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("/Y")); + Dqn_FArray_AddAssert(&cmd_args, src_path); + Dqn_FArray_AddAssert(&cmd_args, dest_path); + + Dqn_Slice cmd_slice = Dqn_FArray_Slice(&cmd_args); if (dry_run) { - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd)); + Dqn_Str8 cmd_rendered = Dqn_Slice_Str8Render(scratch.arena, cmd_slice, DQN_STR8(" ")); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STR_FMT(cmd_rendered)); } else { - Dqn_OS_ExecOrAbort(cmd, build_dir); + Dqn_OS_ExecOrAbort(cmd_slice, build_dir); } } }