Yumbelie
Yumbelie

Reputation: 368

msbuild importing and overriding files

I've got a two projects and a solution file:

c:\dev\base\proja\proja.vbproj
c:\dev\base\proja\myfile1.aspx
c:\dev\base\proja\myfile1.aspx.vb
c:\dev\base\proja\myfile1.aspx.vb.designer
c:\dev\base\proja\myfile2.aspx
c:\dev\base\proja\myfile2.aspx.vb
c:\dev\base\proja\myfile2.aspx.vb.designer

and

c:\dev\base\projb\mysln.sln
c:\dev\base\projb\projb.vbproj
c:\dev\base\projb\myfile2.aspx
c:\dev\base\projb\myfile2.aspx.vb
c:\dev\base\projb\myfile2.aspx.vb.designer

proja.vbproj is the base project, while projb.vbproj is intended to import proja.vbproj and override the myfile2.aspx etc files.

proja.vbproj looks like this:

[...]
<Compile Include="myfile1.aspx.vb">
  <SubType>ASPXCodebehind</SubType>
  <DependentUpon>myfile1.aspx</DependentUpon>
</Compile>
<Compile Include="myfile2.aspx.vb">
  <SubType>ASPXCodebehind</SubType>
  <DependentUpon>myfile2.aspx</DependentUpon>
</Compile>
[...]
<Content Include="myfile1.aspx" />
<Content Include="myfile2.aspx" />
[...]

while projb.vbproj looks like this:

[...]
<Import Project="$(ProjectDir)..\proja\proja.vbproj" />
[...]
<Compile Include="myfile2.aspx.vb">
  <SubType>ASPXCodebehind</SubType>
  <DependentUpon>myfile2.aspx</DependentUpon>
</Compile>
[...]
<Content Include="myfile2.aspx" />
[...]

projb.vbproj is a designed to just override the customised files of proja.vbproj - providing a single normalised location from which to maintain the project, while allowing specific overrides for per-site customizations.

The problem arises when I load projb.vbproj in Visual Studio 2013 and try and build it. It throws a tonne of errors because it cannot resolve the location of the of myfile1.aspx and associated files located in proja.vbproj. This appears to be because the imported paths are relative to the projb.vbproj location rather than proja.vbproj files location.

I've tried pre-appending $(MSBuildProjectDirectory) to all the files in proja.vbproj - but this doesn't resolve the issue as I believe $(MSBuildProjectDirectory) is contextually set based on the project that is being opened rather than imported.

I don't want to copy the entire myproja.vbproj files contents into myprojb.vbproj just to override one file - this seems messy and against the seemingly inheritance-centric methodology of msbuild, but perhaps I'm wrong here...

Is there any way to accomplish what I'm after? That is; override certain file locations of one project with file locations of another without having to duplicate the entire project file?

Upvotes: 0

Views: 470

Answers (1)

stijn
stijn

Reputation: 35901

It's a good thing you're trying to reuse parts of your project but the way you are doing it has a couple of disadvantages (and they are only going to get bigger if your project grows):

  • as you noticed it doesn't work properly
  • you could probably fix this by using $(MsBuildThisFileDirectory), but that would mean whenever you Visual Studio to add files to your project, you'd have to apply the fix again
  • project b directly depends on pretty much everything in project a, such tight coupling is never a good sign
  • if MsBuild sees Compile Include=aaa it adds aaa to the compile list. Even if it's there already. So you're not overriding anything here, you're just adding to the files included in project a. Not sure if that is what you want?

What you can do instead:

  • if projects need the same build settings (for compiler/linker/...), add those settings to a common, seperate file and include that in both projects
  • if projects need common functionality, put just that functionality in a project and reference that project in the other projects. So instead of trying to override things with your build system, which is messy, provide a common base and then add classes to it. (I don't know anything at all about aspx/bb.net but surely it has a way to create 'library' type projects that you can reference in others?)
  • in response to your comment: if only a couple of files are different, you can also use one single project with multiple build configurations. Each build configuration then enables different files. So normally you have configurations like Debug and Release, now you rename those and extra configurations like ReleaseCustom1/ReleaseCustom2.

For example:

 <!-- 500+ Common Files -->
 <Compile Include="myfile1.aspx.vb"/>
 <Compile Include="myfile2.aspx.vb"/>
 <!-- Some Specific Files -->
 <Compile Include="customfile1.aspx" Condition="'$(Configuration)'=='ReleaseCustom1'"/>
 <Compile Include="customfile2.aspx" Condition="'$(Configuration)'=='ReleaseCustom2'"/>

Upvotes: 2

Related Questions