mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-22 06:14:45 -08:00
Setup proper project skeleton with 2 stage build
This commit is contained in:
parent
60e7d1075a
commit
0376a22775
12
README.md
12
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.
|
||||
|
||||
|
@ -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<FileInfo> Files;
|
||||
String Buffer;
|
||||
Array<RequestEntry> Requests;
|
||||
|
||||
void add_files( s32 num, char const** files );
|
||||
|
||||
void add( SymbolInfo signature, Policy policy );
|
||||
|
||||
bool process_requests( Array<Receipt> 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<FileInfo> Files;
|
||||
String Buffer;
|
||||
Array<RequestEntry> Requests;
|
||||
|
||||
void add_files( s32 num, char const** files );
|
||||
|
||||
void add( SymbolInfo signature, Policy policy );
|
||||
|
||||
bool process_requests( Array<Receipt> out_receipts );
|
||||
};
|
||||
#endif
|
||||
|
||||
#pragma endregion Scanner
|
||||
|
||||
GEN_NS_END
|
||||
|
||||
#endif
|
||||
|
17
project/gen/gen_handmade.cpp
Normal file
17
project/gen/gen_handmade.cpp
Normal file
@ -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
|
8
project/handmade_win32.cpp
Normal file
8
project/handmade_win32.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
puts("Handmade Hero!");
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
puts( "Hello World!\n" );
|
||||
return 0;
|
||||
}
|
@ -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
|
||||
write-host "Compiled Handmade Runtime`n"
|
||||
#endregion Handmade Runtime
|
||||
|
||||
Pop-Location
|
||||
|
Loading…
Reference in New Issue
Block a user