Additional paths in msbuild script

2019-04-11 15:31发布

How to specify additional assembly reference paths for the MSBuild tasks?

I have following script so far, but can't figure out how to specify additional search paths.

<ItemGroup>
 <ProjectsToBuild Include="..\Main\Main.sln" />
</ItemGroup>

<!-- The follwing paths should be added to reference search paths for the build tasks -->
<ItemGroup>
 <MyAddRefPath Include="$(MSBuildProjectDirectory)\..\..\Build\Lib1" />
 <MyAddRefPath Include="$(MSBuildProjectDirectory)\..\..\Build\Lib2" />
</ItemGroup>

<MSBuild
 Projects="@(ProjectsToBuild)"
 Properties="Configuration=Debug;OutputPath=$(BuildOutputPath)">
</MSBuild>

UPDATE:

Please show one complete working script which invokes original project, such as an SLN with multiple additional reference paths.

No suggestions on how to improve the project structure please. I know how to build a good structure, but now it's the task of building an existing piece of crap.

4条回答
狗以群分
2楼-- · 2019-04-11 15:47

You've stated that you want to be able to modify the assembly search paths without modifying the project files directly. In order to accomplish that requirement you need to set an environment variable that will override the AssemblySearchPaths. With this technique you will need to provide every assembly reference path used by all the projects in the solutions. (Modifying the projects or copies of the projects would be easier. See final comments.)

One technique is to create a batch file that runs your script at sets the environment variable:

set AssemblySearchPaths="C:\Tacos;C:\Burritos;C:\Chalupas"
msbuild whatever.msbuild

Another way is to define a PropertyGroup in your custom msbuild file (otherwise known as the "hook" needed to make this work):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <ProjectsToBuild Include="..\Main\Main.sln" />
    </ItemGroup>

    <PropertyGroup>
          <AssemblySearchPaths>$(MSBuildProjectDirectory)\..\..\Build\Lib1;$(MSBuildProjectDirectory)\..\..\Build\Lib2</AssemblySearchPaths>
    </PropertyGroup>

    <Target Name="Build">
        <MSBuild Projects="@(ProjectsToBuild)" Properties="AssemblySearchPaths=$(AssemblySearchPaths);Configuration=Debug;OutputPath=$(OutputPath)" />
    </Target>
</Project>

Now if it were me, and for whatever unexplained reason I couldn't modify the project files to include the updated references that I am going to build with, I would make copies of the project files, load them into the IDE, and correct the references in my copies. Synching the projects becomes a simple diff/merge operation which is automatic with modern tools like mercurial (heck I'm sure clearcase could manage it too).

查看更多
\"骚年 ilove
3楼-- · 2019-04-11 15:48

The property you want to modify is AssemblySearchPaths. See the ResolveAssemblyReference task more information.

<Target Name="AddToSearchPaths">  
  <CreateProperty Value="x:\path\to\assemblies;$(AssemblySearchPaths)">  
    <Output PropertyName="AssemblySearchPaths" TaskParameter="Value" />  
  </CreateProperty>  
</Target>

Making use of item groups, as in your example, it would look like:

<Target Name="AddToSearchPaths">  
  <CreateProperty Value="@(MyAddRefPath);$(AssemblySearchPaths)">  
    <Output PropertyName="AssemblySearchPaths" TaskParameter="Value" />  
  </CreateProperty>  
</Target>

Looking in %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets, you can see that the ResolveAssemblyReference Task is executed as part of the ResolveAssemblyReferences target. Thus, you want the newly added target to modify the AssemblySearchPaths property before ResolveAssemblyReferences is executed.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-04-11 16:02

I have finaly figured out how to do it:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<ItemGroup>
    <ProjectsToBuild Include="ConsoleApplication1\ConsoleApplication1.csproj" />
</ItemGroup>

<ItemGroup>
    <AdditionalReferencePaths Include="..\Build\ClassLibrary1" />
    <AdditionalReferencePaths Include="..\Build\ClassLibrary2" />
</ItemGroup>

<PropertyGroup>
    <BuildOutputPath>..\Build\ConsoleApplication1</BuildOutputPath>
</PropertyGroup>

<Target Name="MainBuild">
    <PropertyGroup>
        <AdditionalReferencePathsProp>@(AdditionalReferencePaths)</AdditionalReferencePathsProp>
    </PropertyGroup>
    <MSBuild
        Projects="ConsoleApplication1\ConsoleApplication1.csproj"
        Properties="ReferencePath=$(AdditionalReferencePathsProp);OutputPath=$(BuildOutputPath)"
    >
    </MSBuild>
</Target>

查看更多
Viruses.
5楼-- · 2019-04-11 16:03

...and remember that you don't need to use a target for this, you can use project-scoped properties or items, as...

<ItemGroup>
    <MyAddRefPath Include="$(MSBuildProjectDirectory)\..\..\Build\Lib1" />
    <MyAddRefPath Include="$(MSBuildProjectDirectory)\..\..\Build\Lib2" />    
</ItemGroup>
<PropertyGroup>
    <MyAddRefPath>$(MSBuildProjectDirectory)\..\..\Build\Lib3</MyAddRefPath>
    <!-- add in the property path -->
    <AssemblySearchPaths>$(MyAddRefPath);$(AssemblySearchPaths)</AssemblySearchPaths>
    <!-- add in the item paths -->
    <AssemblySearchPaths>@(MyAddRefPath);$(AssemblySearchPaths)</AssemblySearchPaths>
</PropertyGroup>

...and if you do need to do this in a target to pick up paths from a dynamically populated item group, use inline properties, not the CreateProperty task (if you are not stuck in v2.0)

<Target Name="AddToSearchPaths">
    <PropertyGroup>
        <!-- add in the item paths -->
        <AssemblySearchPaths>@(MyDynamicAddRefPath);$(AssemblySearchPaths)</AssemblySearchPaths>
    </PropertyGroup>
</Target>
查看更多
登录 后发表回答