2015-12-10 21:06:33 +00: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.Linq ;
2016-04-18 03:53:49 +00:00
using System.Threading.Tasks ;
2016-05-02 18:32:24 +00:00
using Microsoft.DotNet.Cli.Utils ;
2015-12-10 21:06:33 +00:00
using Microsoft.DotNet.ProjectModel ;
using Microsoft.DotNet.Tools.Compiler ;
2016-04-20 02:14:59 +00:00
using NuGet.Frameworks ;
2015-12-10 21:06:33 +00:00
namespace Microsoft.DotNet.Tools.Build
{
2016-01-31 05:47:50 +00:00
public class BuildCommand
2015-12-10 21:06:33 +00:00
{
2016-04-22 22:01:56 +00:00
public static int Run ( string [ ] args ) = > Run ( args , null ) ;
2016-05-02 18:32:24 +00:00
public static int Run ( string [ ] args , BuildWorkspace workspace )
2015-12-10 21:06:33 +00:00
{
DebugHelper . HandleDebugSwitch ( ref args ) ;
try
{
2016-04-22 22:01:56 +00:00
var app = new BuildCommandApp (
"dotnet build" ,
".NET Builder" ,
"Builder for the .NET Platform. It performs incremental compilation if it's safe to do so. Otherwise it delegates to dotnet-compile which performs non-incremental compilation" ,
workspace ) ;
2015-12-10 21:06:33 +00:00
return app . Execute ( OnExecute , args ) ;
}
catch ( Exception ex )
{
#if DEBUG
Console . Error . WriteLine ( ex ) ;
#else
Console . Error . WriteLine ( ex . Message ) ;
#endif
return 1 ;
}
}
2016-04-20 02:14:59 +00:00
private static bool OnExecute ( IEnumerable < string > files , IEnumerable < NuGetFramework > frameworks , BuildCommandApp args )
2015-12-10 21:06:33 +00:00
{
2016-04-20 02:14:59 +00:00
var builderCommandApp = args ;
var graphCollector = new ProjectGraphCollector (
! builderCommandApp . ShouldSkipDependencies ,
2016-04-22 22:01:56 +00:00
( project , target ) = > args . Workspace . GetProjectContext ( project , target ) ) ;
2016-04-20 02:14:59 +00:00
2016-04-27 23:04:26 +00:00
IEnumerable < ProjectContext > contexts ;
using ( PerfTrace . Current . CaptureTiming ( string . Empty , nameof ( ResolveRootContexts ) ) )
{
contexts = ResolveRootContexts ( files , frameworks , args ) ;
}
ProjectGraphNode [ ] graph ;
using ( PerfTrace . Current . CaptureTiming ( string . Empty , "Collect graph" ) )
{
graph = graphCollector . Collect ( contexts ) . ToArray ( ) ;
}
2016-04-20 02:14:59 +00:00
var builder = new DotNetProjectBuilder ( builderCommandApp ) ;
return builder . Build ( graph ) . ToArray ( ) . All ( r = > r ! = CompilationResult . Failure ) ;
}
private static IEnumerable < ProjectContext > ResolveRootContexts (
IEnumerable < string > files ,
IEnumerable < NuGetFramework > frameworks ,
BuildCommandApp args )
{
2016-04-20 21:01:32 +00:00
List < Task < ProjectContext > > tasks = new List < Task < ProjectContext > > ( ) ;
2016-04-20 02:14:59 +00:00
foreach ( var file in files )
{
2016-04-27 23:04:26 +00:00
Project project ;
using ( PerfTrace . Current . CaptureTiming ( file , "Loading project.json" ) )
{
project = args . Workspace . GetProject ( file ) ;
}
2016-04-20 02:14:59 +00:00
var projectFrameworks = project . GetTargetFrameworks ( ) . Select ( f = > f . FrameworkName ) ;
if ( ! projectFrameworks . Any ( ) )
{
throw new InvalidOperationException (
$"Project '{file}' does not have any frameworks listed in the 'frameworks' section." ) ;
}
IEnumerable < NuGetFramework > selectedFrameworks ;
if ( frameworks ! = null )
{
var unsupportedByProject = frameworks . Where ( f = > ! projectFrameworks . Contains ( f ) ) ;
if ( unsupportedByProject . Any ( ) )
{
throw new InvalidOperationException (
$"Project \'{file}\' does not support framework: {string.Join(" , ", unsupportedByProject.Select(fx => fx.DotNetFrameworkName))}." ) ;
}
selectedFrameworks = frameworks ;
}
else
{
selectedFrameworks = projectFrameworks ;
}
foreach ( var framework in selectedFrameworks )
{
2016-04-22 22:01:56 +00:00
tasks . Add ( Task . Run ( ( ) = > args . Workspace . GetProjectContext ( file , framework ) ) ) ;
2016-04-20 02:14:59 +00:00
}
}
2016-04-27 23:04:26 +00:00
using ( PerfTrace . Current . CaptureTiming ( string . Empty , "Waiting for project contexts to finish loading" ) )
{
return Task . WhenAll ( tasks ) . GetAwaiter ( ) . GetResult ( ) ;
}
2015-12-10 21:06:33 +00:00
}
}
}