Skip to content

Commit 9b4ce81

Browse files
authored
Integrating interop tests to standard build (#172)
* Integrating interop tests to standard build * While there aren't many interop layer tests at this point, the test module existed but was never hooked into the official build validation process. This adds the test library during build and test stages to ensure they are built and run on all builds * Changed interop build to use a solution for the interop lib and test projects so that the test proj 'publishes' correctly and can run
1 parent c1914e0 commit 9b4ce81

File tree

12 files changed

+75
-108
lines changed

12 files changed

+75
-108
lines changed

Build-Interop.ps1

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ Param(
3939
[switch]$NoClean
4040
)
4141

42-
4342
pushd $PSScriptRoot
4443
$oldPath = $env:Path
4544
try
@@ -81,14 +80,12 @@ try
8180
Invoke-NuGet restore 'src\Interop\LibLLVM\LibLLVM.vcxproj'
8281

8382
Write-Information "Building LibLLVM"
84-
$libLLVMBinLogPath = Join-Path $buildInfo['BinLogsPath'] Ubiquity.NET.Llvm.Interop-restore.binlog
83+
$libLLVMBinLogPath = Join-Path $buildInfo['BinLogsPath'] LibLLVM-Build.binlog
8584
Invoke-MSBuild -Targets 'Build' -Project 'src\Interop\LibLLVM\LibLLVM.vcxproj' -Properties $msBuildProperties -LoggerArgs ($buildInfo['MsBuildLoggerArgs'] + @("/bl:$libLLVMBinLogPath") )
8685

8786
Write-Information "Building Ubiquity.NET.Llvm.Interop"
88-
$interopRestoreBinLogPath = Join-Path $buildInfo['BinLogsPath'] Ubiquity.NET.Llvm.Interop-restore.binlog
89-
$interopBinLog = Join-Path $buildInfo['BinLogsPath'] Ubiquity.NET.Llvm.Interop.binlog
90-
Invoke-MSBuild -Targets 'Restore' -Project 'src\Interop\Ubiquity.NET.Llvm.Interop\Ubiquity.NET.Llvm.Interop.csproj' -Properties $msBuildProperties -LoggerArgs ($buildInfo['MsBuildLoggerArgs'] + @("/bl:$InteropRestoreBinLogPath") )
91-
Invoke-MSBuild -Targets 'Build' -Project 'src\Interop\Ubiquity.NET.Llvm.Interop\Ubiquity.NET.Llvm.Interop.csproj' -Properties $msBuildProperties -LoggerArgs ($buildInfo['MsBuildLoggerArgs'] + @("/bl:$interopBinLog") )
87+
$interopSlnBinLog = Join-Path $buildInfo['BinLogsPath'] Interop.sln.binlog
88+
Invoke-MSBuild -Targets 'Restore;Build' -Project 'src\Interop\Interop.sln' -Properties $msBuildProperties -LoggerArgs ($buildInfo['MsBuildLoggerArgs'] + @("/bl:$interopSlnBinLog") )
9289
}
9390
else
9491
{

Invoke-UnitTests.ps1

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@ try
55

66
$testsFailed = $false
77

8+
Write-Information 'Running Interop tests as x64'
9+
$testsFailed = $testsFailed -or (Invoke-DotNetTest $buildInfo 'src\Interop\InteropTests\InteropTests.csproj')
10+
811
Write-Information 'Running Core library tests as x64'
9-
$testProj = Join-Path $buildInfo['SrcRootPath'] 'Ubiquity.NET.Llvm.Tests\Ubiquity.NET.Llvm.Tests.csproj'
10-
$runSettings = Join-Path $buildInfo['SrcRootPath'] 'x64.runsettings'
11-
dotnet test $testProj -s $runSettings --no-build --no-restore --logger "trx" -r $buildInfo['TestResultsPath']
12-
$testsFailed = $testsFailed -or ($LASTEXITCODE -ne 0)
12+
$testsFailed = $testsFailed -or (Invoke-DotNetTest $buildInfo 'src\Ubiquity.NET.Llvm.Tests\Ubiquity.NET.Llvm.Tests.csproj')
1313

1414
Write-Information 'Running tests for Kaleidoscope Samples as x64'
15-
$testProj = Join-Path $buildInfo['RepoRootPath'] 'Samples\Kaleidoscope\Kaleidoscope.Tests\Kaleidoscope.Tests.csproj'
16-
$runSettings = Join-Path $buildInfo['SrcRootPath'] 'x64.runsettings'
17-
dotnet test $testProj -s $runSettings --no-build --no-restore --logger "trx" -r $buildInfo['TestResultsPath']
18-
$testsFailed = $testsFailed -or ($LASTEXITCODE -ne 0)
15+
$testsFailed = $testsFailed -or (Invoke-DotNetTest $buildInfo 'Samples\Kaleidoscope\Kaleidoscope.Tests\Kaleidoscope.Tests.csproj')
1916

2017
Write-Information 'Running sample app for .NET Core'
2118
pushd (Join-path $buildInfo['BuildOutputPath'] bin\CodeGenWithDebugInfo\Release\netcoreapp3.1)
52 Bytes
Binary file not shown.

PsModules/CommonBuild/CommonBuild.psm1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,13 @@ function Get-GitHubTaggedRelease($org, $project, $tag)
460460
{
461461
Get-GithubReleases $org $project | ?{$_.tag_name -eq $tag}
462462
}
463+
464+
function Invoke-DotNetTest($buildInfo, $projectRelativePath)
465+
{
466+
$testProj = Join-Path $buildInfo['RepoRootPath'] $projectRelativePath
467+
$runSettings = Join-Path $buildInfo['SrcRootPath'] 'x64.runsettings'
468+
$result = dotnet test $testProj -s $runSettings --no-build --no-restore --logger "trx" -r $buildInfo['TestResultsPath'] `
469+
| Out-String
470+
Write-Information $result
471+
return $LASTEXITCODE -ne 0
472+
}

Samples/Kaleidoscope/Kaleidoscope.Runtime/Kaleidoscope-Runtime.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@ a named symbol and then, whenever code calls that symbol the stub calls back to
4848
the application to generate the IR, add the module to the JIT and trigger compilation to native. Thus, achieving
4949
true Just-In-Time compilation.
5050

51-
>[!CAUTION] The truly lazy functionality is currently disabled due to a bug in the underlying LLVM OrcJIT
51+
>[!CAUTION]
52+
> The truly lazy functionality is currently disabled due to a bug in the underlying LLVM OrcJIT
5253
> implementation on Windows.

src/Interop/Interop.sln

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1515
EndProjectSection
1616
EndProject
1717
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ubiquity.NET.Llvm.Interop", "Ubiquity.NET.Llvm.Interop\Ubiquity.NET.Llvm.Interop.csproj", "{67857F7E-8FE8-4201-A90F-5346182C725F}"
18-
ProjectSection(ProjectDependencies) = postProject
19-
{025C2743-8A48-4B37-978A-C3A65F55DC46} = {025C2743-8A48-4B37-978A-C3A65F55DC46}
20-
{6C77A7DE-D464-430F-96A9-A64768763B5F} = {6C77A7DE-D464-430F-96A9-A64768763B5F}
21-
EndProjectSection
22-
EndProject
23-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LlvmBindingsGenerator", "LlvmBindingsGenerator\LlvmBindingsGenerator.csproj", "{025C2743-8A48-4B37-978A-C3A65F55DC46}"
24-
EndProject
25-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibLLVM", "LibLLVM\LibLLVM.vcxproj", "{6C77A7DE-D464-430F-96A9-A64768763B5F}"
26-
ProjectSection(ProjectDependencies) = postProject
27-
{025C2743-8A48-4B37-978A-C3A65F55DC46} = {025C2743-8A48-4B37-978A-C3A65F55DC46}
28-
EndProjectSection
2918
EndProject
3019
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropTests", "InteropTests\InteropTests.csproj", "{BACFB2C9-6E48-4B0F-A4CA-3B5E6F8D286C}"
3120
ProjectSection(ProjectDependencies) = postProject
@@ -54,28 +43,6 @@ Global
5443
{67857F7E-8FE8-4201-A90F-5346182C725F}.Release|x64.Build.0 = Release|Any CPU
5544
{67857F7E-8FE8-4201-A90F-5346182C725F}.Release|x86.ActiveCfg = Release|Any CPU
5645
{67857F7E-8FE8-4201-A90F-5346182C725F}.Release|x86.Build.0 = Release|Any CPU
57-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|Any CPU.Build.0 = Debug|Any CPU
59-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|x64.ActiveCfg = Debug|Any CPU
60-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|x64.Build.0 = Debug|Any CPU
61-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|x86.ActiveCfg = Debug|Any CPU
62-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Debug|x86.Build.0 = Debug|Any CPU
63-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|Any CPU.ActiveCfg = Release|Any CPU
64-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|Any CPU.Build.0 = Release|Any CPU
65-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|x64.ActiveCfg = Release|Any CPU
66-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|x64.Build.0 = Release|Any CPU
67-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|x86.ActiveCfg = Release|Any CPU
68-
{025C2743-8A48-4B37-978A-C3A65F55DC46}.Release|x86.Build.0 = Release|Any CPU
69-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Debug|Any CPU.ActiveCfg = Debug|x64
70-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Debug|Any CPU.Build.0 = Debug|x64
71-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Debug|x64.ActiveCfg = Debug|x64
72-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Debug|x64.Build.0 = Debug|x64
73-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Debug|x86.ActiveCfg = Debug|x64
74-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Release|Any CPU.ActiveCfg = Release|x64
75-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Release|Any CPU.Build.0 = Release|x64
76-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Release|x64.ActiveCfg = Release|x64
77-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Release|x64.Build.0 = Release|x64
78-
{6C77A7DE-D464-430F-96A9-A64768763B5F}.Release|x86.ActiveCfg = Release|x64
7946
{BACFB2C9-6E48-4B0F-A4CA-3B5E6F8D286C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8047
{BACFB2C9-6E48-4B0F-A4CA-3B5E6F8D286C}.Debug|Any CPU.Build.0 = Debug|Any CPU
8148
{BACFB2C9-6E48-4B0F-A4CA-3B5E6F8D286C}.Debug|x64.ActiveCfg = Debug|Any CPU

src/Interop/InteropTests/InteropTests.csproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
<PropertyGroup>
44
<TargetFramework>netcoreapp3.1</TargetFramework>
55
<IsPackable>false</IsPackable>
6+
<LangVersion>8.0</LangVersion>
67
</PropertyGroup>
8+
<ItemGroup>
9+
<ProjectReference Include="..\Ubiquity.NET.Llvm.Interop\Ubiquity.NET.Llvm.Interop.csproj">
10+
<Name>Ubiquity.NET.Llvm.Interop</Name>
11+
<Private>true</Private>
12+
</ProjectReference>
13+
</ItemGroup>
714
<ItemGroup>
815
<PackageReference Include="Microsoft.NET.Test.Sdk" />
916
<PackageReference Include="MSTest.TestFramework" />
1017
<PackageReference Include="MSTest.TestAdapter" />
1118
</ItemGroup>
12-
<ItemGroup>
13-
<ProjectReference Include="..\Ubiquity.NET.Llvm.Interop\Ubiquity.NET.Llvm.Interop.csproj">
14-
<IncludeAssets>All</IncludeAssets>
15-
</ProjectReference>
16-
</ItemGroup>
1719
</Project>

src/Interop/InteropTests/OrcJitTests.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ public class OrcJitTests
2727
[TestMethod]
2828
public void TestLazyIRCompilation( )
2929
{
30-
using( Library.InitializeLLVM( ) )
31-
{
32-
Library.RegisterNative( );
33-
using LLVMContextRef context = LLVMContextCreate( );
34-
string nativeTriple = LLVMGetDefaultTargetTriple();
35-
Assert.IsFalse( string.IsNullOrWhiteSpace( nativeTriple ) );
36-
Assert.IsTrue( LLVMGetTargetFromTriple( nativeTriple, out LLVMTargetRef targetHandle, out string errorMessag ).Succeeded );
37-
using LLVMTargetMachineRef machine = LLVMCreateTargetMachine(
30+
using var libLLVm = Library.InitializeLLVM( );
31+
libLLVm.RegisterTarget( CodeGenTarget.Native );
32+
33+
using LLVMContextRef context = LLVMContextCreate( );
34+
string nativeTriple = LLVMGetDefaultTargetTriple();
35+
Assert.IsFalse( string.IsNullOrWhiteSpace( nativeTriple ) );
36+
Assert.IsTrue( LLVMGetTargetFromTriple( nativeTriple, out LLVMTargetRef targetHandle, out string errorMessag ).Succeeded );
37+
38+
using LLVMTargetMachineRef machine = LLVMCreateTargetMachine(
3839
targetHandle,
3940
nativeTriple,
4041
string.Empty,
@@ -43,13 +44,12 @@ public void TestLazyIRCompilation( )
4344
LLVMRelocMode.LLVMRelocDefault,
4445
LLVMCodeModel.LLVMCodeModelJITDefault );
4546

46-
using LLVMOrcJITStackRef orcJit = LLVMOrcCreateInstance( machine );
47+
using LLVMOrcJITStackRef orcJit = LLVMOrcCreateInstance( machine );
4748

48-
// try several different modules with the same function name replacing the previous
49-
AddAndExecuteTestModule( orcJit, context, machine, 42 );
50-
AddAndExecuteTestModule( orcJit, context, machine, 12345678 );
51-
AddAndExecuteTestModule( orcJit, context, machine, 87654321 );
52-
}
49+
// try several different modules with the same function name replacing the previous
50+
AddAndExecuteTestModule( orcJit, context, machine, 42 );
51+
AddAndExecuteTestModule( orcJit, context, machine, 12345678 );
52+
AddAndExecuteTestModule( orcJit, context, machine, 87654321 );
5353
}
5454

5555
private static void AddAndExecuteTestModule( LLVMOrcJITStackRef orcJit, LLVMContextRef context, LLVMTargetMachineRef machine, int expectedResult )

src/Interop/Ubiquity.NET.Llvm.Interop/Ubiquity.NET.Llvm.Interop.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<Sdk Name="Microsoft.Build.CentralPackageVersions" />
33
<PropertyGroup>
44
<TargetFramework>netstandard2.1</TargetFramework>
5+
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
56
<LangVersion>8.0</LangVersion>
67
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
78
<DebugType>portable</DebugType>
@@ -15,9 +16,9 @@
1516
<Description>.NET Low Level Interop Bindings for Ubiquity.LibLLVM. Direct use of this low level API is discouraged, instead you should use the Ubiquity.NET.Llvm package, which provides a full C# object model projection of the LLVM APIs on top of this library.</Description>
1617
<PackageTags>LLVM,Compiler,JIT,Ubiquity.NET</PackageTags>
1718
<NoPackageAnalysis>true</NoPackageAnalysis>
18-
<RepositoryType>git</RepositoryType>
19-
<RepositoryUrl>https://github.com/UbiquityDotNET/Llvm.NET.git</RepositoryUrl>
2019
<PackageProjectUrl>https://github.com/UbiquityDotNET/Llvm.NET</PackageProjectUrl>
20+
<RepositoryUrl>https://github.com/UbiquityDotNET/Llvm.NET.git</RepositoryUrl>
21+
<RepositoryType>git</RepositoryType>
2122
<PackageLicenseExpression>Apache-2.0 WITH LLVM-exception</PackageLicenseExpression>
2223
</PropertyGroup>
2324
<ItemGroup>

src/Interop/readme-first.md

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,21 @@ PowerShell script.
55

66
The nature of the .NET SDK projects and VCX projects drives the need for the script,instead of
77
VS solution dependencies or even MSBuild project to project references. Unfortunately, due to
8-
the way multi-targeting is done in the newer C# SDK projects project to project references
9-
don't work. The VCXproj files don't have targets for all the .NET targets. Making that all work
10-
seamlessly in VS is just plain hard work that has, thus far, not worked particularly well. Thus,
11-
the design here uses a simpler PowerShell script that takes care of building the correct
12-
platform+configuration+target framework combinations of each and finally builds the NuGet
8+
the way multi-targeting is done in the newer C# SDK projects the project to project references
9+
don't work with C++. The VCXproj files don't have targets for all the .NET targets. Making that
10+
all work seamlessly in VS is just plain hard work that has, thus far, not worked particularly
11+
well. Thus, the design here uses a simpler PowerShell script that takes care of building the
12+
correct platform+configuration+target framework combinations of each and finally builds the NuGet
1313
package from the resulting binaries.
1414

1515
## Projects
16-
### LibLLVM
17-
This is the native project that creates the extended LLVM-C API as an actual DLL. Currently
18-
only Windows 64 bit is supported, though other configurations are plausible with additional
19-
build steps in the PowerShell script to build for other platforms. The extensions are configured
20-
to build with high C++ conformance mode, so they should readily build without much modification
21-
for other platforms given the appropriate build infrastructure is set up.
22-
23-
### Ubiquity.NET.Llvm.Interop
24-
This is the .NET P/Invoke layer that provides the raw API projection to .NET. The, majority
25-
of the code is generated P/Invokes from the LlvmBindingsGenerator tool. There are a few
26-
additional support classes that are consistent across variations in LLVM. While this library
27-
has a runtime dependency on the native LibLLVM binary there is no compile time dependency.
28-
2916
### LlvmBindingsGenerator
3017
This is the P/Invoke generator for the generated interop code in Ubiquity.NET.Llvm.Interop. It uses
31-
CppSharp to parse the C headers and generate the C# P/Invoke API declarations, enums and value
32-
types required to interop with the native code.
18+
CppSharp to parse the C or C++ headers and generate the C# P/Invoke API declarations, enums and value
19+
types required to interop with the native code. The generator has a number of automatic marshaling
20+
rules, but there are ambiguous cases that it needs a configuration file to resolve. The configuration
21+
file provides resolution of the ambiguities and also helps in detection of missing or removed APIs when
22+
moving to a newer version of LLVM.
3323

3424
#### Usage
3525
`LlvmBindingsGenerator <llvmRoot> <extensionsRoot> [OutputPath]`
@@ -46,6 +36,19 @@ change, the PowerShell script takes care of running the generator to update the
4636
code base on each run, even if nothing changes in the end. This is run on every automated build before building
4737
the Ubiquity.NET.Llvm.Interop project so that the generator is tested on every full automated build.
4838

39+
### LibLLVM
40+
This is the native project that creates the extended LLVM-C API as an actual DLL. Currently
41+
only Windows 64 bit is supported, though other configurations are plausible with additional
42+
build steps in the PowerShell script to build for other platforms. The extensions are configured
43+
to build with high C++ conformance mode, so they should readily build without much modification
44+
for other platforms given the appropriate build infrastructure is set up.
45+
46+
### Ubiquity.NET.Llvm.Interop
47+
This is the .NET P/Invoke layer that provides the raw API projection to .NET. The, majority
48+
of the code is generated P/Invokes from the LlvmBindingsGenerator tool. There are a few
49+
additional support classes that are consistent across variations in LLVM. While this library
50+
has a runtime dependency on the native LibLLVM binary there is no compile time dependency.
51+
4952
## Building the Interop libraries
5053
### General requirements
5154
There are some general steps that are required to successfully build the interop NuGet package and a couple
@@ -65,24 +68,13 @@ The interop libraries are built using the Build-Interop.ps1 PowerShell script. T
6568
to correctly build the projects in an automated build as it isn't possible to accomplish all the required
6669
steps in a standard project/solution. (OK, impossible is a bit strong as creating custom targets and tasks
6770
could probably cover it but at the expense of greater complexity). The script is pretty simple though
68-
understanding it is a more complex matter this document is aimed towards.
69-
70-
### Manually (developer inner loop)
71-
While it is possible to use the PowerShell script as part of the development of the interop libraries themselves,
72-
it is generally easier to use the solution file. The solution contains projects for the native libraries, the
73-
bindings generator and the managed interop. _**Using the solution requires that you manually build/run the projects
74-
in the correct order to get changes to propagate correctly.**_
71+
understanding why it is needed is a more complex matter this document is aimed towards.
7572

76-
1. Build LlvmBindingsGenerator project
77-
2. Run LlvmBindingsGenerator (via command line or debugger launch) with the location of the LLVM headers, the
78-
LibLLVM headers, and the output location of generated code for the Ubiquity.NET.Llvm.Interop project.
79-
1. (See above for full command line options for LlvmBindingsGenerator)
80-
2. This, generates C# interop source files AND also generates the native C++ EXPORTS.DEF for the LibLLVM library
81-
and therefore, must run before building either of the other libraries.
82-
3. Build LibLLVM project for all architectures and configurations.
83-
1. At present the only supported runtime and architecture is Windows 64bit so batch building, etc.. isn't required.
84-
Other runtimes and architectures are possible in the future, however.
85-
4. Build the Ubiquity.NET.Llvm.Interop project.
73+
>[!NOTE]
74+
> Building the interop tests via the solution is required as building the CSproj doesn't 'publish' the test.
75+
> If you build via a solution file, then the publish automatically occurs. (You can run the publish target via
76+
> `dotnet publish`, but that's both an extra step AND ends up doing things differently then when you build the
77+
> solution! (There's a publish folder with binaries in it and things are generally in different places - Go Figure!)
8678
8779

8880

0 commit comments

Comments
 (0)