Skip to content

Commit

Permalink
Enable the MSBuildResolver to work under dotnet core (#561)
Browse files Browse the repository at this point in the history
Enable the MSBuildResolver to work under dotnet core
  • Loading branch information
smera committed Jul 17, 2019
1 parent eebb761 commit 3733041
Show file tree
Hide file tree
Showing 45 changed files with 729 additions and 214 deletions.
5 changes: 3 additions & 2 deletions Public/Sdk/Public/Managed/Frameworks/helpers.dsc
Expand Up @@ -4,7 +4,8 @@ namespace Helpers
{
export declare const qualifier : {};

function getToolTemplate() : Transformer.ExecuteArgumentsComposible {
@@public
export function getDotNetToolTemplate() : Transformer.ExecuteArgumentsComposible {
const host = Context.getCurrentHost();

Contract.assert(host.cpuArchitecture === "x64", "The current DotNetCore Runtime package only has x64 version of Node. Ensure this runs on a 64-bit OS -or- update PowerShell.Core package to have other architectures embedded and fix this logic");
Expand Down Expand Up @@ -40,7 +41,7 @@ namespace Helpers
};
}

const toolTemplate = getToolTemplate();
const toolTemplate = getDotNetToolTemplate();

@@public
export function wrapInDotNetExeForCurrentOs(args: Transformer.ExecuteArguments) : Transformer.ExecuteArguments {
Expand Down
4 changes: 2 additions & 2 deletions Public/Sdk/Public/Managed/Shared/types.dsc
Expand Up @@ -129,12 +129,12 @@ export interface LinkResource {
}

@@public
export function isBinary(item: Reference) : item is Binary {
export function isBinary(item: any) : item is Binary {
return item["binary"] !== undefined;
}

@@public
export function isAssembly(item: Reference) : item is Assembly {
export function isAssembly(item: any) : item is Assembly {
return item["name"] !== undefined &&
(item["compile"] !== undefined || item["runtime"] !== undefined) &&
item["contents"] === undefined; // Exclude nuget packages
Expand Down
2 changes: 2 additions & 0 deletions Public/Sdk/Public/Managed/Testing/XUnit/xunitframework.dsc
Expand Up @@ -47,6 +47,7 @@ const xunitNetStandardRuntimeConfigFiles: File[] = Managed.RuntimeConfigFiles.cr
"xunit.console",
Managed.Factory.createBinary(xunitNetCoreConsolePackage, r`/lib/netcoreapp2.0/xunit.console.dll`),
xunitReferences,
undefined, // runtimeContentToSkip
undefined, // appconfig
true);

Expand All @@ -62,6 +63,7 @@ function additionalRuntimeContent(args: Managed.TestArguments) : Deployment.Depl
"xunit.console",
Managed.Factory.createBinary(xunitNetCoreConsolePackage, r`/lib/netcoreapp2.0/xunit.console.dll`),
xunitReferences,
args.runtimeContentToSkip,
undefined, // appConfig
true)),
xunitConsolePackage.getFile(r`/tools/netcoreapp2.0/xunit.runner.utility.netcoreapp10.dll`),
Expand Down
28 changes: 16 additions & 12 deletions Public/Sdk/Public/Managed/helpers.dsc
Expand Up @@ -3,6 +3,7 @@

import * as Shared from "Sdk.Managed.Shared";
import * as Csc from "Sdk.Managed.Tools.Csc";
import * as Deployment from "Sdk.Deployment";

namespace Helpers {

Expand Down Expand Up @@ -53,19 +54,21 @@ namespace Helpers {
* You can control whether to follow the compile or the runtime axis using the optional compile argument.
*/
@@public
export function computeTransitiveReferenceClosure(framework: Shared.Framework, references: Shared.Reference[], compile?: boolean) : Shared.Binary[] {
export function computeTransitiveReferenceClosure(framework: Shared.Framework, references: Shared.Reference[], runtimeContentToSkip: Deployment.DeployableItem[], compile?: boolean) : Shared.Binary[] {
return computeTransitiveClosure([
...references,
...framework.standardReferences
], compile);
],
runtimeContentToSkip,
compile);
}

/**
* Computes a transitive closure or managed binaries for the given list of references.
* You can control whether to follow the compile or the runtime axis using the optional compile argument.
*/
@@public
export function computeTransitiveClosure(references: Shared.Reference[], compile?: boolean) : Shared.Binary[] {
export function computeTransitiveClosure(references: Shared.Reference[], referencesToSkip: Deployment.DeployableItem[], compile?: boolean) : Shared.Binary[] {
let results = MutableSet.empty<Shared.Binary>();
let visitedReferences = MutableSet.empty<Shared.Reference>();

Expand All @@ -75,14 +78,15 @@ namespace Helpers {

for (let ref of allReferences)
{
computeTransitiveReferenceClosureHelper(ref, results, visitedReferences, compile);
const referencesToSkipSet = Set.empty<Deployment.DeployableItem>().add(...(referencesToSkip ? referencesToSkip : []));
computeTransitiveReferenceClosureHelper(ref, referencesToSkipSet, results, visitedReferences, compile);
}

return results.toArray();
}

function computeTransitiveReferenceClosureHelper(ref: Shared.Reference, results: MutableSet<Shared.Binary>, visitedReferences: MutableSet<Shared.Reference>, compile?: boolean) {
if (visitedReferences.contains(ref))
function computeTransitiveReferenceClosureHelper(ref: Shared.Reference, referencesToSkip: Set<Deployment.DeployableItem>,results: MutableSet<Shared.Binary>, visitedReferences: MutableSet<Shared.Reference>, compile?: boolean) {
if (visitedReferences.contains(ref) || referencesToSkip.contains(ref))
{
return;
}
Expand All @@ -95,36 +99,36 @@ namespace Helpers {
}
else if (Shared.isAssembly(ref))
{
if (compile && ref.compile) {
if (compile && ref.compile && !referencesToSkip.contains(ref.compile)) {
results.add(ref.compile);
}
if (!compile && ref.runtime) {
if (!compile && ref.runtime && !referencesToSkip.contains(ref.runtime)) {
results.add(ref.runtime);
}
if (ref.references)
{
for (let nestedRef of ref.references)
{
computeTransitiveReferenceClosureHelper(nestedRef, results, visitedReferences, compile);
computeTransitiveReferenceClosureHelper(nestedRef, referencesToSkip, results, visitedReferences, compile);
}
}
}
else if (Shared.isManagedPackage(ref))
{
if (compile)
{
results.add(...ref.compile);
results.add(...ref.compile.filter(c => !referencesToSkip.contains(c)));
}
else
{
results.add(...ref.runtime);
results.add(...ref.runtime.filter(c => !referencesToSkip.contains(c)));
}

for (let dependency of ref.dependencies)
{
if (Shared.isManagedPackage(dependency))
{
computeTransitiveReferenceClosureHelper(dependency, results, visitedReferences, compile);
computeTransitiveReferenceClosureHelper(dependency, referencesToSkip, results, visitedReferences, compile);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Public/Sdk/Public/Managed/managedSdk.dsc
Expand Up @@ -209,7 +209,7 @@ export function assembly(args: Arguments, targetType: Csc.TargetType) : Result {

if (targetType === "exe")
{
runtimeConfigFiles = RuntimeConfigFiles.createFiles(framework, name, runtimeBinary, references, appConfig);
runtimeConfigFiles = RuntimeConfigFiles.createFiles(framework, name, runtimeBinary, references, args.runtimeContentToSkip, appConfig);
if (framework.applicationDeploymentStyle === "selfContained")
{
const frameworkRuntimeFiles = framework.runtimeContentProvider(qualifier.targetRuntime);
Expand Down
7 changes: 5 additions & 2 deletions Public/Sdk/Public/Managed/runtimeConfigFiles.dsc
Expand Up @@ -5,6 +5,7 @@ import {Transformer} from "Sdk.Transformers";

import * as Json from "Sdk.Json";
import * as Shared from "Sdk.Managed.Shared";
import * as Deployment from "Sdk.Deployment";

namespace RuntimeConfigFiles {

Expand All @@ -18,6 +19,7 @@ namespace RuntimeConfigFiles {
assemblyName: string,
runtimeBinary: Shared.Binary,
references: Shared.Reference[],
runtimeContentToSkip: Deployment.DeployableItem[],
appConfig: File,
testRunnerDeployment?: boolean
) : File[] {
Expand All @@ -44,7 +46,7 @@ namespace RuntimeConfigFiles {
}

return [
createDependenciesJson(framework, assemblyName, runtimeBinary, references, testRunnerDeployment),
createDependenciesJson(framework, assemblyName, runtimeBinary, references, runtimeContentToSkip, testRunnerDeployment),
createRuntimeConfigJson(framework, assemblyName, runtimeConfigFolder, testRunnerDeployment),
];
case "none":
Expand All @@ -68,12 +70,13 @@ namespace RuntimeConfigFiles {
assemblyName: string,
runtimeBinary: Shared.Binary,
references: Shared.Reference[],
runtimeContentToSkip: Deployment.DeployableItem[],
testRunnerDeployment?: boolean
): File {

const specFileOutput = Context.getNewOutputDirectory("DotNetSpecFiles");

const runtimeReferences = Helpers.computeTransitiveReferenceClosure(framework, references, false);
const runtimeReferences = Helpers.computeTransitiveReferenceClosure(framework, references, runtimeContentToSkip, false);

const dependencySpecExtension = `${assemblyName}.deps.json`;
const dependencySpecPath = p`${specFileOutput}/${dependencySpecExtension}`;
Expand Down
18 changes: 17 additions & 1 deletion Public/Sdk/Public/Prelude/Prelude.Configuration.Resolvers.dsc
Expand Up @@ -136,12 +136,28 @@ interface MsBuildResolver extends ResolverBase, UntrackingSettings {
runInContainer?: boolean;

/**
* Collection of directories to search for the required MsBuild assemblies and MsBuild.exe (a.k.a. MSBuild toolset).
* Collection of directories to search for the required MsBuild assemblies and MsBuild.exe/MSBuild.dll (a.k.a. MSBuild toolset).
* If not specified, locations in %PATH% are used.
* Locations are traversed in specification order.
*/
msBuildSearchLocations?: Directory[];

/**
* Whether to use the full framework or dotnet core version of MSBuild. Selected runtime is used both for build evaluation and execution.
* Default is full framework.
* Observe that using the full framework version means that msbuild.exe is expected to be found in msbuildSearchLocations
* (or PATH if not specified). If using the dotnet core version, the same logic applies but to msbuild.dll
*/
msBuildRuntime?: "FullFramework" | "DotNetCore";

/**
* Collection of directories to search for dotnet.exe, when DotNetCore is specified as the msBuildRuntime. If not
* specified, locations in %PATH% are used.
* Locations are traversed in specification order.
* It has no effect if the specified MSBuild runtime is full framework.
*/
dotNetSearchLocations?: Directory[];

/**
* Optional file paths for the projects or solutions that should be used to start parsing. These are relative
* paths with respect to the root traversal.
Expand Down
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import {Transformer} from "Sdk.Transformers";
import {createPublicDotNetRuntime} from "DotNet-Runtime.Common";

const v3 = <StaticDirectory>importFrom("DotNet-Runtime.linux-x64.3.0.0-preview5").extracted;
const v2 = <StaticDirectory>importFrom("DotNet-Runtime.linux-x64.2.2.2").extracted;

@@public
export const extracted = createPublicDotNetRuntime(v3, v2);
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import {Transformer} from "Sdk.Transformers";
import {createPublicDotNetRuntime} from "DotNet-Runtime.Common";

const v3 = <StaticDirectory>importFrom("DotNet-Runtime.osx-x64.3.0.0-preview5").extracted;
const v2 = <StaticDirectory>importFrom("DotNet-Runtime.osx-x64.2.2.2").extracted;

@@public
export const extracted = createPublicDotNetRuntime(v3, v2);
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import {Transformer} from "Sdk.Transformers";
import {createPublicDotNetRuntime} from "DotNet-Runtime.Common";

const v3 = <StaticDirectory>importFrom("DotNet-Runtime.win-x64.3.0.0-preview5").extracted;
const v2 = <StaticDirectory>importFrom("DotNet-Runtime.win-x64.2.2.2").extracted;

@@public
export const extracted = createPublicDotNetRuntime(v3, v2);
22 changes: 22 additions & 0 deletions Public/Sdk/SelfHost/Libraries/Dotnet-Runtime-External/common.dsc
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import {Transformer} from "Sdk.Transformers";

@@public
export function createPublicDotNetRuntime(v3Runtime : StaticDirectory, v2Runtime: StaticDirectory) : StaticDirectory {
const netCoreAppV2 = v2Runtime.contents.filter(file => file.path.isWithin(d`${v2Runtime.root}/shared`));

// We create a package that has dotnet executable and related SDK, plus the V2 SDK
const dotNetRuntimeRoot = Context.getNewOutputDirectory("DotNet-Runtime");

const sealDirectory = Transformer.sealDirectory(
dotNetRuntimeRoot,
[
...v3Runtime.contents.map(file => Transformer.copyFile(file, file.path.relocate(v3Runtime.root, dotNetRuntimeRoot))),
...netCoreAppV2.map(file => Transformer.copyFile(file, file.path.relocate(v2Runtime.root, dotNetRuntimeRoot)))
]
);

return sealDirectory;
}
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// These are the external versions of the architecture-specific DotNet-Runtime packages.
// They are created from the 3.0.0-preview5 version, plus the 2.2 NetCore.App SDK, which is deployed side-by-side
// The latter is required for MSBuild tests

module({
name: "DotNet-Runtime.win-x64",
nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences,
projects: [f`DotNet-Runtime.win-x64.dsc`]
});

module({
name: "DotNet-Runtime.osx-x64",
nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences,
projects: [f`DotNet-Runtime.osx-x64.dsc`]
});

module({
name: "DotNet-Runtime.linux-x64",
nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences,
projects: [f`DotNet-Runtime.linux-x64.dsc`]
});

module({
name: "DotNet-Runtime.Common",
nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences,
projects: [f`common.dsc`]
});
37 changes: 25 additions & 12 deletions Public/Sdk/SelfHost/Libraries/MSBuild/msbuild.dsc
Expand Up @@ -3,16 +3,8 @@

import * as Managed from "Sdk.Managed";
import * as BuildXLSdk from "Sdk.BuildXL";
// import * as Deployment from "Sdk.Deployment";

@@public
export interface MSBuildQualifier extends Qualifier {
configuration: "debug" | "release";
targetFramework: "net472" ;
targetRuntime: "win-x64" | "osx-x64";
};

export declare const qualifier : MSBuildQualifier;
export declare const qualifier: BuildXLSdk.DefaultQualifier;

@@public
export const msbuildReferences: Managed.ManagedNugetPackage[] = [
Expand All @@ -22,12 +14,16 @@ export const msbuildReferences: Managed.ManagedNugetPackage[] = [
importFrom("Microsoft.Build.Tasks.Core").pkg,
];

/** Runtime content for tests */
@@public
export const msbuildRuntimeContent = [
BuildXLSdk.isDotNetCoreBuild ? importFrom("System.Threading.Tasks.Dataflow").pkg : importFrom("DataflowForMSBuild").pkg,
importFrom("System.Numerics.Vectors").pkg,
importFrom("DataflowForMSBuildRuntime").pkg,
// importFrom("System.Collections.Immutable").pkg,
...BuildXLSdk.isTargetRuntimeOsx ? [
importFrom("Microsoft.Build.Runtime").pkg,
...BuildXLSdk.isDotNetCoreBuild ? [
importFrom("Microsoft.NETCore.App.210").pkg,
importFrom("System.Text.Encoding.CodePages").withQualifier({targetFramework: "netstandard2.0"}).pkg,
importFrom("Microsoft.Build.Tasks.Core").withQualifier({targetFramework: "netstandard2.0"}).pkg,
importFrom("Microsoft.Build.Runtime").Contents.all.getFile(r`contentFiles/any/netcoreapp2.1/MSBuild.dll`),
importFrom("Microsoft.Build.Runtime").Contents.all.getFile(r`contentFiles/any/netcoreapp2.1/MSBuild.runtimeconfig.json`),
]
Expand All @@ -36,3 +32,20 @@ export const msbuildRuntimeContent = [
importFrom("Microsoft.Build.Runtime").Contents.all.getFile(r`contentFiles/any/net472/MSBuild.exe.config`),
],
];

function getFrameworkFolder() {
return BuildXLSdk.isDotNetCoreBuild ? "dotnetcore" : qualifier.targetFramework;
}

@@public
export const deployment = [
{
subfolder: a`msbuild`,
contents: [{
subfolder: getFrameworkFolder(),
contents: [
...msbuildRuntimeContent,
...msbuildReferences,]
}]
},
];
2 changes: 1 addition & 1 deletion Public/Sdk/SelfHost/MacOS/coreRT.dsc
Expand Up @@ -17,7 +17,7 @@ export namespace CoreRT {
@@public
export function compileToNative(asm: Shared.Assembly): NativeExecutableResult {
/** Compile to native object file */
const referencesClosure = Managed.Helpers.computeTransitiveClosure(asm.references, /*compile*/ false);
const referencesClosure = Managed.Helpers.computeTransitiveClosure(asm.references, asm.runtimeContentToSkip, /*compile*/ false);
const ilcResult = Ilc.compile({
out: `${asm.name}.o`,
inputs: [
Expand Down

0 comments on commit 3733041

Please sign in to comment.