Skip to content

Commit

Permalink
Revamp build script with corebuild, simplify packaging and versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
kzu committed Dec 4, 2017
1 parent c5a91e2 commit 26bd4a1
Show file tree
Hide file tree
Showing 12 changed files with 325 additions and 218 deletions.
2 changes: 1 addition & 1 deletion GitInfo.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.100-pre
3.0.0-alpha
142 changes: 117 additions & 25 deletions build.cmd
Original file line number Diff line number Diff line change
@@ -1,34 +1,126 @@
:: Optional batch file to quickly build with some defaults.
:: Alternatively, this batch file can be invoked passing msbuild parameters, like: build.cmd "/v:detailed" "/t:Rebuild"
@echo off
setlocal enabledelayedexpansion

@ECHO OFF
:: Perf/usability tweaks for MSBuild
set MSBUILDLOGASYNC=1
set MSBUILDLOGTASKINPUTS=1
set MSBUILDDISABLENODEREUSE=1

:: Ensure MSBuild can be located. Allows for a better error message below.
where msbuild > %TEMP%\msbuild.txt
set /p msb=<%TEMP%\msbuild.txt
set BatchFile=%0
set Root=%~dp0
set NodeReuse=true
set MultiProcessor=/m
set BuildConfiguration=
set MSBuildTarget=
set MSBuildAdditionalArguments=

IF "%msb%"=="" (
echo Please run %~n0 from a Visual Studio Developer Command Prompt.
exit /b -1
:ParseArguments
if "%1" == "" goto :DoneParsing
if /I "%1" == "/?" call :Usage && exit /b 1
if /I "%1" == "/debug" set BuildConfiguration=Debug&&shift&& goto :ParseArguments
if /I "%1" == "/release" set BuildConfiguration=Release&&shift&& goto :ParseArguments
if /I "%1" == "/build" set MSBuildTarget=/t:Build&&shift&& goto :ParseArguments
if /I "%1" == "/clean" set MSBuildTarget=/t:Clean&&shift&& goto :ParseArguments
if /I "%1" == "/rebuild" set MSBuildTarget=/t:Rebuild&&shift&& goto :ParseArguments
if /I "%1" == "/restore" set MSBuildTarget=/t:Restore&&shift&& goto :ParseArguments
if /I "%1" == "/update" set MSBuildTarget=/t:Update&&shift&& goto :ParseArguments
if /I "%1" == "/test" set MSBuildTarget=/t:Test&&shift&& goto :ParseArguments
if /I "%1" == "/no-node-reuse" set NodeReuse=false&&shift&& goto :ParseArguments
if /I "%1" == "/no-multi-proc" set MultiProcessor=&&shift&& goto :ParseArguments
set MSBuildAdditionalArguments=%MSBuildAdditionalArguments% %1&&shift&& goto :ParseArguments
:DoneParsing

:: Detect if MSBuild is in the path
for /f "delims=" %%i in ('where msbuild') do set "MSBuildPath=%%i" & goto :MSBuildPathDone
:MSBuildPathDone

if not exist "%MSBuildPath%" (
call :PrintColor Red "To build this repository, MSBuild.exe must be in the PATH."
echo MSBuild is included with Visual Studio 2017 or later.
echo.
echo If Visual Studio is not installed, visit this page to download:
echo.
echo https://www.visualstudio.com/vs/
echo.
exit /b 1
)

:: Detect MSBuild version >= 15
for /f "delims=" %%i in ('msbuild -nologo -version') do set MSBuildFullVersion=%%i
for /f "delims=. tokens=1" %%a in ("%MSBuildFullVersion%") do (
set MSBuildMajorVersion=%%a
)

if %MSBuildMajorVersion% LSS 15 (
call :PrintColor Red "To build this repository, the MSBuild.exe in the PATH needs to be 15.0 or higher."
echo MSBuild 15.0 is included with Visual Studio 2017 or later.
echo.
echo If Visual Studio is not installed, visit this page to download:
echo.
echo https://www.visualstudio.com/vs/
echo.
echo Located MSBuild in the PATH was "%MSBuildPath%".
exit /b 1
)

:: Ensure developer command prompt variables are set
if "%VisualStudioVersion%" == "" (
for /f "delims=" %%i in ('msbuild -nologo %Root%corebuild\corebuild.targets /t:_GetVsInstallRoot /v:minimal') do set "VsInstallRoot=%%i" & goto :VsInstallRootDone
:VsInstallRootDone
for /f "tokens=* delims= " %%i in ("%VsInstallRoot%") do set "VsInstallRoot=%%i"
set "DeveloperCommandPrompt=%VsInstallRoot%\Common7\Tools\VsDevCmd.bat"
if not exist "%DeveloperCommandPrompt%" (
call :PrintColor Red "Failed to locate 'Common7\Tools\VsDevCmd.bat' under the reported Visual Studio installation root '%VsInstallRoot%'."
echo.
echo If Visual Studio is not installed, visit this page to download:
echo.
echo https://www.visualstudio.com/vs/
echo.
exit /b 1
)
call "%DeveloperCommandPrompt%" || goto :BuildFailed
)

SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
PUSHD "%~dp0" >NUL
if not "%MSBuildTarget%" == "" set MSBuildTargetName=%MSBuildTarget:~3%

@echo on
msbuild "%Root%build.proj" /nologo /nr:%NodeReuse% %MultiProcessor% %MSBuildTarget% /p:target=%MSBuildTargetName% /p:Configuration=%BuildConfiguration% %MSBuildAdditionalArguments%
@echo off
if ERRORLEVEL 1 (
echo.
call :PrintColor Red "Build failed, for full log see msbuild.log."
exit /b 1
)

IF EXIST .nuget\nuget.exe goto restore
IF NOT EXIST .nuget md .nuget
echo Downloading latest version of NuGet.exe...
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile .nuget/nuget.exe"
echo.
call :PrintColor Cyan "Build completed successfully, for full log see msbuild.log"
exit /b 0

:restore
:: Build script packages have no version in the path, so we install them to .nuget\packages to avoid conflicts with
:: solution/project packages.
IF NOT EXIST packages.config goto run
.nuget\nuget.exe install packages.config -OutputDirectory .nuget\packages -ExcludeVersion
:Usage
echo Usage: %BatchFile% [/build^|/clean^|/rebuild^|/restore^|/update^|/test^] [/debug^|/release] [/no-node-reuse] [/no-multi-proc] [OPTIONS]
echo.
echo Build targets:
echo /build Builds the project
echo /clean Cleans a previous build
echo /rebuild Cleans, then builds
echo /restore Only restore NuGet packages
echo /update Updates corebuild targets and dependencies
echo /test Runs tests
echo.
echo Build options:
echo /debug Perform debug build (/p:Configuration=Debug)
echo /release Perform release build (/p:Configuration=Release)
echo /no-node-reuse Prevents MSBuild from reusing existing MSBuild instances,
echo useful for avoiding unexpected behavior on build machines ('/nr:false' switch)
echo /no-multi-proc No multi-proc build, useful for diagnosing build logs (no '/m' switch)
echo /noautoresponse Do not process the msbuild.rsp response file options
echo
echo [OPTIONS] Arbitrary MSBuild switches can also be passed in.
goto :eof

:run
"%msb%" build.proj /v:minimal %1 %2 %3 %4 %5 %6 %7 %8 %9
:BuildFailed
call :PrintColor Red "Build failed with ERRORLEVEL %ERRORLEVEL%"
exit /b 1

POPD >NUL
ENDLOCAL
ECHO ON
:PrintColor
"%Windir%\System32\WindowsPowerShell\v1.0\Powershell.exe" -noprofile write-host -foregroundcolor %1 "'%2'"
197 changes: 39 additions & 158 deletions build.proj
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Rebuild" InitialTargets="Configure" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" TreatAsLocalProperty="Configuration" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="build\corebuild.props" />

<PropertyGroup>
<CI Condition="'$(CI)' == '' and '$(TF_BUILD)' == 'true'">true</CI>
<CI Condition="'$(CI)' == '' ">false</CI>
<Configuration Condition="'$(Configuration)' == '' and '$(CI)' == 'true'">Release</Configuration>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>

<Out Condition=" '$(Out)' == '' ">$(MSBuildThisFileDirectory)out</Out>
<!-- Whether to run integration tests against the MSI-installed Clide in the normal hive or not -->
<TestInstalled Condition=" '$(TestInstalled)' == '' And '$(Configuration)' == 'Release' ">true</TestInstalled>
<Installer>$(MSBuildThisFileDirectory)src\Clide.Vsix\bin\$(Configuration)\Clide.vsix</Installer>
<VsixInstaller>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\$(VisualStudioVersion)', 'InstallDir', null, RegistryView.Registry32))VSIXInstaller.exe</VsixInstaller>

<GitInfoReportImportance>high</GitInfoReportImportance>
<GitIgnoreTagVersion>true</GitIgnoreTagVersion>
<GitIgnoreBranchVersion>true</GitIgnoreBranchVersion>

<CommonBuildProperties>WarningLevel=0;NoWarn=1591;RunCodeAnalysis=false;Configuration=$(Configuration);CI=$(CI)</CommonBuildProperties>
<CommonBuildProperties>WarningLevel=0;NoWarn=1591;RunCodeAnalysis=false;Configuration=$(Configuration)</CommonBuildProperties>
<CommonBuildProperties Condition="'$(Configuration)' == 'Release'">$(CommonBuildProperties);DeployExtension=false</CommonBuildProperties>

<Dev Condition="'$(Dev)' == ''">$(VisualStudioVersion)</Dev>
</PropertyGroup>

<PropertyGroup Condition=" '$(TestInstalled)' == 'true' ">
<!-- When testing the installed version of Clide, it's unnecessary to deploy the built VSIX extension,
since integration tests will run against the normal hive -->
<CommonBuildProperties>$(CommonBuildProperties);DeployExtension=false;RootSuffix=.</CommonBuildProperties>
<!-- When running a CI build, either use the explicit VisualStudioVersion or fallback to All -->
<CommonBuildProperties Condition=" '$(CI)' == 'true' ">$(CommonBuildProperties);VisualStudioVersions=$([MSBuild]::ValueOrDefault('$(VisualStudioVersions)', 'All'))</CommonBuildProperties>
</PropertyGroup>
<PropertyGroup Condition=" '$(TestInstalled)' != 'true' ">
<!-- If we're not going to test the installed version, then we'll use the default (current) VS version and the experimental hive. -->
<CommonBuildProperties>$(CommonBuildProperties);RootSuffix=Exp</CommonBuildProperties>
<!-- Azure-based static NuGet feed -->
<PropertyGroup>
<!-- Azure creds -->
<StorageAccount>kzu</StorageAccount>
<StorageContainer>nuget</StorageContainer>

<SleetInit Condition="'$(SleetInit)' == ''">false</SleetInit>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GitInfo" Version="1.1.32" />
<PackageReference Include="MSBuilder.CI" Version="0.1.2" />
<PackageReference Include="xunit.runner.msbuild" Version="2.3.1" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" />
<PackageReference Include="Sleet.Azure" Version="0.2.5" />
</ItemGroup>

<ItemGroup>
<Solution Include="src\Clide.sln"/>
<NuSpec Include="src\Package\Clide.nuspec" />
Expand All @@ -40,160 +42,39 @@

<Target Name="Clean">
<MSBuild Projects="@(Solution)" Properties="$(CommonBuildProperties)" Targets="Clean" />
<Exec Command="rmdir $(Out) /S /Q" ContinueOnError="true" />
<Exec Command="rmdir src\packages /S /Q" ContinueOnError="true" />
<Exec Command="rmdir $(Out) /S /Q" Condition="Exists('$(Out)')" ContinueOnError="true" />
<!-- Remove all bin/obj recursively under /src -->
<Exec Command='for /d /r . %%d in (bin,obj) do @if exist "%%d" rd /s/q "%%d"' WorkingDirectory='$(MSBuildThisFileDirectory)src' ContinueOnError='true' />
</Target>

<Target Name="Rebuild" DependsOnTargets="Clean;Restore;Build;Package" />

<Target Name="Restore">
<ItemGroup>
<RestoreSolution Include="@(Solution)" />
</ItemGroup>

<MSBuild Projects="%(RestoreSolution.Identity)" Targets="Restore" Properties="$(CommonBuildProperties);RestoreOnly=true" />
</Target>
<!-- Configures the project in preparation for Build. Includes running Restore. -->
<Target Name="Configure" DependsOnTargets="Restore" />

<Target Name="Build" Condition=" '@(Solution)' != '' ">
<Message Text="Build properties: $(CommonBuildProperties)" Importance="high" />
<!-- Targets can be documented, and /t:Help will render the help -->
<Target Name="Build">
<MSBuild Projects="@(Solution)" Properties="$(CommonBuildProperties);Dev=%(Dev.Identity)" />
</Target>

<Target Name="Test" DependsOnTargets="UnitTest;IntegrationTest" />

<Target Name="UnitTest" DependsOnTargets="Build">
<MSBuild Projects="src\Clide.UnitTests\Clide.UnitTests.csproj" BuildInParallel="false" Targets="GetTargetPath" Properties="$(CommonBuildProperties)">
<Output TaskParameter="TargetOutputs" ItemName="UnitTestAssembly" />
</MSBuild>

<Target Name="Package">
<MakeDir Directories="$(Out)" Condition="!Exists('$(Out)')" />
<xunit Assemblies="@(UnitTestAssembly)"
Html="$(Out)\unit-test.html"
Xml="$(Out)\unit-test.xml"
ParallelizeAssemblies="true"
ParallelizeTestCollections="true"
IncludeTraits="$(IncludeTraits)"
ExcludeTraits="$(ExcludeTraits)"
ShadowCopy="false"
WorkingFolder="$(MSBuildThisFileDirectory)src\Clide.UnitTests"
ContinueOnError="ErrorAndContinue" />
<MSBuild Projects="@(Solution)" Properties="$(CommonBuildProperties);IsSystemComponent=true;PackageOutputPath=$(Out)" />
</Target>

<Target Name="IntegrationTest" DependsOnTargets="Build">
<Error Condition=" '$(TestInstalled)' == 'true' And '$(Configuration)' != 'Release' "
Text="Cannot run integration tests with the installed version because the MSI is only built for the Release configuration, and specified configuration is '$(Configuration)'." />
<CallTarget Targets="Install" Condition=" '$(TestInstalled)' == 'true'" />
<Target Name="Clean" />

<MSBuild Projects="src\Clide.IntegrationTests\Clide.IntegrationTests.csproj" BuildInParallel="false" Targets="GetTargetPath" Properties="$(CommonBuildProperties)">
<Output TaskParameter="TargetOutputs" ItemName="IntegrationTestAssembly" />
</MSBuild>
<Target Name="Rebuild" DependsOnTargets="Clean;Restore;Build" />

<MakeDir Directories="$(Out)" Condition="!Exists('$(Out)')" />
<xunit Assemblies="@(IntegrationTestAssembly)"
Html="$(Out)\integration-test.html"
Xml="$(Out)\integration-test.xml"
ParallelizeAssemblies="true"
ParallelizeTestCollections="true"
IncludeTraits="$(IncludeTraits)"
ExcludeTraits="$(ExcludeTraits)"
ShadowCopy="false"
WorkingFolder="$(MSBuildThisFileDirectory)src\Clide.IntegrationTests"
ContinueOnError="ErrorAndContinue" />

<CallTarget Targets="Uninstall" Condition=" '$(TestInstalled)' == 'true'" />
<Target Name="AfterRestore" AfterTargets="Restore">
<MSBuild Projects="%(Solution.FullPath)" Targets="Restore" Properties="$(CommonBuildProperties);RestoreOnly=true" />
</Target>

<Target Name="ReportAppVeyor" AfterTargets="IntegrationTest" Condition=" '$(APPVEYOR)' == 'true' ">
<XmlEval XmlInputPath="$(Out)\integration-test.xml" Query="sum(/assemblies/assembly/collection/@passed)">
<Output TaskParameter="Result" PropertyName="Passed" />
</XmlEval>
<XmlEval XmlInputPath="$(Out)\integration-test.xml" Query="sum(/assemblies/assembly/collection/@failed)">
<Output TaskParameter="Result" PropertyName="Failed" />
</XmlEval>
<XmlEval XmlInputPath="$(Out)\integration-test.xml" Query="sum(/assemblies/assembly/collection/@errors)">
<Output TaskParameter="Result" PropertyName="Errors" />
</XmlEval>

<Exec Command='appveyor AddCompilationMessage "Integration Tests: Passed: $(Passed), Errors: $(Errors), Failed: $(Failed)" -Category Information' />
<Exec Command='appveyor AddCompilationMessage "Integration Tests Failed: $(Failed)" -Category Error'
Condition=" '$(Failed)' != '0' " />
<Target Name="Test">
<xunit Assemblies="@(TestAssembly)" />
</Target>

<Target Name="Install" Condition=" Exists('$(Installer)') ">
<Error Condition=" !Exists('$(VsixInstaller)') " Text="No VSIX installer found at expected path $(VsixInstaller). Cannot run installed Clide tests." />
<Message Importance="high" Text="Installing $(Installer)..." />
<Exec Command='"$(VsixInstaller)" /q "$(Installer)"' />
</Target>

<Target Name="Uninstall" Condition=" Exists('$(Installer)') ">
<Error Condition=" !Exists('$(VsixInstaller)') " Text="No VSIX installer found at expected path $(VsixInstaller). Cannot run installed Clide tests." />
<Message Importance="high" Text="Uninstalling $(Installer)..." />
<Exec Command='"$(VsixInstaller)" /q /u:Clide' />
</Target>

<Target Name="Package" DependsOnTargets="GitInfo;Build">

<MSBuild Projects="@(Solution)" Properties="$(CommonBuildProperties);IsSystemComponent=true" />
<Exec Command="$(PackagesPath)\gitlink\lib\net45\GitLink.exe . -f &quot;%(Solution.Identity)&quot; -u https://github.com/clariuslabs/clide -b &quot;$(GitBranch)&quot; -c &quot;$(Configuration)&quot;" StandardOutputImportance="low" />
<MakeDir Directories="$(Out)" Condition=" !Exists('$(Out)') " />

<MSBuild Projects="src\Installers\Clide.Installer\Clide.Installer.nuproj"
Properties="$(CommonBuildProperties)"
Targets="Build;GetTargetPath">
<Output ItemName='InstallerPackage' TaskParameter='TargetOutputs' />
</MSBuild>

<Copy SourceFiles='%(InstallerPackage.Identity)' DestinationFiles='$(Out)\%(InstallerPackage.Filename)%(InstallerPackage.Extension)' />
<Exec Command='"$(NuGet)" Pack "%(NuSpec.Identity)" $(Args) -Version $(Version) -Properties Id=%(NuSpec.Filename);Configuration=$(Configuration) -OutputDirectory $(Out)' />
</Target>

<PropertyGroup>
<GitInfoTargets>$(PackagesPath)\GitInfo\build\GitInfo.targets</GitInfoTargets>
<XunitBuildDir>$(PackagesPath)\xunit.runner.msbuild\build</XunitBuildDir>
<XunitPlatformDir Condition=" Exists('$(XunitBuildDir)') ">$([System.IO.Directory]::GetDirectories($(XunitBuildDir))[0])</XunitPlatformDir>
<!-- This file is used to detect whether the restore has been performed or not -->
<XunitProps>$([System.IO.Path]::Combine($(XunitPlatformDir), 'xunit.runner.msbuild.props'))</XunitProps>
<PendingRestore Condition=" !Exists('$(GitInfoTargets)') ">true</PendingRestore>
</PropertyGroup>

<!-- Overriden by the GitInfo.targets imports after nuget restore. These are here to satisfy DependsOn -->
<Target Name="GitInfoReport" />
<Target Name="GitInfo" />
<Target Name="GitVersion" />

<!-- Gets overriden by the $(GitInfoTargets) if it exists -->
<Import Project="$(GitInfoTargets)" Condition=" Exists('$(GitInfoTargets)') " />
<Import Project="$(XunitProps)" Condition="Exists('$(XunitProps)')"/>

<Target Name="Configure" DependsOnTargets="GitInfoReport">
<PropertyGroup>
<Version>$(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch)$(GitSemVerDashLabel)</Version>
</PropertyGroup>

<!-- Update AppVeyor build # to match the actual one being used -->
<Exec Command="appveyor UpdateBuild -Version $(Version)" Condition=" '$(APPVEYOR)' == 'true' " ContinueOnError="WarnAndContinue" />
<Target Name="Run">
<!-- TODO: build + deploy to exp, run VS -->
</Target>

<Import Project="$(PackagesPath)\MSBuilder.CodeTaskAssembly\build\MSBuilder.CodeTaskAssembly.props"
Condition="Exists('$(PackagesPath)\MSBuilder.CodeTaskAssembly\build\MSBuilder.CodeTaskAssembly.props')" />

<UsingTask TaskName="XmlEval" TaskFactory="CodeTaskFactory" AssemblyFile="$(CodeTaskAssembly)" Condition=" '$(CodeTaskAssembly)' != '' ">
<ParameterGroup>
<XmlInputPath Required="true" />
<Query Required="true" />
<Result Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System.Xml" />
<Using Namespace="System.Xml.Linq" />
<Using Namespace="System.Xml.XPath" />
<Code Type="Fragment" Language="cs">
Result = XDocument.Load(XmlInputPath).CreateNavigator().Evaluate(Query).ToString();
</Code>
</Task>
</UsingTask>
</Project>
<Import Project="build\corebuild.targets" />
</Project>
Loading

0 comments on commit 26bd4a1

Please sign in to comment.