-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathBuild-LibLLVMAndPackage.ps1
More file actions
152 lines (129 loc) · 7.25 KB
/
Build-LibLLVMAndPackage.ps1
File metadata and controls
152 lines (129 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using module "PSModules/CommonBuild/CommonBuild.psd1"
using module "PSModules/RepoBuild/RepoBuild.psd1"
<#
.SYNOPSIS
Builds the native code Extended LLVM C API DLL for the current RID.
.PARAMETER Configuration
This sets the build configuration to use, default is "Release" though for inner loop development this may be set to "Debug"
.PARAMETER FullInit
Performs a full initialization. A full initialization includes forcing a re-capture of the time stamp for local builds
as well as writes details of the initialization to the information and verbose streams.
.DESCRIPTION
This builds the per RID NuGet library and NUGET package to include it. The FullInit is important for local builds as
it alters the version number used in naming and generation. Thus if only building some parts it is useful for local
builds not to set this. For an automated build it should always be set to force use of the commit of the repo as an ID
for the build. In such cases the time-stamp of the HEAD of the commit for the branch/PR is used so a consistent version
is used for ALL builds of the same source - even across multiple runners operating in parallel.
#>
Param(
[hashtable]$buildInfo,
[ValidateSet('Release','Debug')]
[string]$Configuration="Release",
[switch]$FullInit,
[switch]$SkipLLvm
)
Set-StrictMode -Version 3.0
Push-location $PSScriptRoot
$oldPath = $env:Path
try
{
if(!$buildInfo)
{
$buildInfo = Initialize-BuildEnvironment -FullInit:$FullInit
}
$currentRid = [System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier
# inner loop optimization (shaves time off build if already done)
# Most common inner loop work is with the extended API and final DLL
# not with LLVM itself, so this keeps the loop short.
if(!$SkipLLvm)
{
# Download and unpack the LLVM source from the versioned release tag if not already present
Clone-LlvmFromTag $buildInfo
# Always double check the source version matches expectations, this catches a bump in the script version
# but no download as the previous version is still there. (Mostly a local build problem but a major time
# waster if forgotten. So, test it here as early as possible.)
Assert-LlvmSourceVersion $buildInfo
# Verify CMake version info (Official minimum for LLVM as of 20.1.3)
Assert-CmakeInfo ([Version]::new(3, 20, 0))
$cmakeConfig = New-LlvmCMakeConfig -AllTargets -Name $currentRid -BuildConfig $Configuration -BuildInfo $buildInfo
Generate-CMakeConfig $cmakeConfig
Build-CmakeConfig $cmakeConfig @('lib/all')
# Notify size of build output directory as that's a BIG player in total space used in an
# automated build scenario. (OSS build systems often limit space so it's important to know)
$postBuildSize = Get-ChildItem -Recurse $cmakeConfig['BuildRoot'] | Measure-Object -Property Length -sum | %{[math]::round($_.Sum /1Gb, 3)}
Write-Information "Post Build Size: $($postBuildSize)Gb"
}
# On Windows Build, run source generator to get the generated exports.g.def
if ($IsWindows)
{
#TODO: generalize this for ALL windows architectures (ARM64...)
# SEE: Llvm-Libs.props in the root of this repo for how this is specified for
# the C++ build.
$llvmPlatformConfig = "win-x64"
$llvmPlatformConfigRoot = Join-Path $buildInfo['BuildOutputPath'] $llvmPlatformConfig
$extensionsRoot = Join-Path $buildInfo['SrcRootPath'] 'LibLLVM'
$generatorOptions = @{
LlvmRoot = $buildInfo['LlvmRoot']
ExtensionsRoot = $extensionsRoot
ConfigPathRoot = $llvmPlatformConfigRoot
ExportsDefFilePath = Join-Path $extensionsRoot 'exports.g.def'
}
# run the generator so the output is available to the DLL generation
Invoke-BindingsGenerator $buildInfo $generatorOptions
}
# Build the per target LIBLLVM library (Also per rid)
# NOTE: building a dynamic library exporting C++ is NOT an option. Despite the problems of
# C++ not providing a stable binary ABI (even for the same vendor compiler across multiple versions)
# there is the problem in generating the DLL on Windows (see: https://github.com/llvm/llvm-project/issues/109483)
# Thus, this ONLY deals with the stable C ABI exported by the LLVM-C API AND an extended API specific
# to this repo. If the LLVM issue of building the DLL on Windows is ever resolved, this decision
# is worth reconsidering. (There's still the lack of binary ABI but tool vendors go through a LOT not
# to break things from version to version so isn't as big a deal as long as the same vendor is used.)
#
# For now the DLL ONLY builds for Windows using MSBUILD (VCXPROJ);
# TODO: Convert C++ code to CMAKE, this means leveraging CSmeVer build task as a standalone tool so
# that the version Information is available to the scripts to provide to the build. (See docs generation
# for the Ubiquity.NET.LLvm consuming project for an example of doing that so that the build versioning
# is available to scripting) For now leave it on the legacy direct calls to MSBUILD...
if ($IsWindows)
{
# now build the native DLL that consumes the generated output for the bindings
# Need to invoke NuGet directly for restore of vcxproj as /t:Restore target doesn't support packages.config
# and PackageReference isn't supported for native projects... [Sigh...]
if($null -eq (Find-OnPath nuget))
{
winget install 'Microsoft.NuGet'
}
if($null -eq (Find-OnPath nuget))
{
throw "NuGet.exe not found, even after installation attempt..."
}
Write-Information "Restoring LibLLVM"
$libLLVMVcxProj = Join-Path 'src' 'LibLLVM' 'LibLLVM.vcxproj'
Invoke-External nuget restore $libLLVMVcxProj -PackagesDirectory $buildInfo['NuGetRepositoryPath']
$libLLvmBuildProps = @{ Configuration = $Configuration
LlvmVersion = Get-LlvmVersionString $buildInfo
RuntimeIdentifier = $currentRid
}
$libLlvmBuildPropList = ConvertTo-PropertyList $libLLvmBuildProps
Write-Information "Building LibLLVM"
$libLLVMBinLogPath = Join-Path $buildInfo['BinLogsPath'] "LibLLVM-Build-$currentRid.binlog"
Invoke-external MSBuild '-t:Build' "-p:$libLlvmBuildPropList" "-bl:$libLLVMBinLogPath" '-v:m' $libLLVMVcxProj
}
# Build NuGetPackage for the target library
Invoke-external dotnet pack (Join-Path $buildInfo['SrcRootPath'] 'LibLLVmNuget' 'LibLLVmNuget.csproj') "-p:$libLlvmBuildPropList"
}
catch
{
# everything from the official docs to the various articles in the blog-sphere says this isn't needed
# and in fact it is redundant - They're all WRONG! By re-throwing the exception the original location
# information is retained and the error reported will include the correct source file and line number
# data for the error. Without this, only the error message is retained and the location information is
# Line 1, Column 1, of the outer most script file, which is, of course, completely useless.
throw
}
finally
{
Pop-Location
$env:Path = $oldPath
}