2023-10-10 12:00:35 +00:00
// #include <Windows.h>
2023-10-11 13:04:01 +00:00
# include <stdlib.h>
2023-10-10 12:00:35 +00:00
# define DQN_IMPLEMENTATION
# include "External/tely/External/dqn/dqn.h"
2023-10-12 11:20:29 +00:00
# define DQN_CPP_BUILD_IMPLEMENTATION
# include "External/tely/External/dqn/dqn_cppbuild.h"
2023-10-10 12:00:35 +00:00
2023-10-12 11:20:29 +00:00
#if 0
void RebuildProgramIfRequired ( int argc , char const * * argv )
2023-10-11 13:04:01 +00:00
{
2023-10-12 11:20:29 +00:00
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 ;
2023-10-10 12:00:35 +00:00
}
2023-10-12 11:20:29 +00:00
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 ;
2023-10-10 12:00:35 +00:00
}
2023-10-12 11:20:29 +00:00
// 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 ;
2023-10-10 12:00:35 +00:00
}
2023-10-12 11:20:29 +00:00
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 ) ;
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
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 ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
// 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 ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
if ( rebuild_result . exit_code ) {
Dqn_Fs_Move ( temp_build_program_path , build_program_path , true ) ;
exit ( rebuild_result . exit_code ) ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
Dqn_String8Builder builder = { } ;
builder . allocator = scratch . allocator ;
DQN_FOR_UINDEX ( arg_index , argc )
Dqn_String8Builder_AppendF ( & builder , " %s%s " , arg_index ? " " : " " , argv [ arg_index ] ) ;
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
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 ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
exit ( exec_result . exit_code ) ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
# endif
2023-10-11 13:04:01 +00:00
2023-10-15 08:04:58 +00:00
# define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web]")
2023-10-12 11:20:29 +00:00
int main ( int argc , char const * * argv )
2023-10-11 13:04:01 +00:00
{
2023-10-12 11:20:29 +00:00
Dqn_Library_Init ( Dqn_LibraryOnInit_Nil ) ;
2023-10-11 13:04:01 +00:00
2023-10-15 08:04:58 +00:00
bool dry_run = false ;
bool target_web = false ;
for ( Dqn_usize arg_index = 1 ; arg_index < argc ; arg_index + + ) {
2023-10-16 06:32:32 +00:00
Dqn_String8 arg = Dqn_String8_InitCString8 ( argv [ arg_index ] ) ;
2023-10-12 11:20:29 +00:00
if ( arg = = DQN_STRING8 ( " --help " ) ) {
PRINT_HELP ;
return 0 ;
2023-10-15 08:04:58 +00:00
} else if ( arg = = DQN_STRING8 ( " --dry-run " ) ) {
2023-10-12 11:20:29 +00:00
dry_run = true ;
2023-10-15 08:04:58 +00:00
} else if ( arg = = DQN_STRING8 ( " --web " ) ) {
target_web = true ;
2023-10-12 11:20:29 +00:00
} else {
PRINT_HELP ;
return 0 ;
}
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
#if 0
RebuildProgramIfRequired ( argc , argv ) ;
# else
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " -- Dqn_CPPBuild v0 " ) ;
# endif
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
uint64_t build_timings [ 2 ] = { } ;
build_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
2023-10-11 13:04:01 +00:00
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch ( nullptr ) ;
Dqn_String8 const exe_dir = Dqn_OS_EXEDir ( scratch . arena ) ;
2023-10-14 06:21:23 +00:00
Dqn_String8 const code_dir = exe_dir ;
2023-10-11 13:04:01 +00:00
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 ( ) ; } ;
2023-10-15 12:08:47 +00:00
Dqn_String8 robocopy_cmd [ ] = {
2023-10-16 04:02:18 +00:00
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 ) ) ,
2023-10-15 12:08:47 +00:00
} ;
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*/ { } ) ;
2023-10-12 11:20:29 +00:00
}
2023-10-11 13:04:01 +00:00
}
// NOTE: Raylib ================================================================================
2023-10-15 08:04:58 +00:00
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 , {
2023-10-14 06:21:23 +00:00
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 ) ) ,
} ) ;
2023-10-15 08:04:58 +00:00
Dqn_List < Dqn_String8 > raylib_pc_output_files = Dqn_List_Init < Dqn_String8 > ( scratch . arena , 16 ) ;
uint64_t raylib_pc_timings [ 2 ] = { } ;
2023-10-11 13:04:01 +00:00
{
2023-10-15 08:04:58 +00:00
raylib_pc_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { raylib_pc_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
2023-10-11 13:04:01 +00:00
2023-10-15 08:04:58 +00:00
// 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 ) ) ,
} ) ;
2023-10-11 13:04:01 +00:00
2023-10-15 08:04:58 +00:00
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 ;
}
2023-10-11 13:04:01 +00:00
2023-10-15 08:04:58 +00:00
// 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 ) ;
}
2023-10-12 11:20:29 +00:00
}
2023-10-11 13:04:01 +00:00
}
2023-10-16 13:35:41 +00:00
// 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 ) ;
}
}
2023-10-11 13:04:01 +00:00
// NOTE: Feely Pona Sprite Packer ==============================================================
uint64_t feely_pona_sprite_packer_timings [ 2 ] = { } ;
{
2023-10-15 08:04:58 +00:00
feely_pona_sprite_packer_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
2023-10-11 13:04:01 +00:00
DQN_DEFER { feely_pona_sprite_packer_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
Dqn_CPPBuildContext build_context = { } ;
2023-10-15 08:04:58 +00:00
build_context . compiler = Dqn_CPPBuildCompiler_MSVC ;
2023-10-11 13:04:01 +00:00
build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
2023-10-16 13:35:41 +00:00
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/feely_pona_sprite_packer.cpp " , DQN_STRING_FMT ( code_dir ) ) } ,
2023-10-11 13:04:01 +00:00
} ) ;
build_context . compile_flags = common_compile_flags ;
build_context . link_flags = common_link_flags ;
build_context . build_dir = build_dir ;
2023-10-16 13:35:41 +00:00
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 ) ;
}
2023-10-11 13:04:01 +00:00
}
// NOTE: Feely Pona No DLL =====================================================================
uint64_t feely_pona_no_dll_timings [ 2 ] = { } ;
Dqn_CPPBuildContext feely_pona_no_dll_build_context = { } ;
{
2023-10-15 08:04:58 +00:00
feely_pona_no_dll_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
2023-10-11 13:04:01 +00:00
DQN_DEFER { feely_pona_no_dll_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
2023-10-15 08:04:58 +00:00
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 } ) ;
2023-10-11 13:04:01 +00:00
feely_pona_no_dll_build_context . compile_flags = common_compile_flags ;
2023-10-15 08:04:58 +00:00
feely_pona_no_dll_build_context . build_dir = build_dir ;
2023-10-11 13:04:01 +00:00
// NOTE: Link to raylib object files and windows libs ======================================
Dqn_List < Dqn_String8 > link_flags = Dqn_List_InitSliceCopy ( scratch . arena , 128 , common_link_flags ) ;
{
2023-10-15 08:04:58 +00:00
for ( Dqn_ListIterator < Dqn_String8 > it = { } ; Dqn_List_Iterate ( & raylib_pc_output_files , & it , 0 ) ; )
Dqn_List_Add ( & link_flags , * it . data ) ;
2023-10-11 13:04:01 +00:00
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 ) ;
2023-10-12 11:20:29 +00:00
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 ) ;
}
2023-10-11 13:04:01 +00:00
}
// 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 ( ) ; } ;
2023-10-15 08:04:58 +00:00
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 " ) } ) ;
2023-10-11 13:04:01 +00:00
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 " ) ) ;
2023-10-15 08:04:58 +00:00
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 ;
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
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 ) ;
}
2023-10-11 13:04:01 +00:00
}
// NOTE: Feely Pona platform ===================================================================
uint64_t feely_pona_platform_timings [ 2 ] = { } ;
{
2023-10-15 08:04:58 +00:00
feely_pona_platform_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
2023-10-11 13:04:01 +00:00
DQN_DEFER { feely_pona_platform_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
2023-10-15 08:04:58 +00:00
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 " ) } ) ;
2023-10-11 13:04:01 +00:00
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 " ) ) ;
2023-10-15 08:04:58 +00:00
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 } ) ;
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
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 {
2023-10-14 00:40:07 +00:00
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 ;
2023-10-14 01:20:04 +00:00
Dqn_Fs_CloseFile ( & exe_file ) ;
2023-10-14 00:40:07 +00:00
}
if ( ! exe_is_locked ) {
Dqn_CPPBuild_ExecOrAbort ( build_context , Dqn_CPPBuildMode_AlwaysRebuild ) ;
}
2023-10-12 11:20:29 +00:00
}
2023-10-11 13:04:01 +00:00
}
2023-10-14 06:21:23 +00:00
// NOTE: raylib emscripten =====================================================================
2023-10-15 08:04:58 +00:00
uint64_t raylib_emscripten_timings [ 2 ] = { } ;
uint64_t feely_pona_emscripten_timings [ 2 ] = { } ;
2023-10-14 14:31:33 +00:00
if ( target_web ) {
2023-10-15 08:04:58 +00:00
Dqn_String8 const raylib_emscripten_lib_name = DQN_STRING8 ( " raylib_emscripten.a " ) ;
2023-10-17 01:29:57 +00:00
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
} ) ;
}
2023-10-14 06:21:23 +00:00
2023-10-15 08:04:58 +00:00
// NOTE: Compile each raylib file separately with emcc =====================================
2023-10-14 06:21:23 +00:00
{
2023-10-15 08:04:58 +00:00
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 ) ) ;
2023-10-17 01:29:57 +00:00
Dqn_List < Dqn_String8 > compile_flags = Dqn_List_InitCArrayCopy ( scratch . arena , 32 , {
2023-10-15 08:04:58 +00:00
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 " ) ,
} ) ;
2023-10-17 01:29:57 +00:00
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 ) ;
2023-10-15 08:04:58 +00:00
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 ) ;
}
}
2023-10-14 06:21:23 +00:00
2023-10-15 08:04:58 +00:00
// 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 ) ;
}
2023-10-14 06:21:23 +00:00
}
}
2023-10-17 11:07:20 +00:00
// NOTE: feely pona emscripten =============================================================
2023-10-14 06:21:23 +00:00
{
2023-10-15 08:04:58 +00:00
feely_pona_emscripten_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { feely_pona_emscripten_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
2023-10-17 11:07:20 +00:00
// 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 \n does 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 ;
}
2023-10-15 08:04:58 +00:00
// 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 ) ) } ,
} ) ;
2023-10-17 01:29:57 +00:00
Dqn_String8 output_name = DQN_STRING8 ( " Terry_Cherry " ) ;
Dqn_List < Dqn_String8 > compile_flags = Dqn_List_InitCArrayCopy ( scratch . arena , 32 , {
2023-10-15 08:04:58 +00:00
DQN_STRING8 ( " cmd " ) , DQN_STRING8 ( " /C " ) , DQN_STRING8 ( " emcc.bat " ) ,
2023-10-17 01:29:57 +00:00
DQN_STRING8 ( " -o " ) , Dqn_String8_InitF ( scratch . allocator , " %.*s.html " , DQN_STRING_FMT ( output_name ) ) ,
2023-10-15 08:04:58 +00:00
DQN_STRING8 ( " -Wall " ) ,
2023-10-17 11:07:20 +00:00
DQN_STRING8 ( " --shell-file " ) , html_shell_path ,
2023-10-15 08:04:58 +00:00
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 " ) ,
} ) ;
2023-10-17 01:29:57 +00:00
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 ;
2023-10-14 06:21:23 +00:00
if ( dry_run ) {
2023-10-15 08:04:58 +00:00
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine ( build_context , Dqn_CPPBuildMode_AlwaysRebuild , scratch . allocator ) ;
2023-10-14 06:21:23 +00:00
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " %.*s \n " , DQN_STRING_FMT ( cmd ) ) ;
} else {
2023-10-15 08:04:58 +00:00
Dqn_CPPBuild_ExecOrAbort ( build_context , Dqn_CPPBuildMode_CacheBuild ) ;
2023-10-14 06:21:23 +00:00
}
2023-10-16 06:32:32 +00:00
// NOTE: Move the files to a directory
2023-10-17 01:29:57 +00:00
Dqn_String8 folder_path = Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/%.*s_Emscripten " , DQN_STRING_FMT ( build_dir ) , DQN_STRING_FMT ( output_name ) ) ;
2023-10-16 06:32:32 +00:00
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 ) {
2023-10-17 01:29:57 +00:00
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 ) ) ;
2023-10-16 06:32:32 +00:00
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 ) ;
}
}
2023-10-14 06:21:23 +00:00
}
}
2023-10-12 11:20:29 +00:00
build_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ;
2023-10-14 06:21:23 +00:00
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " \n -- Dqn_CPPBuild Timings (%.2fms) " , Dqn_OS_PerfCounterMs ( build_timings [ 0 ] , build_timings [ 1 ] ) ) ;
2023-10-14 00:40:07 +00:00
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " robocopy: %.2fms " , Dqn_OS_PerfCounterMs ( robocopy_timings [ 0 ] , robocopy_timings [ 1 ] ) ) ;
2023-10-15 08:04:58 +00:00
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " raylib: %.2fms " , Dqn_OS_PerfCounterMs ( raylib_pc_timings [ 0 ] , raylib_pc_timings [ 1 ] ) ) ;
2023-10-16 13:35:41 +00:00
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " qoi_converter: %.2fms " , Dqn_OS_PerfCounterMs ( qoi_converter_timings [ 0 ] , qoi_converter_timings [ 1 ] ) ) ;
2023-10-14 00:40:07 +00:00
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 ] ) ) ;
2023-10-15 08:04:58 +00:00
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 ] ) ) ;
}
2023-10-10 12:00:35 +00:00
return 0 ;
}