diff --git a/code/tools/fxd/.helpers.psm1 b/code/tools/fxd/.helpers.psm1 new file mode 100644 index 0000000000..4f3c1fb5fe --- /dev/null +++ b/code/tools/fxd/.helpers.psm1 @@ -0,0 +1,35 @@ +# from http://stackoverflow.com/questions/2124753/how-i-can-use-powershell-with-the-visual-studio-command-prompt +function Invoke-BatchFile +{ + param([string]$Path) + + $tempFile = [IO.Path]::GetTempFileName() + + ## Store the output of cmd.exe. We also ask cmd.exe to output + ## the environment table after the batch file completesecho + cmd.exe /c " `"$Path`" && set > `"$tempFile`" " + + ## Go through the environment variables in the temp file. + ## For each of them, set the variable in our local environment. + Get-Content $tempFile | Foreach-Object { + if ($_ -match "^(.*?)=(.*)$") + { + Set-Content "env:\$($matches[1])" $matches[2] + } + } + + Remove-Item $tempFile +} + + +function Invoke-VSInit { + $VCDir = (& "$PSScriptRoot\..\ci\vswhere.exe" -latest -prerelease -property installationPath -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64) + + if (!(Test-Path Env:\DevEnvDir)) { + Invoke-BatchFile "$VCDir\VC\Auxiliary\Build\vcvars64.bat" + } + + if (!(Test-Path Env:\DevEnvDir)) { + throw "No VC path!" + } +} diff --git a/code/tools/fxd/build.ps1 b/code/tools/fxd/build.ps1 new file mode 100644 index 0000000000..cfd1a0aa1f --- /dev/null +++ b/code/tools/fxd/build.ps1 @@ -0,0 +1,32 @@ +<# +.Synopsis +Runs MSBuild on the core native project. +#> + +[CmdletBinding(PositionalBinding=$false)] +param ( + [string] $Configuration = 'Debug', + [string] $Game = 'five' +) + +Import-Module $PSScriptRoot\.helpers.psm1 + +Invoke-VSInit + +$BuildPath = "$PSScriptRoot\..\..\build\$Game" + +if ($Game -eq "server") { + $BuildPath += "\windows" +} + +if (!(Test-Path $BuildPath\CitizenMP.sln)) { + .\gen.ps1 -Game $Game +} + +Remove-Item env:\platform + +Invoke-Expression "& $PSScriptRoot\..\ci\nuget.exe restore $BuildPath\CitizenMP.sln" + +$env:UseMultiToolTask = "true" +$env:EnforceProcessCountAcrossBuilds = "true" +msbuild /p:configuration=$Configuration /m @args $BuildPath\CitizenMP.sln diff --git a/code/tools/fxd/dev-sdk.ps1 b/code/tools/fxd/dev-sdk.ps1 new file mode 100644 index 0000000000..94c025d0c6 --- /dev/null +++ b/code/tools/fxd/dev-sdk.ps1 @@ -0,0 +1,11 @@ +<# +.Synopsis +Runs the FxDK dev server for Five. +#> + +$ErrorActionPreference = 'Stop' + +Push-Location $PSScriptRoot\..\..\..\ext\sdk +cmd.exe /c yarn install +cmd.exe /c yarn start +Pop-Location diff --git a/code/tools/fxd/gen.ps1 b/code/tools/fxd/gen.ps1 new file mode 100644 index 0000000000..35b8841994 --- /dev/null +++ b/code/tools/fxd/gen.ps1 @@ -0,0 +1,26 @@ +<# +.Synopsis +Generates Visual Studio project files for the specified Cfx project. + +.Description +This command can be used to (re)generate Visual Studio project files for a game specified on the command line. + +By specifying the -Game argument, a different game can be selected. + +.Parameter Game +Specifies the game to build project files for. This should be any of 'five', 'ny', 'server' or 'rdr3'. + +.Example +fxd gen + +.Example +fxd gen -game server +#> +[CmdletBinding(PositionalBinding=$false)] +param( + [string]$Game = 'five' +) + +Push-Location "$PSScriptRoot\..\..\" +& "$PSScriptRoot\..\ci\premake5.exe" vs2019 "--game=$Game" +Pop-Location diff --git a/code/tools/fxd/get-chrome.ps1 b/code/tools/fxd/get-chrome.ps1 new file mode 100644 index 0000000000..2ecf923a10 --- /dev/null +++ b/code/tools/fxd/get-chrome.ps1 @@ -0,0 +1,17 @@ +<# +.Synopsis +Downloads the 64-bit CEF dependency to vendor/cef/. +#> + +$WorkDir = "$PSScriptRoot\..\..\..\" +$SaveDir = "$WorkDir\code\build\" + +$CefName = (Get-Content $PSScriptRoot\..\ci\build.ps1 | Select-String "CefName =") -replace ".*`"(.*?)`"", "`$1" + +if (!(Test-Path "$SaveDir\$CefName.zip")) { + curl.exe -Lo "$SaveDir\$CefName.zip" "https://runtime.fivem.net/build/cef/$CefName.zip" +} + +& $env:WINDIR\system32\tar.exe -C $WorkDir\vendor\cef -xf "$SaveDir\$CefName.zip" +Copy-Item -Force $WorkDir\vendor\cef\$CefName\* $WorkDir\vendor\cef\ +Remove-Item -Recurse $WorkDir\vendor\cef\$CefName\ diff --git a/code/tools/fxd/help.ps1 b/code/tools/fxd/help.ps1 new file mode 100644 index 0000000000..c400d80073 --- /dev/null +++ b/code/tools/fxd/help.ps1 @@ -0,0 +1,61 @@ +<# +.Synopsis +The help command. +#> + +function Get-Sections($text) +{ + $sectionHash = @{} # collection sections keyed by section name + $sectionOrder = @() # remember insertion order + $rowNum = 0 + $lowBound = 0 + $sectionName = "" + # Handle corner case of no help defined for a given function, + # where help returned just 1 row containing the syntax without an indent. + if ($helpText.Count -eq 1) { $sectionName = $SYNTAX_SECTION; $rowNum = 1 } + else { + $text | ForEach-Object { + # The normal help text has section headers (NAME, SYNOPSIS, SYNTAX, DESCRIPTION, etc.) + # at the start of a line and everything else indented. + # Thus, this signals a new section: + if ($_ -match "^[A-Z]") { + Add-HelpSection $sectionName $text $lowBound ([ref]$sectionHash) ([ref]$sectionOrder)# output prior section + $sectionName = $_ + $lowBound = $rowNum + 1 + } + # Add separate section title for examples (which standard help lacks). + elseif ($_ -match "----\s+EXAMPLE 1\s+----") { + Add-HelpSection $sectionName $text $lowBound ([ref]$sectionHash) ([ref]$sectionOrder)# output prior section + $sectionName = $EXAMPLES_SECTION + $lowBound = $rowNum + } + $rowNum++ + } + } + Add-HelpSection $sectionName $text $lowBound ([ref]$sectionHash) ([ref]$sectionOrder)# output final section + $sectionHash, $sectionOrder +} + +function Add-HelpSection($sectionName, $text, $lowBound, [ref]$hash, [ref]$order) +{ + if ($sectionName) { # output previously collected section + $hash.value[$sectionName] = $text[$lowBound..($rowNum-1)] + $order.value += $sectionName + } +} + +"# fxd: the cfx.re developer utility" +"# https://cfx.re/" + +"" + +"usage: fxd [args]" + +foreach ($CommandScript in Get-ChildItem $PSScriptRoot) { + if ($CommandScript.BaseName[0] -eq '.') { + continue; + } + + $helps = Get-Sections (Get-Help $CommandScript | Out-String -Stream -Width 16384) + "- fxd $($CommandScript.BaseName): $($helps.Synopsis?.Trim() ?? 'No help.')" +} diff --git a/code/tools/fxd/natives.ps1 b/code/tools/fxd/natives.ps1 new file mode 100644 index 0000000000..8a193fdfd6 --- /dev/null +++ b/code/tools/fxd/natives.ps1 @@ -0,0 +1,6 @@ +<# +.Synopsis +Downloads and regenerates natives for all Cfx projects. +#> + +& "$PSScriptRoot\..\..\..\prebuild_natives.cmd" diff --git a/code/tools/fxd/run-sdk.ps1 b/code/tools/fxd/run-sdk.ps1 new file mode 100644 index 0000000000..c056282238 --- /dev/null +++ b/code/tools/fxd/run-sdk.ps1 @@ -0,0 +1,9 @@ +<# +.Synopsis +Starts Five, listening to the FxDK dev server. +#> + +Push-Location $PSScriptRoot\..\..\bin\five\debug +$SdkDir = (Resolve-Path $PSScriptRoot\..\..\..\ext\sdk\resources\sdk-root\).Path.TrimEnd("\").Replace("\", "/") +$LowercaseComputerName = $env:COMPUTERNAME.ToLowerInvariant() +.\FiveM.exe -fxdk +set sdk_url "http://${LowercaseComputerName}:3000/" +set sdk_root_path "$SdkDir" diff --git a/code/tools/fxd/vs.ps1 b/code/tools/fxd/vs.ps1 new file mode 100644 index 0000000000..b1e96d8d56 --- /dev/null +++ b/code/tools/fxd/vs.ps1 @@ -0,0 +1,30 @@ +<# +.Synopsis +Opens Visual Studio for the native project. +#> + +[CmdletBinding(PositionalBinding=$false)] +param ( + [string] $Game = 'five' +) + +Import-Module $PSScriptRoot\.helpers.psm1 + +Invoke-VSInit + +$BuildPath = "$PSScriptRoot\..\..\build\$Game" + +if ($Game -eq "server") { + $BuildPath += "\windows" +} + +if (!(Test-Path $BuildPath\CitizenMP.sln)) { + .\gen.ps1 -Game $Game +} + +Invoke-Expression "& $PSScriptRoot\..\ci\nuget.exe restore $BuildPath\CitizenMP.sln" + +$CurBranch = (git branch --show-current) -replace '[-/\\]', '_' + +Copy-Item -Force $BuildPath\CitizenMP.sln $BuildPath\CitizenMP_${Game}_${CurBranch}.sln +devenv.exe "$BuildPath\CitizenMP_${Game}_${CurBranch}.sln" diff --git a/fxd.cmd b/fxd.cmd new file mode 100644 index 0000000000..48cab8ad0d --- /dev/null +++ b/fxd.cmd @@ -0,0 +1,9 @@ +@echo off +where /q pwsh + +if errorlevel 1 ( + echo You need to have PowerShell 7 installed to run the fxd utility. + exit /B 0 +) + +pwsh .\fxd.ps1 %* \ No newline at end of file diff --git a/fxd.ps1 b/fxd.ps1 new file mode 100644 index 0000000000..359e726ae9 --- /dev/null +++ b/fxd.ps1 @@ -0,0 +1,37 @@ +param( + $Command +) + +$ErrorActionPreference = 'Stop' + + +if (!$Command) { + $Command = 'help' +} + +$CommandScript = "$PSScriptRoot\code\tools\fxd\$Command.ps1" + +if (!(Test-Path $CommandScript)) { + "fxd: invalid command '$Command' - run 'fxd help' for help" + return +} + +if ($args.Contains('-?') -or $args.Contains('-help') -or $args.Contains('--help') -or $args.Contains('/?')) { + $helpArgs = ,($args | Select-Object -Skip 1) + + if ($null -eq $helpArgs[0]) { + $helpArgs = @() + } + + & "Get-Help" $CommandScript @helpArgs | + Out-String | + ForEach-Object { + $_ ` + -replace "[^\s]*\\(.*?)\.ps1", "fxd `$1" ` + -replace "Get-Help fxd ([^ ]+)", "fxd `$1 -?" + } + return +} + +$moreArgs = $args +Invoke-Expression "$CommandScript @moreArgs" \ No newline at end of file