2015-12-10 13:06:33 -08:00
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
2016-01-29 18:21:37 -08:00
using Microsoft.Dotnet.Cli.Compiler.Common ;
2016-01-27 16:20:26 -08:00
using Microsoft.DotNet.Cli.Compiler.Common ;
2015-12-10 13:06:33 -08:00
using Microsoft.DotNet.Cli.Utils ;
using Microsoft.DotNet.ProjectModel ;
using Microsoft.DotNet.ProjectModel.Utilities ;
2016-01-27 16:20:26 -08:00
using Microsoft.DotNet.Tools.Compiler ;
2016-01-29 18:21:37 -08:00
using Microsoft.Extensions.PlatformAbstractions ;
2015-12-10 13:06:33 -08:00
namespace Microsoft.DotNet.Tools.Build
{
2015-12-21 10:42:41 -08:00
// todo: Convert CompileContext into a DAG of dependencies: if a node needs recompilation, the entire path up to root needs compilation
2015-12-10 13:06:33 -08:00
// Knows how to orchestrate compilation for a ProjectContext
// Collects icnremental safety checks and transitively compiles a project context
internal class CompileContext
{
public static readonly string [ ] KnownCompilers = { "csc" , "vbc" , "fsc" } ;
private readonly ProjectContext _rootProject ;
private readonly BuilderCommandApp _args ;
private readonly IncrementalPreconditions _preconditions ;
2015-12-21 10:42:41 -08:00
private readonly ProjectDependenciesFacade _dependencies ;
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
public bool IsSafeForIncrementalCompilation = > ! _preconditions . PreconditionsDetected ( ) ;
2015-12-10 13:06:33 -08:00
public CompileContext ( ProjectContext rootProject , BuilderCommandApp args )
{
_rootProject = rootProject ;
2015-12-21 10:42:41 -08:00
// Cleaner to clone the args and mutate the clone than have separate CompileContext fields for mutated args
// and then reasoning which ones to get from args and which ones from fields.
2016-01-26 06:39:13 -08:00
_args = ( BuilderCommandApp ) args . ShallowCopy ( ) ;
2016-02-03 10:57:25 -08:00
_args . OutputValue = _args . OutputValue ;
_args . BuildBasePathValue = _args . BuildBasePathValue ;
2015-12-10 13:06:33 -08:00
// Set up dependencies
2015-12-21 10:42:41 -08:00
_dependencies = new ProjectDependenciesFacade ( _rootProject , _args . ConfigValue ) ;
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
// gather preconditions
2015-12-10 13:06:33 -08:00
_preconditions = GatherIncrementalPreconditions ( ) ;
}
public bool Compile ( bool incremental )
{
CreateOutputDirectories ( ) ;
2015-12-21 10:42:41 -08:00
// compile dependencies
foreach ( var dependency in Sort ( _dependencies . ProjectDependenciesWithSources ) )
2015-12-10 13:06:33 -08:00
{
2015-12-21 10:42:41 -08:00
if ( incremental )
{
2016-02-03 10:57:25 -08:00
var dependencyProjectContext = ProjectContext . Create ( dependency . Path , dependency . Framework , new [ ] { _rootProject . RuntimeIdentifier } ) ;
2015-12-21 10:42:41 -08:00
2016-02-03 10:57:25 -08:00
if ( ! NeedsRebuilding ( dependencyProjectContext , new ProjectDependenciesFacade ( dependencyProjectContext , _args . ConfigValue ) ) )
2015-12-21 10:42:41 -08:00
{
continue ;
}
}
if ( ! InvokeCompileOnDependency ( dependency ) )
2015-12-10 13:06:33 -08:00
{
return false ;
}
}
2015-12-21 10:42:41 -08:00
if ( incremental & & ! NeedsRebuilding ( _rootProject , _dependencies ) )
{
// todo: what if the previous build had errors / warnings and nothing changed? Need to propagate them in case of incremental
return true ;
}
// compile project
var success = InvokeCompileOnRootProject ( ) ;
2015-12-10 13:06:33 -08:00
PrintSummary ( success ) ;
return success ;
}
2015-12-21 10:42:41 -08:00
private bool NeedsRebuilding ( ProjectContext project , ProjectDependenciesFacade dependencies )
2015-12-10 13:06:33 -08:00
{
2016-02-03 10:57:25 -08:00
return NeedsRebuilding ( project , dependencies , _args . BuildBasePathValue ) ;
2016-01-26 06:39:13 -08:00
}
2016-02-03 10:57:25 -08:00
private bool NeedsRebuilding ( ProjectContext project , ProjectDependenciesFacade dependencies , string baseBuildPath )
2016-01-26 06:39:13 -08:00
{
2016-02-10 08:14:06 -08:00
var compilerIO = GetCompileIO ( project , _args . ConfigValue , baseBuildPath , _args . OutputValue , dependencies , project = = _rootProject ) ;
2015-12-21 10:42:41 -08:00
// rebuild if empty inputs / outputs
if ( ! ( compilerIO . Outputs . Any ( ) & & compilerIO . Inputs . Any ( ) ) )
2015-12-10 13:06:33 -08:00
{
2016-01-26 06:39:13 -08:00
Reporter . Output . WriteLine ( $"Project {project.GetDisplayName()} will be compiled because it either has empty inputs or outputs" ) ;
2015-12-21 10:42:41 -08:00
return true ;
2015-12-10 13:06:33 -08:00
}
2015-12-21 10:42:41 -08:00
//rebuild if missing inputs / outputs
if ( AnyMissingIO ( project , compilerIO . Outputs , "outputs" ) | | AnyMissingIO ( project , compilerIO . Inputs , "inputs" ) )
{
return true ;
}
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
// find the output with the earliest write time
var minOutputPath = compilerIO . Outputs . First ( ) ;
2016-01-27 16:20:26 -08:00
var minDateUtc = File . GetLastWriteTimeUtc ( minOutputPath ) ;
2015-12-21 10:42:41 -08:00
foreach ( var outputPath in compilerIO . Outputs )
{
2016-01-27 16:20:26 -08:00
if ( File . GetLastWriteTimeUtc ( outputPath ) > = minDateUtc )
2015-12-21 10:42:41 -08:00
{
continue ;
}
2016-01-27 16:20:26 -08:00
minDateUtc = File . GetLastWriteTimeUtc ( outputPath ) ;
2015-12-21 10:42:41 -08:00
minOutputPath = outputPath ;
}
// find inputs that are older than the earliest output
2016-01-26 14:53:56 -08:00
var newInputs = compilerIO . Inputs . FindAll ( p = > File . GetLastWriteTimeUtc ( p ) > = minDateUtc ) ;
2015-12-21 10:42:41 -08:00
if ( ! newInputs . Any ( ) )
{
2016-01-26 06:39:13 -08:00
Reporter . Output . WriteLine ( $"Project {project.GetDisplayName()} was previously compiled. Skipping compilation." ) ;
2015-12-21 10:42:41 -08:00
return false ;
}
2016-01-26 06:39:13 -08:00
Reporter . Output . WriteLine ( $"Project {project.GetDisplayName()} will be compiled because some of its inputs were newer than its oldest output." ) ;
Reporter . Verbose . WriteLine ( ) ;
Reporter . Verbose . WriteLine ( $" Oldest output item:" ) ;
2016-01-27 16:20:26 -08:00
Reporter . Verbose . WriteLine ( $" {minDateUtc.ToLocalTime()}: {minOutputPath}" ) ;
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( ) ;
Reporter . Verbose . WriteLine ( $" Inputs newer than the oldest output item:" ) ;
2015-12-21 10:42:41 -08:00
foreach ( var newInput in newInputs )
{
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( $" {File.GetLastWriteTime(newInput)}: {newInput}" ) ;
2015-12-21 10:42:41 -08:00
}
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( ) ;
2015-12-21 10:42:41 -08:00
return true ;
2015-12-10 13:06:33 -08:00
}
2015-12-21 10:42:41 -08:00
private static bool AnyMissingIO ( ProjectContext project , IEnumerable < string > items , string itemsType )
2015-12-10 13:06:33 -08:00
{
2015-12-21 10:42:41 -08:00
var missingItems = items . Where ( i = > ! File . Exists ( i ) ) . ToList ( ) ;
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
if ( ! missingItems . Any ( ) )
{
return false ;
}
2015-12-10 13:06:33 -08:00
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( $"Project {project.GetDisplayName()} will be compiled because expected {itemsType} are missing." ) ;
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
foreach ( var missing in missingItems )
2015-12-10 13:06:33 -08:00
{
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( $" {missing}" ) ;
2015-12-21 10:42:41 -08:00
}
2015-12-10 13:06:33 -08:00
2016-01-26 06:39:13 -08:00
Reporter . Verbose . WriteLine ( ) ; ;
2015-12-21 10:42:41 -08:00
return true ;
}
private void PrintSummary ( bool success )
{
// todo: Ideally it's the builder's responsibility for adding the time elapsed. That way we avoid cross cutting display concerns between compile and build for printing time elapsed
if ( success )
{
Reporter . Output . Write ( " " + _preconditions . LogMessage ( ) ) ;
Reporter . Output . WriteLine ( ) ;
2015-12-10 13:06:33 -08:00
}
2015-12-21 10:42:41 -08:00
Reporter . Output . WriteLine ( ) ;
}
private void CreateOutputDirectories ( )
{
2016-02-03 10:57:25 -08:00
if ( ! string . IsNullOrEmpty ( _args . OutputValue ) )
{
Directory . CreateDirectory ( _args . OutputValue ) ;
}
if ( ! string . IsNullOrEmpty ( _args . BuildBasePathValue ) )
{
Directory . CreateDirectory ( _args . BuildBasePathValue ) ;
}
2015-12-10 13:06:33 -08:00
}
private IncrementalPreconditions GatherIncrementalPreconditions ( )
{
var preconditions = new IncrementalPreconditions ( _args . BuildProfileValue ) ;
2015-12-21 10:42:41 -08:00
if ( _args . ForceUnsafeValue )
{
preconditions . AddForceUnsafePrecondition ( ) ;
}
2015-12-10 13:06:33 -08:00
var projectsToCheck = GetProjectsToCheck ( ) ;
foreach ( var project in projectsToCheck )
{
CollectScriptPreconditions ( project , preconditions ) ;
CollectCompilerNamePreconditions ( project , preconditions ) ;
2015-12-21 10:42:41 -08:00
CollectCheckPathProbingPreconditions ( project , preconditions ) ;
2015-12-10 13:06:33 -08:00
}
return preconditions ;
}
2015-12-21 10:42:41 -08:00
// check the entire project tree that needs to be compiled, duplicated for each framework
2015-12-10 13:06:33 -08:00
private List < ProjectContext > GetProjectsToCheck ( )
{
2015-12-21 10:42:41 -08:00
// include initial root project
2016-01-26 06:39:13 -08:00
var contextsToCheck = new List < ProjectContext > ( 1 + _dependencies . ProjectDependenciesWithSources . Count ) { _rootProject } ;
2015-12-10 13:06:33 -08:00
2015-12-21 10:42:41 -08:00
// convert ProjectDescription to ProjectContext
var dependencyContexts = _dependencies . ProjectDependenciesWithSources . Select
( keyValuePair = > ProjectContext . Create ( keyValuePair . Value . Path , keyValuePair . Value . Framework ) ) ;
2015-12-10 13:06:33 -08:00
contextsToCheck . AddRange ( dependencyContexts ) ;
return contextsToCheck ;
}
2015-12-21 10:42:41 -08:00
private void CollectCheckPathProbingPreconditions ( ProjectContext project , IncrementalPreconditions preconditions )
2015-12-10 13:06:33 -08:00
{
var pathCommands = CompilerUtil . GetCommandsInvokedByCompile ( project )
2016-01-30 21:47:50 -08:00
. Select ( commandName = > Command . CreateDotNet ( commandName , Enumerable . Empty < string > ( ) , project . TargetFramework ) )
2016-01-06 02:27:16 -08:00
. Where ( c = > c . ResolutionStrategy . Equals ( CommandResolutionStrategy . Path ) ) ;
2015-12-10 13:06:33 -08:00
foreach ( var pathCommand in pathCommands )
{
preconditions . AddPathProbingPrecondition ( project . ProjectName ( ) , pathCommand . CommandName ) ;
}
}
private void CollectCompilerNamePreconditions ( ProjectContext project , IncrementalPreconditions preconditions )
{
var projectCompiler = CompilerUtil . ResolveCompilerName ( project ) ;
2015-12-21 10:42:41 -08:00
if ( ! KnownCompilers . Any ( knownCompiler = > knownCompiler . Equals ( projectCompiler , StringComparison . Ordinal ) ) )
2015-12-10 13:06:33 -08:00
{
preconditions . AddUnknownCompilerPrecondition ( project . ProjectName ( ) , projectCompiler ) ;
}
}
private void CollectScriptPreconditions ( ProjectContext project , IncrementalPreconditions preconditions )
{
var preCompileScripts = project . ProjectFile . Scripts . GetOrEmpty ( ScriptNames . PreCompile ) ;
var postCompileScripts = project . ProjectFile . Scripts . GetOrEmpty ( ScriptNames . PostCompile ) ;
if ( preCompileScripts . Any ( ) )
{
preconditions . AddPrePostScriptPrecondition ( project . ProjectName ( ) , ScriptNames . PreCompile ) ;
}
if ( postCompileScripts . Any ( ) )
{
preconditions . AddPrePostScriptPrecondition ( project . ProjectName ( ) , ScriptNames . PostCompile ) ;
}
}
2015-12-21 10:42:41 -08:00
private bool InvokeCompileOnDependency ( ProjectDescription projectDependency )
2015-12-10 13:06:33 -08:00
{
2016-01-22 13:55:13 -08:00
var args = new List < string > ( ) ;
args . Add ( "--framework" ) ;
2016-01-29 18:21:37 -08:00
args . Add ( $"{projectDependency.Framework}" ) ;
2016-01-29 09:21:55 -08:00
2016-01-22 13:55:13 -08:00
args . Add ( "--configuration" ) ;
2016-01-26 06:39:13 -08:00
args . Add ( _args . ConfigValue ) ;
args . Add ( projectDependency . Project . ProjectDirectory ) ;
2015-12-10 13:06:33 -08:00
2016-02-03 10:57:25 -08:00
if ( ! string . IsNullOrWhiteSpace ( _args . BuildBasePathValue ) )
{
args . Add ( "--build-base-path" ) ;
args . Add ( _args . BuildBasePathValue ) ;
}
2016-02-03 12:04:09 -08:00
var compileResult = CommpileCommand . Run ( args . ToArray ( ) ) ;
return compileResult = = 0 ;
2015-12-10 13:06:33 -08:00
}
2015-12-21 10:42:41 -08:00
private bool InvokeCompileOnRootProject ( )
2015-12-10 13:06:33 -08:00
{
2015-12-21 10:42:41 -08:00
// todo: add methods to CompilerCommandApp to generate the arg string?
2016-01-22 13:55:13 -08:00
var args = new List < string > ( ) ;
2016-01-22 14:04:04 -08:00
args . Add ( "--framework" ) ;
2016-01-29 18:21:37 -08:00
args . Add ( _rootProject . TargetFramework . ToString ( ) ) ;
2016-01-22 14:04:04 -08:00
args . Add ( "--configuration" ) ;
args . Add ( _args . ConfigValue ) ;
2016-02-03 10:57:25 -08:00
if ( ! string . IsNullOrEmpty ( _args . OutputValue ) )
{
args . Add ( "--output" ) ;
args . Add ( _args . OutputValue ) ;
}
if ( ! string . IsNullOrEmpty ( _args . BuildBasePathValue ) )
{
args . Add ( "--build-base-path" ) ;
args . Add ( _args . BuildBasePathValue ) ;
}
2016-01-22 14:04:04 -08:00
//native args
2016-01-26 06:39:13 -08:00
if ( _args . IsNativeValue )
{
args . Add ( "--native" ) ;
2016-01-22 13:55:13 -08:00
}
2016-01-26 06:39:13 -08:00
if ( _args . IsCppModeValue )
{
args . Add ( "--cpp" ) ;
2016-01-22 13:55:13 -08:00
}
2016-01-22 14:04:04 -08:00
if ( ! string . IsNullOrWhiteSpace ( _args . ArchValue ) )
{
args . Add ( "--arch" ) ;
args . Add ( _args . ArchValue ) ;
}
2016-01-22 13:55:13 -08:00
2016-01-22 14:04:04 -08:00
if ( ! string . IsNullOrWhiteSpace ( _args . IlcArgsValue ) )
{
args . Add ( "--ilcargs" ) ;
args . Add ( _args . IlcArgsValue ) ;
}
2016-01-22 13:55:13 -08:00
2016-01-22 14:04:04 -08:00
if ( ! string . IsNullOrWhiteSpace ( _args . IlcPathValue ) )
{
args . Add ( "--ilcpath" ) ;
args . Add ( _args . IlcPathValue ) ;
}
2016-01-22 13:55:13 -08:00
2016-01-22 14:04:04 -08:00
if ( ! string . IsNullOrWhiteSpace ( _args . IlcSdkPathValue ) )
{
args . Add ( "--ilcsdkpath" ) ;
args . Add ( _args . IlcSdkPathValue ) ;
}
args . Add ( _rootProject . ProjectDirectory ) ;
2016-02-03 12:04:09 -08:00
var compileResult = CommpileCommand . Run ( args . ToArray ( ) ) ;
2015-12-10 13:06:33 -08:00
2016-02-03 12:04:09 -08:00
var succeeded = compileResult = = 0 ;
2016-01-29 18:21:37 -08:00
if ( succeeded )
{
2016-02-03 10:57:25 -08:00
if ( _rootProject . ProjectFile . HasRuntimeOutput ( _args . ConfigValue ) )
{
MakeRunnable ( ) ;
}
else
{
CopyCompilationOutput ( ) ;
}
}
2016-01-29 18:21:37 -08:00
return succeeded ;
}
2016-02-03 10:57:25 -08:00
private void CopyCompilationOutput ( )
2016-01-29 18:21:37 -08:00
{
2016-02-03 10:57:25 -08:00
if ( ! string . IsNullOrEmpty ( _args . OutputValue ) )
2016-01-29 18:21:37 -08:00
{
2016-02-03 10:57:25 -08:00
var calculator = _rootProject . GetOutputPaths ( _args . ConfigValue , _args . BuildBasePathValue , _args . OutputValue ) ;
var dest = calculator . RuntimeOutputPath ;
var source = calculator . CompilationOutputPath ;
foreach ( var file in calculator . CompilationFiles . All ( ) )
2016-01-29 18:21:37 -08:00
{
2016-02-03 10:57:25 -08:00
var destFileName = file . Replace ( source , dest ) ;
var directoryName = Path . GetDirectoryName ( destFileName ) ;
if ( ! Directory . Exists ( directoryName ) )
{
Directory . CreateDirectory ( directoryName ) ;
}
File . Copy ( file , destFileName , true ) ;
2016-01-29 18:21:37 -08:00
}
}
2015-12-10 13:06:33 -08:00
}
2016-02-03 10:57:25 -08:00
private void MakeRunnable ( )
{
var outputPaths = _rootProject . GetOutputPaths ( _args . ConfigValue , _args . BuildBasePathValue , _args . OutputValue ) ;
var libraryExporter = _rootProject . CreateExporter ( _args . ConfigValue , _args . BuildBasePathValue ) ;
var executable = new Executable ( _rootProject , outputPaths , libraryExporter ) ;
executable . MakeCompilationOutputRunnable ( ) ;
}
2015-12-10 13:06:33 -08:00
private static ISet < ProjectDescription > Sort ( Dictionary < string , ProjectDescription > projects )
{
var outputs = new HashSet < ProjectDescription > ( ) ;
foreach ( var pair in projects )
{
Sort ( pair . Value , projects , outputs ) ;
}
return outputs ;
}
private static void Sort ( ProjectDescription project , Dictionary < string , ProjectDescription > projects , ISet < ProjectDescription > outputs )
{
// Sorts projects in dependency order so that we only build them once per chain
foreach ( var dependency in project . Dependencies )
{
ProjectDescription projectDependency ;
if ( projects . TryGetValue ( dependency . Name , out projectDependency ) )
{
Sort ( projectDependency , projects , outputs ) ;
}
}
outputs . Add ( project ) ;
}
2015-12-21 10:42:41 -08:00
public struct CompilerIO
{
public readonly List < string > Inputs ;
public readonly List < string > Outputs ;
public CompilerIO ( List < string > inputs , List < string > outputs )
{
Inputs = inputs ;
Outputs = outputs ;
}
}
// computes all the inputs and outputs that would be used in the compilation of a project
// ensures that all paths are files
// ensures no missing inputs
2016-02-10 08:14:06 -08:00
public static CompilerIO GetCompileIO ( ProjectContext project , string buildConfiguration , string buildBasePath , string outputPath , ProjectDependenciesFacade dependencies , bool isRootProject )
2015-12-21 10:42:41 -08:00
{
var compilerIO = new CompilerIO ( new List < string > ( ) , new List < string > ( ) ) ;
2016-02-03 10:57:25 -08:00
var calculator = project . GetOutputPaths ( buildConfiguration , buildBasePath , outputPath ) ;
var binariesOutputPath = calculator . CompilationOutputPath ;
2015-12-21 10:42:41 -08:00
// input: project.json
compilerIO . Inputs . Add ( project . ProjectFile . ProjectFilePath ) ;
2016-01-14 13:32:39 -08:00
// input: lock file; find when dependencies change
AddLockFile ( project , compilerIO ) ;
2015-12-21 10:42:41 -08:00
// input: source files
compilerIO . Inputs . AddRange ( CompilerUtil . GetCompilationSources ( project ) ) ;
// todo: Factor out dependency resolution between Build and Compile. Ideally Build injects the dependencies into Compile
// input: dependencies
AddDependencies ( dependencies , compilerIO ) ;
2016-02-03 10:57:25 -08:00
var allOutputPath = new List < string > ( calculator . CompilationFiles . All ( ) ) ;
2016-02-10 08:14:06 -08:00
if ( isRootProject & & project . ProjectFile . HasRuntimeOutput ( buildConfiguration ) )
2016-02-03 10:57:25 -08:00
{
allOutputPath . AddRange ( calculator . RuntimeFiles . All ( ) ) ;
}
2016-01-27 13:07:26 -08:00
// output: compiler outputs
2016-02-03 10:57:25 -08:00
foreach ( var path in allOutputPath )
2016-01-27 13:07:26 -08:00
{
compilerIO . Outputs . Add ( path ) ;
}
2016-02-03 10:57:25 -08:00
2016-01-27 13:07:26 -08:00
// input compilation options files
AddCompilationOptions ( project , buildConfiguration , compilerIO ) ;
2015-12-21 10:42:41 -08:00
2016-02-08 16:06:13 -08:00
// input / output: resources with culture
AddNonCultureResources ( project , calculator . IntermediateOutputDirectoryPath , compilerIO ) ;
2015-12-21 10:42:41 -08:00
// input / output: resources without culture
2016-02-03 10:57:25 -08:00
AddCultureResources ( project , binariesOutputPath , compilerIO ) ;
2015-12-21 10:42:41 -08:00
return compilerIO ;
}
2016-01-14 13:32:39 -08:00
private static void AddLockFile ( ProjectContext project , CompilerIO compilerIO )
{
2016-01-26 06:39:13 -08:00
if ( project . LockFile = = null )
2016-01-14 13:32:39 -08:00
{
var errorMessage = $"Project {project.ProjectName()} does not have a lock file." ;
Reporter . Error . WriteLine ( errorMessage ) ;
throw new InvalidOperationException ( errorMessage ) ;
}
compilerIO . Inputs . Add ( project . LockFile . LockFilePath ) ;
}
2015-12-21 10:42:41 -08:00
private static void AddDependencies ( ProjectDependenciesFacade dependencies , CompilerIO compilerIO )
{
// add dependency sources that need compilation
compilerIO . Inputs . AddRange ( dependencies . ProjectDependenciesWithSources . Values . SelectMany ( p = > p . Project . Files . SourceFiles ) ) ;
2016-01-14 13:32:39 -08:00
// non project dependencies get captured by changes in the lock file
2015-12-21 10:42:41 -08:00
}
2016-01-27 13:07:26 -08:00
private static void AddCompilationOptions ( ProjectContext project , string config , CompilerIO compilerIO )
2015-12-21 10:42:41 -08:00
{
2016-01-14 17:12:59 -08:00
var compilerOptions = CompilerUtil . ResolveCompilationOptions ( project , config ) ;
// input: key file
if ( compilerOptions . KeyFile ! = null )
2015-12-21 10:42:41 -08:00
{
2016-01-14 17:12:59 -08:00
compilerIO . Inputs . Add ( compilerOptions . KeyFile ) ;
2015-12-21 10:42:41 -08:00
}
}
private static void AddNonCultureResources ( ProjectContext project , string intermediaryOutputPath , CompilerIO compilerIO )
{
foreach ( var resourceIO in CompilerUtil . GetNonCultureResources ( project . ProjectFile , intermediaryOutputPath ) )
{
compilerIO . Inputs . Add ( resourceIO . InputFile ) ;
if ( resourceIO . OutputFile ! = null )
{
compilerIO . Outputs . Add ( resourceIO . OutputFile ) ;
}
}
}
private static void AddCultureResources ( ProjectContext project , string outputPath , CompilerIO compilerIO )
{
foreach ( var cultureResourceIO in CompilerUtil . GetCultureResources ( project . ProjectFile , outputPath ) )
{
compilerIO . Inputs . AddRange ( cultureResourceIO . InputFileToMetadata . Keys ) ;
if ( cultureResourceIO . OutputFile ! = null )
{
compilerIO . Outputs . Add ( cultureResourceIO . OutputFile ) ;
}
}
}
2015-12-10 13:06:33 -08:00
}
}