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-12 11:20:29 +00:00
# define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run]")
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 ) ;
if ( argc > 2 ) {
PRINT_HELP ;
return - 1 ;
2023-10-11 13:04:01 +00:00
}
2023-10-12 11:20:29 +00:00
bool dry_run = false ;
if ( argc = = 2 ) {
Dqn_String8 arg = Dqn_String8_InitCString8 ( argv [ 1 ] ) ;
if ( arg = = DQN_STRING8 ( " --help " ) ) {
PRINT_HELP ;
return 0 ;
}
2023-10-11 13:04:01 +00:00
2023-10-12 11:20:29 +00:00
if ( arg = = DQN_STRING8 ( " --dry-run " ) ) {
dry_run = true ;
} 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 ) ;
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 /MIR /NJH /NJS /NDL /NP %.*s \\ Data %.*s \\ Data " , DQN_STRING_FMT ( exe_dir ) , DQN_STRING_FMT ( build_dir ) ) ;
2023-10-12 11:20:29 +00:00
if ( dry_run ) {
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " %.*s \n " , DQN_STRING_FMT ( robocopy_cmd ) ) ;
} else {
Dqn_OS_Exec ( robocopy_cmd , /*working_dir*/ { } ) ;
}
2023-10-11 13:04:01 +00:00
}
// NOTE: Raylib ================================================================================
Dqn_CPPBuildContext raylib_build_context = { } ;
Dqn_String8 const raylib_dir = Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/External/tely/external/raylib " , DQN_STRING_FMT ( exe_dir ) ) ;
uint64_t raylib_timings [ 2 ] = { } ;
{
raylib_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { raylib_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
raylib_build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rcore.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/utils.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/raudio.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rmodels.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rtext.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rtextures.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rshapes.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/rglfw.c " , DQN_STRING_FMT ( raylib_dir ) ) } ,
} ) ;
raylib_build_context . include_dirs = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s " , DQN_STRING_FMT ( raylib_dir ) ) ,
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/external/glfw/include " , DQN_STRING_FMT ( raylib_dir ) ) ,
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/glfw/deps/mingw " , DQN_STRING_FMT ( raylib_dir ) ) ,
} ) ;
raylib_build_context . compile_flags = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
DQN_STRING8 ( " cl " ) ,
DQN_STRING8 ( " /w " ) ,
DQN_STRING8 ( " /c " ) ,
DQN_STRING8 ( " /D _DEFAULT_SOURCE " ) ,
DQN_STRING8 ( " /D PLATFORM_DESKTOP " ) ,
DQN_STRING8 ( " /W4 " ) ,
DQN_STRING8 ( " /Z7 " ) ,
DQN_STRING8 ( " /MT " ) ,
DQN_STRING8 ( " /EHsc " ) ,
DQN_STRING8 ( " /nologo " ) ,
} ) ;
raylib_build_context . link_flags = common_link_flags ;
raylib_build_context . build_dir = build_dir ;
2023-10-12 11:20:29 +00:00
if ( dry_run ) {
Dqn_String8 cmd = Dqn_CPPBuild_ToCommandLine ( raylib_build_context , Dqn_CPPBuildMode_AlwaysRebuild , scratch . allocator ) ;
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " %.*s \n " , DQN_STRING_FMT ( cmd ) ) ;
} else {
Dqn_CPPBuild_ExecOrAbort ( raylib_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 ] = { } ;
{
feely_pona_sprite_packer_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { feely_pona_sprite_packer_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
Dqn_String8 code_dir = exe_dir ;
Dqn_CPPBuildContext build_context = { } ;
build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_CPPBuildCompileFile { { } , Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/feely_pona_sprite_packer.h " , DQN_STRING_FMT ( code_dir ) ) } ,
} ) ;
build_context . compile_flags = common_compile_flags ;
build_context . link_flags = common_link_flags ;
build_context . build_dir = build_dir ;
2023-10-12 11:20:29 +00:00
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 = { } ;
{
feely_pona_no_dll_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { feely_pona_no_dll_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
Dqn_String8 code_dir = exe_dir ;
feely_pona_no_dll_build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_CPPBuildCompileFile {
{ Dqn_Slice_InitCArrayCopy ( scratch . arena , { DQN_STRING8 ( " /Tp " ) } ) } ,
2023-10-12 11:20:29 +00:00
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/feely_pona_unity_nodll.h " , DQN_STRING_FMT ( code_dir ) )
2023-10-11 13:04:01 +00:00
} ,
} ) ;
feely_pona_no_dll_build_context . include_dirs = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s " , DQN_STRING_FMT ( raylib_dir ) ) ,
} ) ;
feely_pona_no_dll_build_context . compile_flags = common_compile_flags ;
// NOTE: Link to raylib object files and windows libs ======================================
Dqn_List < Dqn_String8 > link_flags = Dqn_List_InitSliceCopy ( scratch . arena , 128 , common_link_flags ) ;
{
for ( Dqn_CPPBuildCompileFile file : raylib_build_context . compile_files ) {
Dqn_String8 file_stem = Dqn_String8_FileNameNoExtension ( file . path ) ;
Dqn_String8 obj_file = Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/%.*s.obj " , DQN_STRING_FMT ( raylib_build_context . build_dir ) , DQN_STRING_FMT ( file_stem ) ) ;
Dqn_List_Add ( & link_flags , obj_file ) ;
}
Dqn_List_Add ( & link_flags , DQN_STRING8 ( " gdi32.lib " ) ) ;
Dqn_List_Add ( & link_flags , DQN_STRING8 ( " opengl32.lib " ) ) ;
Dqn_List_Add ( & link_flags , DQN_STRING8 ( " winmm.lib " ) ) ;
Dqn_List_Add ( & link_flags , DQN_STRING8 ( " user32.lib " ) ) ;
Dqn_List_Add ( & link_flags , DQN_STRING8 ( " shell32.lib " ) ) ;
}
feely_pona_no_dll_build_context . link_flags = Dqn_List_ToSliceCopy ( & link_flags , scratch . arena ) ;
feely_pona_no_dll_build_context . build_dir = build_dir ;
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 ( ) ; } ;
Dqn_String8 code_dir = exe_dir ;
Dqn_CPPBuildContext build_context = { } ;
build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_CPPBuildCompileFile {
{ Dqn_Slice_InitCArrayCopy ( scratch . arena , { DQN_STRING8 ( " /Tp " ) } ) } ,
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/feely_pona_unity.h " , DQN_STRING_FMT ( code_dir ) )
} ,
} ) ;
Dqn_List < 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 ( " /Fotely_dll_msvc " ) ) ;
Dqn_List_Add ( & compile_flags , DQN_STRING8 ( " /Fetely_dll_msvc " ) ) ;
build_context . compile_flags = Dqn_List_ToSliceCopy ( & compile_flags , scratch . arena ) ;
build_context . link_flags = feely_pona_no_dll_build_context . link_flags ;
build_context . build_dir = build_dir ;
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 ] = { } ;
{
feely_pona_platform_timings [ 0 ] = Dqn_OS_PerfCounterNow ( ) ;
DQN_DEFER { feely_pona_platform_timings [ 1 ] = Dqn_OS_PerfCounterNow ( ) ; } ;
Dqn_String8 code_dir = exe_dir ;
Dqn_CPPBuildContext build_context = { } ;
build_context . compile_files = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
Dqn_CPPBuildCompileFile {
{ Dqn_Slice_InitCArrayCopy ( scratch . arena , { DQN_STRING8 ( " /Tp " ) } ) } ,
Dqn_FsPath_ConvertF ( scratch . arena , " %.*s/tely_platform_raylib_unity.h " , DQN_STRING_FMT ( tely_dir ) )
} ,
} ) ;
build_context . include_dirs = Dqn_Slice_InitCArrayCopy ( scratch . arena , {
raylib_dir ,
} ) ;
Dqn_List < Dqn_String8 > compile_flags = Dqn_List_InitSliceCopy ( scratch . arena , 128 , common_compile_flags ) ;
Dqn_List_Add ( & compile_flags , DQN_STRING8 ( " /Fofeely_pona_msvc " ) ) ;
Dqn_List_Add ( & compile_flags , DQN_STRING8 ( " /Fefeely_pona_msvc " ) ) ;
build_context . compile_flags = Dqn_List_ToSliceCopy ( & compile_flags , scratch . arena ) ;
build_context . link_flags = feely_pona_no_dll_build_context . link_flags ;
build_context . build_dir = build_dir ;
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
}
2023-10-12 11:20:29 +00:00
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_timings [ 0 ] , raylib_timings [ 1 ] ) ) ;
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " feely pona sprite packer: %.2fms " , Dqn_OS_PerfCounterMs ( feely_pona_sprite_packer_timings [ 0 ] , feely_pona_sprite_packer_timings [ 1 ] ) ) ;
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " feely pona (no dll): %.2fms " , Dqn_OS_PerfCounterMs ( feely_pona_no_dll_timings [ 0 ] , feely_pona_no_dll_timings [ 1 ] ) ) ;
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " feely pona (dll): %.2fms " , Dqn_OS_PerfCounterMs ( feely_pona_dll_timings [ 0 ] , feely_pona_dll_timings [ 1 ] ) ) ;
Dqn_Print_StdLnF ( Dqn_PrintStd_Out , " feely pona (platform): %.2fms " , Dqn_OS_PerfCounterMs ( feely_pona_platform_timings [ 0 ] , feely_pona_platform_timings [ 1 ] ) ) ;
2023-10-10 12:00:35 +00:00
return 0 ;
}