├── gitversion.yml ├── delphi-build.yml └── README.md /gitversion.yml: -------------------------------------------------------------------------------- 1 | # Runs GitVersion to determine the SemVer for the build based on git commit history. 2 | # This version is then stashed in pipeline variable 'gitversion' which may then be 3 | # referenced in subsequent pipeline steps as $(gitversion). 4 | # 5 | # This version is also used to set the label for the Azure DevOps pipeline run. 6 | # 7 | # NOTE: 8 | # This template expects and requires that GitVersion is installed on the build 9 | # machine (https://github.com/GitTools/GitVersion) 10 | # 11 | # Install on Windows using chocolatey: choco install GitVersion.Portable 12 | # 13 | # The Git command-line client is also required (not by GitVersion itself but due 14 | # the need to run Git commands to sync tags). 15 | 16 | steps: 17 | - powershell: | 18 | # First make sure that local tags reflect remote tags (otherwise any which were 19 | # deleted in the remote will still be in the local repo). The two commands that 20 | # follow first delete ALL local tags then fetch tags from the remote) 21 | 22 | git tag -l | %{git tag -d $_} 23 | git fetch --tags 24 | 25 | # Now we can run GitVersion, confident that any tag-based versioning will reflect 26 | # the tags in the repo. 27 | 28 | $GitVersion = GitVersion | ConvertFrom-Json 29 | 30 | # Set output variables. To consume these in subsequent steps map the output 31 | # variables as job variables for those jobs 32 | 33 | Write-Host "##vso[task.setvariable variable=Major;isOutput=true]$($GitVersion.Major)" 34 | Write-Host "##vso[task.setvariable variable=Minor;isOutput=true]$($GitVersion.Minor)" 35 | Write-Host "##vso[task.setvariable variable=Patch;isOutput=true]$($GitVersion.Patch)" 36 | Write-Host "##vso[task.setvariable variable=PreReleaseLabel;isOutput=true]$($GitVersion.PreReleaseLabel)" 37 | Write-Host "##vso[task.setvariable variable=PreReleaseNumber;isOutput=true]$($GitVersion.PreReleaseNumber)" 38 | 39 | Write-Host "##vso[task.setvariable variable=SemVer;isOutput=true]$($GitVersion.SemVer)" 40 | 41 | Write-Host "##vso[build.updatebuildnumber]$($GitVersion.SemVer)" 42 | name: GitVersion 43 | displayName: GitVersion 44 | -------------------------------------------------------------------------------- /delphi-build.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | delphiVersion: '' 3 | project: '' 4 | appType: 'CONSOLE' # CONSOLE (default) or GUI 5 | platform: 'x86' 6 | searchPath: '' 7 | unitScopes: 'System;System.Win;Vcl;WinApi' 8 | fixPack: 'true' 9 | preBuild: [] 10 | preBuildInline: '' 11 | postBuild: [] 12 | postBuildInline: '' 13 | 14 | steps: 15 | - ${{ parameters.preBuild }} 16 | - powershell: | 17 | function CreateDir 18 | { 19 | param([string]$path) 20 | if (-Not(Test-Path $path)) { New-Item $path -ItemType directory | Out-Null } 21 | } 22 | 23 | function Delete 24 | { 25 | param([string]$item) 26 | if (Test-Path $item) { Remove-Item $item | Out-Null } 27 | } 28 | 29 | $dVer = '${{ parameters.delphiVersion }}' 30 | $project = '${{ parameters.project }}' 31 | $appType = '${{ parameters.appType }}' 32 | $platform = '${{ parameters.platform }}' 33 | $uses = '${{ parameters.searchPath }}' 34 | $unitScopes = '${{ parameters.unitScopes }}' 35 | $fixPack = '${{ parameters.fixPack }}' 36 | $verbose = '${{ parameters.verbose }}' 37 | 38 | # Human meaningful into useful 39 | 40 | $bits = if($platform -eq 'x64') {'64'} else {'32'} 41 | 42 | $verMap = @{ '2'=90; '3'=100; '4'=120; '5'=130; '6'=140; '7'=150; 43 | '2005'=170; '2006'=180; '2007'=185; '2009'=200; '2010'=210; 44 | 'xe'=220; 'xe2'=230; 'xe3'=240; 'xe4'=250; 'xe5'=260; 'xe6'=270; 'xe7'=280; 'xe8'=290; 45 | '10'=300; '10.1'=310; '10.2'=320; '10.3'=330; '10.4'=340 } 46 | 47 | if ($verMap.ContainsKey($dVer)) { $d = $verMap[$dVer] } 48 | else { Write-Host "##vso[task.logissue type=error]Delphi $dVer is not supported" 49 | exit } 50 | 51 | $dXE = 220 52 | 53 | # Useful references 54 | 55 | $cd = Get-Location 56 | $bin = Join-Path $cd '\.bin' 57 | $results = Join-Path $cd '\.results' 58 | 59 | CreateDir('.bin') 60 | CreateDir('.results') 61 | 62 | $dprName = $(Split-Path -Leaf $project) 63 | $dprPath = $(Split-Path -Path $project) 64 | 65 | $cfg = $dprName + '.cfg' 66 | $dpr = $dprName + '.dpr' 67 | $exe = Join-Path $bin $($dprName + '.exe') 68 | 69 | $dr = Join-Path 'c:\dcc' $dVer 70 | $db = Join-Path $dr 'bin' 71 | $dl = Join-Path $dr 'lib' 72 | 73 | if (-Not(Test-Path $db)) { 74 | Write-Host "##vso[task.complete result=Skipped;]Delphi $dVer not available on this machine." 75 | exit } 76 | 77 | # If an IDE FixPack compiler is found, use that instead. 78 | 79 | $dcc = $db + '\dcc' + $bits + '.exe' 80 | 81 | if($fixPack -eq 'true') { 82 | Write-Host 'Checking for IDE FixPack compilers' 83 | 84 | $dccSpeed = $db + '\dcc' + $bits + 'speed.exe' 85 | $fastDcc = $db + '\fastdcc' + $bits + '.exe' 86 | 87 | if (Test-Path $dccSpeed) { $dcc = $dccSpeed } 88 | elseif (Test-Path $fastDcc) { $dcc = $fastDcc } } 89 | 90 | # Setup lib and search path 91 | 92 | if ($d -eq $dXE) { $dl = $dl + '\win32\release' } 93 | elseif ($d -gt $dXE) { $dl = $dl + '\win' + $bits + '\release' } 94 | 95 | $uses = $dl + ';' + $uses 96 | 97 | Set-Location $dprPath 98 | try { 99 | # Remove any previous build and config 100 | 101 | Delete($exe) 102 | Delete($cfg) 103 | Delete($('dcc' + $bits + '.cfg')) 104 | 105 | New-Item $cfg -ItemType file | Out-Null 106 | 107 | Add-Content $cfg $('-D' + $appType) 108 | Add-Content $cfg $('-E' + $bin) 109 | Add-Content $cfg $('-N' + $bin) 110 | Add-Content $cfg $('-U' + $uses) 111 | if ($d -gt $dXE) { Add-Content $cfg $('-NS' + $unitScopes) } 112 | 113 | ${{ parameters.preBuildInline }} 114 | 115 | Write-Host $('Config [' + $cfg + ']:') 116 | type $cfg 117 | 118 | Copy-Item $cfg $("dcc$bits.cfg") 119 | 120 | # Invoke the compiler 121 | $cmd = $dcc + ' ' + $dpr 122 | $out = 'dccoutput.txt' 123 | if ($appType -eq 'CONSOLE') { $cmd = $cmd + ' -CC' } 124 | 125 | Write-Host $(':>[' + $cmd + ']') 126 | Invoke-Expression $cmd | Select-String -SimpleMatch -Pattern 'Fatal: ','Error: ','Hint: ','Warning: ' > $out 127 | 128 | $hintsOrWarnings = $(Get-Item $out).length > 0 129 | if ($hintsOrWarnings) { Write-Host 'Finished with hints/warnings:'; type $out } else { Write-Host 'Done' } 130 | Delete($out) 131 | } 132 | finally { Set-Location $cd } 133 | 134 | # Report outcome 135 | if (Test-Path $exe) { 136 | Move-Item $exe "$(Build.BinariesDirectory)" 137 | 138 | if ( $hintsOrWarnings ) { Write-Host '##vso[task.logissue type=warning]Build completed with hints/warnings. :/' } 139 | else { Write-Host '##vso[task.complete result=Succeeded;]Build completed OK. :)' } 140 | 141 | ${{ parameters.postBuildInline }} } 142 | else { Write-Host '##vso[task.logissue type=error]Build failed. :(' 143 | exit 1 } 144 | 145 | displayName: 'Delphi ${{ parameters.delphiVersion }} build (${{ parameters.platform }}) of ${{ parameters.project }}' 146 | - ${{ parameters.postBuild }} 147 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # azure-pipeline-templates 2 | A collection of (hopefully) useful templates for Azure DevOps Pipelines. For documentation for each template, see below. 3 | 4 | To use these templates in your Azure DevOps build pipeline, refer to the following: 5 | 6 | * [Azure DevOps: Pipelines using templates in other repositories](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#using-other-repositories) 7 | * [GitHub: Creating a Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) 8 | * [Azure DevOps: Service Connections for GitHub](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-github) 9 | 10 | 11 | 12 | ## delphi-build.yml 13 | A Powershell script based template for building Delphi projects. This template currently only supports **Win32** and **Win64** builds of VCL projects. _It is untested with FMX projects_ (so it may work, it just hadn't been tried). 14 | 15 | ### Pre-Requisites 16 | 17 | As well as the configuration required in your GitHub account and Azure DevOps project in order to be able to references this template, the following are also required. 18 | 19 | #### A Self-Hosted Azure DevOps Build Agent 20 | Delphi compilers are not supported by the hosted build agents provided by Microsoft for Azure DevOps builds. You will need to configure your own, self-hosted build machine with an agent installed. This is really straightforward to accomplish and a guide (of sorts) to this is [available on my blog](http://www.deltics.co.nz/blog/posts/2659). 21 | 22 | #### Delphi Compilers 23 | A build agent running this build job is assumed to have Delphi command-line compiler support with available Delphi versions in locations on the build agent hard-drive as follows: 24 | 25 | - `c:\dcc\\bin` for compiler binaries (dcc32.exe and dcc64.exe etc) 26 | - `c:\dcc\\lib` for compiler libraries 27 | 28 | The `` component of the path **must** correspond to the values passed to the **delphiVersion** parameter supported by the template. See the **Usage** information for that parameter below for the requireded values. For example, for **Delphi 7**: 29 | 30 | c:\dcc\7\bin 31 | c:\dcc\7\lib 32 | 33 | Later versions of Delphi may have multiple subfolders under the `lib` folder. Whilst currently only **Windows** target platforms are supported it is recommended that you copy _all_ of these folders if you intend supporting other target platforms in the future (as and when supported by this template). Unless you cannot afford the disk space - these do take up a fair chunk! 34 | 35 | For example, for **Delphi 10.3 Rio**: 36 | 37 | c:\dcc\10.3\bin 38 | c:\dcc\10.3\lib\android 39 | c:\dcc\10.3\lib\iosDevice32 40 | c:\dcc\10.3\lib\iosDevice64 41 | c:\dcc\10.3\lib\iossimulator 42 | c:\dcc\10.3\lib\linux64 43 | c:\dcc\10.3\lib\osx32 44 | c:\dcc\10.3\lib\win32 45 | c:\dcc\10.3\lib\win32c 46 | c:\dcc\10.3\lib\win64 47 | 48 | These folders may be 'donated' from a full Delphi installation of the corresponding Delphi version. _Please abide by the terms of your Delphi license agreement_. 49 | 50 | _**NOTE:** Neither `bin` nor any of the `lib` folders should be included on the build machine `PATH`._ 51 | 52 | #### IDE FixPack Compilers 53 | Depending on the Delphi version involved these are named either `dccNNspeed.exe` or `fastdccNN.exe`. If installed, these should be placed in the corresponding `c:\dcc\\bin` folder alongside the standard Delphi compiler. 54 | 55 | An explanation of the benefits of these compilers as well as the compilers themselves may be found on [Andreas Hausladen's blog and downloads site](https://www.idefixpack.de/blog/ide-tools/ide-fix-pack/). 56 | 57 | ### Template Parameters 58 | 59 | |Parameter|Usage| 60 | |:--------|:----| 61 | |**delphiVersion**|Specifies the version of Delphi to be used for the build. This is a **required** parameter and must have one of the following values: `7, 2005, 2006, 2007, 2009, 2010, xe, xe2, xe3, xe4, xe5, xe6, xe7, xe8, 10, 10.1, 10.2, 10.3` 62 | |**project**|Identifies the path and filename of the project to be compiled. This is a **required** parameter and must identify a _dpr_ file (_without_ the `dpr` extension)| 63 | |**appType**|Identifies whether to build a console application or a Gui application. If specified it must have the value `CONSOLE` or `GUI`. If not specified `CONSOLE` is assumed.| 64 | |**platform**|Identifies the target platform for the build. If specified it must have the value `x86` (for Win32 builds) or `x64` (for Win64). If not specified `x86` is assumed. Whatever value is specified is ignored for Delphi versions earlier than XE2 (only Win32 builds are supported up to Delphi XE).| 65 | |**searchPath**|An **optional** path to be added to `-I`, `-R` and `-U` search paths for the compiler. That is, `include`, `resource` and `unit` search paths, respectively.| 66 | |**unitScopes**|An **optional** set of scope namespace prefixes for use with XE2 and later. If not specified then `System;System.Win;Vcl;WinApi` is assumed.| 67 | |**fixPack**|An **optional** parameter that determines whether the build will attempt to use the relevant IDE FixPack compiler for the Delphi version. If any value other than `true` is specified then the standard Delphi compiler will be used. If not specified then `true` is assumed. Whether `true` is specified or assumed, FixPack compilers will only be used if present on the build machine, otherwise the standard compiler will be used instead.| 68 | |**verbose**|An **optional** parameter that determines whether Delphi compiler output is complete or limited to only hints, warnings and errors. For verbose output, specify `true`. Any other value is equivalent to `false`. If not specified then `false` is assumed.| 69 | |**preBuild: []**|An **optional** parameter that defines an additional step (or steps) to be performed _before_ the Delphi build step itself. _If any specified preBuild step(s) fail then the Delphi build step will not be performed_.| 70 | |**preBuildInline: []**|An **optional** parameter that defines additional Powershell script statements to be performed by the build step immediately before executing the compiler. _Errors occuring during execution of these script statements may cause the Delphi build step to fail even if the Delphi compilation is successful._| 71 | |**postBuild: []**|An **optional** parameter that defines an additional step (or steps) to be performed _after_ the Delphi build step itself. _If any specified preBuild step(s) fail then the Delphi build step will not be performed_.| 72 | |**postBuildInline: []**|An **optional** parameter that defines additional Powershell script statements to be performed by the build step _immediately after_ executing the compiler, but only if the compilation was successful. _Errors occuring during execution of these script statements may cause the Delphi build step to fail even if the Delphi compilation was successful._| 73 | 74 | ### Job Behaviour 75 | 1. Any `preBuild` steps are executed before the main build step itself. 76 | 77 | 2. The main build step uses the specified Delphi version and platform to determine the compiler for use in the build and the required `lib` path to be added (as a minimum) to the search paths. If required, IDE FixPack compilers are located and specified for use in preference over the standard compilers. 78 | 79 | 3. Two folders are created in the initial working folder. For simplicity you can think of this as the "root" of the repository from which you are building. The two folders are for compiler output (`.bin`) and test results (`.results`). _The build step itself makes no use of the `.results` folder and its use in any consuming build pipeline is entirely optional_. 80 | 81 | 4. The working directory is then set to the folder containing the specified project where a compiler configuration file is created for that project (`.cfg`). This is created with settings for search paths (`-I`, `-R`, `-U`), application target (`-D` = `CONSOLE` or `GUI`) and output directories for exe (`-E`) and dcu (`-N`) files. These last two are both set to the `.bin` folder created at step 3. _NOTE: The search path settings applied to `-I`, `-R` and `-U` are all set initially to only the `lib` folder applicable to the Delphi version involved_. 82 | 83 | 5. After executing any `preBuildInline` statements the compiler is then invoked. _This is a good place to run `duget restore` as this will restore dependencies and update search paths in the `.cfg` as required_. 84 | 85 | 6. The working folder is reset to the 'root' of the repo and if the expected `exe` file is found in the `.bin` folder, the compilation is deemed successful and any `postBuildInline` statements are executed. If the `exe` file is not found, failure is reported and the job status set to failed. Any resulting `exe` file in the `.bin` folder is moved to the `$(Build.BinariesDirectory)` (this is a location created and maintained by the Azure DevOps pipeline which can be referred to using that variable name in any pipeline). 86 | 87 | 7. Finally, any `postBuild` steps are executed. If no [step conditions](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/conditions?view=azure-devops&tabs=yaml) are specified on those to determine otherwise, `postBuild` steps are only executed if the main build step and any `preBuild` steps were successful. 88 | 89 | 90 | ### Roadmap 91 | _**NOTE:** There is no timeline in mind for any of these features. Development of this template is driven primarily by my own needs, however contributions or suggestions from others are encouraged and gratefully received._ 92 | 93 | 1. Support for additional compiler configuration settings via parameters. 94 | 2. Validation of support for FMX builds. 95 | 3. Support for platforms other than Windows. 96 | 4. For building with MS Build (as an alternative to reliance on compiler configuration files). 97 | 5. Built-in support for **duget** steps ? 98 | 6. Ultimately, replacement of this template with a packaged Task, distributed thru the Visual Studio Marketplace. 99 | --------------------------------------------------------------------------------