2016-04-14 18:02:26 -07:00
using System ;
using System.Collections.Generic ;
2016-03-10 03:19:00 -08:00
using System.IO ;
using System.Linq ;
using Microsoft.DotNet.Cli.Build.Framework ;
2016-04-28 16:30:32 -07:00
using Microsoft.DotNet.InternalAbstractions ;
2016-04-14 18:02:26 -07:00
using static Microsoft . DotNet . Cli . Build . Framework . BuildHelpers ;
2016-03-10 03:19:00 -08:00
namespace Microsoft.DotNet.Cli.Build
{
2016-04-14 18:02:26 -07:00
public class Crossgen
2016-03-10 03:19:00 -08:00
{
2016-04-14 18:02:26 -07:00
private string _coreClrVersion ;
private string _crossGenPath ;
// 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.
public Crossgen ( string coreClrVersion )
{
_coreClrVersion = coreClrVersion ;
_crossGenPath = GetCrossgenPathForVersion ( ) ;
}
private string GetCrossgenPathForVersion ( )
2016-03-10 03:19:00 -08:00
{
2016-04-28 16:30:32 -07:00
string arch = RuntimeEnvironment . RuntimeArchitecture ;
2016-03-10 03:19:00 -08:00
string packageId ;
if ( CurrentPlatform . IsWindows )
{
packageId = $"runtime.win7-{arch}.Microsoft.NETCore.Runtime.CoreCLR" ;
}
else if ( CurrentPlatform . IsUbuntu )
{
packageId = "runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR" ;
}
else if ( CurrentPlatform . IsCentOS | | CurrentPlatform . IsRHEL )
{
// CentOS runtime is in the runtime.rhel.7-x64... package.
packageId = "runtime.rhel.7-x64.Microsoft.NETCore.Runtime.CoreCLR" ;
}
else if ( CurrentPlatform . IsOSX )
{
packageId = "runtime.osx.10.10-x64.Microsoft.NETCore.Runtime.CoreCLR" ;
}
else if ( CurrentPlatform . IsDebian )
{
2016-04-12 09:41:33 -05:00
packageId = "runtime.debian.8-x64.Microsoft.NETCore.Runtime.CoreCLR" ;
2016-03-10 03:19:00 -08:00
}
else
{
return null ;
}
return Path . Combine (
Dirs . NuGetPackages ,
packageId ,
2016-04-14 18:02:26 -07:00
_coreClrVersion ,
2016-03-10 03:19:00 -08:00
"tools" ,
$"crossgen{Constants.ExeSuffix}" ) ;
}
2016-04-14 18:02:26 -07:00
public void CrossgenDirectory ( BuildTargetContext c , string pathToAssemblies )
{
// Check if we need to skip crossgen
if ( string . Equals ( Environment . GetEnvironmentVariable ( "DISABLE_CROSSGEN" ) , "1" ) )
{
c . Warn ( "Skipping crossgen for because DISABLE_CROSSGEN is set to 1" ) ;
return ;
}
2016-04-15 10:31:17 -07:00
string sharedFxPath = c . BuildContext . Get < string > ( "SharedFrameworkPath" ) ;
// HACK
// The input directory can be a portable FAT app (example the CLI itself).
// In that case there can be RID specific managed dependencies which are not right next to the app binary (example System.Diagnostics.TraceSource).
// We need those dependencies during crossgen. For now we just pass all subdirectories of the input directory as input to crossgen.
// The right fix -
// If the assembly has deps.json then parse the json file to get all the dependencies, pass these dependencies as input to crossgen.
// else pass the current directory of assembly as input to crossgen.
var addtionalPaths = Directory . GetDirectories ( pathToAssemblies , "*" , SearchOption . AllDirectories ) . ToList ( ) ;
var paths = new List < string > ( ) { sharedFxPath , pathToAssemblies } ;
paths . AddRange ( addtionalPaths ) ;
var platformAssembliesPaths = string . Join ( Path . PathSeparator . ToString ( ) , paths . Distinct ( ) ) ;
var env = new Dictionary < string , string > ( )
{
// disable partial ngen
{ "COMPLUS_ZapDisable" , "0" }
} ;
2016-04-14 18:02:26 -07:00
foreach ( var file in Directory . GetFiles ( pathToAssemblies ) )
{
string fileName = Path . GetFileName ( file ) ;
if ( fileName = = "mscorlib.dll" | | fileName = = "mscorlib.ni.dll" | | ! PEUtils . HasMetadata ( file ) )
{
continue ;
}
string tempPathName = Path . ChangeExtension ( file , "readytorun" ) ;
IList < string > crossgenArgs = new List < string > {
"-readytorun" , "-in" , file , "-out" , tempPathName ,
2016-04-14 18:54:25 -07:00
"-platform_assemblies_paths" , platformAssembliesPaths
2016-04-14 18:02:26 -07:00
} ;
2016-04-14 18:36:33 -07:00
ExecSilent ( _crossGenPath , crossgenArgs , env ) ;
2016-04-14 18:02:26 -07:00
2016-05-02 19:51:12 -07:00
File . Copy ( tempPathName , file , overwrite : true ) ;
File . Delete ( tempPathName ) ;
2016-04-14 18:02:26 -07:00
}
}
2016-03-10 03:19:00 -08:00
}
}