Skip to content
Permalink
Browse files

[Build] NuGetAssemblyResolver WIP

  • Loading branch information
xen2 committed Oct 21, 2018
1 parent 5caacef commit d0c771fe450c5849da21d0715b292eba253cfe0a
@@ -0,0 +1,164 @@
// Copyright (c) Xenko contributors (https://xenko.com)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NuGet.Commands;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;

namespace Xenko.Core.Assets.CompilerApp
{
class NuGetAssemblyResolver
{
[ModuleInitializer(-100000)]
internal static void __Initialize__()
{
var settings = NuGet.Configuration.Settings.LoadDefaultSettings(Directory.GetCurrentDirectory());
var packageSourceProvider = new PackageSourceProvider(settings);

// not sure what these do, but it was in the NuGet command line.
var resourceProviders = new List<Lazy<INuGetResourceProvider>>();
resourceProviders.AddRange(Repository.Provider.GetCoreV3());

// Setup source provider as a V3 only.
var sourceRepositoryProvider = new SourceRepositoryProvider(settings, resourceProviders);

var installPath = SettingsUtility.GetGlobalPackagesFolder(settings);
var assemblies = new List<string>();

{
var logger = new Logger();
var configJson = JObject.Parse(@"
{
""dependencies"": {
""Xenko.Core.Assets.CompilerApp"": ""3.1.0.1-dev""
},
""frameworks"": {
""net462"": { }
}
}");

var specPath = Path.Combine("TestProject", "project.json");
var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath);

using (var context = new SourceCacheContext())
{
context.IgnoreFailedSources = true;

var provider = RestoreCommandProviders.Create(installPath, new List<string>(), sourceRepositoryProvider.GetRepositories(), context, new LocalPackageFileCache(), logger);
var request = new RestoreRequest(spec, provider, context, logger)
{
LockFilePath = "project.lock.json",
};

var command = new RestoreCommand(request);

Console.WriteLine("Restoring");
// Act
var result = command.ExecuteAsync().Result;
Console.WriteLine("Restoring done");

foreach (var library in result.LockFile.Libraries)
{
foreach (var file in library.Files)
{
if (file.StartsWith("lib/net"))
{
assemblies.Add(Path.Combine(installPath, library.Path, file));
}
}
}
}
}

AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
{
var aname = new AssemblyName(eventArgs.Name);
if (aname.Name.StartsWith("Microsoft.Build") && aname.Name != "Microsoft.Build.Locator")
return null;
var assemblyPath = assemblies.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x) == aname.Name);
if (assemblyPath != null)
{
return Assembly.LoadFrom(assemblyPath);
}
return null;
};
}

public class Logger : ILogger
{
private List<string> logs = new List<string>();

public void LogDebug(string data)
{
logs.Add(data);
}

public void LogVerbose(string data)
{
logs.Add(data);
}

public void LogInformation(string data)
{
Console.WriteLine(data);
logs.Add(data);
}

public void LogMinimal(string data)
{
logs.Add(data);
}

public void LogWarning(string data)
{
logs.Add(data);
}

public void LogError(string data)
{
logs.Add(data);
}

public void LogInformationSummary(string data)
{
logs.Add(data);
}

public void LogErrorSummary(string data)
{
logs.Add(data);
}

public void Log(LogLevel level, string data)
{
}

public Task LogAsync(LogLevel level, string data)
{
return Task.CompletedTask;
}

public void Log(ILogMessage message)
{
}

public Task LogAsync(ILogMessage message)
{
return Task.CompletedTask;
}
}
}
}
@@ -2,8 +2,7 @@
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.

using System;

using Xenko.Core;
using System.IO;

namespace Xenko.Core.Assets.CompilerApp
{
@@ -13,16 +12,19 @@ private static int Main(string[] args)
{
try
{
// Override search path since we are in a unit test directory
DirectoryHelper.PackageDirectoryOverride = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\..\..\..");

// Set the XenkoDir environment variable
var installDir = DirectoryHelper.GetInstallationDirectory("Xenko");
Environment.SetEnvironmentVariable("XenkoDir", installDir);

// Running first time? If yes, create nuget redirect package.
var packageVersion = new PackageVersion(XenkoVersion.NuGetVersion);
if (PackageStore.Instance.IsDevelopmentStore)
{
PackageStore.Instance.CheckDeveloperTargetRedirects("Xenko", packageVersion, PackageStore.Instance.InstallationPath).Wait();
}
//var packageVersion = new PackageVersion(XenkoVersion.NuGetVersion);
//if (PackageStore.Instance.IsDevelopmentStore)
//{
// PackageStore.Instance.CheckDeveloperTargetRedirects("Xenko", packageVersion, PackageStore.Instance.InstallationPath).Wait();
//}

var packageBuilder = new PackageBuilderApp();
var returnValue = packageBuilder.Run(args);
@@ -411,7 +411,7 @@ public async Task<NugetLocalPackage> InstallPackage(string packageId, PackageVer
var projectContext = new EmptyNuGetProjectContext()
{
ActionType = NuGetActionType.Install,
PackageExtractionContext = new PackageExtractionContext(NativeLogger),
PackageExtractionContext = new PackageExtractionContext(PackageSaveMode.Defaultv3, XmlDocFileSaveMode.Skip, NativeLogger, null, null),
};

ActivityCorrelationId.StartNew();
@@ -465,15 +465,16 @@ public async Task<NugetLocalPackage> InstallPackage(string packageId, PackageVer
{
if (operation.NuGetProjectActionType == NuGetProjectActionType.Install)
{
using (var downloadResult = await PackageDownloader.GetDownloadResourceResultAsync(primarySources, packageIdentity, downloadContext, InstallPath, NativeLogger, token))
var sources = new List<SourceRepository> { operation.SourceRepository };
using (var downloadResult = await PackageDownloader.GetDownloadResourceResultAsync(sources, operation.PackageIdentity, downloadContext, InstallPath, NativeLogger, token))
{
if (downloadResult.Status != DownloadResourceResultStatus.Available)
throw new InvalidOperationException($"Could not download package {packageIdentity}");
throw new InvalidOperationException($"Could not download package {operation.PackageIdentity}");

using (var installResult = await GlobalPackagesFolderUtility.AddPackageAsync(packageIdentity, downloadResult.PackageStream, InstallPath, NativeLogger, token))
using (var installResult = await GlobalPackagesFolderUtility.AddPackageAsync(downloadResult.PackageSource, operation.PackageIdentity, downloadResult.PackageStream, InstallPath, Guid.Empty, NativeLogger, token))
{
if (installResult.Status != DownloadResourceResultStatus.Available)
throw new InvalidOperationException($"Could not install package {packageIdentity}");
throw new InvalidOperationException($"Could not install package {operation.PackageIdentity}");
}
}
}
@@ -532,7 +533,7 @@ public async Task UninstallPackage(NugetPackage package, ProgressReport progress
var projectContext = new EmptyNuGetProjectContext()
{
ActionType = NuGetActionType.Uninstall,
PackageExtractionContext = new PackageExtractionContext(NativeLogger)
PackageExtractionContext = new PackageExtractionContext(PackageSaveMode.Defaultv3, XmlDocFileSaveMode.Skip, NativeLogger, null, null),
};

// Simply delete the installed package and its .nupkg installed in it.
@@ -669,7 +670,7 @@ private async Task FindSourcePacakgesByIdHelper(string packageId, List<NugetServ
foreach (var repo in repositories)
{
var metadataResource = await repo.GetResourceAsync<PackageMetadataResource>(CancellationToken.None);
var metadataList = await metadataResource.GetMetadataAsync(packageId, true, true, NativeLogger, cancellationToken);
var metadataList = await metadataResource.GetMetadataAsync(packageId, true, true, null, NativeLogger, cancellationToken);
foreach (var metadata in metadataList)
{
resultList.Add(new NugetServerPackage(metadata, repo.PackageSource.Source));
@@ -734,7 +735,7 @@ public async Task<IEnumerable<NugetPackage>> GetUpdates(PackageName packageName,
foreach (var repo in repositories)
{
var metadataResource = await repo.GetResourceAsync<PackageMetadataResource>(cancellationToken);
var metadataList = await metadataResource.GetMetadataAsync(packageName.Id, includePrerelease, includeAllVersions, NativeLogger, cancellationToken);
var metadataList = await metadataResource.GetMetadataAsync(packageName.Id, includePrerelease, includeAllVersions, null, NativeLogger, cancellationToken);
foreach (var metadata in metadataList)
{
res.Add(new NugetServerPackage(metadata, repo.PackageSource.Source));
@@ -8,8 +8,8 @@
<XenkoAssemblyProcessorOptions>--auto-module-initializer --serialization</XenkoAssemblyProcessorOptions>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NuGet.Protocol" Version="4.5.0" />
<PackageReference Include="NuGet.PackageManagement" Version="4.5.0" />
<PackageReference Include="NuGet.Protocol" Version="4.8.0" />
<PackageReference Include="NuGet.PackageManagement" Version="4.8.0" />
<Reference Include="System.Core" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="WindowsBase" />
@@ -30,7 +30,9 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Xenko.Core\Xenko.Core.csproj" />
<ProjectReference Include="..\Xenko.Core\Xenko.Core.csproj">
<PrivateAssets>contentfiles;analyzers</PrivateAssets>
</ProjectReference>
<PackageReference Include="SharpDX" Version="4.0.1" Condition="'$(TargetFramework)' == 'uap10.0'" />
</ItemGroup>

@@ -52,8 +52,9 @@ public static void PreloadLibrary(string libraryName)

// We are trying to load the dll from a shadow path if it is already registered, otherwise we use it directly from the folder
var dllFolder = NativeLibraryInternal.GetShadowPathForNativeDll(libraryName);
var callingAssembly = Assembly.GetCallingAssembly();
if (dllFolder == null)
dllFolder = Path.Combine(Path.GetDirectoryName(typeof(NativeLibrary).GetTypeInfo().Assembly.Location), cpu);
dllFolder = Path.Combine(Path.GetDirectoryName(callingAssembly.Location), cpu);
if (!Directory.Exists(dllFolder))
dllFolder = Path.Combine(Environment.CurrentDirectory, cpu);
var libraryFilename = Path.Combine(dllFolder, libraryName);
@@ -1,4 +1,4 @@
<Project>
<Project>

<Import Project="..\..\targets\Xenko.Core.PreSettings.targets" />
<Import Project="Sdk.props" Sdk="MSBuild.Sdk.Extras" Version="1.6.55" />
@@ -54,6 +54,8 @@
<Compile Include="..\..\shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<None Include="build\**\*.targets" PackagePath="build\" Pack="true" />
<None Include="..\..\..\deps\AssemblyProcessor\*.*" PackagePath="tools\AssemblyProcessor\" Pack="true" />
</ItemGroup>

<ItemGroup>
@@ -0,0 +1,66 @@
<Project InitialTargets="XenkoCheckRequirements" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--Check requirements when running this build file -->
<Target Name="XenkoCheckRequirements">
<Error Condition="'$(XenkoPlatform)' == ''" Text="The property %24(XenkoPlatform) must be defined by the project"/>

<!-- If we compile without Visual Studio, still properly resolve platform if SolutionPath is given -->
<MSBuild Projects="$(SolutionPath)"
Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(BuildingSolutionFile)' != 'true' and '$(SolutionPath)' != '' and '$(SolutionPath)' != '*Undefined*'"
Targets="GetSolutionConfigurationContents"
Properties="Configuration=$(Configuration);Platform=$(SolutionPlatform)"
ContinueOnError="$(ContinueOnError)">
<Output TaskParameter="TargetOutputs" PropertyName="CurrentSolutionConfigurationContents"/>
</MSBuild>
</Target>

<!--
*****************************************************************************************************************************
Platform Detection
*****************************************************************************************************************************
-->
<PropertyGroup>
<!-- Windows10 was renammed into UWP -->
<XenkoPlatform Condition="'$(XenkoPlatform)' == 'Windows10'">UWP</XenkoPlatform>
<!-- Default mappings -->
<XenkoPlatform Condition="'$(XenkoPlatform)' == '' And '$(TargetPlatformIdentifier)' == 'UAP'">UWP</XenkoPlatform>
<XenkoPlatform Condition="'$(XenkoPlatform)' == '' And '$(TargetFrameworkIdentifier)' == 'MonoAndroid'">Android</XenkoPlatform>
<XenkoPlatform Condition="'$(XenkoPlatform)' == '' And '$(TargetFrameworkIdentifier)' == 'Xamarin.iOS'">iOS</XenkoPlatform>
<XenkoPlatform Condition="'$(XenkoPlatform)' == ''">Windows</XenkoPlatform>
</PropertyGroup>

<!--
*****************************************************************************************************************************
Assembly Processor
*****************************************************************************************************************************
-->
<PropertyGroup>
<!--By default, turn on assembly processor-->
<XenkoAssemblyProcessor Condition="'$(XenkoAssemblyProcessor)' == ''">true</XenkoAssemblyProcessor>
<XenkoAssemblyProcessorPath>$(MSBuildThisFileDirectory)..\tools\AssemblyProcessor\Xenko.Core.AssemblyProcessor.Packed.exe</XenkoAssemblyProcessorPath>
</PropertyGroup>
<UsingTask TaskName="AssemblyProcessorTask" AssemblyFile="$(XenkoAssemblyProcessorPath)" Condition=" '$(XenkoAssemblyProcessorPath)' != '' And '$(XenkoAssemblyProcessorDev)' != 'true' "/>
<Target Name="XenkoRunAssemblyProcessor" DependsOnTargets="ResolveProjectReferences">
<WriteLinesToFile File="$(IntermediateOutputPath)XenkoReferences.cache" Lines="@(ReferencePath)" Overwrite="true" />
<PropertyGroup>
<XenkoAssemblyProcessorOptions Condition="'$(XenkoAssemblyProcessorOptions)' == ''">--auto-notify-property --parameter-key --auto-module-initializer --serialization</XenkoAssemblyProcessorOptions>
<!-- If building user solutions (not unit tests), provide assembly processor with ProjectReferences paths so that they can be readded to assembly references for serialization module initializer (otherwise .exe don't have real reference on Game assemblies with auto load scene game) -->
<XenkoAssemblyProcessorOptions Condition="'$(XenkoUnitTest)' != 'true'">$(XenkoAssemblyProcessorOptions) @(_ResolvedProjectReferencePaths->'--add-reference=%22%(Identity)%22',' ')</XenkoAssemblyProcessorOptions>
<XenkoAssemblyProcessorOptions Condition="'$(DocumentationFile)' != ''">$(XenkoAssemblyProcessorOptions) --docfile="$(DocumentationFile)"</XenkoAssemblyProcessorOptions>
<XenkoAssemblyProcessorOptions>$(XenkoAssemblyProcessorOptions) --references-file="$(IntermediateOutputPath)XenkoReferences.cache"</XenkoAssemblyProcessorOptions>
<XenkoAssemblyProcessorOptions>$(XenkoAssemblyProcessorOptions) --platform=$(XenkoPlatform) --targetFramework=$(XenkoNETFrameworkVersion) "$(IntermediateOutputPath)$(TargetName)$(TargetExt)"</XenkoAssemblyProcessorOptions>
<XenkoAssemblyProcessorOptions Condition="'$(AssemblyOriginatorKeyFile)' != ''">$(XenkoAssemblyProcessorOptions) --signkeyfile="$(AssemblyOriginatorKeyFile)" --delete-on-error</XenkoAssemblyProcessorOptions>
</PropertyGroup>

<!-- Run assembly processor -->
<Message Condition=" '$(XenkoAssemblyProcessorDev)' != 'true' " Importance="low" Text="&quot;$(XenkoAssemblyProcessorPath)&quot; $(XenkoAssemblyProcessorOptions)"/>
<AssemblyProcessorTask Condition=" '$(XenkoAssemblyProcessorDev)' != 'true' " Arguments="$(XenkoAssemblyProcessorOptions)"/>
<!-- Dev mode: don't use task to avoid locking the file -->
<Exec Condition=" '$(XenkoAssemblyProcessorDev)' == 'true' " Command="&quot;$(XenkoAssemblyProcessorPath)&quot; $(XenkoAssemblyProcessorOptions)"/>
</Target>
<PropertyGroup Condition=" '$(XenkoAssemblyProcessor)' == 'true'">
<PrepareForRunDependsOn>
XenkoRunAssemblyProcessor;
$(PrepareForRunDependsOn)
</PrepareForRunDependsOn>
</PropertyGroup>
</Project>

0 comments on commit d0c771f

Please sign in to comment.
You can’t perform that action at this time.