Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added build script for Mac/Linux #59

Merged
merged 2 commits into from
Apr 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 244 additions & 0 deletions build.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
# !/usr/bin/perl

use strict;
use Getopt::Long;
use Data::Dumper;
use File::Path qw(make_path);
use File::Spec::Functions qw(rel2abs catfile);
use File::Basename;
use FindBin qw($RealBin);
use Cwd qw(abs_path);
use POSIX;

#set the timestamp in case we need to create a directory
use constant DATETIME=>strftime("%Y-%m-%d_%H-%M-%S", localtime);

# The source solution
my $solutionToBuild = catfile(catfile($RealBin, 'src'), 'MSBuild.sln');

my $usage = <<"USAGE";
Usage build.pl [-root=<outputRoot>] [-fullbuild] [-verify] [-tests] [-all] [-quiet] [-silent]

The script can build MSBuild.exe using mono, verify by
rebuilding with the generated MSBuild.exe and run tests.
If the output root is not specified, the bin and packages
subdirectories are created in the source tree (as well as
bin-verify and packages-verify if verification build runs).
If output root is provided, a dated subdirectory is created
under the output root and the same subdirectories appear
there. The tests are run either on the xbuild generated
binaries or, if verification is done, on the verification
binaries.

Options:
root - specifies the output root. The root is the
source tree by default.
fullBuild - do a rebuild instead of the incremental build.
This only makes a difference without the root
options, as the rooted build are always clean.
verify - rebuild the source with the binaries generated
by the xbuild.
tests - run the tests.
all - shorthand for -verify and -tests flags.
quiet - don't show any build output, only summaries
silent - show nothing, not even summaries

USAGE


# Quick check if we are in the right place and that mono is installed
# (just checking for solution and xbuild presence)
die ("Solution $solutionToBuild does not exist\n") unless -e $solutionToBuild;
die ("xbuild was not found") unless -e "/usr/bin/xbuild";

my $buildRoot;
my $runTests;
my $verification;
my $quiet;
my $silent;
my $fullBuild;
my $allSteps;
my $help;

die $usage unless GetOptions(
'root=s' => \$buildRoot,
'verify' => \$verification,
'tests' => \$runTests,
'quiet' => \$quiet,
'silent' => \$silent,
'fullBuild' => \$fullBuild,
'all' => \$allSteps,
'help' => \$help
);

if ($help) {
print $usage;
exit (0);
}

# The all steps flag override some other
if ($allSteps) {
$verification = 1;
$runTests = 1;
}

# We need nunit-console to run tests
my $nunitConsole;
if ($runTests) {
# Find the nunit console program
my $n = `which nunit-console`;
chomp $n;

die ("Tests are requested, but nunit-console was not found") unless -e "/usr/bin/nunit-console";

# Resolve any links
$nunitConsole = abs_path($n);
# Use version 4 if found
$n = $nunitConsole . '4';
$nunitConsole = $n if -e $n;
}


# Find the location where we're going to store results
# If no root is specifed, use the script location (we'll create
# bin, packages, bin-verify, packages-verify directories and the
# logs there.
# If root is specified, make a dated subdirectory there. That
# will be our root.
if (!$buildRoot) {
$buildRoot = $RealBin;
}
else {
$buildRoot = catfile(rel2abs($buildRoot), DATETIME);
# Just make sure it's not a file
die ("Verification root '$buildRoot' exists and is a file") if -f $buildRoot;
make_path($buildRoot);
}

# Make some paths
my $binRoot = catfile($buildRoot, "bin", "");
my $verBinRoot = catfile($buildRoot, "bin-verify", "");
my $packageRoot = catfile ($buildRoot, "packages", "");
my $verPackageRoot = catfile ($buildRoot, "packages-verify", "");

# The regex to parse build logs
my $extractRegex = qr!^\s*Build binary target directory: '($buildRoot.+?)/?'!;

my $msbuildPath;
my $exitCode;
my $errorCount;

# Run the first build
($exitCode, $errorCount, $msbuildPath) = runbuild('xbuild', '', '/');

die ("Build with xbuild failed (code $exitCode)") unless $exitCode == 0;
die ("Build with xbuild failed (error count $errorCount") unless $errorCount == 0;
die ("Build succeeded, but MSBuild.exe binary was not found") unless -e $msbuildPath;

# Use the MSBuild.exe we created and rebuild (if requested)
if ($verification) {
my $MSBuildProgram = catfile($msbuildPath, 'MSBuild.exe');
$MSBuildProgram = 'mono ' . $MSBuildProgram if $^O == "MSWin32";
my $newMSBuildPath;
($exitCode, $errorCount, $newMSBuildPath) = runbuild($MSBuildProgram, '-verify', '-');
die ("Build with msbuild failed (code $exitCode)") unless $exitCode == 0;
die ("Build with msbuild failed (error count $errorCount") unless $errorCount == 0;
print "New MSBuild path: $newMSBuildPath\n";
$msbuildPath = $newMSBuildPath if -e $newMSBuildPath;
}

if ($runTests) {
# Get the dlls for testing
my @file = glob catfile($msbuildPath, '*UnitTest*.dll');
runtests (@file);
}

# This functions runs a build.
# runbuild(program, suffix, switch)
# program -- the build (xbuild or msbuild)
# suffix -- appended to log and output directory names
# switch -- either - or /
sub runbuild {
die ('runbuild sub was not called correctly') unless @_ == 3;
my ($program, $suffix, $switch) = @_;

# Get paths of output directories and the log
my $binDir = catfile($buildRoot, "bin$suffix", "");
my $packagesDir = catfile ($buildRoot, "packages$suffix", "");
my $logFile = catfile($buildRoot, "MSBuild${suffix}.log");

# If we need to rebuild, add a switch for the task
my $rebuildSwitch = $fullBuild ? "${switch}t:Rebuild " : "";

# Generate and print the command we run
my $command = "$program ${switch}nologo ${switch}v:q ${switch}tv:4.0 $rebuildSwitch " .
"${switch}p:Configuration=Debug-MONO " .
"${switch}p:BinDir=$binDir ${switch}p:PackagesDir=$packagesDir " .
"${switch}fl \"${switch}flp:LogFile=$logFile;V=diag\" $solutionToBuild";
print $command . "\n" unless $silent;

# Run build, parsing it's output to count errors and warnings
# Harakiri if can't run
open(BUILD_OUTPUT, "$command 2>&1 |") or die "Cannot run $program, error $!";
my $warningCount = 0;
my $errorCount = 0;
for (<BUILD_OUTPUT>) {
print $_ unless ($quiet || $silent);
m/:\s+error / && ($errorCount++, next);
m/:\s+warning / && ($warningCount++, next);
}

die "Failed to run $program, exit code $!" if $! != 0;
close BUILD_OUTPUT;
my $exitCode = $? >> 8;

# Search the log for the full output path
my $msbuildPath;
if (open LOG, '<', $logFile) {
m/$extractRegex/ && ($msbuildPath = $1, last) for <LOG>;
close (LOG);
}
else {
# It's not an error if the path cannot be found. At worst, we cannot verify
print "Warning: Cannot open log file $logFile: $!" if $! && !$silent;
}

print "Errors: $errorCount, Warnings $warningCount\n" unless $silent;
return ($exitCode, $errorCount, $msbuildPath);
}

# This function runs the test. It gets the list of dlls to test.
sub runtests {
my @files = @_;

# Create directory for output
my $testResultsDir = catfile($buildRoot, 'TestResults');
make_path($testResultsDir);

# Output file names in that directory
my $xmlResultFile = catfile($testResultsDir, 'Results.xml');
my $outputFile = catfile($testResultsDir, 'TestOutput.txt');

# Build the command to run the test
my $command = "$nunitConsole -xml:$xmlResultFile " . join (' ', @files);
print $command . "\n" unless $silent;

# Run it silently
system("$command 2>&1 >$outputFile");

# Count the passed/failed tests by readin the output XML file
my $testsFailed = 0;
my $testsSucceeded = 0;

my $testRegex = qr!^\s*<test-case.+executed="True".+success="((?:True)|(?:False))"!;

if (open LOG, '<', $xmlResultFile) {
m/$testRegex/ && ($1 eq 'True' ? $testsSucceeded++ : $testsFailed++) for <LOG>;
close (LOG);
}
else {
print "Warning: Cannot open log file $xmlResultFile: $!" if $! && !$silent;
}
my $testsRan = $testsSucceeded + $testsFailed;
print "Tests ran: $testsRan, tests succeeded: $testsSucceeded, tests failed: $testsFailed\n" unless $silent;
}
10 changes: 5 additions & 5 deletions dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@
<BinDir>$(ProjectDir)bin$([System.IO.Path]::DirectorySeparatorChar)</BinDir>
<TestWorkingDir>$(BinDir)tests$([System.IO.Path]::DirectorySeparatorChar)</TestWorkingDir>
<PackagesDir>$(ProjectDir)packages$([System.IO.Path]::DirectorySeparatorChar)</PackagesDir>
<ToolsDir>$(PackagesDir)Microsoft.DotNet.BuildTools.$(MSBuildToolsVersion)$([System.IO.Path]::DirectorySeparatorChar)lib$([System.IO.Path]::DirectorySeparatorChar)</ToolsDir>
<ToolsDir>$([System.IO.Path]::Combine($(PackagesDir)Microsoft.DotNet.BuildTools.$(MSBuildToolsVersion),"lib")$([System.IO.Path]::DirectorySeparatorChar)</ToolsDir>
</PropertyGroup>

<!-- Common nuget properties -->
<PropertyGroup>
<NuGetDir>$(PackagesDir)</NuGetDir>
<NuGetToolPath>$(PackagesDir)NuGet.exe</NuGetToolPath>
<NuGetConfigFile>$(SourceDir).nuget$([System.IO.Path]::DirectorySeparatorChar)NuGet.Config</NuGetConfigFile>
<NuGetConfigFile>$([System.IO.Path]::Combine("$(SourceDir).nuget","NuGet.Config"))</NuGetConfigFile>
<NuGetConfigCommandLine>-ConfigFile "$(NuGetConfigFile)"</NuGetConfigCommandLine>

<NugetRestoreCommand>"$(NuGetToolPath)"</NugetRestoreCommand>
<NugetRestoreCommand>$(NugetRestoreCommand) install</NugetRestoreCommand>
<NugetRestoreCommand>$(NugetRestoreCommand) -OutputDirectory "$(PackagesDir.TrimEnd('\/'.ToCharArray()))"</NugetRestoreCommand>
<NugetRestoreCommand>$(NugetRestoreCommand) -OutputDirectory "$(PackagesDir.TrimEnd('\'))"</NugetRestoreCommand>
<NugetRestoreCommand>$(NugetRestoreCommand) $(NuGetConfigCommandLine)</NugetRestoreCommand>
<NugetRestoreCommand Condition="'$(OS)' != 'Windows_NT'">mono $(NuGetRestoreCommand)</NugetRestoreCommand>
</PropertyGroup>
Expand Down Expand Up @@ -67,10 +67,10 @@

<!-- Setup the default output and intermediate paths -->
<PropertyGroup>
<BaseOutputPath>$(ProjectDir)bin$([System.IO.Path]::DirectorySeparatorChar)</BaseOutputPath>
<BaseOutputPath>$(BinDir)</BaseOutputPath>
<BaseOutputPathWithConfig>$([System.IO.Path]::Combine($(BaseOutputPath)$(OS),$(Configuration)))$([System.IO.Path]::DirectorySeparatorChar)</BaseOutputPathWithConfig>
<BaseOutputPathWithConfig Condition="'$(Platform)' != 'AnyCPU'">$([System.IO.Path]::Combine($(BaseOutputPath)$(Platform),$(OS),$(Configuration)))$([System.IO.Path]::DirectorySeparatorChar)</BaseOutputPathWithConfig>
<OutputPath>$(BaseOutputPathWithConfig)$([System.IO.Path]::DirectorySeparatorChar)</OutputPath>
<OutputPath>$(BaseOutputPathWithConfig)</OutputPath>

<BaseIntermediateOutputPath>$(BaseOutputPath)obj$([System.IO.Path]::DirectorySeparatorChar)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$([System.IO.Path]::Combine($(BaseIntermediateOutputPath)$(MSBuildProjectName),$(OS),$(Configuration)))$([System.IO.Path]::DirectorySeparatorChar)</IntermediateOutputPath>
Expand Down
6 changes: 5 additions & 1 deletion dir.targets
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@
Needed to avoid the IntialTargets from having an Output which ends up getting
added to the output references when you have a project to project reference.
-->
<Target Name="_RestoreBuildToolsWrapper" DependsOnTargets="_RestoreBuildTools" />
<Target Name="_RestoreBuildToolsWrapper" DependsOnTargets="_DisplayBuildInfo;_RestoreBuildTools" />

<Target Name="_DisplayBuildInfo">
<Message Importance="High" Text="Build binary target directory: '$(BaseOutputPathWithConfig)'" />
</Target>

<Target Name="_RestoreBuildTools"
Inputs="$(MSBuildThisFileFullPath);$(MSBuildThisFileDirectory)dir.props"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
2 changes: 1 addition & 1 deletion src/XMakeBuildEngine/Microsoft.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@
</Reference>
<Reference Include="System.Threading.Tasks.Dataflow, Version=4.5.24.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Tpl.Dataflow.4.5.24\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath>
<HintPath>$(PackagesDir)Microsoft.Tpl.Dataflow.4.5.24\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll</HintPath>
<Private>True</Private>
</Reference>
<!-- If TargetRetailBuildFramework is set to true, reference the public key version. Otherwise reference the project. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
<Name>Microsoft.Build</Name>
</ProjectReference>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<Name>Microsoft.Build</Name>
</ProjectReference>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Microsoft.Build.UnitTests
public class CommandLineSwitchesTests
{
[TestFixtureSetUp]
public static void Setup(TestContext testContext)
public static void Setup()
{
// Make sure resources are initialized
MSBuildApp.Initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<HintPath>$(PackagesDir)NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
Expand Down