mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-22 14:24:43 -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.
|
Any code I do for this series will be here.
|
||||||
|
|
||||||
Building requires msvc or llvm's clang + lld, and powershell 7
|
|
||||||
|
|
||||||
## Scripts
|
## Scripts
|
||||||
|
|
||||||
* `build.ps1` - Builds the project use `.\scripts\build msvc` or `.\scripts\build clang`, add `release` to build in release mode
|
* `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
|
* `clean.ps1` - Cleans the project
|
||||||
* `update.ps1` - Updates the project dependencies to their latest from their respective repos. (Not done automatically on build)
|
* `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 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
|
GEN_NS_END
|
||||||
|
|
||||||
#pragma region GENCPP IMPLEMENTATION GUARD
|
#pragma region GENCPP IMPLEMENTATION GUARD
|
||||||
@ -23089,6 +22921,174 @@ void Builder::write()
|
|||||||
|
|
||||||
#pragma endregion 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
|
GEN_NS_END
|
||||||
|
|
||||||
#endif
|
#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;
|
|
||||||
}
|
|
@ -288,6 +288,7 @@ if ( $vendor -match "msvc" )
|
|||||||
$path_project = Join-Path $path_root 'project'
|
$path_project = Join-Path $path_root 'project'
|
||||||
$path_build = Join-Path $path_project 'build'
|
$path_build = Join-Path $path_project 'build'
|
||||||
$path_deps = Join-Path $path_project 'dependencies'
|
$path_deps = Join-Path $path_project 'dependencies'
|
||||||
|
$path_gen = Join-Path $path_project 'gen'
|
||||||
|
|
||||||
$update_deps = Join-Path $PSScriptRoot 'update_deps.ps1'
|
$update_deps = Join-Path $PSScriptRoot 'update_deps.ps1'
|
||||||
|
|
||||||
@ -300,14 +301,39 @@ if ( (Test-Path $path_deps) -eq $false ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$includes = @(
|
$includes = @(
|
||||||
|
$path_gen,
|
||||||
$path_project,
|
$path_project,
|
||||||
$path_deps
|
$path_deps
|
||||||
)
|
)
|
||||||
|
|
||||||
$unit = Join-Path $path_project 'sanity.cpp'
|
$compiler_args = @(
|
||||||
$executable = Join-Path $path_build 'sanity.exe'
|
($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 = @(
|
$compile_args = @(
|
||||||
)
|
)
|
||||||
|
|
||||||
build-simple $includes $compiler_args $unit $executable
|
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