613 lines
32 KiB
C++
613 lines
32 KiB
C++
#define DQN_IMPLEMENTATION
|
|
#include "External/tely/External/dqn/dqn.h"
|
|
|
|
#define DQN_CPP_BUILD_IMPLEMENTATION
|
|
#include "External/tely/External/dqn/dqn_cppbuild.h"
|
|
|
|
struct BuildTime
|
|
{
|
|
Dqn_Str8 name;
|
|
uint64_t timestamps[2];
|
|
};
|
|
|
|
enum Compiler
|
|
{
|
|
Compiler_MSVC,
|
|
Compiler_GCC,
|
|
Compiler_EMCC,
|
|
Compiler_Count,
|
|
};
|
|
|
|
#define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web|--fast-dev-build|--msvc|--gcc]")
|
|
int main(int argc, char const **argv)
|
|
{
|
|
// NOTE: Preamble ==============================================================================
|
|
Dqn_Library_Init(Dqn_LibraryOnInit_Nil);
|
|
Dqn_FArray32<BuildTime> build_timings = {};
|
|
BuildTime *global_build_timings = Dqn_FArray_Make(&build_timings, Dqn_ZeroMem_Yes);
|
|
global_build_timings->name = DQN_STR8("Dqn_CPPBuild Summary (Total)");
|
|
global_build_timings->timestamps[0] = Dqn_OS_PerfCounterNow();
|
|
|
|
#if 0
|
|
RebuildProgramIfRequired(argc, argv);
|
|
#else
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "-- Dqn_CPPBuild v0");
|
|
#endif
|
|
|
|
bool build_using_compiler[Compiler_Count] = {};
|
|
|
|
// NOTE: Parse arguments =======================================================================
|
|
bool dry_run = false;
|
|
bool fast_dev_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")) {
|
|
PRINT_HELP;
|
|
return 0;
|
|
} else if (arg == DQN_STR8("--dry-run")) {
|
|
dry_run = true;
|
|
} else if (arg == DQN_STR8("--fast-dev-build")) {
|
|
fast_dev_build = true;
|
|
} else if (arg == DQN_STR8("--gcc")) {
|
|
build_using_compiler[Compiler_GCC] = true;
|
|
} else if (arg == DQN_STR8("--msvc")) {
|
|
build_using_compiler[Compiler_MSVC] = true;
|
|
} else if (arg == DQN_STR8("--web")) {
|
|
build_using_compiler[Compiler_EMCC] = true;
|
|
} else {
|
|
PRINT_HELP;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// NOTE: Add a default compiler target if none were specified
|
|
{
|
|
size_t total_compiler_targets = 0;
|
|
for (bool is_set : build_using_compiler)
|
|
total_compiler_targets += DQN_CAST(size_t)is_set;
|
|
|
|
if (total_compiler_targets == 0) {
|
|
#if defined(DQN_OS_WIN32)
|
|
build_using_compiler[Compiler_MSVC] = true;
|
|
#else
|
|
compiler_targets[Compiler_GCC] = true;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// NOTE: Setup build ===========================================================================
|
|
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));
|
|
|
|
#define RecordScopeTime(...) \
|
|
BuildTime *build_time_ = Dqn_FArray_Make<BuildTime>(&build_timings, Dqn_ZeroMem_Yes); \
|
|
build_time_->name = Dqn_Str8_InitF(scratch.allocator, ##__VA_ARGS__); \
|
|
build_time_->timestamps[0] = Dqn_OS_PerfCounterNow(); \
|
|
DQN_DEFER { build_time_->timestamps[1] = Dqn_OS_PerfCounterNow(); }
|
|
|
|
bool assets_copied = false;
|
|
for (Dqn_usize compiler_index = 0; compiler_index < Compiler_Count; compiler_index++) {
|
|
if (!build_using_compiler[compiler_index])
|
|
continue;
|
|
|
|
Compiler compiler = DQN_CAST(Compiler) compiler_index;
|
|
Dqn_Str8 obj_file_extension = compiler == Compiler_MSVC ? DQN_STR8("obj") : DQN_STR8("o");
|
|
Dqn_Str8 compiler_label = {};
|
|
switch (compiler) {
|
|
case Compiler_MSVC: compiler_label = DQN_STR8("msvc"); break;
|
|
case Compiler_GCC: compiler_label = DQN_STR8("gcc"); break;
|
|
case Compiler_EMCC: compiler_label = DQN_STR8("emcc"); break;
|
|
case Compiler_Count: break;
|
|
}
|
|
|
|
// NOTE: Compile flags =========================================================================
|
|
Dqn_FArray32<Dqn_Str8> common_compile_flags_no_warnings = {};
|
|
if (compiler == Compiler_MSVC) {
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {
|
|
DQN_STR8("cl"),
|
|
DQN_STR8("-Z7"),
|
|
DQN_STR8("-MT"),
|
|
DQN_STR8("-EHsc"),
|
|
DQN_STR8("-nologo"),
|
|
});
|
|
} else if (compiler == Compiler_GCC) {
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {
|
|
DQN_STR8("g++"),
|
|
DQN_STR8("-g"),
|
|
});
|
|
} else {
|
|
DQN_ASSERT(compiler == Compiler_EMCC);
|
|
#if defined(DQN_OS_WIN32)
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {
|
|
DQN_STR8("cmd"),
|
|
DQN_STR8("/c"),
|
|
DQN_STR8("emcc.bat"),
|
|
});
|
|
#else
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {
|
|
DQN_STR8("emcc"),
|
|
DQN_STR8("-Os"), // Optimise for size
|
|
});
|
|
#endif
|
|
}
|
|
|
|
Dqn_FArray32<Dqn_Str8> common_link_flags = {};
|
|
Dqn_FArray32<Dqn_Str8> common_compile_flags = common_compile_flags_no_warnings;
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {DQN_STR8("-w")});
|
|
if (compiler == Compiler_MSVC) {
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags, {DQN_STR8("-W4")});
|
|
Dqn_FArray_AddCArrayAssert(&common_link_flags, {
|
|
DQN_STR8("-link"),
|
|
DQN_STR8("-incremental:no"),
|
|
});
|
|
} else {
|
|
Dqn_FArray_AddCArrayAssert(&common_compile_flags, {
|
|
DQN_STR8("-Wall"),
|
|
});
|
|
Dqn_FArray_AddCArrayAssert(&common_link_flags, {
|
|
DQN_STR8("-lm"),
|
|
});
|
|
}
|
|
|
|
// NOTE: Link flags ============================================================================
|
|
// NOTE: Build context =========================================================================
|
|
Dqn_CPPBuildContext common_build_context = {};
|
|
common_build_context.build_dir = build_dir;
|
|
common_build_context.flags_style = compiler == Compiler_MSVC ? Dqn_CPPBuildFlagsStyle_MSVC : Dqn_CPPBuildFlagsStyle_GCC;
|
|
|
|
// NOTE: Build program =========================================================================
|
|
// NOTE: Copy assets ===========================================================================
|
|
if (!assets_copied) {
|
|
RecordScopeTime("Copy assets");
|
|
assets_copied = true;
|
|
|
|
Dqn_FArray32<Dqn_Str8> cmd_array = {};
|
|
#if defined(DQN_OS_WIN32)
|
|
Dqn_FArray_AddCArray(&cmd_array, {
|
|
DQN_STR8("robocopy"),
|
|
DQN_STR8("/MIR"), // Mirror
|
|
DQN_STR8("/NJH"), // No job header
|
|
DQN_STR8("/NJS"), // No job summary
|
|
DQN_STR8("/NDL"),
|
|
DQN_STR8("/NP"), // No progress
|
|
});
|
|
#else
|
|
cmd_array = Dqn_FArray_AddCArray(&cmd_array, {
|
|
DQN_STR8("cp"),
|
|
DQN_STR8("--recursive"),
|
|
DQN_STR8("--force"),
|
|
});
|
|
#endif
|
|
|
|
DQN_MSVC_WARNING_PUSH
|
|
DQN_MSVC_WARNING_DISABLE(6063)
|
|
DQN_MSVC_WARNING_DISABLE(6064)
|
|
// TODO(doyle): The stringify macro in AddCArrayAssert triggers MSVC's code '-analyze'
|
|
// flag because it forwards the '%.*s' into Dqn_Log_TypeFCallSite which takes in a
|
|
// format string.
|
|
//
|
|
// warning C6064: Missing integer argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '1'.
|
|
// warning C6063: Missing string argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '2'.
|
|
// warning C6064: Missing integer argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '3'.
|
|
// warning C6063: Missing string argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '4'.
|
|
|
|
// NOTE: Copy the fonts
|
|
{
|
|
Dqn_FArray32<Dqn_Str8> font_cmd_array = cmd_array;
|
|
Dqn_FArray_AddCArrayAssert(&font_cmd_array, {
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(exe_dir)), // Source
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(build_dir)), // Dest
|
|
});
|
|
|
|
Dqn_Slice<Dqn_Str8> cmd_slice = Dqn_FArray_Slice(&font_cmd_array);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%s'", Dqn_Slice_Str8RenderSpaceSeparated(scratch.arena, cmd_slice).data);
|
|
if (!dry_run)
|
|
Dqn_OS_Exec(cmd_slice, /*working_dir*/ {});
|
|
}
|
|
|
|
// NOTE: Copy the audio
|
|
{
|
|
Dqn_FArray32<Dqn_Str8> audio_cmd_array = cmd_array;
|
|
Dqn_FArray_AddCArrayAssert(&audio_cmd_array, {
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(exe_dir)), // Source
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(build_dir)), // Dest
|
|
});
|
|
|
|
Dqn_Slice<Dqn_Str8> cmd_slice = Dqn_FArray_Slice(&audio_cmd_array);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%s'", Dqn_Slice_Str8RenderSpaceSeparated(scratch.arena, cmd_slice).data);
|
|
if (!dry_run)
|
|
Dqn_OS_Exec(cmd_slice, /*working_dir*/ {});
|
|
}
|
|
|
|
// NOTE: Copy the texture atlas
|
|
{
|
|
Dqn_Str8 atlas_dest_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures", DQN_STR_FMT(build_dir));
|
|
Dqn_Fs_MakeDir(atlas_dest_dir);
|
|
|
|
Dqn_Str8 atlas_txt_src = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.txt", DQN_STR_FMT(exe_dir));
|
|
Dqn_Str8 atlas_txt_dest = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.txt", DQN_STR_FMT(build_dir));
|
|
|
|
Dqn_Str8 atlas_png_src = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.png", DQN_STR_FMT(exe_dir));
|
|
Dqn_Str8 atlas_png_dest = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.png", DQN_STR_FMT(build_dir));
|
|
|
|
if (!Dqn_Fs_Copy(atlas_txt_src, atlas_txt_dest, true /*overwrite*/)) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(atlas_txt_src), DQN_STR_FMT(atlas_txt_dest));
|
|
return -1;
|
|
}
|
|
|
|
if (!Dqn_Fs_Copy(atlas_png_src, atlas_png_dest, true /*overwrite*/)) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(atlas_png_src), DQN_STR_FMT(atlas_png_dest));
|
|
return -1;
|
|
}
|
|
}
|
|
DQN_MSVC_WARNING_POP
|
|
|
|
}
|
|
|
|
// NOTE: Raylib ============================================================================
|
|
Dqn_Str8 raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/raylib", DQN_STR_FMT(tely_dir));
|
|
Dqn_FArray32<Dqn_Str8> raylib_obj_files = {};
|
|
{
|
|
RecordScopeTime("%.*s Raylib ", DQN_STR_FMT(compiler_label));
|
|
|
|
Dqn_FArray32<Dqn_Str8> base_files = Dqn_FArray_InitCArray<Dqn_Str8, 32>({
|
|
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)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rmodels.c", DQN_STR_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtext.c", DQN_STR_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtextures.c", DQN_STR_FMT(raylib_dir)),
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STR_FMT(raylib_dir)),
|
|
});
|
|
if (compiler != Compiler_EMCC) {
|
|
Dqn_FArray_AddCArrayAssert(&base_files, {
|
|
Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STR_FMT(raylib_dir))
|
|
});
|
|
}
|
|
|
|
Dqn_FArray32<Dqn_Str8> compile_flags = common_compile_flags_no_warnings;
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {DQN_STR8("-c")});
|
|
if (compiler == Compiler_EMCC) {
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-Os"),
|
|
DQN_STR8("-D"), DQN_STR8("PLATFORM_WEB"),
|
|
DQN_STR8("-D"), DQN_STR8("GRAPHICS_API_OPENGL_ES2"),
|
|
});
|
|
} else {
|
|
if (compiler == Compiler_GCC) {
|
|
DQN_ASSERT(compile_flags.data[0] == DQN_STR8("g++"));
|
|
compile_flags.data[0] = DQN_STR8("gcc");
|
|
}
|
|
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-D"), DQN_STR8("PLATFORM_DESKTOP"),
|
|
});
|
|
}
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
build_context.compile_flags = Dqn_FArray_Slice(&compile_flags);
|
|
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)),
|
|
});
|
|
|
|
for (Dqn_Str8 base_file : 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, "%.*s_%.*s.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(file_stem), DQN_STR_FMT(obj_file_extension));
|
|
Dqn_FArray_AddAssert(&raylib_obj_files, build_file.output_file_path);
|
|
|
|
build_context.compile_files = Dqn_Slice_Init(&build_file, 1);
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run)
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
}
|
|
|
|
// NOTE: Sokol =============================================================================
|
|
Dqn_Str8 sokol_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol", DQN_STR_FMT(tely_dir));
|
|
Dqn_FArray32<Dqn_Str8> sokol_obj_files = {};
|
|
{
|
|
RecordScopeTime("%.*s Sokol", DQN_STR_FMT(compiler_label));
|
|
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol/sokol_audio.c", DQN_STR_FMT(tely_dir));
|
|
build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s_sokol.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(obj_file_extension));
|
|
|
|
Dqn_FArray32<Dqn_Str8> compile_flags = common_compile_flags_no_warnings;
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-c"),
|
|
});
|
|
if (compiler == Compiler_EMCC)
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {DQN_STR8("-Os")});
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
build_context.compile_flags = Dqn_FArray_Slice(&compile_flags);
|
|
build_context.compile_files = Dqn_Slice_Init(&build_file, 1);
|
|
Dqn_FArray_AddAssert(&sokol_obj_files, build_file.output_file_path);
|
|
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run)
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
|
|
// NOTE: Feely Pona Sprite Packer ==============================================================
|
|
if (compiler == Compiler_MSVC) {
|
|
RecordScopeTime("Sprite Packer");
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.cpp", DQN_STR_FMT(code_dir));
|
|
build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s_feely_pona_sprite_packer.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(obj_file_extension));
|
|
if (compiler == Compiler_MSVC) {
|
|
build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")});
|
|
} else {
|
|
build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xc++")});
|
|
build_file.suffix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xnone")});
|
|
}
|
|
|
|
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;
|
|
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run)
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild);
|
|
}
|
|
|
|
// NOTE: Feely Pona Link Flags =============================================================
|
|
Dqn_FArray32<Dqn_Str8> feely_pona_raylib_backend_link_flags = {};
|
|
{
|
|
Dqn_FArray_AddArrayAssert(&feely_pona_raylib_backend_link_flags, sokol_obj_files.data, sokol_obj_files.size);
|
|
Dqn_FArray_AddArrayAssert(&feely_pona_raylib_backend_link_flags, raylib_obj_files.data, raylib_obj_files.size);
|
|
if (compiler == Compiler_MSVC) {
|
|
Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, {
|
|
DQN_STR8("gdi32.lib"), // raylib
|
|
DQN_STR8("opengl32.lib"), // raylib
|
|
DQN_STR8("winmm.lib"), // raylib
|
|
DQN_STR8("user32.lib"),
|
|
DQN_STR8("shell32.lib"),
|
|
});
|
|
} else if (compiler == Compiler_GCC) {
|
|
Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, {
|
|
DQN_STR8("-lpthread"),
|
|
});
|
|
|
|
#if defined(DQN_OS_UNIX)
|
|
Dqn_FArray_AddCArrayAssert(&csight_raylib_backend_link_flags, {
|
|
DQN_STR8("-ldl"),
|
|
DQN_STR8("-lasound"),
|
|
});
|
|
#else
|
|
Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, {
|
|
DQN_STR8("-lgdi32"), // raylib
|
|
DQN_STR8("-lopengl32"), // raylib
|
|
DQN_STR8("-lwinmm"), // raylib
|
|
DQN_STR8("-lole32"), // sokol audio
|
|
DQN_STR8("-lbcrypt"), // dqn
|
|
DQN_STR8("-lwininet"), // dqn
|
|
DQN_STR8("-ldbghelp"), // dqn
|
|
});
|
|
#endif
|
|
}
|
|
}
|
|
|
|
Dqn_FArray32<Dqn_Str8> feely_pona_backend_include_dirs = Dqn_FArray_InitCArray<Dqn_Str8, 32>({
|
|
sokol_dir,
|
|
raylib_dir,
|
|
});
|
|
|
|
// NOTE: Feely Pona No DLL =================================================================
|
|
if (!fast_dev_build || compiler == Compiler_EMCC) {
|
|
RecordScopeTime("%.*s Feely Pona", DQN_STR_FMT(compiler_label));
|
|
|
|
Dqn_CPPBuildCompileFile build_file = {};
|
|
build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.cpp", DQN_STR_FMT(code_dir));
|
|
if (compiler == Compiler_EMCC)
|
|
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "Terry_Cherry.html");
|
|
else
|
|
build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s_terry_cherry", DQN_STR_FMT(compiler_label));
|
|
|
|
Dqn_FArray32<Dqn_Str8> compile_flags = common_compile_flags;
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"),
|
|
DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"),
|
|
});
|
|
|
|
if (compiler == Compiler_EMCC) {
|
|
// NOTE: Write Feely Pona version into Emscripten HTML Shell
|
|
Dqn_Str8 html_shell_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(build_dir));
|
|
{
|
|
Dqn_Str8 html_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(code_dir));
|
|
Dqn_Str8 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_STR_FMT(html_path)))
|
|
return -1;
|
|
|
|
Dqn_Str8 version_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_version.txt", DQN_STR_FMT(code_dir));
|
|
Dqn_Str8 version_buffer = Dqn_Fs_Read(version_path, scratch.allocator);
|
|
Dqn_Str8SplitAllocResult version_parts = Dqn_Str8_SplitAlloc(scratch.allocator, version_buffer, DQN_STR8("\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_STR_FMT(version_path),
|
|
DQN_STR_FMT(version_buffer))) {
|
|
return -1;
|
|
}
|
|
|
|
Dqn_Str8 date = Dqn_Str8_TrimWhitespaceAround(version_parts.data[0]);
|
|
Dqn_Str8 commit_hash = Dqn_Str8_TrimWhitespaceAround(version_parts.data[1]);
|
|
Dqn_Str8 commit_count = Dqn_Str8_TrimWhitespaceAround(version_parts.data[2]);
|
|
Dqn_Str8 version_text = Dqn_Str8_InitF(scratch.allocator,
|
|
"%.*s edition rev. %.*s-%.*s",
|
|
DQN_STR_FMT(date),
|
|
DQN_STR_FMT(commit_count),
|
|
DQN_STR_FMT(commit_hash));
|
|
|
|
Dqn_Str8 html_buffer_processed = Dqn_Str8_Replace(html_buffer,
|
|
DQN_STR8("@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_STR_FMT(html_shell_path)))
|
|
return -1;
|
|
}
|
|
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-Wall"),
|
|
DQN_STR8("-s"), DQN_STR8("USE_GLFW=3"),
|
|
DQN_STR8("-s"), DQN_STR8("TOTAL_MEMORY=512MB"),
|
|
DQN_STR8("-s"), DQN_STR8("TOTAL_STACK=32MB"),
|
|
DQN_STR8("-s"), DQN_STR8("ALLOW_MEMORY_GROWTH"),
|
|
DQN_STR8("--shell-file"), html_shell_path,
|
|
DQN_STR8("--preload-file"), DQN_STR8("Data"),
|
|
DQN_STR8("-msimd128"),
|
|
DQN_STR8("-msse2"),
|
|
});
|
|
|
|
bool debug_build = false;
|
|
if (debug_build) {
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
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
|
|
});
|
|
} else {
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-Os"),
|
|
});
|
|
}
|
|
}
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
build_context.compile_files = Dqn_Slice_Init(&build_file, 1);
|
|
build_context.include_dirs = Dqn_FArray_Slice(&feely_pona_backend_include_dirs);
|
|
build_context.compile_flags = Dqn_FArray_Slice(&compile_flags);
|
|
build_context.link_flags = Dqn_FArray_Slice(&feely_pona_raylib_backend_link_flags);
|
|
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run)
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild);
|
|
|
|
// NOTE: Copy generated files for web target to directory
|
|
if (compiler == Compiler_EMCC) {
|
|
Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry", DQN_STR_FMT(build_dir));
|
|
if (!Dqn_Fs_DirExists(folder_path)) {
|
|
if (!Dqn_Fs_MakeDir(folder_path)) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Failed to make directory '%.*s'", DQN_STR_FMT(folder_path));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
Dqn_Str8 const generated_file_extension[] = {
|
|
DQN_STR8("data"),
|
|
DQN_STR8("html"),
|
|
DQN_STR8("js"),
|
|
DQN_STR8("wasm"),
|
|
};
|
|
|
|
for (Dqn_Str8 file_ext : generated_file_extension) {
|
|
Dqn_Str8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry.%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(file_ext));
|
|
Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(file_ext));
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Moving '%.*s' to '%.*s'\n", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path));
|
|
if (!dry_run && !Dqn_Fs_Move(src_path, dest_path, true /*overwrite*/)) {
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path));
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// NOTE: Feely Pona Dev DLL ================================================================
|
|
if (compiler == Compiler_MSVC) {
|
|
RecordScopeTime("%.*s Feely Pona Dev DLL", DQN_STR_FMT(compiler_label));
|
|
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", DQN_STR_FMT(compiler_label));
|
|
build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")});
|
|
|
|
Dqn_FArray32<Dqn_Str8> 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 (!fast_dev_build)
|
|
Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-analyze"));
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
build_context.compile_files = Dqn_Slice_Init(&build_file, 1);
|
|
build_context.compile_flags = Dqn_FArray_Slice(&compile_flags);
|
|
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run)
|
|
Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild);
|
|
}
|
|
|
|
// NOTE: Feely Pona Dev ====================================================================
|
|
if (compiler == Compiler_MSVC) {
|
|
RecordScopeTime("%.*s Feely Pona Dev", DQN_STR_FMT(compiler_label));
|
|
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, "%.*s_terry_cherry_dev", DQN_STR_FMT(compiler_label));
|
|
build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")});
|
|
|
|
Dqn_FArray32<Dqn_Str8> compile_flags = common_compile_flags;
|
|
Dqn_FArray_AddCArrayAssert(&compile_flags, {
|
|
DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"),
|
|
DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM_DLL"),
|
|
});
|
|
|
|
Dqn_CPPBuildContext build_context = common_build_context;
|
|
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_raylib_backend_link_flags);
|
|
build_context.include_dirs = Dqn_FArray_Slice(&feely_pona_backend_include_dirs);
|
|
|
|
Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena);
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd));
|
|
if (!dry_run) {
|
|
Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s_feely_pona_dev.exe", DQN_STR_FMT(build_dir), DQN_STR_FMT(compiler_label));
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
global_build_timings->timestamps[1] = Dqn_OS_PerfCounterNow();
|
|
|
|
Dqn_usize longest_name = 0;
|
|
for (BuildTime build_time : build_timings)
|
|
longest_name = DQN_MAX(longest_name, build_time.name.size + 1);
|
|
|
|
for (Dqn_usize build_index = 0; build_index < build_timings.size; build_index++) {
|
|
BuildTime build_time = build_timings.data[build_index];
|
|
Dqn_Print_StdF(Dqn_PrintStd_Out, "%.*s:", DQN_STR_FMT(build_time.name));
|
|
if (build_time.name.size < longest_name)
|
|
Dqn_Print_StdF(Dqn_PrintStd_Out, "%*s", DQN_CAST(int)(longest_name - build_time.name.size), "");
|
|
Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.2fms", Dqn_OS_PerfCounterMs(build_time.timestamps[0], build_time.timestamps[1]));
|
|
}
|
|
return 0;
|
|
}
|