2016-02-15 10:07:39 -08:00
using System ;
2016-02-02 10:04:50 -08:00
using System.Collections.Generic ;
using System.IO ;
using System.Runtime.InteropServices ;
2016-02-15 10:07:39 -08:00
using Microsoft.DotNet.Cli.Build.Framework ;
using Microsoft.Extensions.PlatformAbstractions ;
2016-02-02 10:04:50 -08:00
using static Microsoft . DotNet . Cli . Build . FS ;
using static Microsoft . DotNet . Cli . Build . Framework . BuildHelpers ;
2016-03-16 15:54:02 -07:00
using System.Text.RegularExpressions ;
using System.Reflection.PortableExecutable ;
2016-02-02 10:04:50 -08:00
namespace Microsoft.DotNet.Cli.Build
{
public class CompileTargets
{
2016-03-24 08:37:08 -05:00
public static readonly string CoreCLRVersion = "1.0.2-rc2-23924" ;
2016-02-18 01:21:30 -08:00
public static readonly string AppDepSdkVersion = "1.0.6-prerelease-00003" ;
2016-02-26 16:00:54 -08:00
public static readonly bool IsWinx86 = CurrentPlatform . IsWindows & & CurrentArchitecture . Isx86 ;
2016-02-02 10:04:50 -08:00
public static readonly List < string > AssembliesToCrossGen = GetAssembliesToCrossGen ( ) ;
public static readonly string [ ] BinariesForCoreHost = new [ ]
{
"csi" ,
"csc" ,
"vbc"
} ;
public static readonly string [ ] ProjectsToPublish = new [ ]
{
"dotnet"
} ;
public static readonly string [ ] FilesToClean = new [ ]
{
2016-02-16 12:23:17 -08:00
"README.md"
2016-02-02 10:04:50 -08:00
} ;
public static readonly string [ ] ProjectsToPack = new [ ]
{
"Microsoft.DotNet.Cli.Utils" ,
"Microsoft.DotNet.ProjectModel" ,
"Microsoft.DotNet.ProjectModel.Loader" ,
"Microsoft.DotNet.ProjectModel.Workspaces" ,
"Microsoft.Extensions.DependencyModel" ,
"Microsoft.Extensions.Testing.Abstractions"
} ;
2016-03-16 15:54:02 -07:00
public const string SharedFrameworkName = "Microsoft.NETCore.App" ;
private static string CoreHostBaseName = > $"corehost{Constants.ExeSuffix}" ;
private static string DotnetHostFxrBaseName = > $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}" ;
private static string HostPolicyBaseName = > $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}" ;
2016-03-01 17:42:44 -08:00
// Updates the stage 2 with recent changes.
[Target(nameof(PrepareTargets.Init), nameof(CompileStage2))]
public static BuildTargetResult UpdateBuild ( BuildTargetContext c )
{
return c . Success ( ) ;
}
2016-02-02 10:04:50 -08:00
[Target(nameof(PrepareTargets.Init), nameof(CompileCoreHost), nameof(CompileStage1), nameof(CompileStage2))]
public static BuildTargetResult Compile ( BuildTargetContext c )
{
return c . Success ( ) ;
}
[Target]
public static BuildTargetResult CompileCoreHost ( BuildTargetContext c )
{
// Generate build files
var cmakeOut = Path . Combine ( Dirs . Corehost , "cmake" ) ;
Rmdir ( cmakeOut ) ;
Mkdirp ( cmakeOut ) ;
2016-02-15 10:07:39 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-02-02 10:04:50 -08:00
// Run the build
2016-02-22 01:41:25 -08:00
string version = DotNetCli . Stage0 . Exec ( "" , "--version" ) . CaptureStdOut ( ) . Execute ( ) . StdOut ;
string rid = Array . Find < string > ( version . Split ( Environment . NewLine . ToCharArray ( ) ) , ( e ) = > e . Contains ( "Runtime Id:" ) ) . Replace ( "Runtime Id:" , "" ) . Trim ( ) ;
2016-02-02 10:04:50 -08:00
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
// Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir?
// See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason.
2016-02-23 18:04:49 -08:00
var visualStudio = IsWinx86 ? "Visual Studio 14 2015" : "Visual Studio 14 2015 Win64" ;
2016-02-26 16:00:54 -08:00
var archMacro = IsWinx86 ? "-DCLI_CMAKE_PLATFORM_ARCH_I386=1" : "-DCLI_CMAKE_PLATFORM_ARCH_AMD64=1" ;
2016-02-22 01:41:25 -08:00
var ridMacro = $"-DCLI_CMAKE_RUNTIME_ID:STRING={rid}" ;
2016-02-02 10:04:50 -08:00
ExecIn ( cmakeOut , "cmake" ,
Path . Combine ( c . BuildContext . BuildDirectory , "src" , "corehost" ) ,
2016-02-26 16:00:54 -08:00
archMacro ,
2016-02-22 01:41:25 -08:00
ridMacro ,
2016-02-02 10:04:50 -08:00
"-G" ,
2016-02-23 18:04:49 -08:00
visualStudio ) ;
2016-02-02 10:04:50 -08:00
var pf32 = RuntimeInformation . OSArchitecture = = Architecture . X64 ?
Environment . GetEnvironmentVariable ( "ProgramFiles(x86)" ) :
Environment . GetEnvironmentVariable ( "ProgramFiles" ) ;
if ( configuration . Equals ( "Release" ) )
{
// Cmake calls it "RelWithDebInfo" in the generated MSBuild
configuration = "RelWithDebInfo" ;
}
Exec ( Path . Combine ( pf32 , "MSBuild" , "14.0" , "Bin" , "MSBuild.exe" ) ,
Path . Combine ( cmakeOut , "ALL_BUILD.vcxproj" ) ,
$"/p:Configuration={configuration}" ) ;
// Copy the output out
2016-02-16 12:59:25 -08:00
File . Copy ( Path . Combine ( cmakeOut , "cli" , configuration , "corehost.exe" ) , Path . Combine ( Dirs . Corehost , "corehost.exe" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( cmakeOut , "cli" , configuration , "corehost.pdb" ) , Path . Combine ( Dirs . Corehost , "corehost.pdb" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( cmakeOut , "cli" , "dll" , configuration , "hostpolicy.dll" ) , Path . Combine ( Dirs . Corehost , "hostpolicy.dll" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( cmakeOut , "cli" , "dll" , configuration , "hostpolicy.pdb" ) , Path . Combine ( Dirs . Corehost , "hostpolicy.pdb" ) , overwrite : true ) ;
2016-02-22 01:41:25 -08:00
File . Copy ( Path . Combine ( cmakeOut , "cli" , "fxr" , configuration , "hostfxr.dll" ) , Path . Combine ( Dirs . Corehost , "hostfxr.dll" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( cmakeOut , "cli" , "fxr" , configuration , "hostfxr.pdb" ) , Path . Combine ( Dirs . Corehost , "hostfxr.pdb" ) , overwrite : true ) ;
2016-02-02 10:04:50 -08:00
}
else
{
2016-02-22 01:41:25 -08:00
ExecIn ( cmakeOut , Path . Combine ( c . BuildContext . BuildDirectory , "src" , "corehost" , "build.sh" ) ,
"--arch" ,
"amd64" ,
"--rid" ,
rid ) ;
2016-02-02 10:04:50 -08:00
// Copy the output out
2016-03-16 15:54:02 -07:00
File . Copy ( Path . Combine ( cmakeOut , "cli" , "corehost" ) , Path . Combine ( Dirs . Corehost , CoreHostBaseName ) , overwrite : true ) ;
2016-03-17 10:07:03 -07:00
File . Copy ( Path . Combine ( cmakeOut , "cli" , "dll" , HostPolicyBaseName ) , Path . Combine ( Dirs . Corehost , HostPolicyBaseName ) , overwrite : true ) ;
File . Copy ( Path . Combine ( cmakeOut , "cli" , "fxr" , DotnetHostFxrBaseName ) , Path . Combine ( Dirs . Corehost , DotnetHostFxrBaseName ) , overwrite : true ) ;
2016-02-02 10:04:50 -08:00
}
return c . Success ( ) ;
}
[Target]
public static BuildTargetResult CompileStage1 ( BuildTargetContext c )
{
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) ) ;
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "test" ) ) ;
2016-03-16 17:54:44 -07:00
2016-03-16 15:54:02 -07:00
if ( Directory . Exists ( Dirs . Stage1 ) )
{
Utils . DeleteDirectory ( Dirs . Stage1 ) ;
}
Directory . CreateDirectory ( Dirs . Stage1 ) ;
CopySharedHost ( Dirs . Stage1 ) ;
2016-03-16 17:54:44 -07:00
PublishSharedFramework ( c , Dirs . Stage1 , DotNetCli . Stage0 ) ;
2016-03-16 15:54:02 -07:00
return CompileCliSdk ( c ,
2016-02-02 10:04:50 -08:00
dotnet : DotNetCli . Stage0 ,
outputDir : Dirs . Stage1 ) ;
}
[Target]
public static BuildTargetResult CompileStage2 ( BuildTargetContext c )
{
2016-02-15 10:07:39 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-02-02 10:04:50 -08:00
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) ) ;
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "test" ) ) ;
2016-03-16 17:54:44 -07:00
2016-03-16 15:54:02 -07:00
if ( Directory . Exists ( Dirs . Stage2 ) )
{
Utils . DeleteDirectory ( Dirs . Stage2 ) ;
}
Directory . CreateDirectory ( Dirs . Stage2 ) ;
2016-03-16 17:54:44 -07:00
PublishSharedFramework ( c , Dirs . Stage2 , DotNetCli . Stage1 ) ;
2016-03-16 15:54:02 -07:00
CopySharedHost ( Dirs . Stage2 ) ;
var result = CompileCliSdk ( c ,
2016-02-02 10:04:50 -08:00
dotnet : DotNetCli . Stage1 ,
outputDir : Dirs . Stage2 ) ;
2016-02-15 09:42:17 -08:00
2016-02-02 10:04:50 -08:00
if ( ! result . Success )
{
return result ;
}
// Build projects that are packed in NuGet packages, but only on Windows
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
var packagingOutputDir = Path . Combine ( Dirs . Stage2Compilation , "forPackaging" ) ;
Mkdirp ( packagingOutputDir ) ;
2016-02-15 09:42:17 -08:00
foreach ( var project in ProjectsToPack )
2016-02-02 10:04:50 -08:00
{
// Just build them, we'll pack later
DotNetCli . Stage1 . Build (
"--build-base-path" ,
packagingOutputDir ,
"--configuration" ,
configuration ,
Path . Combine ( c . BuildContext . BuildDirectory , "src" , project ) )
. Execute ( )
. EnsureSuccessful ( ) ;
}
}
return c . Success ( ) ;
}
2016-03-16 15:54:02 -07:00
private static void CopySharedHost ( string outputDir )
2016-02-02 10:04:50 -08:00
{
2016-03-16 15:54:02 -07:00
// corehost will be renamed to dotnet at some point and then this can be removed.
File . Copy (
Path . Combine ( Dirs . Corehost , CoreHostBaseName ) ,
Path . Combine ( outputDir , $"dotnet{Constants.ExeSuffix}" ) , true ) ;
File . Copy (
Path . Combine ( Dirs . Corehost , DotnetHostFxrBaseName ) ,
Path . Combine ( outputDir , DotnetHostFxrBaseName ) , true ) ;
}
2016-03-16 17:54:44 -07:00
public static void PublishSharedFramework ( BuildTargetContext c , string outputDir , DotNetCli dotnetCli )
2016-03-16 15:54:02 -07:00
{
string SharedFrameworkSourceRoot = Path . Combine ( Dirs . RepoRoot , "src" , "sharedframework" , "framework" ) ;
2016-03-16 17:54:44 -07:00
string SharedFrameworkNugetVersion = c . BuildContext . Get < string > ( "SharedFrameworkNugetVersion" ) ;
2016-03-16 15:54:02 -07:00
// We publish to a sub folder of the PublishRoot so tools like heat and zip can generate folder structures easier.
string SharedFrameworkNameAndVersionRoot = Path . Combine ( outputDir , "shared" , SharedFrameworkName , SharedFrameworkNugetVersion ) ;
if ( Directory . Exists ( SharedFrameworkNameAndVersionRoot ) )
{
Utils . DeleteDirectory ( SharedFrameworkNameAndVersionRoot ) ;
}
string publishFramework = "dnxcore50" ; // Temporary, use "netcoreapp" when we update nuget.
string publishRuntime ;
if ( PlatformServices . Default . Runtime . OperatingSystemPlatform = = Platform . Windows )
{
publishRuntime = $"win7-{PlatformServices.Default.Runtime.RuntimeArchitecture}" ;
}
else
{
publishRuntime = PlatformServices . Default . Runtime . GetRuntimeIdentifier ( ) ;
}
dotnetCli . Publish (
"--output" , SharedFrameworkNameAndVersionRoot ,
"-r" , publishRuntime ,
"-f" , publishFramework ,
SharedFrameworkSourceRoot ) . Execute ( ) . EnsureSuccessful ( ) ;
// Clean up artifacts that dotnet-publish generates which we don't need
File . Delete ( Path . Combine ( SharedFrameworkNameAndVersionRoot , $"framework{Constants.ExeSuffix}" ) ) ;
File . Delete ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "framework.dll" ) ) ;
File . Delete ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "framework.pdb" ) ) ;
File . Delete ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "framework.runtimeconfig.json" ) ) ;
// Rename the .deps file
var destinationDeps = Path . Combine ( SharedFrameworkNameAndVersionRoot , $"{SharedFrameworkName}.deps.json" ) ;
File . Move ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "framework.deps" ) , Path . Combine ( SharedFrameworkNameAndVersionRoot , $"{SharedFrameworkName}.deps" ) ) ;
File . Move ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "framework.deps.json" ) , destinationDeps ) ;
// Generate RID fallback graph
string runtimeGraphGeneratorRuntime = null ;
switch ( PlatformServices . Default . Runtime . OperatingSystemPlatform )
{
case Platform . Windows :
runtimeGraphGeneratorRuntime = "win" ;
break ;
case Platform . Linux :
runtimeGraphGeneratorRuntime = "linux" ;
break ;
case Platform . Darwin :
runtimeGraphGeneratorRuntime = "osx" ;
break ;
}
if ( ! string . IsNullOrEmpty ( runtimeGraphGeneratorRuntime ) )
{
var runtimeGraphGeneratorName = "RuntimeGraphGenerator" ;
var runtimeGraphGeneratorProject = Path . Combine ( Dirs . RepoRoot , "tools" , runtimeGraphGeneratorName ) ;
var runtimeGraphGeneratorOutput = Path . Combine ( Dirs . Output , "tools" , runtimeGraphGeneratorName ) ;
dotnetCli . Publish (
"--output" , runtimeGraphGeneratorOutput ,
runtimeGraphGeneratorProject ) . Execute ( ) . EnsureSuccessful ( ) ;
var runtimeGraphGeneratorExe = Path . Combine ( runtimeGraphGeneratorOutput , $"{runtimeGraphGeneratorName}{Constants.ExeSuffix}" ) ;
Cmd ( runtimeGraphGeneratorExe , "--project" , SharedFrameworkSourceRoot , "--deps" , destinationDeps , runtimeGraphGeneratorRuntime )
2016-03-22 17:46:14 -05:00
. Execute ( )
. EnsureSuccessful ( ) ;
2016-03-16 15:54:02 -07:00
}
else
{
c . Error ( $"Could not determine rid graph generation runtime for platform {PlatformServices.Default.Runtime.OperatingSystemPlatform}" ) ;
}
// corehost will be renamed to dotnet at some point and then we will not need to rename it here.
File . Copy (
Path . Combine ( Dirs . Corehost , CoreHostBaseName ) ,
Path . Combine ( SharedFrameworkNameAndVersionRoot , $"dotnet{Constants.ExeSuffix}" ) ) ;
File . Copy (
Path . Combine ( Dirs . Corehost , HostPolicyBaseName ) ,
Path . Combine ( SharedFrameworkNameAndVersionRoot , HostPolicyBaseName ) , true ) ;
if ( File . Exists ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "mscorlib.ni.dll" ) ) )
{
// Publish already places the crossgen'd version of mscorlib into the output, so we can
// remove the IL version
File . Delete ( Path . Combine ( SharedFrameworkNameAndVersionRoot , "mscorlib.dll" ) ) ;
}
CrossgenSharedFx ( c , SharedFrameworkNameAndVersionRoot ) ;
2016-03-23 16:37:59 -07:00
// Generate .version file for sharedfx
var version = SharedFrameworkNugetVersion ;
var content = $@"{c.BuildContext[" CommitHash "]}{Environment.NewLine}{version}{Environment.NewLine}" ;
File . WriteAllText ( Path . Combine ( SharedFrameworkNameAndVersionRoot , ".version" ) , content ) ;
2016-03-16 15:54:02 -07:00
}
2016-02-02 10:04:50 -08:00
2016-03-16 15:54:02 -07:00
private static BuildTargetResult CompileCliSdk ( BuildTargetContext c , DotNetCli dotnet , string outputDir )
{
2016-02-15 10:07:39 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-03-16 15:54:02 -07:00
var buildVersion = c . BuildContext . Get < BuildVersion > ( "BuildVersion" ) ;
outputDir = Path . Combine ( outputDir , "sdk" , buildVersion . NuGetVersion ) ;
2016-02-02 10:04:50 -08:00
2016-03-16 15:54:02 -07:00
Rmdir ( outputDir ) ;
Mkdirp ( outputDir ) ;
2016-02-02 10:04:50 -08:00
foreach ( var project in ProjectsToPublish )
{
2016-02-18 01:09:23 -08:00
// TODO: Use the flag once we get a full build round tripped
// --version-suffix buildVesion.VersionSuffix
2016-02-02 10:04:50 -08:00
dotnet . Publish (
"--native-subdirectory" ,
"--output" ,
2016-03-16 15:54:02 -07:00
outputDir ,
2016-02-02 10:04:50 -08:00
"--configuration" ,
configuration ,
Path . Combine ( c . BuildContext . BuildDirectory , "src" , project ) )
2016-03-16 15:54:02 -07:00
. Environment ( "DOTNET_BUILD_VERSION" , buildVersion . VersionSuffix )
2016-02-02 10:04:50 -08:00
. Execute ( )
. EnsureSuccessful ( ) ;
}
FixModeFlags ( outputDir ) ;
// Copy corehost
2016-03-16 15:54:02 -07:00
File . Copy ( Path . Combine ( Dirs . Corehost , $"corehost{Constants.ExeSuffix}" ) , Path . Combine ( outputDir , $"corehost{Constants.ExeSuffix}" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( Dirs . Corehost , $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}" ) , Path . Combine ( outputDir , $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}" ) , overwrite : true ) ;
File . Copy ( Path . Combine ( Dirs . Corehost , $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}" ) , Path . Combine ( outputDir , $"{Constants.DynamicLibPrefix}hostfxr{Constants.DynamicLibSuffix}" ) , overwrite : true ) ;
2016-02-02 10:04:50 -08:00
// Corehostify binaries
2016-02-15 09:42:17 -08:00
foreach ( var binaryToCorehostify in BinariesForCoreHost )
2016-02-02 10:04:50 -08:00
{
try
{
// Yes, it is .exe even on Linux. This is the managed exe we're working with
2016-03-16 15:54:02 -07:00
File . Copy ( Path . Combine ( outputDir , $"{binaryToCorehostify}.exe" ) , Path . Combine ( outputDir , $"{binaryToCorehostify}.dll" ) ) ;
File . Delete ( Path . Combine ( outputDir , $"{binaryToCorehostify}.exe" ) ) ;
File . Copy ( Path . Combine ( outputDir , $"corehost{Constants.ExeSuffix}" ) , Path . Combine ( outputDir , binaryToCorehostify + Constants . ExeSuffix ) ) ;
2016-02-02 10:04:50 -08:00
}
2016-02-15 09:42:17 -08:00
catch ( Exception ex )
2016-02-02 10:04:50 -08:00
{
return c . Failed ( $"Failed to corehostify '{binaryToCorehostify}': {ex.ToString()}" ) ;
}
}
2016-02-18 18:03:26 -08:00
// dotnet.exe is from stage0. But we must be using the newly built corehost in stage1
2016-03-16 15:54:02 -07:00
File . Delete ( Path . Combine ( outputDir , $"dotnet{Constants.ExeSuffix}" ) ) ;
File . Copy ( Path . Combine ( outputDir , $"corehost{Constants.ExeSuffix}" ) , Path . Combine ( outputDir , $"dotnet{Constants.ExeSuffix}" ) ) ;
2016-02-18 18:03:26 -08:00
2016-02-02 10:04:50 -08:00
// Crossgen Roslyn
2016-03-16 15:54:02 -07:00
var result = CrossgenCliSdk ( c , outputDir ) ;
2016-02-02 10:04:50 -08:00
if ( ! result . Success )
{
return result ;
}
// Copy AppDeps
2016-03-16 15:54:02 -07:00
result = CopyAppDeps ( c , outputDir ) ;
2016-02-15 09:42:17 -08:00
if ( ! result . Success )
2016-02-02 10:04:50 -08:00
{
return result ;
}
// Generate .version file
2016-03-23 17:13:58 -07:00
var version = buildVersion . NuGetVersion ;
2016-02-12 17:16:28 -08:00
var content = $@"{c.BuildContext[" CommitHash "]}{Environment.NewLine}{version}{Environment.NewLine}" ;
2016-02-02 10:04:50 -08:00
File . WriteAllText ( Path . Combine ( outputDir , ".version" ) , content ) ;
return c . Success ( ) ;
}
private static BuildTargetResult CopyAppDeps ( BuildTargetContext c , string outputDir )
{
var appDepOutputDir = Path . Combine ( outputDir , "appdepsdk" ) ;
Rmdir ( appDepOutputDir ) ;
Mkdirp ( appDepOutputDir ) ;
// Find toolchain package
string packageId ;
2016-02-23 18:04:49 -08:00
2016-03-02 16:20:45 -05:00
if ( CurrentPlatform . IsWindows )
2016-02-02 10:04:50 -08:00
{
2016-03-02 16:20:45 -05:00
if ( CurrentArchitecture . Isx86 )
2016-02-23 18:04:49 -08:00
{
// https://github.com/dotnet/cli/issues/1550
c . Warn ( "Native compilation is not yet working on Windows x86" ) ;
return c . Success ( ) ;
}
2016-02-02 10:04:50 -08:00
packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep" ;
}
2016-03-02 16:20:45 -05:00
else if ( CurrentPlatform . IsUbuntu )
2016-02-02 10:04:50 -08:00
{
2016-03-02 16:20:45 -05:00
packageId = "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.AppDep" ;
}
2016-03-03 18:38:58 +00:00
else if ( CurrentPlatform . IsCentOS | | CurrentPlatform . IsRHEL | | CurrentPlatform . IsDebian )
2016-03-02 16:20:45 -05:00
{
c . Warn ( $"Native compilation is not yet working on {CurrentPlatform.Current}" ) ;
return c . Success ( ) ;
2016-02-02 10:04:50 -08:00
}
2016-03-02 16:20:45 -05:00
else if ( CurrentPlatform . IsOSX )
2016-02-02 10:04:50 -08:00
{
packageId = "toolchain.osx.10.10-x64.Microsoft.DotNet.AppDep" ;
}
else
{
return c . Failed ( "Unsupported OS Platform" ) ;
}
var appDepPath = Path . Combine (
Dirs . NuGetPackages ,
packageId ,
AppDepSdkVersion ) ;
CopyRecursive ( appDepPath , appDepOutputDir , overwrite : true ) ;
return c . Success ( ) ;
}
2016-03-16 15:54:02 -07:00
private static BuildTargetResult CrossgenCliSdk ( BuildTargetContext c , string outputDir )
2016-02-02 10:04:50 -08:00
{
// Check if we need to skip crossgen
if ( string . Equals ( Environment . GetEnvironmentVariable ( "DOTNET_BUILD_SKIP_CROSSGEN" ) , "1" ) )
{
2016-03-16 15:54:02 -07:00
c . Warn ( "Skipping crossgen for Cli Sdk because DOTNET_BUILD_SKIP_CROSSGEN is set" ) ;
2016-02-02 10:04:50 -08:00
return c . Success ( ) ;
}
// Find crossgen
2016-03-10 03:19:00 -08:00
var crossGenExePath = Microsoft . DotNet . Cli . Build . Crossgen . GetCrossgenPathForVersion ( CoreCLRVersion ) ;
if ( string . IsNullOrEmpty ( crossGenExePath ) )
2016-02-02 10:04:50 -08:00
{
return c . Failed ( "Unsupported OS Platform" ) ;
}
// We have to copy crossgen next to mscorlib
var crossgen = Path . Combine ( outputDir , $"crossgen{Constants.ExeSuffix}" ) ;
File . Copy ( crossGenExePath , crossgen , overwrite : true ) ;
Chmod ( crossgen , "a+x" ) ;
// And if we have mscorlib.ni.dll, we need to rename it to mscorlib.dll
if ( File . Exists ( Path . Combine ( outputDir , "mscorlib.ni.dll" ) ) )
{
File . Copy ( Path . Combine ( outputDir , "mscorlib.ni.dll" ) , Path . Combine ( outputDir , "mscorlib.dll" ) , overwrite : true ) ;
}
foreach ( var assemblyToCrossgen in AssembliesToCrossGen )
{
c . Info ( $"Crossgenning {assemblyToCrossgen}" ) ;
2016-03-22 00:26:26 -07:00
ExecInSilent ( outputDir , crossgen , "-readytorun" , "-nologo" , "-platform_assemblies_paths" , outputDir , assemblyToCrossgen ) ;
2016-02-02 10:04:50 -08:00
}
c . Info ( "Crossgen complete" ) ;
// Check if csc/vbc.ni.exe exists, and overwrite the dll with it just in case
if ( File . Exists ( Path . Combine ( outputDir , "csc.ni.exe" ) ) & & ! File . Exists ( Path . Combine ( outputDir , "csc.ni.dll" ) ) )
{
File . Move ( Path . Combine ( outputDir , "csc.ni.exe" ) , Path . Combine ( outputDir , "csc.ni.dll" ) ) ;
}
if ( File . Exists ( Path . Combine ( outputDir , "vbc.ni.exe" ) ) & & ! File . Exists ( Path . Combine ( outputDir , "vbc.ni.dll" ) ) )
{
File . Move ( Path . Combine ( outputDir , "vbc.ni.exe" ) , Path . Combine ( outputDir , "vbc.ni.dll" ) ) ;
}
return c . Success ( ) ;
}
2016-03-16 15:54:02 -07:00
public static BuildTargetResult CrossgenSharedFx ( BuildTargetContext c , string pathToAssemblies )
{
// Check if we need to skip crossgen
2016-03-18 15:18:18 -07:00
if ( string . Equals ( Environment . GetEnvironmentVariable ( "DONT_CROSSGEN_SHAREDFRAMEWORK" ) , "1" ) )
2016-03-16 15:54:02 -07:00
{
2016-03-18 15:18:18 -07:00
c . Warn ( "Skipping crossgen for SharedFx because DONT_CROSSGEN_SHAREDFRAMEWORK is set to 1" ) ;
2016-03-16 15:54:02 -07:00
return c . Success ( ) ;
}
2016-03-16 17:54:44 -07:00
2016-03-16 15:54:02 -07:00
foreach ( var file in Directory . GetFiles ( pathToAssemblies ) )
{
string fileName = Path . GetFileName ( file ) ;
if ( fileName = = "mscorlib.dll" | | fileName = = "mscorlib.ni.dll" | | ! HasMetadata ( file ) )
{
continue ;
}
string tempPathName = Path . ChangeExtension ( file , "readytorun" ) ;
// This is not always correct. The version of crossgen we need to pick up is whatever one was restored as part
// of the Microsoft.NETCore.Runtime.CoreCLR package that is part of the shared library. For now, the version hardcoded
// in CompileTargets and the one in the shared library project.json match and are updated in lock step, but long term
// we need to be able to look at the project.lock.json file and figure out what version of Microsoft.NETCore.Runtime.CoreCLR
// was used, and then select that version.
ExecSilent ( Crossgen . GetCrossgenPathForVersion ( CompileTargets . CoreCLRVersion ) ,
"-readytorun" , "-in" , file , "-out" , tempPathName , "-platform_assemblies_paths" , pathToAssemblies ) ;
File . Delete ( file ) ;
File . Move ( tempPathName , file ) ;
}
return c . Success ( ) ;
}
private static bool HasMetadata ( string pathToFile )
{
try
{
using ( var inStream = File . OpenRead ( pathToFile ) )
{
using ( var peReader = new PEReader ( inStream ) )
{
return peReader . HasMetadata ;
}
}
}
catch ( BadImageFormatException ) { }
return false ;
}
2016-02-02 10:04:50 -08:00
private static List < string > GetAssembliesToCrossGen ( )
{
2016-03-14 15:08:03 -05:00
return new List < string >
2016-02-02 10:04:50 -08:00
{
"System.Collections.Immutable.dll" ,
"System.Reflection.Metadata.dll" ,
"Microsoft.CodeAnalysis.dll" ,
"Microsoft.CodeAnalysis.CSharp.dll" ,
"Microsoft.CodeAnalysis.VisualBasic.dll" ,
"csc.dll" ,
"vbc.dll"
} ;
}
}
}