mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-31 06:50:54 -07:00 
			
		
		
		
	Setup proper project skeleton with 2 stage build
This commit is contained in:
		
							
								
								
									
										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; |  | ||||||
| } |  | ||||||
| @@ -285,9 +285,10 @@ if ( $vendor -match "msvc" ) | |||||||
| } | } | ||||||
| #endregion Configuration | #endregion Configuration | ||||||
|  |  | ||||||
| $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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user