Skip to content

Commit

Permalink
AOT Support (#24)
Browse files Browse the repository at this point in the history
* Implement prototype AOT module for ADL.

* Add dynamic assembly provider API.

* Implement dynamic module providing.

* Fix numerous warnings.

* More warning fixes.

* Add persistent dynamic assembly provider.

* Add null check.

* Correct test cleanup algorithm.

* Don't mangle the assembly name.

* Remove the on-disk library path from the pregenerated type keying.

* Implement loading of AOT types in the native builder.

* Implement tool logic.

* Add metadata.

* Add an extra check for empty output directories.

* Correct various warnings.

* Add documentation for the AOT feature.

* Add a short note about calling the discover method multiple times.

* Ensure that the output directory is not empty.

* Add some cursory tool tests.

* Bump version.

* Correct attribute target, and reduce some nesting.

* Remove some redundancies and annotate some input parameters.

* Ensure that AOT tests are not parallelized.

* Remove leftover unused files.

* Fix version.

* Fix bad tag.

* Rebase onto master, merge changes.

* Rebase onto master, and add coverage runs for the AOT tests.

* Add platform targets to AOT project files.

* Correct configurations in the solution file.

* Add the clean step to the AOT tests.

* Install System.ValueTuple and upgrade some packages.

* Use normal tuple instead of ValueTuple.

* Use wait spins to ensure that we aren't trying to copy modules before they've been written.

* Remove custom copying code, and use builtin mechanisms for output dir.

* Correct access violations in AOT tests.

* Add test for skipping pregenerated types.

* Remove spurious semicolon.

* Make type cache nonstatic, and correct tests accordingly.

* Revert "Make type cache nonstatic, and correct tests accordingly."

This reverts commit da42df4.

* Remove skip test.
  • Loading branch information
Nihlus authored Apr 20, 2018
1 parent 565a716 commit ecafa71
Show file tree
Hide file tree
Showing 54 changed files with 2,016 additions and 126 deletions.
45 changes: 37 additions & 8 deletions AdvanceDLSupport.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", ".\docs", "{96E3AE84
docs\library_scanning.md = docs\library_scanning.md
docs\developer_docs.md = docs\developer_docs.md
docs\indirect-calling.md = docs\indirect-calling.md
docs\ahead-of-time.md = docs\ahead-of-time.md
docs\interface-composition.md = docs\interface-composition.md
EndProjectSection
EndProject
Expand All @@ -43,6 +44,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.DllMap", "Mono.DllMap\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.DllMap.Tests", "Mono.DllMap.Tests\Mono.DllMap.Tests.csproj", "{BAAA6344-0DCF-4DC9-B422-572E8640F8EC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedDLSupport.AOT", "AdvancedDLSupport.AOT\AdvancedDLSupport.AOT.csproj", "{89D77744-C0FB-4478-A31F-3936FEB02768}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedDLSupport.AOT.Tests", "AdvancedDLSupport.AOT.Tests\AdvancedDLSupport.AOT.Tests.csproj", "{1831033A-AA9A-43D9-BB3C-842D21DD6E80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedDLSupport.Benchmark", "AdvancedDLSupport.Benchmark\AdvancedDLSupport.Benchmark.csproj", "{D9633011-4D7B-4285-B70C-D99EE6DA52DF}"
EndProject
Global
Expand Down Expand Up @@ -103,17 +108,41 @@ Global
{BAAA6344-0DCF-4DC9-B422-572E8640F8EC}.Debug|x64.Build.0 = Debug|x64
{BAAA6344-0DCF-4DC9-B422-572E8640F8EC}.Release|x64.ActiveCfg = Release|x64
{BAAA6344-0DCF-4DC9-B422-572E8640F8EC}.Release|x64.Build.0 = Release|x64
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|x86.ActiveCfg = Debug|x86
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|x86.Build.0 = Debug|x86
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|x64.ActiveCfg = Debug|x64
{89D77744-C0FB-4478-A31F-3936FEB02768}.Debug|x64.Build.0 = Debug|x64
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|Any CPU.Build.0 = Release|Any CPU
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|x86.ActiveCfg = Release|x86
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|x86.Build.0 = Release|x86
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|x64.ActiveCfg = Release|x64
{89D77744-C0FB-4478-A31F-3936FEB02768}.Release|x64.Build.0 = Release|x64
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|x86.ActiveCfg = Debug|x86
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|x86.Build.0 = Debug|x86
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|x64.ActiveCfg = Debug|x64
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Debug|x64.Build.0 = Debug|x64
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|Any CPU.Build.0 = Release|Any CPU
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|x86.ActiveCfg = Release|x86
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|x86.Build.0 = Release|x86
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|x64.ActiveCfg = Release|x64
{1831033A-AA9A-43D9-BB3C-842D21DD6E80}.Release|x64.Build.0 = Release|x64
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x86.ActiveCfg = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x86.Build.0 = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x64.ActiveCfg = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x64.Build.0 = Debug|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x86.ActiveCfg = Debug|x86
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x86.Build.0 = Debug|x86
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x64.ActiveCfg = Debug|x64
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Debug|x64.Build.0 = Debug|x64
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|Any CPU.Build.0 = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x86.ActiveCfg = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x86.Build.0 = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x64.ActiveCfg = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x64.Build.0 = Release|Any CPU
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x86.ActiveCfg = Release|x86
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x86.Build.0 = Release|x86
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x64.ActiveCfg = Release|x64
{D9633011-4D7B-4285-B70C-D99EE6DA52DF}.Release|x64.Build.0 = Release|x64
EndGlobalSection
EndGlobal
2 changes: 2 additions & 0 deletions AdvanceDLSupport.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">None</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_STYLE/@EntryValue">Space</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ADL/@EntryIndexedValue">ADL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AIX/@EntryIndexedValue">AIX</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AOT/@EntryIndexedValue">AOT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARM/@EntryIndexedValue">ARM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARMV/@EntryIndexedValue">ARMV</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BSD/@EntryIndexedValue">BSD</s:String>
Expand Down
26 changes: 26 additions & 0 deletions AdvancedDLSupport.AOT.Tests/AdvancedDLSupport.AOT.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461</TargetFrameworks>
<IsPackable>false</IsPackable>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU;x86;x64</Platforms>
<Prefer32bit>false</Prefer32bit>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<Content Include="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AdvancedDLSupport.AOT\AdvancedDLSupport.AOT.csproj" />
</ItemGroup>
<!-- Common CMake build steps -->
<Import Project="targets\CMake-Unix.targets" Condition="'$(OS)' == 'Unix'" />
<Import Project="targets\CMake-Win.targets" Condition="'$(OS)' == 'Windows_NT'" />
</Project>
20 changes: 20 additions & 0 deletions AdvancedDLSupport.AOT.Tests/Data/Classes/AOTMixedModeClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using AdvancedDLSupport.AOT.Tests.Data.Interfaces;

namespace AdvancedDLSupport.AOT.Tests.Data.Classes
{
public abstract class AOTMixedModeClass : NativeLibraryBase, IAOTLibrary
{
public AOTMixedModeClass(string path, Type interfaceType, ImplementationOptions options, TypeTransformerRepository transformerRepository)
: base(path, interfaceType, options, transformerRepository)
{
}

public abstract int Multiply(int a, int b);

public int Add(int a, int b)
{
return a + b;
}
}
}
8 changes: 8 additions & 0 deletions AdvancedDLSupport.AOT.Tests/Data/Interfaces/IAOTLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace AdvancedDLSupport.AOT.Tests.Data.Interfaces
{
[AOTType]
public interface IAOTLibrary
{
int Multiply(int a, int b);
}
}
16 changes: 16 additions & 0 deletions AdvancedDLSupport.AOT.Tests/Fixtures/InitialCleanupFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.IO;

namespace AdvancedDLSupport.AOT.Tests.Fixtures
{
public class InitialCleanupFixture
{
public InitialCleanupFixture()
{
var targetDirectory = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "aot-test"));
if (targetDirectory.Exists)
{
targetDirectory.Delete(true);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;

namespace AdvancedDLSupport.AOT.Tests.TestBases
{
public class NativeLibraryBuilderTestBase : PregeneratedAssemblyBuilderTestBase
{
protected NativeLibraryBuilder LibraryBuilder { get; }

[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
protected NativeLibraryBuilderTestBase()
{
LibraryBuilder = new NativeLibraryBuilder(GetImplementationOptions());
}

protected override ImplementationOptions GetImplementationOptions()
{
return ImplementationOptions.UseLazyBinding;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using AdvancedDLSupport.AOT.Tests.Fixtures;
using Xunit;

namespace AdvancedDLSupport.AOT.Tests.TestBases
{
public class PregeneratedAssemblyBuilderTestBase : IClassFixture<InitialCleanupFixture>
{
protected string OutputDirectory { get; }

protected Assembly SourceAssembly { get; }
protected PregeneratedAssemblyBuilder Builder { get; }

[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
protected PregeneratedAssemblyBuilderTestBase()
{
SourceAssembly = Assembly.GetAssembly(typeof(PregeneratedAssemblyBuilderTestBase));
Builder = new PregeneratedAssemblyBuilder(GetImplementationOptions());

OutputDirectory = Path.Combine(Directory.GetCurrentDirectory(), "aot-test");
}

protected virtual ImplementationOptions GetImplementationOptions()
{
return 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.IO;
using System.Reflection;
using AdvancedDLSupport.AOT.Tests.Data.Interfaces;
using AdvancedDLSupport.AOT.Tests.TestBases;
using Xunit;

namespace AdvancedDLSupport.AOT.Tests.Tests.Integration
{
public class NativeLibraryBuilderTests
{
public class DiscoverCompiledTypes : NativeLibraryBuilderTestBase
{
[Fact]
public void CanDiscoverPrecompiledTypes()
{
// Pregenerate the types
Builder.WithSourceAssembly(GetType().Assembly);
var result = Builder.Build(OutputDirectory);

var searchPattern = $"*{result}*.dll";
NativeLibraryBuilder.DiscoverCompiledTypes(OutputDirectory, searchPattern);
}

[Fact]
public void UsesPrecompiledTypesIfDiscovered()
{
// Pregenerate the types
Builder.WithSourceAssembly(GetType().Assembly);
var result = Builder.Build(OutputDirectory);

var searchPattern = $"*{result}*.dll";
NativeLibraryBuilder.DiscoverCompiledTypes(OutputDirectory, searchPattern);

var library = LibraryBuilder.ActivateInterface<IAOTLibrary>("AOTTests");

var libraryAssembly = library.GetType().Assembly;

Assert.False(libraryAssembly.GetCustomAttribute<AOTAssemblyAttribute>() is null);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.IO;
using AdvancedDLSupport.AOT.Tests.Data.Classes;
using AdvancedDLSupport.AOT.Tests.Data.Interfaces;
using AdvancedDLSupport.AOT.Tests.TestBases;
using Xunit;

namespace AdvancedDLSupport.AOT.Tests.Tests.Integration
{
public class PregeneratedAssemblyBuilderTests
{
public class Build : PregeneratedAssemblyBuilderTestBase
{
[Fact]
public void GeneratesAnOutputFileForASourceAssembly()
{
Builder.WithSourceAssembly(SourceAssembly);
var result = Builder.Build(OutputDirectory);

var outputFile = Path.Combine(OutputDirectory, result);
Assert.True(File.Exists(outputFile));
}

[Fact]
public void GeneratesAnOutputFileForASourceExplicitCombination()
{
Builder.WithSourceExplicitTypeCombination<AOTMixedModeClass, IAOTLibrary>();
var result = Builder.Build(OutputDirectory);

var outputFile = Path.Combine(OutputDirectory, result);
Assert.True(File.Exists(outputFile));
}
}
}
}
41 changes: 41 additions & 0 deletions AdvancedDLSupport.AOT.Tests/Tests/Integration/ProgramTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.IO;
using AdvancedDLSupport.AOT.Tests.Fixtures;
using Xunit;

namespace AdvancedDLSupport.AOT.Tests.Tests.Integration
{
public class ProgramTests : IClassFixture<InitialCleanupFixture>
{
[Fact]
public void ReturnsInputAssemblyNotFoundIfOneOrMoreAssembliesDoNotExist()
{
var args = "--input-assemblies aaaa.dll".Split(' ');

var result = Program.Main(args);

Assert.Equal(ExitCodes.InputAssemblyNotFound, (ExitCodes)result);
}

[Fact]
public void ReturnsFailedToLoadAssemblyIfOneOrMoreAssembliesCouldNotBeLoaded()
{
File.Create("empty.dll").Close();
var args = "--input-assemblies empty.dll".Split(' ');

var result = Program.Main(args);

File.Delete("empty.dll");
Assert.Equal(ExitCodes.FailedToLoadAssembly, (ExitCodes)result);
}

[Fact]
public void ReturnsSuccessIfNoErrorsWereGenerated()
{
var args = "--input-assemblies AdvancedDLSupport.AOT.Tests.dll -o aot-test".Split(' ');

var result = Program.Main(args);

Assert.Equal(ExitCodes.Success, (ExitCodes)result);
}
}
}
11 changes: 11 additions & 0 deletions AdvancedDLSupport.AOT.Tests/c/CMake/install-functions.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function(install_for_frameworks FRAMEWORKS)
foreach(framework ${FRAMEWORKS})
message("Framework: ${framework}")
install(TARGETS
AOTTests
COMPONENT
standard
DESTINATION
${INSTALL_PATH_ABSOLUTE}/${framework})
endforeach()
endfunction()
46 changes: 46 additions & 0 deletions AdvancedDLSupport.AOT.Tests/c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.5)
project(c)

include(CMake/install-functions.cmake)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)

set(BUILD_PLATFORM "x64" CACHE STRING "The target build platform.")
set(TARGET_FRAMEWORKS "net461" CACHE STRING "The target frameworks")
set(BASE_INSTALL_PATH "${CMAKE_BINARY_DIR}/lib" CACHE STRING "The base path (not including the framework where the output binaries should be installed.")
set(PROJECT_PATH "${CMAKE_BINARY_DIR}/lib" CACHE STRING "The base path of the project.")

if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
set(IS_UNIX_COMPILER true)
endif()

if (IS_UNIX_COMPILER)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long -pedantic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
elseif ( MSVC )
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} /W4")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()


include_directories(${CMAKE_SOURCE_DIR})

set(SHARED_HEADERS src/comp.h)

add_library(AOTTests SHARED src/AOTTests.c ${SHARED_HEADERS})

if (IS_UNIX_COMPILER)
# Any CPU is assumed to be 64-bit
if (BUILD_PLATFORM STREQUAL "x64" OR BUILD_PLATFORM STREQUAL "AnyCPU")
set_target_properties(AOTTests PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
elseif (BUILD_PLATFORM STREQUAL "x86")
set_target_properties(AOTTests PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
endif()
elseif (MSVC)
# Handled in MSBuild
endif()

get_filename_component(INSTALL_PATH_ABSOLUTE "${PROJECT_PATH}/${BASE_INSTALL_PATH}" ABSOLUTE)

install_for_frameworks("${TARGET_FRAMEWORKS}")
8 changes: 8 additions & 0 deletions AdvancedDLSupport.AOT.Tests/c/src/AOTTests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stdint.h>
#include "comp.h"

__declspec(dllexport) int32_t Multiply(int32_t a, int32_t b)
{
return a * b;
}

Loading

0 comments on commit ecafa71

Please sign in to comment.