2015-10-30 15:40:13 -07:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
2015-11-01 02:30:34 -08:00
using System.Runtime.InteropServices ;
2015-10-30 15:40:13 -07:00
using Microsoft.Dnx.Runtime.Common.CommandLine ;
using Microsoft.DotNet.Cli.Utils ;
using Microsoft.Extensions.ProjectModel ;
using NuGet.Frameworks ;
2015-11-01 02:46:05 -08:00
namespace Microsoft.DotNet.Tools.Run
2015-10-30 15:40:13 -07:00
{
public class Program
{
public static int Main ( string [ ] args )
{
DebugHelper . HandleDebugSwitch ( ref args ) ;
var app = new CommandLineApplication ( throwOnUnexpectedArg : false ) ;
app . Name = "dotnet run" ;
app . FullName = ".NET Executor" ;
app . Description = "Runner for the .NET Platform" ;
app . HelpOption ( "-h|--help" ) ;
var framework = app . Option ( "-f|--framework <FRAMEWORK>" , "Compile a specific framework" , CommandOptionType . MultipleValue ) ;
var configuration = app . Option ( "-c|--configuration <CONFIGURATION>" , "Configuration under which to build" , CommandOptionType . SingleValue ) ;
2015-11-01 16:21:10 -08:00
var preserveTemporaryOutput = app . Option ( "-t|--preserve-temporary" , "Keep the output's temporary directory around" , CommandOptionType . NoValue ) ;
2015-11-06 08:18:36 -08:00
var project = app . Option ( "-p|--project <PROJECT_PATH>" , "The path to the project to run (defaults to the current directory). Can be a path to a project.json or a project directory." , CommandOptionType . SingleValue ) ;
2015-10-30 15:40:13 -07:00
app . OnExecute ( ( ) = >
{
// Locate the project and get the name and full path
2015-11-06 08:18:36 -08:00
var path = project . Value ( ) ;
2015-10-30 10:34:02 -07:00
if ( ! string . IsNullOrEmpty ( path ) )
2015-10-30 15:40:13 -07:00
{
2015-10-30 10:34:02 -07:00
if ( File . Exists ( path ) & & ( Path . GetExtension ( path ) = = ".csx" ) )
{
return RunInteractive ( path ) ;
}
}
else
{
path = Directory . GetCurrentDirectory ( ) ;
2015-10-30 15:40:13 -07:00
}
var contexts = ProjectContext . CreateContextForEachFramework ( path ) ;
2015-10-30 10:34:02 -07:00
ProjectContext context ;
2015-10-30 15:40:13 -07:00
if ( ! framework . HasValue ( ) )
{
2015-10-30 10:34:02 -07:00
context = contexts . First ( ) ;
2015-10-30 15:40:13 -07:00
}
else
{
2015-10-30 10:34:02 -07:00
var fx = NuGetFramework . Parse ( framework . Value ( ) ) ;
context = contexts . FirstOrDefault ( c = > c . TargetFramework . Equals ( fx ) ) ;
2015-10-30 15:40:13 -07:00
}
2015-10-30 10:34:02 -07:00
return Run ( context , configuration . Value ( ) ? ? Constants . DefaultConfiguration , app . RemainingArguments , preserveTemporaryOutput . HasValue ( ) ) ;
2015-10-30 15:40:13 -07:00
} ) ;
try
{
return app . Execute ( args ) ;
}
catch ( Exception ex )
{
#if DEBUG
Console . Error . WriteLine ( ex ) ;
#else
Console . Error . WriteLine ( ex . Message ) ;
#endif
return 1 ;
}
}
2015-11-01 02:30:34 -08:00
private static int Run ( ProjectContext context , string configuration , List < string > remainingArguments , bool preserveTemporaryOutput )
2015-10-30 15:40:13 -07:00
{
// Create a temporary directory
var tempDir = Path . Combine ( Path . GetTempPath ( ) , Guid . NewGuid ( ) . ToString ( "N" ) ) ;
// Compile to that directory
2015-11-03 00:01:04 -08:00
var result = Command . Create ( $"dotnet-compile" , $"--output \" { tempDir } \ " --temp-output \"{tempDir}\" --framework \"{context.TargetFramework}\" --configuration \"{configuration}\" {context.ProjectFile.ProjectDirectory}" )
2015-11-01 16:21:10 -08:00
. ForwardStdOut ( onlyIfVerbose : true )
2015-10-30 15:40:13 -07:00
. ForwardStdErr ( )
. Execute ( ) ;
2015-11-01 01:44:53 -07:00
2015-10-30 15:40:13 -07:00
if ( result . ExitCode ! = 0 )
{
return result . ExitCode ;
}
// Now launch the output and give it the results
var outputName = Path . Combine ( tempDir , context . ProjectFile . Name + Constants . ExeSuffix ) ;
2015-11-01 02:30:34 -08:00
if ( ! RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
if ( context . TargetFramework . IsDesktop ( ) )
{
// Run mono if we're running a desktop target on non windows
remainingArguments . Insert ( 0 , outputName + ".exe" ) ;
2015-11-01 20:41:58 -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
remainingArguments . Insert ( 0 , "--debug" ) ;
}
2015-11-01 02:30:34 -08:00
outputName = "mono" ;
}
}
2015-10-30 15:40:13 -07:00
result = Command . Create ( outputName , string . Join ( " " , remainingArguments ) )
. ForwardStdOut ( )
. ForwardStdErr ( )
. EnvironmentVariable ( "CLRHOST_CLR_PATH" , AppContext . BaseDirectory )
. Execute ( ) ;
// Clean up
if ( ! preserveTemporaryOutput )
{
Directory . Delete ( tempDir , recursive : true ) ;
}
return result . ExitCode ;
}
2015-10-30 10:34:02 -07:00
private static int RunInteractive ( string scriptName )
{
2015-11-06 16:11:09 -08:00
var command = Command . Create ( $"dotnet-repl-csi" , scriptName )
2015-10-30 10:34:02 -07:00
. ForwardStdOut ( )
. ForwardStdErr ( ) ;
var result = command . Execute ( ) ;
return result . ExitCode ;
}
2015-10-30 15:40:13 -07:00
}
}