592 lines
33 KiB
C++
592 lines
33 KiB
C++
// #include <Windows.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define DQN_IMPLEMENTATION
|
|
#include "External/tely/External/dqn/dqn.h"
|
|
|
|
#define DQN_CPP_BUILD_IMPLEMENTATION
|
|
#include "External/tely/External/dqn/dqn_cppbuild.h"
|
|
|
|
#if 0
|
|
void RebuildProgramIfRequired(int argc, char const **argv)
|
|
{
|
|
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
|
Dqn_String8 const exe_dir = Dqn_OS_EXEDir(scratch.arena);
|
|
Dqn_String8 build_program_path = Dqn_OS_EXEPath(scratch.arena);
|
|
Dqn_FsInfo build_program_info = Dqn_Fs_GetInfo(build_program_path);
|
|
Dqn_FsInfo source_path = Dqn_Fs_GetInfo(Dqn_String8_InitCString8(__FILE__));
|
|
|
|
if (!build_program_info.exists) {
|
|
Dqn_WinError error = Dqn_Win_LastError(scratch.arena);
|
|
Dqn_Log_WarningF("Failed to get the last write time of the build program '%.*s', skipping rebuild (%d): %.*s",
|
|
DQN_STRING_FMT(build_program_path), error.code, DQN_STRING_FMT(error.msg));
|
|
return;
|
|
}
|
|
|
|
if (!source_path.exists) {
|
|
Dqn_WinError error = Dqn_Win_LastError(scratch.arena);
|
|
Dqn_Log_WarningF(
|
|
"Failed to get the last write time of the build program's source code '%s', skipping rebuild (%d): %.*s",
|
|
__FILE__, error.code, DQN_STRING_FMT(error.msg));
|
|
return;
|
|
}
|
|
|
|
// NOTE: The build program is newer than the source path, no rebuild required
|
|
if (source_path.last_write_time_in_s < build_program_info.last_write_time_in_s) {
|
|
return;
|
|
}
|
|
|
|
Dqn_Log_InfoF("Build program source code has changed, rebuilding the program (timestamps changed source was %I64u, build program was %I64u)",
|
|
source_path.last_write_time_in_s,
|
|
build_program_info.last_write_time_in_s);
|
|
|
|
Dqn_String8 temp_build_program_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s.old", DQN_STRING_FMT(build_program_path));
|
|
if (!Dqn_Fs_Move(build_program_path, temp_build_program_path, true)) {
|
|
Dqn_WinError error = Dqn_Win_LastError(scratch.arena);
|
|
Dqn_Log_WarningF("Failed to backup the build program for rebuilding, skipping rebuild (%d): %.*s", error.code, DQN_STRING_FMT(error.msg));
|
|
return;
|
|
}
|
|
|
|
// NOTE: Rebuild the build program because a change was detected ===============
|
|
Dqn_String8 rebuild_cmd = Dqn_String8_InitF(scratch.allocator, "cl /Z7 /W4 /nologo %s /incremental:no /link", __FILE__);
|
|
Dqn_OSExecResult rebuild_result = Dqn_OS_Exec(rebuild_cmd, exe_dir /*working_dir*/);
|
|
if (rebuild_result.os_error_code) {
|
|
Dqn_WinError error = Dqn_Win_LastError(scratch.arena);
|
|
Dqn_Log_ErrorF("Detected change in the build program's source code '%s' but the OS failed to rebuild the program, skipping rebuild (%d): %.*s", __FILE__, error.code, DQN_STRING_FMT(error.msg));
|
|
return;
|
|
}
|
|
|
|
if (rebuild_result.exit_code) {
|
|
Dqn_Fs_Move(temp_build_program_path, build_program_path, true);
|
|
exit(rebuild_result.exit_code);
|
|
}
|
|
|
|
Dqn_String8Builder builder = {};
|
|
builder.allocator = scratch.allocator;
|
|
DQN_FOR_UINDEX (arg_index, argc)
|
|
Dqn_String8Builder_AppendF(&builder, "%s%s", arg_index ? " " : "", argv[arg_index]);
|
|
|
|
Dqn_String8 rebootstrap_cmd = Dqn_String8Builder_Build(&builder, scratch.allocator);
|
|
Dqn_OSExecResult exec_result = Dqn_OS_Exec(rebootstrap_cmd, exe_dir /*working_dir*/);
|
|
if (exec_result.os_error_code) {
|
|
Dqn_WinError error = Dqn_Win_LastError(scratch.arena);
|
|
Dqn_Log_ErrorF("Detected change in the build program's source code '%s' but the OS failed to rebuild the program, skipping rebuild (%d): %.*s", __FILE__, error.code, DQN_STRING_FMT(error.msg));
|
|
Dqn_Fs_Move(temp_build_program_path, build_program_path, true);
|
|
return;
|
|
}
|
|
|
|
exit(exec_result.exit_code);
|
|
}
|
|
#endif
|
|
|
|
#define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web]")
|
|
int main(int argc, char const **argv)
|
|
{
|
|
Dqn_Library_Init(Dqn_LibraryOnInit_Nil);
|
|
|
|
bool dry_run = false;
|
|
bool target_web = false;
|
|
for (Dqn_usize arg_index = 1; arg_index < argc; arg_index++) {
|
|
Dqn_String8 arg = Dqn_String8_InitCString8(argv[arg_index]);
|
|
if (arg == DQN_STRING8("--help")) {
|
|
PRINT_HELP;
|
|
return 0;
|
|
} else if (arg == DQN_STRING8("--dry-run")) {
|
|
dry_run = true;
|
|
} else if (arg == DQN_STRING8("--web")) {
|
|
target_web = true;
|
|
} else {
|
|
PRINT_HELP;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
RebuildProgramIfRequired(argc, argv);
|
|
#else
|
|
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_String8 const exe_dir = Dqn_OS_EXEDir(scratch.arena);
|
|
Dqn_String8 const code_dir = exe_dir;
|
|
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<Dqn_String8> 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<Dqn_String8> 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 /NJH /NJS /NDL /NP %.*s\\Data\\Textures %.*s\\Data\\Textures atlas.*", DQN_STRING_FMT(exe_dir), DQN_STRING_FMT(build_dir)),
|
|
Dqn_String8_InitF(scratch.allocator, "robocopy /MIR /NJH /NJS /NDL /NP %.*s\\Data\\Fonts %.*s\\Data\\Fonts", DQN_STRING_FMT(exe_dir), DQN_STRING_FMT(build_dir)),
|
|
Dqn_String8_InitF(scratch.allocator, "robocopy /MIR /NJH /NJS /NDL /NP %.*s\\Data\\Audio %.*s\\Data\\Audio", DQN_STRING_FMT(exe_dir), DQN_STRING_FMT(build_dir)),
|
|
};
|
|
|
|
for (Dqn_String8 cmd : robocopy_cmd) {
|
|
if (dry_run)
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
else
|
|
Dqn_OS_Exec(cmd, /*working_dir*/ {});
|
|
}
|
|
}
|
|
|
|
// NOTE: Raylib ================================================================================
|
|
Dqn_String8 const raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely/external/raylib", DQN_STRING_FMT(exe_dir));
|
|
Dqn_Slice<Dqn_String8> const raylib_base_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rcore.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/utils.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/raudio.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rmodels.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtext.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtextures.c", DQN_STRING_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STRING_FMT(raylib_dir)),
|
|
});
|
|
|
|
Dqn_List<Dqn_String8> raylib_pc_output_files = Dqn_List_Init<Dqn_String8>(scratch.arena, 16);
|
|
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_CPPBuildContext build_context = {};
|
|
{
|
|
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)),
|
|
});
|
|
|
|
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("/Z7"),
|
|
DQN_STRING8("/MT"),
|
|
DQN_STRING8("/EHsc"),
|
|
DQN_STRING8("/nologo"),
|
|
});
|
|
build_context.build_dir = build_dir;
|
|
build_context.compiler = Dqn_CPPBuildCompiler_MSVC;
|
|
}
|
|
|
|
// NOTE: Compile each file separately with a custom output name ============================
|
|
for (Dqn_String8 base_file : raylib_base_files) {
|
|
Dqn_String8 file_stem = Dqn_String8_FileNameNoExtension(base_file);
|
|
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = base_file;
|
|
build_file.output_file_path = Dqn_String8_InitF(scratch.allocator, "raylib_%.*s.obj", DQN_STRING_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);
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
|
|
// NOTE: Build rlgfw =======================================================================
|
|
{
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STRING_FMT(raylib_dir));
|
|
build_file.output_file_path = Dqn_String8_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);
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
}
|
|
|
|
// NOTE: QOI Converter =========================================================================
|
|
uint64_t qoi_converter_timings[2] = {};
|
|
{
|
|
qoi_converter_timings[0] = Dqn_OS_PerfCounterNow();
|
|
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, {
|
|
Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/qoiconv.c", DQN_STRING_FMT(code_dir)) },
|
|
});
|
|
|
|
build_context.compile_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("cl"), DQN_STRING8("-O2"), DQN_STRING8("-MT"), DQN_STRING8("/nologo")});
|
|
build_context.link_flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/link"), DQN_STRING8("/incremental:no")});
|
|
build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/stb", DQN_STRING_FMT(tely_dir))});
|
|
build_context.build_dir = build_dir;
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
|
|
// 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_CPPBuildContext build_context = {};
|
|
build_context.compiler = Dqn_CPPBuildCompiler_MSVC;
|
|
build_context.compile_files = Dqn_Slice_InitCArrayCopy(scratch.arena, {
|
|
Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.cpp", 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;
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
|
|
// 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_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity_nodll.h", DQN_STRING_FMT(code_dir));
|
|
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")});
|
|
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 = common_compile_flags;
|
|
feely_pona_no_dll_build_context.build_dir = build_dir;
|
|
|
|
// NOTE: Link to raylib object files and windows libs ======================================
|
|
Dqn_List<Dqn_String8> link_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_link_flags);
|
|
{
|
|
for (Dqn_ListIterator<Dqn_String8> it = {}; Dqn_List_Iterate(&raylib_pc_output_files, &it, 0); )
|
|
Dqn_List_Add(&link_flags, *it.data);
|
|
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);
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild);
|
|
}
|
|
}
|
|
|
|
// 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_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STRING_FMT(code_dir));
|
|
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "tely_dll_msvc", DQN_STRING_FMT(code_dir));
|
|
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")});
|
|
|
|
Dqn_List<Dqn_String8> 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("/Fetely_dll_msvc"));
|
|
|
|
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_no_dll_build_context.link_flags;
|
|
build_context.build_dir = build_dir;
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild);
|
|
}
|
|
}
|
|
|
|
// 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_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/tely_platform_raylib_unity.h", DQN_STRING_FMT(tely_dir));
|
|
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "feely_pona_msvc", DQN_STRING_FMT(code_dir));
|
|
build_file.flags = Dqn_Slice_InitCArrayCopy(scratch.arena, {DQN_STRING8("/Tp")});
|
|
|
|
Dqn_List<Dqn_String8> compile_flags = Dqn_List_InitSliceCopy(scratch.arena, 128, common_compile_flags);
|
|
Dqn_List_Add(&compile_flags, DQN_STRING8("/Fefeely_pona_msvc"));
|
|
|
|
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_no_dll_build_context.link_flags;
|
|
build_context.build_dir = build_dir;
|
|
build_context.include_dirs = Dqn_Slice_InitCArrayCopy(scratch.arena, {raylib_dir});
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_String8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_msvc.exe", DQN_STRING_FMT(build_dir));
|
|
bool exe_is_locked = false;
|
|
if (Dqn_Fs_Exists(exe_path)) {
|
|
Dqn_FsFile exe_file = Dqn_Fs_OpenFile(exe_path, Dqn_FsFileOpen_OpenIfExist, Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write);
|
|
exe_is_locked = exe_file.error_size;
|
|
Dqn_Fs_CloseFile(&exe_file);
|
|
}
|
|
|
|
if (!exe_is_locked) {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild);
|
|
}
|
|
}
|
|
}
|
|
|
|
// NOTE: raylib emscripten =====================================================================
|
|
uint64_t raylib_emscripten_timings[2] = {};
|
|
uint64_t feely_pona_emscripten_timings[2] = {};
|
|
if (target_web) {
|
|
Dqn_String8 const raylib_emscripten_lib_name = DQN_STRING8("raylib_emscripten.a");
|
|
bool debug_build = false;
|
|
|
|
Dqn_List<Dqn_String8> build_specific_compile_flags = {};
|
|
if (debug_build) {
|
|
build_specific_compile_flags = Dqn_List_InitCArrayCopy<Dqn_String8>(scratch.arena, 32, {
|
|
DQN_STRING8("-s"), DQN_STRING8("ASSERTIONS=2"),
|
|
DQN_STRING8("-s"), DQN_STRING8("SAFE_HEAP=0"),
|
|
DQN_STRING8("-s"), DQN_STRING8("STACK_OVERFLOW_CHECK=2"),
|
|
DQN_STRING8("--profiling-funcs"), // Expose function names in stack trace
|
|
DQN_STRING8("-g"), // Debug symbols
|
|
});
|
|
} else {
|
|
build_specific_compile_flags = Dqn_List_InitCArrayCopy<Dqn_String8>(scratch.arena, 32, {
|
|
DQN_STRING8("-Os"), // Optimise for size
|
|
});
|
|
}
|
|
|
|
// NOTE: Compile each raylib file separately with emcc =====================================
|
|
{
|
|
raylib_emscripten_timings[0] = Dqn_OS_PerfCounterNow();
|
|
DQN_DEFER { raylib_emscripten_timings[1] = Dqn_OS_PerfCounterNow(); };
|
|
|
|
// NOTE: Setup build context ===========================================================
|
|
Dqn_List<Dqn_String8> raylib_emscripten_output_files = Dqn_List_Init<Dqn_String8>(scratch.arena, 16);
|
|
Dqn_CPPBuildContext raylib_emscripten_build_context = {};
|
|
raylib_emscripten_build_context.compiler = Dqn_CPPBuildCompiler_GCC;
|
|
|
|
for (Dqn_String8 base_file : raylib_base_files) {
|
|
Dqn_String8 file_stem = Dqn_String8_FileNameNoExtension(base_file);
|
|
|
|
// NOTE: Append "emscripten" suffix to the object files
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = base_file;
|
|
build_file.output_file_path = Dqn_String8_InitF(scratch.allocator, "raylib_%.*s_emscripten.o", DQN_STRING_FMT(file_stem));
|
|
|
|
Dqn_List<Dqn_String8> compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, {
|
|
DQN_STRING8("cmd"),
|
|
DQN_STRING8("/C"),
|
|
DQN_STRING8("emcc.bat"),
|
|
DQN_STRING8("-c"), // Compile and assemble, but do not link
|
|
DQN_STRING8("-Wall"),
|
|
DQN_STRING8("-Os"), // Optimize for size
|
|
DQN_STRING8("-D PLATFORM_WEB"),
|
|
DQN_STRING8("-D GRAPHICS_API_OPENGL_ES2"),
|
|
});
|
|
Dqn_List_AddList(&compile_flags, build_specific_compile_flags);
|
|
|
|
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(&raylib_emscripten_output_files, build_file.output_file_path);
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(raylib_emscripten_build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
|
|
// NOTE: Build the wasm raylib library =================================================
|
|
{
|
|
Dqn_String8Builder builder = {};
|
|
builder.allocator = scratch.allocator;
|
|
Dqn_String8Builder_AppendF(&builder, "cmd /C emar.bat rcs %.*s", DQN_STRING_FMT(raylib_emscripten_lib_name));
|
|
|
|
for (Dqn_ListIterator<Dqn_String8> it = {}; Dqn_List_Iterate(&raylib_emscripten_output_files, &it, 0); )
|
|
Dqn_String8Builder_AppendF(&builder, " %.*s", DQN_STRING_FMT(*it.data));
|
|
|
|
Dqn_String8 cmd = Dqn_String8Builder_Build(&builder, scratch.allocator);
|
|
if (dry_run) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_OS_ExecOrAbort(cmd, build_dir);
|
|
}
|
|
}
|
|
}
|
|
|
|
// NOTE: feely pona emscripten =============================================================
|
|
{
|
|
feely_pona_emscripten_timings[0] = Dqn_OS_PerfCounterNow();
|
|
DQN_DEFER { feely_pona_emscripten_timings[1] = Dqn_OS_PerfCounterNow(); };
|
|
|
|
// NOTE: feely pona emscripten shell =======================================================
|
|
Dqn_String8 html_shell_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STRING_FMT(build_dir));
|
|
{
|
|
Dqn_String8 html_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STRING_FMT(code_dir));
|
|
Dqn_String8 html_buffer = Dqn_Fs_Read(html_path, scratch.allocator);
|
|
if (!DQN_CHECKF(html_buffer.size,
|
|
"Failed to read Emscripten HTML shell file. The file at\n\n '%.*s'\n\ndoes not exist or is not readable",
|
|
DQN_STRING_FMT(html_path)))
|
|
return -1;
|
|
|
|
Dqn_String8 version_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_version.txt", DQN_STRING_FMT(code_dir));
|
|
Dqn_String8 version_buffer = Dqn_Fs_Read(version_path, scratch.allocator);
|
|
Dqn_String8SplitAllocResult version_parts = Dqn_String8_SplitAlloc(scratch.allocator, version_buffer, DQN_STRING8("\n"));
|
|
|
|
if (!DQN_CHECKF(version_parts.size == 3,
|
|
"Version file '%.*s' must have 3 lines containing, date, commit hash and number of commits. The buffer we tried extracting information from was\n\n%.*s\n\n",
|
|
DQN_STRING_FMT(version_path),
|
|
DQN_STRING_FMT(version_buffer))) {
|
|
return -1;
|
|
}
|
|
|
|
Dqn_String8 date = Dqn_String8_TrimWhitespaceAround(version_parts.data[0]);
|
|
Dqn_String8 commit_hash = Dqn_String8_TrimWhitespaceAround(version_parts.data[1]);
|
|
Dqn_String8 commit_count = Dqn_String8_TrimWhitespaceAround(version_parts.data[2]);
|
|
Dqn_String8 version_text = Dqn_String8_InitF(scratch.allocator,
|
|
"%.*s edition rev. %.*s-%.*s",
|
|
DQN_STRING_FMT(date),
|
|
DQN_STRING_FMT(commit_count),
|
|
DQN_STRING_FMT(commit_hash));
|
|
|
|
Dqn_String8 html_buffer_processed = Dqn_String8_Replace(html_buffer,
|
|
DQN_STRING8("@version@"),
|
|
version_text,
|
|
0 /*start_index*/,
|
|
scratch.allocator);
|
|
if (!DQN_CHECKF(Dqn_Fs_Write(html_shell_path,
|
|
html_buffer_processed),
|
|
"Failed to write Emscripten HTML shell with the project version inserted into it. We were unable to write to the target location\n\n '%.*s'\n",
|
|
DQN_STRING_FMT(html_shell_path)))
|
|
return -1;
|
|
}
|
|
|
|
// 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, {
|
|
Dqn_CPPBuildCompileFile{{}, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity_nodll.cpp", DQN_STRING_FMT(code_dir)) },
|
|
});
|
|
|
|
Dqn_String8 output_name = DQN_STRING8("Terry_Cherry");
|
|
Dqn_List<Dqn_String8> compile_flags = Dqn_List_InitCArrayCopy(scratch.arena, 32, {
|
|
DQN_STRING8("cmd"), DQN_STRING8("/C"), DQN_STRING8("emcc.bat"),
|
|
DQN_STRING8("-o"), Dqn_String8_InitF(scratch.allocator, "%.*s.html", DQN_STRING_FMT(output_name)),
|
|
DQN_STRING8("-Wall"),
|
|
DQN_STRING8("--shell-file"), html_shell_path,
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STRING_FMT(build_dir), DQN_STRING_FMT(raylib_emscripten_lib_name)),
|
|
DQN_STRING8("-s"), DQN_STRING8("USE_GLFW=3"),
|
|
DQN_STRING8("-s"), DQN_STRING8("TOTAL_MEMORY=512MB"),
|
|
DQN_STRING8("-s"), DQN_STRING8("TOTAL_STACK=32MB"),
|
|
DQN_STRING8("-s"), DQN_STRING8("ALLOW_MEMORY_GROWTH"),
|
|
DQN_STRING8("--preload-file"), DQN_STRING8("Data"),
|
|
DQN_STRING8("-msimd128"),
|
|
DQN_STRING8("-msse2"),
|
|
});
|
|
Dqn_List_AddList(&compile_flags, build_specific_compile_flags);
|
|
|
|
build_context.compile_flags = Dqn_List_ToSliceCopy(&compile_flags, scratch.arena);
|
|
build_context.build_dir = build_dir;
|
|
|
|
if (dry_run) {
|
|
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.allocator);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
|
|
// NOTE: Move the files to a directory
|
|
Dqn_String8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s_Emscripten", DQN_STRING_FMT(build_dir), DQN_STRING_FMT(output_name));
|
|
if (!Dqn_Fs_DirExists(folder_path)) {
|
|
Dqn_String8 mkdir_cmd = Dqn_String8_InitF(scratch.allocator, "mkdir %.*s", DQN_STRING_FMT(folder_path));
|
|
Dqn_OS_ExecOrAbort(mkdir_cmd, {});
|
|
}
|
|
|
|
Dqn_String8 const generated_file_extension[] = {
|
|
DQN_STRING8("data"),
|
|
DQN_STRING8("html"),
|
|
DQN_STRING8("js"),
|
|
DQN_STRING8("wasm"),
|
|
};
|
|
|
|
for (Dqn_String8 file_ext : generated_file_extension) {
|
|
Dqn_String8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STRING_FMT(build_dir), DQN_STRING_FMT(output_name), DQN_STRING_FMT(file_ext));
|
|
Dqn_String8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STRING_FMT(folder_path), DQN_STRING_FMT(output_name), DQN_STRING_FMT(file_ext));
|
|
Dqn_String8 cmd = Dqn_String8_InitF(scratch.allocator, "cmd /C move /Y %.*s %.*s", DQN_STRING_FMT(src_path), DQN_STRING_FMT(dest_path));
|
|
if (dry_run) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.*s\n", DQN_STRING_FMT(cmd));
|
|
} else {
|
|
Dqn_OS_ExecOrAbort(cmd, build_dir);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
build_timings[1] = Dqn_OS_PerfCounterNow();
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "\n-- Dqn_CPPBuild Timings (%.2fms)", Dqn_OS_PerfCounterMs(build_timings[0], build_timings[1]));
|
|
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_pc_timings[0], raylib_pc_timings[1]));
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, " qoi_converter: %.2fms", Dqn_OS_PerfCounterMs(qoi_converter_timings[0], qoi_converter_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-raylib): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_platform_timings[0], feely_pona_platform_timings[1]));
|
|
if (target_web) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, " raylib (emscripten): %.2fms", Dqn_OS_PerfCounterMs(raylib_emscripten_timings[0], raylib_emscripten_timings[1]));
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona (emscripten): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_emscripten_timings[0], feely_pona_emscripten_timings[1]));
|
|
}
|
|
return 0;
|
|
}
|