diff --git a/scripts/build.ci.ps1 b/scripts/build.ci.ps1 index 4f3d812..b7522c8 100644 --- a/scripts/build.ci.ps1 +++ b/scripts/build.ci.ps1 @@ -3,9 +3,17 @@ # That or just rewrite it in an sh script and call it a day. Import-Module ./helpers/target_arch.psm1 -$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1' +$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' + $path_root = git rev-parse --show-toplevel +Import-Module $target_arch +Import-Module $format_cpp + Push-Location $path_root #region Arguments @@ -52,290 +60,12 @@ if ( $bootstrap -eq $false -and $singleheader -eq $false -and $test -eq $false ) throw "No build target specified. One must be specified, this script will not assume one" } +. $vendor_toolchain +. $incremental_checks + write-host "Building gencpp with $vendor" write-host "Build Type: $(if ($release) {"Release"} else {"Debug"} )" -function run-compiler -{ - param( $compiler, $unit, $compiler_args ) - - write-host "`Compiling $unit" - 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 ( Test-Path($unit) ) { - write-host "$unit compile finished in $($time_taken.TotalMilliseconds) ms" - } - else { - write-host "Compile failed for $unit" -ForegroundColor Red - } -} - -function run-linker -{ - param( $linker, $binary, $linker_args ) - - write-host "`Linking $binary" - 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 ( Test-Path($binary) ) { - write-host "$binary linking finished in $($time_taken.TotalMilliseconds) ms" - } - else { - write-host "Linking failed for $binary" -ForegroundColor Red - } -} - -function run-compile-and-link -{ - param( $vendor, $unit, $compiler_args, $linker_args ) - - write-host "`Compiling & Linking $unit" - write-host "Compiler config:" - $compiler_args | ForEach-Object { - write-host $_ -ForegroundColor Cyan - } - write-host "Linker config:" - $linker_args | ForEach-Object { - write-host $_ -ForegroundColor Cyan - } - - $time_taken = Measure-Command { - & $vendor $compiler_args $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 ( Test-Path($binary) ) { - # write-host "$binary compile & link finished in $($time_taken.TotalMilliseconds) ms" - # } - # else { - # write-host "Compile & Link failed for $binary" -ForegroundColor Red - # } -} - -if ( $vendor -match "clang" ) -{ - # https://clang.llvm.org/docs/ClangCommandLineReference.html - $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_preprocess = '-E' - $flag_include = '-I' - $flag_library = '-l' - $flag_library_path = '-L' - $flag_link_win = '-Wl,' - $flag_link_win_subsystem_console = '/SUBSYSTEM:CONSOLE' - $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_path_output = '-o' - $flag_preprocess_non_intergrated = '-no-integrated-cpp' - $flag_profiling_debug = '-fdebug-info-for-profiling' - $flag_target_arch = '-target' - $flag_wall = '-Wall' - $flag_warning = '-W' - $flag_warning_as_error = '-Werror' - $flag_win_nologo = '/nologo' - - $ignore_warning_ms_include = 'no-microsoft-include' - - $target_arch = Get-TargetArchClang - - $warning_ignores = @( - $ignore_warning_ms_include - ) - - # https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170 - $libraries = @( - 'Kernel32' # For Windows API - # 'msvcrt', # For the C Runtime (Dynamically Linked) - # 'libucrt', - 'libcmt' # For the C Runtime (Static Linkage) - ) - - function build-simple - { - param( $includes, $unit, $executable ) - Write-Host "build-simple: clang" - - $object = $executable -replace '\.exe', '.obj' - $pdb = $executable -replace '\.exe', '.pdb' - - $compiler_args = @( - $flag_no_color_diagnostics, - $flag_target_arch, $target_arch, - $flag_wall, - $flag_preprocess_non_intergrated, - ( $flag_define + 'GEN_TIME' ), - # ( $flag_path_output + $object ), - ( $flag_path_output + $executable ) - ( $flag_include + $includes ) - ) - if ( $release -eq $false ) { - $compiler_args += ( $flag_define + 'Build_Debug' ) - $compiler_args += $flag_debug, $flag_debug_codeview, $flag_profiling_debug - $compiler_args += $flag_no_optimization - } - - $warning_ignores | ForEach-Object { - $compiler_args += $flag_warning + $_ - } - - # $compiler_args += $flag_preprocess - - # $compiler_args += $flag_compile, $unit - # run-compiler $compiler $unit $compiler_args - - $linker_args = @( - $flag_link_win_subsystem_console, - $flag_link_win_machine_64, - $( $flag_link_win_path_output + $executable ) - ) - if ( $release -eq $false ) { - $linker_args += $flag_link_win_debug - $linker_args += $flag_link_win_pdb + $pdb - } - else { - } - - $libraries | ForEach-Object { - $linker_args += $_ + '.lib' - } - - # $linker_args += $object - # run-linker $linker $executable $linker_args - - $compiler_args += $unit - # $linker_args += $object - run-compile-and-link $compiler $unit $compiler_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_compile = '/c' - $flag_debug = '/Zi' - $flag_define = '/D' - $flag_include = '/I' - $flag_full_src_path = '/FC' - $flag_nologo = '/nologo' - $flag_dll = '/LD' - $flag_dll_debug = '/LDd' - $flag_linker = '/link' - $flag_link_debug = '/DEBUG' - $flag_link_pdb = '/PDB:' - $flag_link_machine_32 = '/MACHINE:X86' - $flag_link_machine_64 = '/MACHINE:X64' - $flag_link_path_output = '/OUT:' - $flag_link_rt_dll = '/MD' - $flag_link_rt_dll_debug = '/MDd' - $flag_link_rt_static = '/MT' - $flag_link_rt_static_debug = '/MTd' - $flag_link_subsystem_console = '/SUBSYSTEM:CONSOLE' - $flag_link_subsystem_windows = '/SUBSYSTEM:WINDOWS' - $flag_no_optimization = '/Od' - $flag_out_name = '/OUT:' - $flag_path_interm = '/Fo' - $flag_path_debug = '/Fd' - $flag_path_output = '/Fe' - $flag_preprocess_conform = '/Zc:preprocessor' - - # This works because this project uses a single unit to build - function build-simple - { - param( $includes, $unit, $executable ) - Write-Host "build-simple: msvc" - - $object = $executable -replace '\.exe', '.obj' - $pdb = $executable -replace '\.exe', '.pdb' - - $compiler_args = @( - $flag_nologo, - $flag_preprocess_conform, - $flag_debug, - ( $flag_define + 'GEN_TIME' ), - $flag_full_src_path, - ( $flag_path_interm + $path_build + '\' ), - ( $flag_path_output + $path_build + '\' ) - ) - if ( $release -eq $false ) { - $compiler_args += ( $flag_define + 'Build_Debug' ) - $compiler_args += ( $flag_path_debug + $path_build + '\' ) - $compiler_args += $flag_link_rt_static_debug - $compiler_args += $flag_no_optimization - } - else { - $compiler_args += $flag_link_rt_static - } - $compiler_args += $includes | ForEach-Object { $flag_include + $_ } - $compiler_args += $flag_compile, $unit - run-compiler $compiler $unit $compiler_args - - $linker_args = @( - $flag_nologo, - $flag_link_machine_64, - $flag_link_subsystem_console, - ( $flag_link_path_output + $executable ) - ) - if ( $release -eq $false ) { - $linker_args += $flag_link_debug - $linker_args += $flag_link_pdb + $pdb - } - else { - } - - $linker_args += $object - run-linker $linker $executable $linker_args - } - - $compiler = 'cl' - $linker = 'link' -} -#endregion Configuration - #region Building $path_build = Join-Path $path_root build $path_project = Join-Path $path_root project @@ -359,11 +89,18 @@ if ( $bootstrap ) New-Item -ItemType Directory -Path $path_comp_gen } + $compiler_args = @() + $compiler_args += ( $flag_define + 'GEN_TIME' ) + + $linker_args = @( + $flag_link_win_subsystem_console + ) + $includes = @( $path_project) $unit = join-path $path_project "bootstrap.cpp" $executable = join-path $path_build "bootstrap.exe" - build-simple $includes $unit $executable + build-simple $path_build $includes $compiler_args $linker_args $unit $executable Push-Location $path_project if ( Test-Path( $executable ) ) { @@ -394,7 +131,14 @@ if ( $singleheader ) $unit = join-path $path_singleheader "singleheader.cpp" $executable = join-path $path_build "singleheader.exe" - build-simple $includes $unit $executable + $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_singleheader if ( Test-Path( $executable ) ) { @@ -431,7 +175,14 @@ if ( $test ) $unit = join-path $path_test "test.cpp" $executable = join-path $path_build "test.exe" - build-simple $includes $unit $executable + $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_test Write-Host $path_test @@ -449,29 +200,7 @@ if ( $test ) #endregion Building #region Formatting -function format-cpp -{ - param( $path, $include, $exclude ) - - # Format generated gencpp - Write-Host "`nBeginning format" - $formatParams = @( - '-i' # In-place - '-style=file:./scripts/.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 "`nFormatting complete in $($time_taken.TotalMilliseconds) ms" -} - +push-location $path_scripts if ( $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) { $path_gen = join-path $path_project gen @@ -485,6 +214,7 @@ if ( $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) $exclude = $null format-cpp $path_gen $include $exclude format-cpp $path_comp_gen @( 'ast_inlines.hpp', 'ecode.hpp', 'especifier.hpp', 'eoperator.hpp', 'etoktype.cpp' ) $null + } if ( $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp")) ) @@ -506,6 +236,7 @@ if ( $test -and $false ) $exclude = $null format-cpp $path_gen $include $exclude } +pop-location #endregion Formatting Pop-Location # $path_root diff --git a/scripts/helpers/devshell.ps1 b/scripts/helpers/devshell.ps1 index dc68bd3..33ca0ce 100644 --- a/scripts/helpers/devshell.ps1 +++ b/scripts/helpers/devshell.ps1 @@ -23,5 +23,6 @@ if ( -not (Test-Path $vs_devshell) ) { # Launch the Visual Studio Developer Shell Push-Location +write-host @args & $vs_devshell @args Pop-Location diff --git a/scripts/helpers/format_cpp.psm1 b/scripts/helpers/format_cpp.psm1 new file mode 100644 index 0000000..e975494 --- /dev/null +++ b/scripts/helpers/format_cpp.psm1 @@ -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 diff --git a/scripts/helpers/incremental_checks.ps1 b/scripts/helpers/incremental_checks.ps1 new file mode 100644 index 0000000..97802ce --- /dev/null +++ b/scripts/helpers/incremental_checks.ps1 @@ -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 +} diff --git a/scripts/helpers/vendor_toolchain.ps1 b/scripts/helpers/vendor_toolchain.ps1 new file mode 100644 index 0000000..3d38f65 --- /dev/null +++ b/scripts/helpers/vendor_toolchain.ps1 @@ -0,0 +1,365 @@ +# 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 = '/TC' + $flag_all_cpp = '/TP' + $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-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', '.obj' + $map = $unit -replace '\.cpp', '.map' + $object = join-path $path_output (split-path $object -Leaf) + $map = join-path $path_output (split-path $map -Leaf) + + # The PDB file has to also be time-stamped so that we can reload the DLL at runtime + $pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb" + + $compiler_args += @( + ( $flag_define + 'INTELLISENSE_DIRECTIVES=0' ), + $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' + + # This works because this project uses a single unit to build + 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)$', '.obj' + $map = $unit -replace '\.(cpp)$', '.map' + $object = join-path $path_output (split-path $object -Leaf) + $map = join-path $path_output (split-path $map -Leaf) + + # The PDB file has to also be time-stamped so that we can reload the DLL at runtime + $pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb" + + $compiler_args += @( + $flag_nologo, + ( $flag_define + 'INTELLISENSE_DIRECTIVES=0'), + # $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' +}