2015-11-20 19:00:56 -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 ;
using System.Runtime.InteropServices ;
using Microsoft.DotNet.Cli.Utils ;
2015-11-27 16:19:54 -08:00
using Microsoft.DotNet.ProjectModel ;
2016-02-03 10:57:25 -08:00
using Microsoft.Extensions.PlatformAbstractions ;
2015-11-20 19:00:56 -08:00
using NuGet.Frameworks ;
namespace Microsoft.DotNet.Tools.Run
{
2016-01-30 21:47:50 -08:00
public partial class RunCommand
2015-11-20 19:00:56 -08:00
{
public string Framework = null ;
public string Configuration = null ;
public string Project = null ;
public IReadOnlyList < string > Args = null ;
ProjectContext _context ;
List < string > _args ;
public int Start ( )
{
2015-11-23 16:31:27 -08:00
if ( IsInteractive ( ) )
2015-11-20 19:00:56 -08:00
{
return RunInteractive ( Project ) ;
}
else
{
return RunExecutable ( ) ;
}
}
2015-11-23 16:31:27 -08:00
private bool IsInteractive ( )
2015-11-20 19:00:56 -08:00
{
if ( ! string . IsNullOrEmpty ( Project ) )
{
2015-11-23 16:31:27 -08:00
if ( File . Exists ( Project ) & & ( Path . GetExtension ( Project ) . ToLowerInvariant ( ) = = ".csx" ) )
2015-11-20 19:00:56 -08:00
{
2015-11-23 16:31:27 -08:00
return true ;
2015-11-20 19:00:56 -08:00
}
}
2015-11-23 16:31:27 -08:00
return false ;
}
private void CalculateDefaultsForNonAssigned ( )
{
2015-11-23 19:58:11 -08:00
if ( string . IsNullOrWhiteSpace ( Project ) )
{
Project = Directory . GetCurrentDirectory ( ) ;
}
2015-11-20 19:00:56 -08:00
if ( string . IsNullOrWhiteSpace ( Configuration ) )
{
Configuration = Constants . DefaultConfiguration ;
}
2016-02-03 10:57:25 -08:00
var rids = PlatformServices . Default . Runtime . GetAllCandidateRuntimeIdentifiers ( ) ;
2016-02-19 15:12:04 -08:00
2015-11-20 19:00:56 -08:00
if ( Framework = = null )
{
2016-02-03 10:57:25 -08:00
var defaultFrameworks = new [ ]
{
2016-04-07 11:51:41 -07:00
FrameworkConstants . FrameworkIdentifiers . NetCoreApp ,
2016-02-03 10:57:25 -08:00
FrameworkConstants . FrameworkIdentifiers . NetStandardApp ,
} ;
2016-02-19 15:12:04 -08:00
var contexts = ProjectContext . CreateContextForEachFramework ( Project , null ) ;
2016-02-03 10:57:25 -08:00
2016-02-19 15:12:04 -08:00
ProjectContext context ;
if ( contexts . Count ( ) = = 1 )
{
context = contexts . Single ( ) ;
}
else
2016-02-03 10:57:25 -08:00
{
2016-02-19 15:12:04 -08:00
context = contexts . FirstOrDefault ( c = > defaultFrameworks . Contains ( c . TargetFramework . Framework ) ) ;
if ( context = = null )
{
2016-02-24 10:49:00 -08:00
throw new InvalidOperationException ( $"Couldn't find target to run. Possible causes:" + Environment . NewLine +
"1. No project.lock.json file or restore failed - run `dotnet restore`" + Environment . NewLine +
2016-03-15 11:50:14 -07:00
$"2. project.lock.json has multiple targets none of which is in default list ({string.Join(" , ", defaultFrameworks)})" ) ;
2016-02-19 15:12:04 -08:00
}
2016-02-03 10:57:25 -08:00
}
2016-02-19 15:12:04 -08:00
_context = context . CreateRuntimeContext ( rids ) ;
2015-11-20 19:00:56 -08:00
}
else
{
2016-02-03 10:57:25 -08:00
_context = ProjectContext . Create ( Project , NuGetFramework . Parse ( Framework ) , rids ) ;
2015-11-20 19:00:56 -08:00
}
if ( Args = = null )
{
_args = new List < string > ( ) ;
}
else
{
_args = new List < string > ( Args ) ;
}
}
private int RunExecutable ( )
{
2015-11-23 19:58:11 -08:00
CalculateDefaultsForNonAssigned ( ) ;
2015-11-20 19:00:56 -08:00
// Compile to that directory
2016-02-03 12:04:09 -08:00
var result = Build . BuildCommand . Run ( new [ ]
2016-02-04 19:12:02 -08:00
{
$"--framework" ,
$"{_context.TargetFramework}" ,
$"--configuration" ,
2016-02-03 10:57:25 -08:00
Configuration ,
2016-02-04 19:12:02 -08:00
$"{_context.ProjectFile.ProjectDirectory}"
} ) ;
2015-11-20 19:00:56 -08:00
2016-02-03 12:04:09 -08:00
if ( result ! = 0 )
2015-11-20 19:00:56 -08:00
{
2016-02-03 12:04:09 -08:00
return result ;
2015-11-20 19:00:56 -08:00
}
2016-04-07 20:50:44 -07:00
List < string > hostArgs = new List < string > ( ) ;
2016-03-31 09:00:25 -07:00
if ( ! _context . TargetFramework . IsDesktop ( ) )
{
// Add Nuget Packages Probing Path
var nugetPackagesRoot = _context . PackagesDirectory ;
var probingPathArg = "--additionalprobingpath" ;
2016-04-07 20:50:44 -07:00
hostArgs . Insert ( 0 , nugetPackagesRoot ) ;
hostArgs . Insert ( 0 , probingPathArg ) ;
2016-03-31 09:00:25 -07:00
}
2016-03-14 16:34:02 -07:00
2015-11-20 19:00:56 -08:00
// Now launch the output and give it the results
2016-03-15 11:50:14 -07:00
var outputPaths = _context . GetOutputPaths ( Configuration ) ;
var outputName = outputPaths . RuntimeFiles . Executable ;
2016-01-26 06:39:13 -08:00
2015-11-20 19:00:56 -08:00
if ( ! RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
if ( _context . TargetFramework . IsDesktop ( ) )
{
// Run mono if we're running a desktop target on non windows
2016-01-26 06:39:13 -08:00
_args . Insert ( 0 , outputName ) ;
2015-11-20 19:00:56 -08:00
if ( string . Equals ( Configuration , "Debug" , StringComparison . OrdinalIgnoreCase ) )
{
// If we're compiling for the debug configuration then add the --debug flag
// other options may be passed using the MONO_OPTIONS env var
_args . Insert ( 0 , "--debug" ) ;
}
outputName = "mono" ;
}
}
2016-03-15 11:50:14 -07:00
Command command ;
if ( outputName . EndsWith ( FileNameSuffixes . DotNet . DynamicLib , StringComparison . OrdinalIgnoreCase ) )
{
// The executable is a ".dll", we need to call it through dotnet.exe
2016-03-14 16:34:02 -07:00
var muxer = new Muxer ( ) ;
2016-04-07 20:50:44 -07:00
command = Command . Create ( muxer . MuxerPath , Enumerable . Concat (
Enumerable . Concat ( new string [ ] { "exec" } , hostArgs ) ,
Enumerable . Concat ( new string [ ] { outputName } , _args ) ) ) ;
2016-03-15 11:50:14 -07:00
}
else
{
2016-04-07 20:50:44 -07:00
command = Command . Create ( outputName , Enumerable . Concat ( hostArgs , _args ) ) ;
2016-03-15 11:50:14 -07:00
}
result = command
2015-11-20 19:00:56 -08:00
. ForwardStdOut ( )
. ForwardStdErr ( )
2016-02-03 12:04:09 -08:00
. Execute ( )
. ExitCode ;
2015-12-13 22:40:11 -08:00
2016-02-03 12:04:09 -08:00
return result ;
2015-11-20 19:00:56 -08:00
}
private static int RunInteractive ( string scriptName )
{
2016-03-15 11:50:14 -07:00
var command = Command . CreateDotNet ( $"repl-csi" , new [ ] { scriptName } )
2015-11-20 19:00:56 -08:00
. ForwardStdOut ( )
. ForwardStdErr ( ) ;
var result = command . Execute ( ) ;
return result . ExitCode ;
}
}
}