diff --git a/scripts/build.ci.ps1 b/scripts/build.ci.ps1 index acaabbe..d35ef22 100644 --- a/scripts/build.ci.ps1 +++ b/scripts/build.ci.ps1 @@ -22,6 +22,7 @@ Push-Location $path_root $verbose = $false [bool] $bootstrap = $false [bool] $singleheader = $false +[bool] $unreal = $false [bool] $test = $false [array] $vendors = @( "clang", "msvc" ) @@ -36,6 +37,7 @@ if ( $args ) { $args | ForEach-Object { "debug" { $release = $false } "bootstrap" { $bootstrap = $true } "singleheader" { $singleheader = $true } + "unreal" { $unreal = $true } "test" { $test = $true } } }} @@ -64,7 +66,7 @@ else { $optimize = $true } -if ( $bootstrap -eq $false -and $singleheader -eq $false -and $test -eq $false ) { +if ( $bootstrap -eq $false -and $singleheader -eq $false -and $unreal -eq $false -and $test -eq $false ) { throw "No build target specified. One must be specified, this script will not assume one" } @@ -80,6 +82,7 @@ $path_build = Join-Path $path_root build $path_project = Join-Path $path_root project $path_scripts = Join-Path $path_root scripts $path_singleheader = Join-Path $path_root singleheader +$path_unreal = Join-Path $path_root unreal_engine $path_test = Join-Path $path_root test if ( $bootstrap ) @@ -162,6 +165,44 @@ if ( $singleheader ) Pop-Location } +if ( $unreal ) +{ + $path_build = join-path $path_unreal build + $path_gen = join-path $path_unreal gen + + if ( -not(Test-Path($path_build) )) { + New-Item -ItemType Directory -Path $path_build + } + if ( -not(Test-Path($path_gen) )) { + New-Item -ItemType Directory -Path $path_gen + } + + $includes = @( $path_project ) + $unit = join-path $path_unreal "unreal.cpp" + $executable = join-path $path_build "unreal.exe" + + $compiler_args = @() + $compiler_args += ( $flag_define + 'GEN_TIME' ) + + $linker_args = @( + $flag_link_win_subsystem_console + ) + + build-simple $path_build $includes $compiler_args $linker_args $unit $executable + + Push-Location $path_unreal + if ( Test-Path( $executable ) ) { + write-host "`nRunning unreal variant generator" + $time_taken = Measure-Command { & $executable + | ForEach-Object { + write-host `t $_ -ForegroundColor Green + } + } + write-host "`n Unreal variant generator completed in $($time_taken.TotalMilliseconds) ms" + } + Pop-Location +} + if ( $test ) { $path_gen = join-path $path_test gen @@ -229,7 +270,6 @@ push-location $path_scripts if ( $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) { $path_gen = join-path $path_project gen - $path_comp_gen = join-path $path_project components/gen $include = @( 'gen.hpp', 'gen.cpp', 'gen.dep.hpp', 'gen.dep.cpp', @@ -252,6 +292,19 @@ if ( $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp")) format-cpp $path_gen $include $exclude } +if ( $unreal -and (Test-Path( Join-Path $path_unreal "gen/gen.hpp")) ) +{ + $path_gen = join-path $path_unreal gen + $include = @( + 'gen.hpp', 'gen.cpp', + 'gen.dep.hpp', 'gen.dep.cpp', + 'gen.builder.hpp', 'gen.builder.cpp' + 'gen.scanner.hpp', 'gen.scanner.cpp' + ) + $exclude = $null + format-cpp $path_gen $include $exclude +} + if ( $test -and $false ) { $path_gen = join-path $path_test gen diff --git a/scripts/unreal.refactor b/scripts/unreal.refactor new file mode 100644 index 0000000..babdf22 --- /dev/null +++ b/scripts/unreal.refactor @@ -0,0 +1,25 @@ + __VERSION 1 + +// This is a example template to be used with the refactor program +// Use it to refactor the naming convention of this library to your own. +// Can be used as an aid to help use use your project's implementation if it fullfills the dependencies of this project. +// Example: Most likely have a memory and string library already, just rename the functions and make sure the args are the same. +// Program: https://github.com/Ed94/refactor + +// NOTE: Due to the current limitations of the program, not every symbol in the library can be renamed. +// This is due to the program not actually parsing C/C++. + +// not : Ignore +// include : #includes +// word : Alphanumeric or underscore +// namespace : Prefix search and replace (c-namspaces). +// regex : Unavailable in __VERSION 1. + +// Precedence (highest to lowest): +// word, namespace, regex + +// Gen Macro namespace +// namespace GEN_, new_namespace_ + +word forceinline, FORCEINLINE +word spec_forceinline, spec_FORCEINLINE diff --git a/unreal_engine/components/dependencies.header_start.hpp b/unreal_engine/components/dependencies.header_start.hpp new file mode 100644 index 0000000..e314c43 --- /dev/null +++ b/unreal_engine/components/dependencies.header_start.hpp @@ -0,0 +1,126 @@ +#pragma once + +#pragma region Platform Detection + +/* Platform architecture */ + +#if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ ) +# ifndef GEN_ARCH_64_BIT +# define GEN_ARCH_64_BIT 1 +# endif +#else +# ifndef GEN_ARCH_32_BItxt_StrCaT +# define GEN_ARCH_32_BIT 1 +# endif +#endif + +/* Platform OS */ + +#if defined( _WIN32 ) || defined( _WIN64 ) +# ifndef GEN_SYSTEM_WINDOWS +# define GEN_SYSTEM_WINDOWS 1 +# endif +#elif defined( __APPLE__ ) && defined( __MACH__ ) +# ifndef GEN_SYSTEM_OSX +# define GEN_SYSTEM_OSX 1 +# endif +# ifndef GEN_SYSTEM_MACOS +# define GEN_SYSTEM_MACOS 1 +# endif +# include +# if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1 +# ifndef GEN_SYSTEM_IOS +# define GEN_SYSTEM_IOS 1 +# endif +# endif +#elif defined( __unix__ ) +# ifndef GEN_SYSTEM_UNIX +# define GEN_SYSTEM_UNIX 1 +# endif +# if defined( ANDROID ) || defined( __ANDROID__ ) +# ifndef GEN_SYSTEM_ANDROID +# define GEN_SYSTEM_ANDROID 1 +# endif +# ifndef GEN_SYSTEM_LINUX +# define GEN_SYSTEM_LINUX 1 +# endif +# elif defined( __linux__ ) +# ifndef GEN_SYSTEM_LINUX +# define GEN_SYSTEM_LINUX 1 +# endif +# elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) +# ifndef GEN_SYSTEM_FREEBSD +# define GEN_SYSTEM_FREEBSD 1 +# endif +# elif defined( __OpenBSD__ ) +# ifndef GEN_SYSTEM_OPENBSD +# define GEN_SYSTEM_OPENBSD 1 +# endif +# elif defined( __EMSCRIPTEN__ ) +# ifndef GEN_SYSTEM_EMSCRIPTEN +# define GEN_SYSTEM_EMSCRIPTEN 1 +# endif +# elif defined( __CYGWIN__ ) +# ifndef GEN_SYSTEM_CYGWIN +# define GEN_SYSTEM_CYGWIN 1 +# endif +# else +# error This UNIX operating system is not supported +# endif +#else +# error This operating system is not supported +#endif + +/* Platform compiler */ + +#if defined( _MSC_VER ) +# define GEN_COMPILER_MSVC 1 +#elif defined( __GNUC__ ) +# define GEN_COMPILER_GCC 1 +#elif defined( __clang__ ) +# define GEN_COMPILER_CLANG 1 +#elif defined( __MINGW32__ ) +# define GEN_COMPILER_MINGW 1 +# error Unknown compiler +#endif + +#if defined( __has_attribute ) +# define GEN_HAS_ATTRIBUTE( attribute ) __has_attribute( attribute ) +#else +# define GEN_HAS_ATTRIBUTE( attribute ) ( 0 ) +#endif + +#if defined(GEN_GCC_VERSION_CHECK) +# undef GEN_GCC_VERSION_CHECK +#endif +#if defined(GEN_GCC_VERSION) +# define GEN_GCC_VERSION_CHECK(major,minor,patch) (GEN_GCC_VERSION >= GEN_VERSION_ENCODE(major, minor, patch)) +#else +# define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#define GEN_DEF_INLINE static +#define GEN_IMPL_INLINE static inline + +#pragma endregion Platform Detection + +#pragma region Mandatory Includes + +# include +# include + +# if defined( GEN_SYSTEM_WINDOWS ) +# include +# endif + +#pragma endregion Mandatory Includes + +#ifdef GEN_DONT_USE_NAMESPACE +# define GEN_NS +# define GEN_NS_BEGIN +# define GEN_NS_END +#else +# define GEN_NS gen:: +# define GEN_NS_BEGIN namespace gen { +# define GEN_NS_END } +#endif diff --git a/unreal_engine/components/header_start.hpp b/unreal_engine/components/header_start.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/unreal_engine/unreal.cpp b/unreal_engine/unreal.cpp index 198fd56..389eb8f 100644 --- a/unreal_engine/unreal.cpp +++ b/unreal_engine/unreal.cpp @@ -4,6 +4,7 @@ #include "gen.cpp" #include "helpers/push_ignores.inline.hpp" +#include "helpers/helper.hpp" GEN_NS_BEGIN #include "dependencies/parsing.cpp" @@ -57,4 +58,139 @@ int gen_main() Code ue_forceinline = code_str(FORCEINLINE); // Code + + // gen_dep.hpp + { + CodeBody header_start = def_body( CodeT::Global_Body ); + { + FileContents content = file_read_contents( GlobalAllocator, true, project_dir "dependencies/header_start.hpp" ); + CodeBody ori_header_start = parse_global_body( StrC { content.size, (char const*)content.data }); + + for (Code code = ori_header_start.begin(); + code != ori_header_start.end(); + ++ code ) + { + header_start.append(code); + if (code->Type == CodeT::Preprocess_Pragma && code->Content.starts_with(txt("once"))) + { + header_start.append( fmt_newline ); + header_start.append( push_ignores ); + } + } + } + + CodeBody macros = def_body( CodeT::Global_Body ); + { + FileContents content = file_read_contents( GlobalAllocator, true, project_dir "dependencies/macros.hpp" ); + CodeBody ori_macros = parse_global_body( StrC { content.size, (char const*)content.data }); + + for (Code code = ori_macros.begin(); + code != ori_macros.end(); + ++ code ) + { + switch (code->Type) + { + using namespace ECode; + case Preprocess_Define: + { + CodeDefine define = code.cast(); + if ( define->Name.starts_with(txt("global")) ) + { + macros.append(parse_global_body(txt("#define global // Global variables"))); + continue; + } + + macros.append(define); + } + break; + + case Preprocess_Pragma: + { + macros.append(code); + continue; + + local_persist bool found = false; + if (found) + { + macros.append(code); + continue; + } + + if (code->Content.starts_with(txt("region ForceInline Definition"))) + { + macros.append(code); + ++ code; + + CodeBody replacement = parse_global_body(StrC(txt( +R"(#ifdef GEN_COMPILER_MSVC + #define FORCEINLINE __forceinline + #define neverinline __declspec( noinline ) +#elif defined( GEN_COMPILER_GCC ) + #define FORCEINLINE inline __attribute__( ( __always_inline__ ) ) + #define neverinline __attribute__( ( __noinline__ ) ) +#elif defined( GEN_COMPILER_CLANG ) + #if __has_attribute( __always_inline__ ) + #define FORCEINLINE inline __attribute__( ( __always_inline__ ) ) + #define neverinline __attribute__( ( __noinline__ ) ) + #else + #define FORCEINLINE + #define neverinline + #endif +#else + #define FORCEINLINE + #define neverinline +#endif)"))); + macros.append(replacement); + + while (code->Type != ECode::Preprocess_Pragma + || ! code->Content.starts_with(txt("endregion ForceInline Definition"))) + ++ code; + + macros.append( code ); + found = true; + } + } + break; + + default: + macros.append(code); + break; + } + } + } + + Code basic_types = scan_file( project_dir "dependencies/basic_types.hpp" ); + Code debug = scan_file( project_dir "dependencies/debug.hpp" ); + Code memory = scan_file( project_dir "dependencies/memory.hpp" ); + Code string_ops = scan_file( project_dir "dependencies/string_ops.hpp" ); + Code printing = scan_file( project_dir "dependencies/printing.hpp" ); + Code containers = scan_file( project_dir "dependencies/containers.hpp" ); + Code hashing = scan_file( project_dir "dependencies/hashing.hpp" ); + Code strings = scan_file( project_dir "dependencies/strings.hpp" ); + Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" ); + Code timing = scan_file( project_dir "dependencies/timing.hpp" ); + + Builder + header = Builder::open("gen/gen.dep.hpp"); + header.print_fmt( generation_notice ); + header.print( header_start ); + header.print_fmt( "\nGEN_NS_BEGIN\n" ); + + header.print( macros ); + header.print( basic_types ); + header.print( debug ); + header.print( memory ); + header.print( string_ops ); + header.print( printing ); + header.print( containers ); + header.print( hashing ); + header.print( strings ); + header.print( filesystem ); + header.print( timing ); + + header.print_fmt( "\nGEN_NS_END\n" ); + header.print( fmt_newline ); + header.print( pop_ignores ); + header.write(); + } }