Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relative paths with MSBuild project vs solution

I have a number of projects which are joined into a solution. Every project has it's own directory structure, and csproj files are located on diferrent level of folder structure. Every csproj has OutputPath property specified. OutputPath - is a relative path and it varies from project to project in such a way so all projects have the same output dir. It is work OK if I build a separate project. But everything changes if I try to build solution file. In this case every project output folder differs (depends on a number of '..\' in that project's OutputPath).

I do know, that before some moment all was working fine. Nobody changed build.cmd neither any sln or csproj files. But now I have situation described above.

So my question is - what affects how relative path is evaluated? I mean how can I force relative OutputPath to be evaluated starting from folder where csproj file of that particular project is located. Not from folder where .sln file is.

Let's assume I have following directory structure:

dir1
  a.sln
  dir2
    a.csproj
  dir21
    dir3
      b.csproj

a.csproj has output path set to '../../_bin' which is just above dir1 if counted from a.csproj folder b.csproj has output path set to '../../../_bin' which is same - just about dir1 if counted from b.csproj

a.sln contains both - a.csproj and b.csproj.

When I run msbuild I get a project build to 'dir1/../../_bin' and b project to 'dir1/../../../_bin' - both relative paths of projects files are counted from solution file location, not project files.

like image 937
DarkDeny Avatar asked Feb 08 '13 15:02

DarkDeny


2 Answers

Well, I was able to find out what was causing this. That was custom .targets file, which was inferring SolutionDir property at the start of any msbuild. I did find out that by using MSBuild Explorer. The tool proved to be very useful in my case - I was not aware of third party .target files on my system.

like image 157
DarkDeny Avatar answered Nov 12 '22 15:11

DarkDeny


From Msbuild Import Element description

Relative paths in imported projects are interpreted relative to the directory of the importing project. Therefore, if a project file is imported into several project files in different locations, the relative paths in the imported project file will be interpreted differently for each imported project.

All MSBuild reserved properties that relate to the project file, for example, MSBuildProjectDirectory and MSBuildProjectFile, that are referenced in an imported project are assigned values based on the importing project file.

If you add more details or few samples to your question - it will be easier to understand exact problem.

Edit: Okay, lets try to pinpoint that mystery. First of all - OutputPath could be affected by Environment variables.

2nd - during build sln file transformed into msbuild project file format and stored in temp file. You can get that temporary file if you execute in cmd "set msbuildemitsolution=1" and then trigger build via command line. There you can check that file and see how your individual projects called. But I suppose you will see multiple .csproj /> entries. And global msbuild properties inherited by that calls.

So I suspect if everything was fine before some point and no changes were made - you are missing OutputPath environment variable or some other variable that contributed to construction of OutputPath.

BTW - I think if you want to fix your issue with forcing relative dir - you also can use $(MSBuildProjectDirectory). This is one of msbuild reserved properties (from here), but this will require yo adjust your OutputPath in each csproj file. What i, personally, prefer to avoid, because it could affect some other targets and introduce subtle issues.

like image 2
Alexey Shcherbak Avatar answered Nov 12 '22 16:11

Alexey Shcherbak