24. Health and Mana

Decided to try using gencpp for the first time with UE (just codegen, not parsing).

I used it to generate the AttributeSet
This commit is contained in:
Edward R. Gonzalez 2024-04-13 16:18:57 -04:00
parent 5a4fc6381b
commit ced71b6a22
26 changed files with 27619 additions and 10 deletions

5
.gitignore vendored
View File

@ -20,3 +20,8 @@ Project/Saved/Screenshots
*/Binaries/Win64/*.patch_*.*
Project/Saved/ImGui
Project/Saved/ImGui/imgui.ini
GasaGen_*.pdb
Project/Binaries/GasaGen.exe
Project/Binaries/GasaGen.map
Project/Binaries/GasaGen.obj
Project/Binaries/vc140.pdb

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "cppvsdbg",
"request": "launch",
"name": "Debug GenGas vsdbg",
"program": "${workspaceFolder}/Project/Binaries/GasaGen.exe",
"args": [],
"cwd": "${workspaceFolder}/Project/",
"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis"
},
]
}

View File

@ -1,2 +1,39 @@
#include "GasaAttributeSet.h"
// This was generated by GasaGen/GasaGen.cpp
#include "GasaAttributeSet.h"
#include "AbilitySystemComponent.h"
#include "Net/UnrealNetwork.h"
#include "Networking/GasaNetLibrary.h"
UGasaAttributeSet::UGasaAttributeSet()
{
}
void UGasaAttributeSet::Client_OnRep_Health( FGameplayAttributeData& PrevHealth )
{
GAMEPLAYATTRIBUTE_REPNOTIFY( UGasaAttributeSet, Health, PrevHealth )
}
void UGasaAttributeSet::Client_OnRep_MaxHealth( FGameplayAttributeData& PrevMaxHealth )
{
GAMEPLAYATTRIBUTE_REPNOTIFY( UGasaAttributeSet, MaxHealth, PrevMaxHealth )
}
void UGasaAttributeSet::Client_OnRep_Mana( FGameplayAttributeData& PrevMana )
{
GAMEPLAYATTRIBUTE_REPNOTIFY( UGasaAttributeSet, Mana, PrevMana )
}
void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMana )
{
GAMEPLAYATTRIBUTE_REPNOTIFY( UGasaAttributeSet, MaxMana, PrevMaxMana )
}
void UGasaAttributeSet::GetLifetimeReplicatedProps( TArray< FLifetimeProperty >& OutLifetimeProps ) const
{
Super::GetLifetimeReplicatedProps( OutLifetimeProps );
DOREPLIFETIME_DEFAULT_GAS( UGasaAttributeSet, Health );
DOREPLIFETIME_DEFAULT_GAS( UGasaAttributeSet, MaxHealth );
DOREPLIFETIME_DEFAULT_GAS( UGasaAttributeSet, Mana );
DOREPLIFETIME_DEFAULT_GAS( UGasaAttributeSet, MaxMana );
}

View File

@ -1,15 +1,38 @@
#pragma once
#include "AttributeSet.h"
// This was generated by GasaGen/GasaGen.cpp
#include "AttributeSet.h"
#include "GasaAttributeSet.generated.h"
UCLASS()
class GASA_API UGasaAttributeSet : public UAttributeSet
UCLASS() class GASA_API UGasaAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
};
UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData Health;
UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData MaxHealth;
UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData Mana;
UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData MaxMana;
UGasaAttributeSet();
UFUNCTION()
void Client_OnRep_Health( FGameplayAttributeData& PrevHealth );
UFUNCTION()
void Client_OnRep_MaxHealth( FGameplayAttributeData& PrevMaxHealth );
UFUNCTION()
void Client_OnRep_Mana( FGameplayAttributeData& PrevMana );
UFUNCTION()
void Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMana );
#pragma region UObject
void GetLifetimeReplicatedProps( TArray< FLifetimeProperty >& OutLifetimeProps ) const override;
#pragma endregion UObject
};

View File

@ -1,6 +1,5 @@
#pragma once
namespace Gasa
{
constexpr float NetCullDist_Default = 225000000.0f;
@ -11,5 +10,8 @@ namespace Gasa
constexpr float NetCullDist_Distant = 7000.0f * 7000.0f;
constexpr float NetCullDist_Far = 8500.0f * 8500.0f;
constexpr float NetCullDist_VeryFar = 10000.0f * 10000.0f;
constexpr float NetCullDist_VisualMax = 15000.0f * 15000.0f;
constexpr float NetCullDist_VisualMax = 15000.0f * 15000.0f;
#define DOREPLIFETIME_DEFAULT_GAS(Class, ReplicatedVar) \
DOREPLIFETIME_CONDITION_NOTIFY(Class, ReplicatedVar, COND_None, REPNOTIFY_Always)
}

View File

@ -0,0 +1,178 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
// #define GEN_DEFINE_ATTRIBUTE_TOKENS
#define GEN_IMPLEMENTATION
#include "gen.cpp"
#include "gen.builder.cpp"
using namespace gen;
// Program assumes its working directory is the project
#define path_config "./Source/Config/"
#define path_module_gasa "./Source/Gasa/"
#define path_gasa_ability_system path_module_gasa "AbilitySystem/"
void def_attribute_fields( CodeBody body, Array<StringCached> fields )
{
for ( String field : fields )
{
Code field_uproperty = code_str(
UPROPERTY(ReplicatedUsing=Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category="Attributes")
);
CodeType type_FGameplayAttributeData = def_type( txt("FGameplayAttributeData"));
body.append(fmt_newline);
body.append( field_uproperty );
body.append(fmt_newline);
body.append( def_variable( type_FGameplayAttributeData, StrC(field)) );
}
}
void def_attribute_field_on_reps( CodeBody body, Array<StringCached> fields )
{
for ( String field : fields )
{
Code umeta_UFUNCTION = code_str( UFUNCTION() );
body.append(fmt_newline);
body.append( umeta_UFUNCTION );
body.append(fmt_newline);
body.append( code_fmt( "field", (StrC)field, stringize(
void Client_OnRep_<field>(FGameplayAttributeData& Prev<field>);
)));
}
}
void impl_attribute_fields( CodeBody body, Array<StringCached> fields )
{
for ( String field : fields )
{
body.append(fmt_newline);
CodeFn field_impl = parse_function( token_fmt( "field", (StrC)field, stringize(
void UGasaAttributeSet::Client_OnRep_<field>(FGameplayAttributeData& Prev<field>)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UGasaAttributeSet, <field>, Prev<field>)
}
)));
body.append( field_impl );
}
}
int gen_main()
{
gen::init();
log_fmt("Generating code for the Gasa module");
Code umeta_uclass = code_str( UCLASS() );
Code umeta_generated_body = code_str( GENERATED_BODY() );
Code gasa_api = code_str( GASA_API );
CodeType type_UAttributeSet = def_type( txt("UAttributeSet") );
CodeComment generation_notice = def_comment(txt("This was generated by GasaGen/GasaGen.cpp"));
Array<StringCached> attribute_fields = Array<StringCached>::init( GlobalAllocator);
attribute_fields.append( get_cached_string(txt("Health")));
attribute_fields.append( get_cached_string(txt("MaxHealth")));
attribute_fields.append( get_cached_string(txt("Mana")));
attribute_fields.append( get_cached_string(txt("MaxMana")));
Builder header = Builder::open( path_gasa_ability_system "GasaAttributeSet.h");
{
header.print(generation_notice);
header.print(fmt_newline);
{
CodeInclude Include_AttributeSet = def_include(txt("AttributeSet.h"));
CodeInclude Include_GasaAttributeSet_Generated = def_include(txt("GasaAttributeSet.generated.h"));
CodeAttributes attributes = def_attributes( gasa_api->Name);
CodeClass GasaAttributeSet = {};
{
CodeBody body = def_body( CodeT::Class_Body );
{
body.append( umeta_generated_body);
body.append( fmt_newline);
body.append( access_public );
def_attribute_fields( body, attribute_fields);
body.append(fmt_newline);
body.append( def_constructor() );
def_attribute_field_on_reps( body, attribute_fields);
body.append(fmt_newline);
body.append(fmt_newline);
body.append( def_pragma( txt("region UObject")));
body.append( parse_function( code(
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
)));
body.append( def_pragma( txt("endregion UObject")));
}
GasaAttributeSet = def_class( txt("UGasaAttributeSet"), body
, type_UAttributeSet
, AccessSpec::Public
, attributes
);
}
header.print( Include_AttributeSet);
header.print( fmt_newline);
header.print( Include_GasaAttributeSet_Generated);
header.print( fmt_newline);
header.print(umeta_uclass);
header.print(GasaAttributeSet);
}
header.write();
}
Builder source = Builder::open( path_gasa_ability_system "GasaAttributeSet.cpp" );
{
source.print(generation_notice);
source.print( def_include( txt("GasaAttributeSet.h")));
source.print(fmt_newline);
source.print( def_include( txt("AbilitySystemComponent.h")));
source.print( def_include( txt("Net/UnrealNetwork.h")));
source.print( def_include( txt("Networking/GasaNetLibrary.h")));
{
CodeBody body = def_body( CodeT::Global_Body );
body.append(fmt_newline);
body.append(code_str(
UGasaAttributeSet::UGasaAttributeSet() {}
));
body.append(fmt_newline);
impl_attribute_fields(body, attribute_fields);
CodeFn GetLifetimeOfReplicatedProps;
{
CodeBody field_lifetimes = def_body( CodeT::Function_Body);
for (StringCached field : attribute_fields)
{
field_lifetimes.append( code_fmt( "field", (StrC)field, stringize(
DOREPLIFETIME_DEFAULT_GAS(UGasaAttributeSet, <field>);
)));
}
GetLifetimeOfReplicatedProps = parse_function( token_fmt( "body", (StrC)(field_lifetimes.to_string()), stringize(
void UGasaAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
<body>
}
)));
}
body.append(GetLifetimeOfReplicatedProps);
source.print(body);
}
source.write();
}
// gen::deinit();
return 0;
}

View File

@ -0,0 +1,63 @@
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
#include "gen.builder.hpp"
GEN_NS_BEGIN
Builder Builder::open( char const* path )
{
Builder result;
FileError error = file_open_mode( &result.File, EFileMode_WRITE, path );
if ( error != EFileError_NONE )
{
log_failure( "gen::File::open - Could not open file: %s", path );
return result;
}
result.Buffer = String::make_reserve( GlobalAllocator, Builder_StrBufferReserve );
// log_fmt("$Builder - Opened file: %s\n", result.File.filename );
return result;
}
void Builder::pad_lines( s32 num )
{
Buffer.append( "\n" );
}
void Builder::print( Code code )
{
String str = code->to_string();
// const sw len = str.length();
// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data );
Buffer.append( str );
}
void Builder::print_fmt( char const* fmt, ... )
{
sw res;
char buf[ GEN_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1;
va_end( va );
// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf );
Buffer.append( buf, res );
}
void Builder::write()
{
bool result = file_write( &File, Buffer, Buffer.length() );
if ( result == false )
log_failure( "gen::File::write - Failed to write to file: %s\n", file_name( &File ) );
log_fmt( "Generated: %s\n", File.filename );
file_close( &File );
Buffer.free();
}
GEN_NS_END

View File

@ -0,0 +1,24 @@
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
#pragma once
#include "gen.hpp"
GEN_NS_BEGIN
struct Builder
{
FileInfo File;
String Buffer;
static Builder open( char const* path );
void pad_lines( s32 num );
void print( Code );
void print_fmt( char const* fmt, ... );
void write();
};
GEN_NS_END

12123
Project/Source/GasaGen/gen.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,593 @@
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
#pragma once
#include "gen.hpp"
GEN_NS_BEGIN
#pragma region ADT
enum ADT_Type : u32
{
EADT_TYPE_UNINITIALISED, /* node was not initialised, this is a programming error! */
EADT_TYPE_ARRAY,
EADT_TYPE_OBJECT,
EADT_TYPE_STRING,
EADT_TYPE_MULTISTRING,
EADT_TYPE_INTEGER,
EADT_TYPE_REAL,
};
enum ADT_Props : u32
{
EADT_PROPS_NONE,
EADT_PROPS_NAN,
EADT_PROPS_NAN_NEG,
EADT_PROPS_INFINITY,
EADT_PROPS_INFINITY_NEG,
EADT_PROPS_FALSE,
EADT_PROPS_TRUE,
EADT_PROPS_NULL,
EADT_PROPS_IS_EXP,
EADT_PROPS_IS_HEX,
// Used internally so that people can fill in real numbers they plan to write.
EADT_PROPS_IS_PARSED_REAL,
};
enum ADT_NamingStyle : u32
{
EADT_NAME_STYLE_DOUBLE_QUOTE,
EADT_NAME_STYLE_SINGLE_QUOTE,
EADT_NAME_STYLE_NO_QUOTES,
};
enum ADT_AssignStyle : u32
{
EADT_ASSIGN_STYLE_COLON,
EADT_ASSIGN_STYLE_EQUALS,
EADT_ASSIGN_STYLE_LINE,
};
enum ADT_DelimStyle : u32
{
EADT_DELIM_STYLE_COMMA,
EADT_DELIM_STYLE_LINE,
EADT_DELIM_STYLE_NEWLINE,
};
enum ADT_Error : u32
{
EADT_ERROR_NONE,
EADT_ERROR_INTERNAL,
EADT_ERROR_ALREADY_CONVERTED,
EADT_ERROR_INVALID_TYPE,
EADT_ERROR_OUT_OF_MEMORY,
};
struct ADT_Node
{
char const* name;
struct ADT_Node* parent;
/* properties */
ADT_Type type : 4;
u8 props : 4;
#ifndef GEN_PARSER_DISABLE_ANALYSIS
u8 cfg_mode : 1;
u8 name_style : 2;
u8 assign_style : 2;
u8 delim_style : 2;
u8 delim_line_width : 4;
u8 assign_line_width : 4;
#endif
/* adt data */
union
{
char const* string;
Array< ADT_Node > nodes; ///< zpl_array
struct
{
union
{
f64 real;
s64 integer;
};
#ifndef GEN_PARSER_DISABLE_ANALYSIS
/* number analysis */
s32 base;
s32 base2;
u8 base2_offset : 4;
s8 exp : 4;
u8 neg_zero : 1;
u8 lead_digit : 1;
#endif
};
};
};
/* ADT NODE LIMITS
* delimiter and assignment segment width is limited to 128 whitespace symbols each.
* real number limits decimal position to 128 places.
* real number exponent is limited to 64 digits.
*/
/**
* @brief Initialise an ADT object or array
*
* @param node
* @param backing Memory allocator used for descendants
* @param name Node's name
* @param is_array
* @return error code
*/
u8 adt_make_branch( ADT_Node* node, AllocatorInfo backing, char const* name, b32 is_array );
/**
* @brief Destroy an ADT branch and its descendants
*
* @param node
* @return error code
*/
u8 adt_destroy_branch( ADT_Node* node );
/**
* @brief Initialise an ADT leaf
*
* @param node
* @param name Node's name
* @param type Node's type (use zpl_adt_make_branch for container nodes)
* @return error code
*/
u8 adt_make_leaf( ADT_Node* node, char const* name, ADT_Type type );
/**
* @brief Fetch a node using provided URI string.
*
* This method uses a basic syntax to fetch a node from the ADT. The following features are available
* to retrieve the data:
*
* - "a/b/c" navigates through objects "a" and "b" to get to "c"
* - "arr/[foo=123]/bar" iterates over "arr" to find any object with param "foo" that matches the value "123", then gets its field called "bar"
* - "arr/3" retrieves the 4th element in "arr"
* - "arr/[apple]" retrieves the first element of value "apple" in "arr"
*
* @param node ADT node
* @param uri Locator string as described above
* @return zpl_adt_node*
*
* @see code/apps/examples/json_get.c
*/
ADT_Node* adt_query( ADT_Node* node, char const* uri );
/**
* @brief Find a field node within an object by the given name.
*
* @param node
* @param name
* @param deep_search Perform search recursively
* @return zpl_adt_node * node
*/
ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search );
/**
* @brief Allocate an unitialised node within a container at a specified index.
*
* @param parent
* @param index
* @return zpl_adt_node * node
*/
ADT_Node* adt_alloc_at( ADT_Node* parent, sw index );
/**
* @brief Allocate an unitialised node within a container.
*
* @param parent
* @return zpl_adt_node * node
*/
ADT_Node* adt_alloc( ADT_Node* parent );
/**
* @brief Move an existing node to a new container at a specified index.
*
* @param node
* @param new_parent
* @param index
* @return zpl_adt_node * node
*/
ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, sw index );
/**
* @brief Move an existing node to a new container.
*
* @param node
* @param new_parent
* @return zpl_adt_node * node
*/
ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent );
/**
* @brief Swap two nodes.
*
* @param node
* @param other_node
* @return
*/
void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node );
/**
* @brief Remove node from container.
*
* @param node
* @return
*/
void adt_remove_node( ADT_Node* node );
/**
* @brief Initialise a node as an object
*
* @param obj
* @param name
* @param backing
* @return
*/
b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing );
/**
* @brief Initialise a node as an array
*
* @param obj
* @param name
* @param backing
* @return
*/
b8 adt_set_arr( ADT_Node* obj, char const* name, AllocatorInfo backing );
/**
* @brief Initialise a node as a string
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_str( ADT_Node* obj, char const* name, char const* value );
/**
* @brief Initialise a node as a float
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_flt( ADT_Node* obj, char const* name, f64 value );
/**
* @brief Initialise a node as a signed integer
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_int( ADT_Node* obj, char const* name, s64 value );
/**
* @brief Append a new node to a container as an object
*
* @param parent
* @param name
* @return*
*/
ADT_Node* adt_append_obj( ADT_Node* parent, char const* name );
/**
* @brief Append a new node to a container as an array
*
* @param parent
* @param name
* @return*
*/
ADT_Node* adt_append_arr( ADT_Node* parent, char const* name );
/**
* @brief Append a new node to a container as a string
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_str( ADT_Node* parent, char const* name, char const* value );
/**
* @brief Append a new node to a container as a float
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_flt( ADT_Node* parent, char const* name, f64 value );
/**
* @brief Append a new node to a container as a signed integer
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_int( ADT_Node* parent, char const* name, s64 value );
/* parser helpers */
/**
* @brief Parses a text and stores the result into an unitialised node.
*
* @param node
* @param base
* @return*
*/
char* adt_parse_number( ADT_Node* node, char* base );
/**
* @brief Parses a text and stores the result into an unitialised node.
* This function expects the entire input to be a number.
*
* @param node
* @param base
* @return*
*/
char* adt_parse_number_strict( ADT_Node* node, char* base_str );
/**
* @brief Parses and converts an existing string node into a number.
*
* @param node
* @return
*/
ADT_Error adt_str_to_number( ADT_Node* node );
/**
* @brief Parses and converts an existing string node into a number.
* This function expects the entire input to be a number.
*
* @param node
* @return
*/
ADT_Error adt_str_to_number_strict( ADT_Node* node );
/**
* @brief Prints a number into a file stream.
*
* The provided file handle can also be a memory mapped stream.
*
* @see zpl_file_stream_new
* @param file
* @param node
* @return
*/
ADT_Error adt_print_number( FileInfo* file, ADT_Node* node );
/**
* @brief Prints a string into a file stream.
*
* The provided file handle can also be a memory mapped stream.
*
* @see zpl_file_stream_new
* @param file
* @param node
* @param escaped_chars
* @param escape_symbol
* @return
*/
ADT_Error adt_print_string( FileInfo* file, ADT_Node* node, char const* escaped_chars, char const* escape_symbol );
#pragma endregion ADT
#pragma region CSV
enum CSV_Error : u32
{
ECSV_Error__NONE,
ECSV_Error__INTERNAL,
ECSV_Error__UNEXPECTED_END_OF_INPUT,
ECSV_Error__MISMATCHED_ROWS,
};
typedef ADT_Node CSV_Object;
GEN_DEF_INLINE u8 csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header );
u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header, char delim );
void csv_free( CSV_Object* obj );
GEN_DEF_INLINE void csv_write( FileInfo* file, CSV_Object* obj );
GEN_DEF_INLINE String csv_write_string( AllocatorInfo a, CSV_Object* obj );
void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delim );
String csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delim );
/* inline */
GEN_IMPL_INLINE u8 csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header )
{
return csv_parse_delimiter( root, text, allocator, has_header, ',' );
}
GEN_IMPL_INLINE void csv_write( FileInfo* file, CSV_Object* obj )
{
csv_write_delimiter( file, obj, ',' );
}
GEN_IMPL_INLINE String csv_write_string( AllocatorInfo a, CSV_Object* obj )
{
return csv_write_string_delimiter( a, obj, ',' );
}
#pragma endregion CSV
// 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 CodeFile
{
using namespace Parser;
String FilePath;
TokArray Tokens;
Array<ParseFailure> ParseFailures;
Code CodeRoot;
};
namespace Parser
{
struct ParseFailure
{
String Reason;
Code Node;
};
}
CodeFile scan_file( char const* path )
{
using namespace Parser;
CodeFile
result = {};
result.FilePath = String::make( GlobalAllocator, path );
Code code = scan_file( path );
result.CodeRoot = code;
ParseContext context = parser_get_last_context();
result.Tokens = context.Tokens;
result.ParseFailures = context.Failures;
return result;
}
#endif
GEN_NS_END

171
scripts/.clang-format Normal file
View File

@ -0,0 +1,171 @@
# Format Style Options - Created with Clang Power Tools
---
AccessModifierOffset: -4
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: Left
AlignConsecutiveAssignments:
Enabled: true
AcrossEmptyLines: true
AcrossComments: false
AlignCompound: true
PadOperators: true
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: true
AcrossComments: false
AlignConsecutiveDeclarations:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: true
AcrossComments: false
AlignEscapedNewlines: Left
AlignOperands: DontAlign
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortLambdasOnASingleLine: None
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BeforeLambdaBody: false
BeforeWhile: false
BreakAfterAttributes: Always
BreakArrays: true
# BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: true
BreakInheritanceList: BeforeComma
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakStringLiterals: true
ColumnLimit: 160
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequires: true
IndentWidth: 4
IndentWrappedFunctionNames: true
# InsertNewlineAtEOF: true
# InsertTrailingCommas: Wrapped
LambdaBodyIndentation: OuterScope
Language: Cpp
MaxEmptyLinesToKeep: 4
NamespaceIndentation: All
PointerAlignment: Left
QualifierAlignment: Leave
ReferenceAlignment: Left
ReflowComments: true
# RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 40
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: true
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptControlMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpacesBeforeTrailingComments: 4
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesInAngles: true
SpacesInCStyleCastParentheses: true
SpacesInConditionalStatement: true
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 20
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: c++17
TabWidth: 4
UseTab: ForIndentation
...

112
scripts/gen_pass_gasa.ps1 Normal file
View File

@ -0,0 +1,112 @@
Clear-Host
$target_arch = Join-Path $PSScriptRoot 'helpers/target_arch.psm1'
$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
$format_cpp = Join-Path $PSScriptRoot 'helpers/format_cpp.psm1'
$incremental_checks = Join-Path $PSScriptRoot 'helpers/incremental_checks.ps1'
$vendor_toolchain = Join-Path $PSScriptRoot 'helpers/vendor_toolchain.ps1'
$update_deps = Join-Path $PSScriptRoot 'update_deps.ps1'
$path_root = git rev-parse --show-toplevel
Import-Module $target_arch
Import-Module $format_cpp
#region Arguments
$vendor = $null
$release = $null
$verbose = $false
[bool] $bootstrap = $false
[bool] $singleheader = $false
[bool] $test = $false
[array] $vendors = @( "clang", "msvc" )
# This is a really lazy way of parsing the args, could use actual params down the line...
if ( $args ) { $args | ForEach-Object {
switch ($_){
{ $_ -in $vendors } { $vendor = $_; break }
"verbose" { $verbose = $true }
"release" { $release = $true }
"debug" { $release = $false }
}
}}
#endregion Arguments
#region Configuration
if ($IsWindows) {
# This library was really designed to only run on 64-bit systems.
# (Its a development tool after all)
& $devshell -arch amd64
}
if ( $vendor -eq $null ) {
write-host "No vendor specified, assuming clang available"
$compiler = "clang"
}
if ( $release -eq $null ) {
write-host "No build type specified, assuming debug"
$release = $false
}
elseif ( $release -eq $false ) {
$debug = $true
}
else {
$optimize = $true
}
. $vendor_toolchain
. $incremental_checks
write-host "Building GasaGen with $vendor"
write-host "Build Type: $(if ($release) {"Release"} else {"Debug"} )"
#region Building
$path_project = Join-Path $path_root 'Project'
$path_binaries = Join-Path $path_project 'Binaries'
$path_scripts = Join-Path $path_root 'scripts'
$path_source = Join-Path $path_project 'Source'
$path_gasa = join-path $path_source 'Gasa'
$path_gasagen = join-path $path_source 'GasaGen'
$exe_gasagen = join-path $path_binaries 'GasaGen.exe'
function build-gengasa
{
$includes = @( $path_gasagen )
$unit = join-path $path_gasagen 'GasaGen.cpp'
$compiler_args = @()
$compiler_args += ($flag_define + 'GEN_TIME')
$linker_args = @()
$linker_args += $flag_link_win_subsystem_console
build-simple $path_binaries $includes $compiler_args $linker_args $unit $exe_gasagen
}
build-gengasa
function run-gengasa
{
Push-Location $path_project
if ( Test-Path( $exe_gasagen ) ) {
write-host "`nRunning GasaGen"
$time_taken = Measure-Command { & $exe_gasagen
| ForEach-Object {
write-host `t $_ -ForegroundColor Green
}
}
write-host "`GasaGen completed in $($time_taken.TotalMilliseconds) ms"
}
Pop-Location
$path_AbilitySystem = join-path $path_gasa 'AbilitySystem'
$include = @(
'GasaAttributeSet.h', 'GasaAttributeSet.cpp'
)
format-cpp $path_AbilitySystem $include $null
}
run-gengasa

682
scripts/gencpp.natvis Normal file
View File

@ -0,0 +1,682 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="gen::AllocatorInfo">
<DisplayString>Data:{Data} Proc:{Proc}</DisplayString>
</Type>
<Type Name="gen::Pool">
<DisplayString>NumBlocks: {NumBlocks} TotalSize: {TotalSize}</DisplayString>
<Expand>
<LinkedListItems>
<Size>NumBlocks</Size>
<HeadPointer>FreeList</HeadPointer>
<NextPointer>FreeList</NextPointer>
<ValueNode>PhysicalStart</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="gen::Array&lt;*&gt;">
<DisplayString>Num:{((Header*)((char*)Data - sizeof(Header)))->Num},
Capacity:{((Header*)((char*)Data - sizeof(Header)))->Capacity}</DisplayString>
<Expand>
<Synthetic Name="Header">
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
<Expand>
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
<Item Name="Capacity">((Header*)((char*)Data - sizeof(Header)))->Capacity</Item>
<Item Name="Num">((Header*)((char*)Data - sizeof(Header)))->Num</Item>
</Expand>
</Synthetic>
<ArrayItems>
<Size>((Header*)((char*)Data - sizeof(Header)))->Capacity</Size>
<ValuePointer>Data</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="gen::StrC">
<DisplayString>Len:{Len} Ptr:{Ptr, [Len]s}</DisplayString>
</Type>
<Type Name="gen::String">
<DisplayString Condition="Data == nullptr">null</DisplayString>
<DisplayString>{Data,na}</DisplayString>
<Expand>
<Synthetic Name="Header">
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
<Expand>
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
<Item Name="Capacity">((Header*)((char*)Data - sizeof(Header)))->Capacity</Item>
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="gen::String::Header">
<DisplayString>Length: {Length}, Capacity: {Capacity}</DisplayString>
<Expand>
<Item Name="Allocator">Allocator</Item>
<Item Name="Length">Length</Item>
<Item Name="Capacity">Capacity</Item>
</Expand>
</Type>
<Type Name="gen::AST">
<DisplayString Condition="this != nullptr">{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Content">Content</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
<Item Name="NumEntries">NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::Code">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} Type: {ast->Type}</DisplayString>
<Expand HideRawView="false">
<Item Name="Content">ast->Content</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="ModuleFlags" Condition="ast->ModuleFlags != ModuleFlag::Invalid">
ast->ModuleFlags</Item>
<Item Name="ArrSpecs" Condition="ast->ArrSpecs[0] &lt; 18">ast->ArrSpecs</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="NumEntries">ast->NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::AST_Body">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Parent">Parent</Item>
<Item Name="Front">Front</Item>
<Item Name="Back">Back</Item>
<Item Name="NumEntries">NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::AST_Attributes">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Content">Content</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Comment">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Content">Content</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Class">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="ParentType">ParentType</Item>
<Item Name="ParentAccess">ParentAccess</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Enum">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Attributes">Attributes</Item>
<Item Name="UnderlyingType">UnderlyingType</Item>
<Item Name="Body">Body</Item>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Exec">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Extern">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Include">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Content">Content</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Friend">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Declaration">Declaration</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Fn">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="Specs">Specs</Item>
<Item Name="ReturnType">ReturnType</Item>
<Item Name="Params">Params</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Module">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_NS">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
<Item Name="Body">Body</Item>
</Expand>
</Type>
<Type Name="gen::AST_Operator">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="Specs">Specs</Item>
<Item Name="ReturnType">ReturnType</Item>
<Item Name="Op">Op</Item>
<Item Name="Params">Params</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_OpCast">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Specs">Specs</Item>
<Item Name="ValueType">ValueType</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Param">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ValueType">ValueType</Item>
<Item Name="Value">Value</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Last">Last</Item>
<Item Name="Next">Next</Item>
<Item Name="NumEntries">NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::AST_Specifiers">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Specs">Specs</Item>
<Item Name="NumEntries">NumEntries</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Struct">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="ParentType">ParentType</Item>
<Item Name="ParentAccess">ParentAccess</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Template">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Declaration">Declaration</Item>
<Item Name="Params">Params</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Type">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Attributes">Attributes</Item>
<Item Name="Specs">Specs</Item>
<Item Name="ArrExpr">ArrExpr</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Typedef">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="UnderlyingType">UnderlyingType</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Union">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="Body">Body</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Using">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="UnderlyingType">UnderlyingType</Item>
<Item Name="Parent">Parent</Item>
<Item Name="ParentAccess">ParentAccess</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_UsingNamespace">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="Name">Name</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::AST_Var">
<DisplayString>{Name} Type: {Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ModuleFlags</Item>
<Item Name="Attributes">Attributes</Item>
<Item Name="Specs">Specs</Item>
<Item Name="ValueType">ValueType</Item>
<Item Name="Value">Value</Item>
<Item Name="Parent">Parent</Item>
<Item Name="Prev">Prev</Item>
<Item Name="Next">Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeBody">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Front">ast->Front</Item>
<Item Name="Back">ast->Back</Item>
<Item Name="NumEntries">ast->NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::CodeAttributes">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Content">ast->Content</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeComment">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Content">ast->Content</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeClass">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="ParentType">ast->ParentType</Item>
<Item Name="ParentAccess">ast->ParentAccess</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeExec">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Body">ast->Body</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Name">ast->Name</Item>
<Item Name="Type">ast->Type</Item>
</Expand>
</Type>
<Type Name="gen::CodeEnum">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="UnderlyingType">ast->UnderlyingType</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="Parent">ast->Parent</Item>
</Expand>
</Type>
<Type Name="gen::CodeInclude">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Content">ast->Content</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeFriend">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Declaration">ast->Declaration</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeFn">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="Specs">ast->Specs</Item>
<Item Name="ReturnType">ast->ReturnType</Item>
<Item Name="Params">ast->Params</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeModule">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeNS">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeOperator">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="Specs">ast->Specs</Item>
<Item Name="ReturnType">ast->ReturnType</Item>
<Item Name="Op">ast->Op</Item>
<Item Name="Params">ast->Params</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeOpCast">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ValueType">ast->ValueType</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeParam">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ValueType">ast->ValueType</Item>
<Item Name="Value">ast->Value</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Last">ast->Last</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="NumEntries">ast->NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::CodeSpecifiers">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Specs">ast->Specs</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="NumEntries">ast->NumEntries</Item>
</Expand>
</Type>
<Type Name="gen::CodeStruct">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="ParentType">ast->ParentType</Item>
<Item Name="ParentAccess">ast->ParentAccess</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeTemplate">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Params">ast->Params</Item>
<Item Name="Declaration">ast->Declaration</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeType">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="Specs">ast->Specs</Item>
<Item Name="ArrExpr">ast->ArrExpr</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeTypedef">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="UnderlyingType">ast->UnderlyingType</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeUnion">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="Body">ast->Body</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeUsing">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="UnderlyingType">ast->UnderlyingType</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::CodeUsingNamespace">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Name">ast->Name</Item>
<Item Name="Type">ast->Type</Item>
</Expand>
</Type>
<Type Name="gen::CodeVar">
<DisplayString Condition="ast == nullptr">Null</DisplayString>
<DisplayString Condition="ast != nullptr">{ast->Name} {ast->Type}</DisplayString>
<Expand>
<Item Name="ModuleFlags">ast->ModuleFlags</Item>
<Item Name="Attributes">ast->Attributes</Item>
<Item Name="Specs">ast->Specs</Item>
<Item Name="ValueType">ast->ValueType</Item>
<Item Name="Value">ast->Value</Item>
<Item Name="Parent">ast->Parent</Item>
<Item Name="Prev">ast->Prev</Item>
<Item Name="Next">ast->Next</Item>
</Expand>
</Type>
<Type Name="gen::parser::Token">
<DisplayString>Length:{Length} Text:{Text, [Length]s} Type:{Type}</DisplayString>
</Type>
<Type Name="gen::parser::TokArray">
<DisplayString>Current[ { Arr[Idx] } ] Idx:{ Idx }</DisplayString>
</Type>
</AutoVisualizer>

View File

@ -0,0 +1,28 @@
if ($env:VCINSTALLDIR) {
return
}
$ErrorActionPreference = "Stop"
# Use vswhere to find the latest Visual Studio installation
$vswhere_out = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
if ($null -eq $vswhere_out) {
Write-Host "ERROR: Visual Studio installation not found"
exit 1
}
# Find Launch-VsDevShell.ps1 in the Visual Studio installation
$vs_path = $vswhere_out
$vs_devshell = Join-Path $vs_path "\Common7\Tools\Launch-VsDevShell.ps1"
if ( -not (Test-Path $vs_devshell) ) {
Write-Host "ERROR: Launch-VsDevShell.ps1 not found in Visual Studio installation"
Write-Host Tested path: $vs_devshell
exit 1
}
# Launch the Visual Studio Developer Shell
Push-Location
write-host @args
& $vs_devshell @args
Pop-Location

View File

@ -0,0 +1,26 @@
# format_cpp.psm1
function format-cpp
{
param( $path, $include, $exclude )
# Format generated gencpp
Write-Host "Beginning format"
$formatParams = @(
'-i' # In-place
'-style=file:.clang-format'
'-verbose'
)
$targetFiles = @(
Get-ChildItem -Recurse -Path $path -Include $include -Exclude $exclude
| Select-Object -ExpandProperty FullName
)
$time_taken = Measure-Command {
clang-format $formatParams $targetFiles
}
Write-Host "Formatting complete in $($time_taken.TotalMilliseconds) ms`n"
}
Export-ModuleMember -Function format-cpp

View File

@ -0,0 +1,73 @@
# This is meant to be used with build.ps1, and is not a standalone script.
function check-FileForChanges
{
param(
[Parameter(Mandatory=$true)]
[string]$path_file
)
if (-not (Test-Path $path_file -PathType Leaf)) {
Write-Error "The provided path is not a valid file: $path_file"
return $false
}
$file_name = Split-Path $path_file -Leaf
$path_csv = Join-Path $path_build ($file_name + "_file_hash.csv")
$csv_file_hash = $null
if (Test-Path $path_csv) {
$csv_file_hash = Import-Csv $path_csv | Select-Object -ExpandProperty value
}
$current_hash_info = Get-FileHash -Path $path_file -Algorithm MD5
$current_file_hash = $current_hash_info.Hash
# Save the current hash to the CSV
[PSCustomObject]@{
name = $path_file
value = $current_file_hash
} | Export-Csv $path_csv -NoTypeInformation
if ($csv_file_hash -and $csv_file_hash -eq $current_file_hash) {
return $false
} else {
return $true
}
}
# Check to see if the module has changed files since the last build
function check-ModuleForChanges
{
param( [string]$path_module, [array]$excludes )
$module_name = split-path $path_module -leaf
$path_csv = Join-Path $path_build ($module_name + "_module_hashes.csv")
$csv_file_hashes = $null
if ( test-path $path_csv ) {
$csv_file_hashes = @{}
import-csv $path_csv | foreach-object {
$csv_file_hashes[ $_.name ] = $_.value
}
}
$file_hashes = @{}
get-childitem -path $path_module -recurse -file -Exclude $excludes | foreach-object {
$id = $_.fullname
$hash_info = get-filehash -path $id -Algorithm MD5
$file_hashes[ $id ] = $hash_info.Hash
}
$file_hashes.GetEnumerator() | foreach-object { [PSCustomObject]$_ } |
export-csv $path_csv -NoTypeInformation
if ( -not $csv_file_hashes ) { return $true }
if ( $csv_file_hashes.Count -ne $file_hashes.Count ) { return $true }
foreach ( $key in $csv_file_hashes.Keys ) {
if ( $csv_file_hashes[ $key ] -ne $file_hashes[ $key ] ) {
return $true
}
}
return $false
}

View File

@ -0,0 +1,25 @@
# target_arch.psm1
function Get-TargetArchClang {
# Get the target architecture by querying clang itself
$output = & clang -v 2>&1
foreach ($line in $output) {
if ($line -like "*Target:*") {
$clangTarget = ($line -split ':')[1].Trim()
return $clangTarget
}
}
throw "Clang target architecture could not be determined."
}
function Get-TargetArchMSVC {
# Assuming you've set the Visual Studio environment variables using `vcvarsall.bat`
# This looks for the `VSCMD_ARG_TGT_ARCH` environment variable which Visual Studio sets to indicate the target architecture.
$arch = $env:VSCMD_ARG_TGT_ARCH
if (-not $arch) {
throw "MSVC target architecture could not be determined. Ensure you've initialized the Visual Studio environment."
}
return $arch
}
Export-ModuleMember -Function Get-TargetArchClang, Get-TargetArchMSVC

View File

@ -0,0 +1,525 @@
# This is meant to be used with build.ps1, and is not a standalone script.
if ($IsWindows) {
# This HandmadeHero implementation is only designed for 64-bit systems
& $devshell -arch amd64
}
if ( $vendor -eq $null ) {
write-host "No vendor specified, assuming clang available"
$vendor = "clang"
}
if ( $dev ) {
if ( $debug -eq $null ) {
$debug = $true
}
if ( $optimize -eq $null ) {
$optimize = $false
}
}
function run-compiler
{
param( $compiler, $unit, $compiler_args )
if ( $analysis ) {
$compiler_args += $flag_syntax_only
}
write-host "`Compiling $unit"
if ( $verbose ) {
write-host "Compiler config:"
$compiler_args | ForEach-Object {
write-host $_ -ForegroundColor Cyan
}
}
$time_taken = Measure-Command {
& $compiler $compiler_args 2>&1 | ForEach-Object {
$color = 'White'
switch ($_){
{ $_ -match "error" } { $color = 'Red' ; break }
{ $_ -match "warning" } { $color = 'Yellow'; break }
}
write-host `t $_ -ForegroundColor $color
}
}
if ( $LASTEXITCODE -eq 0 ) {
write-host "$unit compile finished in $($time_taken.TotalMilliseconds) ms`n"
return $true
}
else {
write-host "Compile failed for $unit`n" -ForegroundColor Red
return $false
}
}
function run-linker
{
param( $linker, $binary, $linker_args )
write-host "`Linking $binary"
if ( $verbose ) {
write-host "Linker config:"
$linker_args | ForEach-Object {
write-host $_ -ForegroundColor Cyan
}
}
$time_taken = Measure-Command {
& $linker $linker_args 2>&1 | ForEach-Object {
$color = 'White'
switch ($_){
{ $_ -match "error" } { $color = 'Red' ; break }
{ $_ -match "warning" } { $color = 'Yellow'; break }
}
write-host `t $_ -ForegroundColor $color
}
}
if ( $LASTEXITCODE -eq 0 ) {
write-host "$binary linking finished in $($time_taken.TotalMilliseconds) ms`n"
return $true
}
else {
write-host "Linking failed for $binary`n" -ForegroundColor Red
return $false
}
}
if ( $vendor -match "clang" )
{
# https://clang.llvm.org/docs/ClangCommandLineReference.html
$flag_all_c = '-x c'
$flag_all_cpp = '-x c++'
$flag_compile = '-c'
$flag_color_diagnostics = '-fcolor-diagnostics'
$flag_no_color_diagnostics = '-fno-color-diagnostics'
$flag_debug = '-g'
$flag_debug_codeview = '-gcodeview'
$flag_define = '-D'
$flag_exceptions_disabled = '-fno-exceptions'
$flag_preprocess = '-E'
$flag_include = '-I'
$flag_section_data = '-fdata-sections'
$flag_section_functions = '-ffunction-sections'
$flag_library = '-l'
$flag_library_path = '-L'
$flag_linker = '-Wl,'
if ( $IsWindows ) {
$flag_link_dll = '/DLL'
$flag_link_mapfile = '/MAP:'
$flag_link_optimize_references = '/OPT:REF'
}
if ( $IsLinux ) {
$flag_link_mapfile = '--Map='
$flag_link_optimize_references = '--gc-sections'
}
$flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
$flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
$flag_link_win_machine_32 = '/MACHINE:X86'
$flag_link_win_machine_64 = '/MACHINE:X64'
$flag_link_win_debug = '/DEBUG'
$flag_link_win_pdb = '/PDB:'
$flag_link_win_path_output = '/OUT:'
$flag_no_optimization = '-O0'
$flag_optimize_fast = '-O2'
$flag_optimize_size = '-O1'
$flag_optimize_intrinsics = '-Oi'
$flag_path_output = '-o'
$flag_preprocess_non_intergrated = '-no-integrated-cpp'
$flag_profiling_debug = '-fdebug-info-for-profiling'
$flag_set_stack_size = '-stack='
$flag_syntax_only = '-fsyntax-only'
$flag_target_arch = '-target'
$flag_time_trace = '-ftime-trace'
$flag_verbose = '-v'
$flag_wall = '-Wall'
$flag_warning = '-W'
$flag_warnings_as_errors = '-Werror'
$flag_win_nologo = '/nologo'
$ignore_warning_ms_include = 'no-microsoft-include'
$ignore_warning_return_type_c_linkage = 'no-return-type-c-linkage'
$target_arch = Get-TargetArchClang
$warning_ignores = @(
$ignore_warning_ms_include,
$ignore_warning_return_type_c_linkage
)
# https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170
if ( $IsWindows ) {
$libraries = @(
'Kernel32' # For Windows API
# 'msvcrt', # For the C Runtime (Dynamically Linked)
# 'libucrt',
'libcmt' # For the C Runtime (Static Linkage)
)
}
function build
{
param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [array]$units, [string]$binary )
$result = $false
#Write-Host "build: clang"
$map = $binary -replace '\.(exe|dll)$', '.map'
$map = join-path $path_output (split-path $map -Leaf)
# This allows dll reloads at runtime to work (jankily, use below if not interested)
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
# $pdb = $binary -replace '\.(exe|dll)$', ".pdb"
$compiler_args += @(
$flag_no_color_diagnostics,
$flag_exceptions_disabled,
$flag_target_arch, $target_arch,
$flag_wall,
$flag_preprocess_non_intergrated
# $flag_section_data,
# $flag_section_functions,
)
if ( $verbose ) {
# $compiler_args += $flag_verbose
# $compiler_args += $flag_time_trace
}
if ( $optimize ) {
$compiler_args += $flag_optimize_fast
}
else {
$compiler_args += $flag_no_optimization
}
if ( $debug ) {
$compiler_args += ( $flag_define + 'Build_Debug=1' )
$compiler_args += $flag_debug, $flag_debug_codeview, $flag_profiling_debug
}
else {
$compiler_args += ( $flag_define + 'Build_Debug=0' )
}
$warning_ignores | ForEach-Object {
$compiler_args += $flag_warning + $_
}
$compiler_args += $includes | ForEach-Object { $flag_include + $_ }
$objects = @()
foreach ( $unit in $units )
{
$object = $unit -replace '\.(cpp|c)$', '.obj'
$object = join-path $path_output (split-path $object -Leaf)
$objects += $object
$unit_compiler_args = $compiler_args
$unit_compiler_args += ( $flag_path_output + $object )
$unit_compiler_args += $flag_compile, $unit
run-compiler $compiler $unit $unit_compiler_args
}
$linker_args += @(
$flag_link_win_machine_64,
$( $flag_link_win_path_output + $binary )
)
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
$linker_args += $flag_link_mapfile + $map
}
$libraries | ForEach-Object {
$linker_args += $_ + '.lib'
}
$linker_args += $objects
return run-linker $linker $binary $linker_args
}
function build-simple
{
param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
$result = $false
#Write-Host "build-simple: clang"
$object = $unit -replace '\.(cpp|c)$', '.obj'
$map = $unit -replace '\.(cpp|c)$', '.map'
$object = join-path $path_output (split-path $object -Leaf)
$map = join-path $path_output (split-path $map -Leaf)
# This allows dll reloads at runtime to work (jankily, use below if not interested)
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
# $pdb = $binary -replace '\.(exe|dll)$', ".pdb"
$compiler_args += @(
$flag_no_color_diagnostics,
$flag_exceptions_disabled,
$flag_target_arch, $target_arch,
$flag_wall,
$flag_preprocess_non_intergrated,
# $flag_section_data,
# $flag_section_functions,
( $flag_path_output + $object )
)
if ( $verbose ) {
# $compiler_args += $flag_verbose
# $compiler_args += $flag_time_trace
}
if ( $optimize ) {
$compiler_args += $flag_optimize_fast
}
else {
$compiler_args += $flag_no_optimization
}
if ( $debug ) {
$compiler_args += ( $flag_define + 'Build_Debug=1' )
$compiler_args += $flag_debug, $flag_debug_codeview, $flag_profiling_debug
}
else {
$compiler_args += ( $flag_define + 'Build_Debug=0' )
}
$warning_ignores | ForEach-Object {
$compiler_args += $flag_warning + $_
}
$compiler_args += $includes | ForEach-Object { $flag_include + $_ }
$compiler_args += $flag_compile, $unit
if ( (run-compiler $compiler $unit $compiler_args) -eq $false ) {
return $false
}
$linker_args += @(
$flag_link_win_machine_64,
$( $flag_link_win_path_output + $binary )
)
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
$linker_args += $flag_link_mapfile + $map
}
$libraries | ForEach-Object {
$linker_args += $_ + '.lib'
}
$linker_args += $object
return run-linker $linker $binary $linker_args
}
$compiler = 'clang++'
$linker = 'lld-link'
}
if ( $vendor -match "msvc" )
{
# https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category?view=msvc-170
$flag_all_c = '/TC'
$flag_all_cpp = '/TP'
$flag_compile = '/c'
$flag_debug = '/Zi'
$flag_define = '/D'
$flag_exceptions_disabled = '/EHsc-'
$flag_RTTI_disabled = '/GR-'
$flag_include = '/I'
$flag_full_src_path = '/FC'
$flag_nologo = '/nologo'
$flag_dll = '/LD'
$flag_dll_debug = '/LDd'
$flag_linker = '/link'
$flag_link_dll = '/DLL'
$flag_link_no_incremental = '/INCREMENTAL:NO'
$flag_link_mapfile = '/MAP:'
$flag_link_optimize_references = '/OPT:REF'
$flag_link_win_debug = '/DEBUG'
$flag_link_win_pdb = '/PDB:'
$flag_link_win_machine_32 = '/MACHINE:X86'
$flag_link_win_machine_64 = '/MACHINE:X64'
$flag_link_win_path_output = '/OUT:'
$flag_link_win_rt_dll = '/MD'
$flag_link_win_rt_dll_debug = '/MDd'
$flag_link_win_rt_static = '/MT'
$flag_link_win_rt_static_debug = '/MTd'
$flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE'
$flag_link_win_subsystem_windows = '/SUBSYSTEM:WINDOWS'
$flag_no_optimization = '/Od'
$flag_optimize_fast = '/O2'
$flag_optimize_size = '/O1'
$flag_optimize_intrinsics = '/Oi'
$flag_optimized_debug = '/Zo'
$flag_out_name = '/OUT:'
$flag_path_interm = '/Fo'
$flag_path_debug = '/Fd'
$flag_path_output = '/Fe'
$flag_preprocess_conform = '/Zc:preprocessor'
$flag_set_stack_size = '/F'
$flag_syntax_only = '/Zs'
$flag_wall = '/Wall'
$flag_warnings_as_errors = '/WX'
function build
{
param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [array]$units, [string]$binary )
$result = $false
#Write-Host "build-simple: msvc"
$map = $binary -replace '\.(exe|dll)$', '.map'
$map = join-path $path_output (split-path $map -Leaf)
# This allows dll reloads at runtime to work (jankily, use below if not interested)
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
# $pdb = $binary -replace '\.(exe|dll)$', ".pdb"
$compiler_args += @(
$flag_nologo,
# $flag_all_cpp,
$flag_exceptions_disabled,
( $flag_define + '_HAS_EXCEPTIONS=0' ),
$flag_RTTI_disabled,
$flag_preprocess_conform,
$flag_full_src_path,
( $flag_path_interm + $path_output + '\' ),
( $flag_path_output + $path_output + '\' )
)
if ( $verbose ) {
}
if ( $optimize ) {
$compiler_args += $flag_optimize_fast
}
else {
$compiler_args += $flag_no_optimization
}
if ( $debug )
{
$compiler_args += $flag_debug
$compiler_args += ( $flag_define + 'Build_Debug=1' )
$compiler_args += ( $flag_path_debug + $path_output + '\' )
$compiler_args += $flag_link_win_rt_static_debug
if ( $optimize ) {
$compiler_args += $flag_optimized_debug
}
}
else {
$compiler_args += ( $flag_define + 'Build_Debug=0' )
$compiler_args += $flag_link_win_rt_static
}
$compiler_args += $includes | ForEach-Object { $flag_include + $_ }
$objects = @()
foreach ( $unit in $units )
{
$object = $unit -replace '\.(cpp|c)$', '.obj'
$object = join-path $path_output (split-path $object -Leaf)
$objects += $object
$unit_compiler_args = $compiler_args
# $unit_compiler_args += ( $flag_path_output + $object )
$unit_compiler_args += $flag_compile, $unit
run-compiler $compiler $unit $unit_compiler_args
}
$linker_args += @(
$flag_nologo,
$flag_link_win_machine_64,
$flag_link_no_incremental,
( $flag_link_win_path_output + $binary )
)
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
$linker_args += $flag_link_mapfile + $map
}
else {
}
$linker_args += $objects
return run-linker $linker $binary $linker_args
}
function build-simple
{
param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
$result = $false
#Write-Host "build-simple: msvc"
$object = $unit -replace '\.(cpp|c)$', '.obj'
$map = $unit -replace '\.(cpp|c)$', '.map'
$object = join-path $path_output (split-path $object -Leaf)
$map = join-path $path_output (split-path $map -Leaf)
# This allows dll reloads at runtime to work (jankily, use below if not interested)
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
# $pdb = $binary -replace '\.(exe|dll)$', ".pdb"
$compiler_args += @(
$flag_nologo,
# $flag_all_cpp,
$flag_exceptions_disabled,
( $flag_define + '_HAS_EXCEPTIONS=0' ),
$flag_RTTI_disabled,
$flag_preprocess_conform,
$flag_full_src_path,
( $flag_path_interm + $path_output + '\' ),
( $flag_path_output + $path_output + '\' )
)
if ( $verbose ) {
}
if ( $optimize ) {
$compiler_args += $flag_optimize_fast
}
else {
$compiler_args += $flag_no_optimization
}
if ( $debug )
{
$compiler_args += $flag_debug
$compiler_args += ( $flag_define + 'Build_Debug=1' )
$compiler_args += ( $flag_path_debug + $path_output + '\' )
$compiler_args += $flag_link_win_rt_static_debug
if ( $optimize ) {
$compiler_args += $flag_optimized_debug
}
}
else {
$compiler_args += ( $flag_define + 'Build_Debug=0' )
$compiler_args += $flag_link_win_rt_static
}
$compiler_args += $includes | ForEach-Object { $flag_include + $_ }
$compiler_args += $flag_compile, $unit
if ( (run-compiler $compiler $unit $compiler_args) -eq $false ) {
return $false;
}
$linker_args += @(
$flag_nologo,
$flag_link_win_machine_64,
$flag_link_no_incremental,
( $flag_link_win_path_output + $binary )
)
if ( $debug ) {
$linker_args += $flag_link_win_debug
$linker_args += $flag_link_win_pdb + $pdb
$linker_args += $flag_link_mapfile + $map
}
else {
}
$linker_args += $object
return run-linker $linker $binary $linker_args
}
$compiler = 'cl'
$linker = 'link'
}