From 0376a22775728b3ed589f3814dd20a985c2269f6 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 8 Sep 2023 15:14:09 -0400 Subject: [PATCH] Setup proper project skeleton with 2 stage build --- README.md | 12 +- project/dependencies/gen.hpp | 336 +++++++++++++++++------------------ project/gen/gen_handmade.cpp | 17 ++ project/handmade_win32.cpp | 8 + project/sanity.cpp | 7 - scripts/build.ps1 | 34 +++- 6 files changed, 234 insertions(+), 180 deletions(-) create mode 100644 project/gen/gen_handmade.cpp create mode 100644 project/handmade_win32.cpp delete mode 100644 project/sanity.cpp diff --git a/README.md b/README.md index 62cc1a5..b0991af 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,20 @@ Any code I do for this series will be here. -Building requires msvc or llvm's clang + lld, and powershell 7 + ## Scripts * `build.ps1` - Builds the project use `.\scripts\build msvc` or `.\scripts\build clang`, add `release` to build in release mode * `clean.ps1` - Cleans the project * `update.ps1` - Updates the project dependencies to their latest from their respective repos. (Not done automatically on build) + +## Notes + +Building requires msvc or llvm's clang + lld, and powershell 7 + +The build is done in two stages: + +1. Build and run metaprogram to scan and generate dependent code. +2. Build the handmade hero runtime. + diff --git a/project/dependencies/gen.hpp b/project/dependencies/gen.hpp index b470a90..f62b12c 100644 --- a/project/dependencies/gen.hpp +++ b/project/dependencies/gen.hpp @@ -8657,174 +8657,6 @@ struct Builder }; #pragma endregion Builder - -#pragma region Scanner - -// This is a simple file reader that reads the entire file into memory. -// It has an extra option to skip the first few lines for undesired includes. -// This is done so that includes can be kept in dependency and component files so that intellisense works. -Code scan_file( char const* path ) -{ - FileInfo file; - - FileError error = file_open_mode( &file, EFileMode_READ, path ); - if ( error != EFileError_NONE ) - { - GEN_FATAL( "scan_file: Could not open: %s", path ); - } - - sw fsize = file_size( &file ); - if ( fsize <= 0 ) - { - GEN_FATAL( "scan_file: %s is empty", path ); - } - - String str = String::make_reserve( GlobalAllocator, fsize ); - file_read( &file, str, fsize ); - str.get_header().Length = fsize; - - // Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks - // Its designed so that the directive should be the first thing in the file. - // Anything that comes before it will also be omitted. - { -#define current ( *scanner ) -#define matched 0 -#define move_fwd() \ - do \ - { \ - ++scanner; \ - --left; \ - } while ( 0 ) - const StrC directive_start = txt( "ifdef" ); - const StrC directive_end = txt( "endif" ); - const StrC def_intellisense = txt( "GEN_INTELLISENSE_DIRECTIVES" ); - - bool found_directive = false; - char const* scanner = str.Data; - s32 left = fsize; - while ( left ) - { - // Processing directive. - if ( current == '#' ) - { - move_fwd(); - while ( left && char_is_space( current ) ) - move_fwd(); - - if ( ! found_directive ) - { - if ( left && str_compare( scanner, directive_start.Ptr, directive_start.Len ) == matched ) - { - scanner += directive_start.Len; - left -= directive_start.Len; - - while ( left && char_is_space( current ) ) - move_fwd(); - - if ( left && str_compare( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) - { - scanner += def_intellisense.Len; - left -= def_intellisense.Len; - - found_directive = true; - } - } - - // Skip to end of line - while ( left && current != '\r' && current != '\n' ) - move_fwd(); - move_fwd(); - - if ( left && current == '\n' ) - move_fwd(); - - continue; - } - - if ( left && str_compare( scanner, directive_end.Ptr, directive_end.Len ) == matched ) - { - scanner += directive_end.Len; - left -= directive_end.Len; - - // Skip to end of line - while ( left && current != '\r' && current != '\n' ) - move_fwd(); - move_fwd(); - - if ( left && current == '\n' ) - move_fwd(); - - // sptr skip_size = fsize - left; - if ( ( scanner + 2 ) >= ( str.Data + fsize ) ) - { - mem_move( str, scanner, left ); - str.get_header().Length = left; - break; - } - - mem_move( str, scanner, left ); - str.get_header().Length = left; - - break; - } - } - - move_fwd(); - } -#undef move_fwd -#undef matched -#undef current - } - - file_close( &file ); - return untyped_str( str ); -} - -#if 0 -struct Policy -{ - // Nothing for now. -}; - -struct SymbolInfo -{ - StringCached File; - char const* Marker; - Code Signature; -}; - -struct Scanner -{ - struct RequestEntry - { - SymbolInfo Info; - }; - - struct Receipt - { - StringCached File; - Code Defintion; - bool Result; - }; - - AllocatorInfo MemAlloc; - - static void set_allocator( AllocatorInfo allocator ); - - Array Files; - String Buffer; - Array Requests; - - void add_files( s32 num, char const** files ); - - void add( SymbolInfo signature, Policy policy ); - - bool process_requests( Array out_receipts ); -}; -#endif - -#pragma endregion Scanner - GEN_NS_END #pragma region GENCPP IMPLEMENTATION GUARD @@ -23089,6 +22921,174 @@ void Builder::write() #pragma endregion Builder + +#pragma region Scanner + +// This is a simple file reader that reads the entire file into memory. +// It has an extra option to skip the first few lines for undesired includes. +// This is done so that includes can be kept in dependency and component files so that intellisense works. +Code scan_file( char const* path ) +{ + FileInfo file; + + FileError error = file_open_mode( &file, EFileMode_READ, path ); + if ( error != EFileError_NONE ) + { + GEN_FATAL( "scan_file: Could not open: %s", path ); + } + + sw fsize = file_size( &file ); + if ( fsize <= 0 ) + { + GEN_FATAL( "scan_file: %s is empty", path ); + } + + String str = String::make_reserve( GlobalAllocator, fsize ); + file_read( &file, str, fsize ); + str.get_header().Length = fsize; + + // Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks + // Its designed so that the directive should be the first thing in the file. + // Anything that comes before it will also be omitted. + { +#define current ( *scanner ) +#define matched 0 +#define move_fwd() \ + do \ + { \ + ++scanner; \ + --left; \ + } while ( 0 ) + const StrC directive_start = txt( "ifdef" ); + const StrC directive_end = txt( "endif" ); + const StrC def_intellisense = txt( "GEN_INTELLISENSE_DIRECTIVES" ); + + bool found_directive = false; + char const* scanner = str.Data; + s32 left = fsize; + while ( left ) + { + // Processing directive. + if ( current == '#' ) + { + move_fwd(); + while ( left && char_is_space( current ) ) + move_fwd(); + + if ( ! found_directive ) + { + if ( left && str_compare( scanner, directive_start.Ptr, directive_start.Len ) == matched ) + { + scanner += directive_start.Len; + left -= directive_start.Len; + + while ( left && char_is_space( current ) ) + move_fwd(); + + if ( left && str_compare( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) + { + scanner += def_intellisense.Len; + left -= def_intellisense.Len; + + found_directive = true; + } + } + + // Skip to end of line + while ( left && current != '\r' && current != '\n' ) + move_fwd(); + move_fwd(); + + if ( left && current == '\n' ) + move_fwd(); + + continue; + } + + if ( left && str_compare( scanner, directive_end.Ptr, directive_end.Len ) == matched ) + { + scanner += directive_end.Len; + left -= directive_end.Len; + + // Skip to end of line + while ( left && current != '\r' && current != '\n' ) + move_fwd(); + move_fwd(); + + if ( left && current == '\n' ) + move_fwd(); + + // sptr skip_size = fsize - left; + if ( ( scanner + 2 ) >= ( str.Data + fsize ) ) + { + mem_move( str, scanner, left ); + str.get_header().Length = left; + break; + } + + mem_move( str, scanner, left ); + str.get_header().Length = left; + + break; + } + } + + move_fwd(); + } +#undef move_fwd +#undef matched +#undef current + } + + file_close( &file ); + return untyped_str( str ); +} + +#if 0 +struct Policy +{ + // Nothing for now. +}; + +struct SymbolInfo +{ + StringCached File; + char const* Marker; + Code Signature; +}; + +struct Scanner +{ + struct RequestEntry + { + SymbolInfo Info; + }; + + struct Receipt + { + StringCached File; + Code Defintion; + bool Result; + }; + + AllocatorInfo MemAlloc; + + static void set_allocator( AllocatorInfo allocator ); + + Array Files; + String Buffer; + Array Requests; + + void add_files( s32 num, char const** files ); + + void add( SymbolInfo signature, Policy policy ); + + bool process_requests( Array out_receipts ); +}; +#endif + +#pragma endregion Scanner + GEN_NS_END #endif diff --git a/project/gen/gen_handmade.cpp b/project/gen/gen_handmade.cpp new file mode 100644 index 0000000..abc032b --- /dev/null +++ b/project/gen/gen_handmade.cpp @@ -0,0 +1,17 @@ +#if GEN_TIME +#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS +#define GEN_IMPLEMENTATION +#define GEN_BENCHMARK +#define GEN_ENFORCE_STRONG_CODE_TYPES +#include "gen.hpp" +using namespace gen; + +int gen_main() +{ + gen::init(); + log_fmt("Generating code for Handmade Hero\n"); + + gen::deinit(); + return 0; +} +#endif diff --git a/project/handmade_win32.cpp b/project/handmade_win32.cpp new file mode 100644 index 0000000..c1cf2b2 --- /dev/null +++ b/project/handmade_win32.cpp @@ -0,0 +1,8 @@ +#include + +int main() +{ + puts("Handmade Hero!"); + + return 0; +} diff --git a/project/sanity.cpp b/project/sanity.cpp deleted file mode 100644 index 7522726..0000000 --- a/project/sanity.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "stdio.h" - -int main() -{ - puts( "Hello World!\n" ); - return 0; -} diff --git a/scripts/build.ps1 b/scripts/build.ps1 index a4f2464..dd9d2b5 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -285,9 +285,10 @@ if ( $vendor -match "msvc" ) } #endregion Configuration -$path_project = Join-Path $path_root 'project' +$path_project = Join-Path $path_root 'project' $path_build = Join-Path $path_project 'build' $path_deps = Join-Path $path_project 'dependencies' +$path_gen = Join-Path $path_project 'gen' $update_deps = Join-Path $PSScriptRoot 'update_deps.ps1' @@ -300,14 +301,39 @@ if ( (Test-Path $path_deps) -eq $false ) { } $includes = @( + $path_gen, $path_project, $path_deps ) -$unit = Join-Path $path_project 'sanity.cpp' -$executable = Join-Path $path_build 'sanity.exe' +$compiler_args = @( + ($flag_define + 'GEN_TIME') +) + +#region Handmade Generate +$unit = Join-Path $path_gen 'gen_handmade.cpp' +$executable = Join-Path $path_build 'gen_handmade.exe' + +build-simple $includes $compiler_args $unit $executable +write-host "Compiled Handmade Generate`n" + +& $executable + +if ( $false ) { + Remove-Item (Get-ChildItem -Path $path_build -Recurse -Force) +} +#endregion Handmade Generate + +#region Handmade Runtime + +$unit = Join-Path $path_project 'handmade_win32.cpp' +$executable = Join-Path $path_build 'handmade_win32.exe' $compile_args = @( ) -build-simple $includes $compiler_args $unit $executable \ No newline at end of file +build-simple $includes $compiler_args $unit $executable +write-host "Compiled Handmade Runtime`n" +#endregion Handmade Runtime + +Pop-Location