|
1 | 1 | # MSBuild.CustomOutputPath |
2 | | -This MSBuild extension allows customizing the output path when building a solution or project from inside Visual Studio or command line. It replaces the default relative directories Obj and Bin with a user-defined path, without changing the project files. This is designed to be used for speeding up the build process by using a different drive for MSbuild output, i.e. a RAM drive. |
| 2 | +This MSBuild extension allows changing the output paths when building a solution or project using Visual Studio or from the command line. It replaces the default relative directories Obj and Bin with user-defined paths without changing the project files. This is designed to be used for speeding up the build process by using a different drive for MSbuild output, i.e. a RAM drive. |
3 | 3 |
|
4 | 4 | ## Content |
5 | 5 | The extension consists of: |
6 | | -- a .props file which can be edited to configure the extension |
| 6 | +- a .props file which defines the properties used by the extension |
7 | 7 | - a before.targets file which runs before Microsoft.Common.targets |
8 | 8 | - a after.targets file which runs after Microsoft.Common.targets |
9 | 9 | - a .dll which contains the MSBuild tasks used by the targets |
10 | 10 |
|
11 | 11 | ## How it works |
12 | | -The extension integrates with `Microsoft.Common.targets` and sets well-known properties such as `IntermediateOutputPath` and `OutDir` to be prefixed by the user-defined path also known as the **base output path**. The rest is handled by Microsoft.Common.targets. |
13 | | -The final paths may look like `$(BaseOutputPath)\MySolution\MyProject\obj\Debug`. Same for the `bin` directory. |
| 12 | +The extension integrates with `Microsoft.Common.targets` and sets well-known properties such as `IntermediateOutputPath` and `OutDir`. The values of these properties are set to begin with a user-defined path known as the **base output path**, followed by the name of the solution and the name of the project, i.e. `$(BaseOutputPath)\MySolution\MyProject\bin\Debug`. |
| 13 | + |
| 14 | +The base output path can be configured by setting the environment variable `MSBuildBaseOutputPath`, i.e. 'R:\Build', or by setting property `BaseOutputPath` from the command line. |
| 15 | +If the base output path is not set at build time then a _warning_ is issued and the build process will use the default output paths. If the base output path is set but the drive is N/A at build time, then the build fails with **error**. |
14 | 16 |
|
15 | 17 | ## Features |
16 | 18 |
|
17 | | -#### Configure the base output path |
18 | | -There are several ways to configure the base output path. You can set the environment variable `MSBuildBaseOutputPath` or edit the .props file and change it there. The default value is **R:\Build**. |
| 19 | +#### Use links in output directory |
| 20 | +This feature ensures that most of the files copied in the output directory are either hard links or symbolic links, instead of being actual copies of the original files. This saves disk space and minimizes the number of write operations, thus speeding up the build. This is enabled by default and it can be disabled by setting property `UseLinksInOutputDirectory` to `false`. |
| 21 | + |
| 22 | +**Warning**: manual changes of linked output files propagate to the original files! |
| 23 | + |
| 24 | + |
| 25 | +#### Link default output directory to the custom output directory [Visual Studio only] |
| 26 | +When building from Visual Studio, the project's default output directory i.e. `bin\debug` will be converted to a symbolic link which points to the custom output directory. This ensures the IDE can run startup projects or unit test projects using the base output path. |
| 27 | + |
| 28 | +**Known issue**: the first build of a startup project which is configured to use the _VS hosting process_ on debug will fail because the default output directory cannot be deleted while the process is running. As a workaround, disable the VS hosting process manually before the build and re-enable it after the build. |
| 29 | + |
| 30 | +**How to undo this**: make sure that property `BaseOutputPath` is not defined. |
| 31 | + |
| 32 | + |
| 33 | +#### MSBuild integration |
| 34 | +The extension can be automatically imported by MSBuild using `Microsoft.Common.targets`'s before and after imports. It can also be imported manally. I.e.: |
| 35 | +```xml |
| 36 | +<Import Project="$(MSBuildExtensionsPath)\CustomOutputPathExtension\Before.CustomOutputPath.targets" /> |
| 37 | +<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| 38 | +<Import Project="$(MSBuildExtensionsPath)\CustomOutputPathExtension\After.CustomOutputPath.targets" /> |
| 39 | +``` |
19 | 40 |
|
20 | | -#### Link default target directory to the custom target directory [Visual Studio only] |
21 | | -When building from inside Visual Studio, the project's default target directory i.e. `bin\debug` will be converted to a symbolic link which points to the custom output directory. This ensures the IDE can run startup projects or unit test projects using the base output path. |
| 41 | +Projects which do not import the common targets, such as [WiX Toolset](http://wixtoolset.org), have to integrate the extension targets manually. I.e.: |
| 42 | +```xml |
| 43 | +<PropertyGroup> |
| 44 | + <CustomBeforeWixTargets>$(MSBuildExtensionsPath)\CustomOutputPathExtension\Before.CustomOutputPath.targets</CustomBeforeWixTargets> |
| 45 | + <CustomAfterWixTargets>$(MSBuildExtensionsPath)\CustomOutputPathExtension\After.CustomOutputPath.targets</CustomAfterWixTargets> |
| 46 | +</PropertyGroup> |
| 47 | +``` |
22 | 48 |
|
23 | | -Note: symlink creation requires _administrative privileges_ so this needs to run from an elevated process. |
| 49 | +#### ReSharper build |
| 50 | +All features enabled when using Visual Studio are also enabled when running the [ReSharper build](https://blog.jetbrains.com/dotnet/2015/10/15/introducing-resharper-build) from Visual Studio. |
24 | 51 |
|
25 | | -**How to undo this**: edit the .props file and make sure that property `BaseOutputPath` is not defined. |
| 52 | +## Extensibility |
| 53 | +The extension allows solution-level customization of the output paths. There are two targets file that can be defined in a solution's directory: `Before.CustomOutputPath.targets` and `After.CustomOutputPath.targets`. These files can contain solution-specific logic to further configure the output path. |
26 | 54 |
|
27 | | -#### Extensibility |
28 | | -The extension allows local customization of the base output path. There are two targets file that can be defined in a solution's directory: `Before.CustomOutputPath.targets` and `After.CustomOutputPath.targets`. These files can contain solution-specific logic to further configure the output path. |
| 55 | +Note that 'before' and 'after' are relative to the execution of `Microsoft.Common.targets` which means i.e. 'before' cannot use properties which are defined in `Microsoft.Common.targets`, i.e. `$(TargetExt)`. |
29 | 56 |
|
30 | | -Note that 'before' and 'after' are relative to the execution of `Microsoft.Common.targets` which means i.e. 'before' cannot use properties which are defined in `Microsoft.Common.targets` such as `$(TargetExt)`. |
| 57 | +## Notes |
| 58 | +Symbolic link creation requires **administrative privileges**. Make sure to run the extension in an elevated process. |
0 commit comments