MSBuild recompile project when only output path change - compilation

We have two projects A and B. B referes to A. We created two targets for MSBuild to compile where difference is only in output path (it is separated file, not projects csproj's). Immidiate folder for both project are standard I mean obj folder.
We run first target (MSBuild from command line with /t switch) - everything compile ok. We didn't change anything in cs but we changed output path and compile. In that case A is not recompiled but B is fully recompiled. So in output path we had A with the same version but B versions are different.
Do you know why B project is recompiled?
EDIT
After some research it looks like MSBuild takes output path as part of cache hash (this file: obj\Debug\CoreCompileInputs.cache).
We call MSBuild like this:
msbuild mysolution.sln /p:OutputPath=c:\mydir
and csprojs are standard VS2017 csproj.

Related

Build specific Visual studio project under project solution using Msbuild and devenv

I have Visual studio project solution which has multiple .csproj. Each .csproj has some reference libraries.The project settings are made in such a way the reference libraries are built first and then .csproj is built. This works as expected when i run it in visual studio IDE. But when i try to execute using msbuild i'm getting an error saying target doesn't exist. Gone through many posts related to this issue ,tried possible things.But didn't built.Looks like i might be doing something silly or missing something in the settings.
Also tried using devenv from commandline. With this option i dont see any error but at same time the project doesnt build.I dont see any message after execution of command.Im using visual studio 2015
Here is my project structure
Poject.sln
ProjectA
porjectB
projectC
Libraries
libA
libB
msbuild "project.sln" target:"D:\Projects\Source\Demo\ProjectA\ProjectA.csproj" /t:build
"/p:Configuration=Debug" "/p:platform=x86"
I see the below error
"D:\project.sln" (D:\Projects\Source\Demo\ProjectA\;build target) (1) ->
D:\project.sln.metaproj : error MSB4057: The target "D:\Projects\Source\Demo\ProjectA" does not exist in the project. [D:\project.sln]
Here is the command used using devenv
devenv.exe "project.sln" /build Debug /project `"D:\Projects\source\Demo\Applications\ProjectA\ProjectA.csproj" /projectconfig Debug
After executing the above its doesnt build and i dont see any error too.
error MSB4057: The target "D:\Projects\Source\Demo\ProjectA" does not
exist in the project.
The error indicates your path in command is not valid and project.sln can't recognize the path. So you actually meet one path-related issue. And you should pass the ProjectA to the targets argument instead of ProjectA.csproj! More details see tip3 in For MSBuild.
For MSBuild:
1.If you're only trying to build ProjectA and its reference libraries.
Navigate(cd) to path where ProjectA.csproj exists, and then use command msbuild ProjectA.csproj /t:build /p:Configuration=Debug /p:platform=x86
Also you can directly use command msbuild AbsolutePath\ProjectA.csproj /t:build /p:Configuration=Debug /p:platform=x86. It's not necessary to use " to cover the path and arguments.
(ProjectA.csproj file should have definitions about the reference to those two library projects, so msbuild ProjectA.csproj will build those two projects first. You don't need to specify the xx.sln in your command.)
2.If you're trying to build whole solution(all the projects):
msbuild project.sln /t:build /p:Configuration=xxx /p:platform=xxx
Navigate to solution folder when you run above command, or use absolutepath\project.sln with that command.
3.When you want to build specific projects(more than one) in solution:
Check How to: Build Specific Targets in Solutions By Using MSBuild.exe. Since you're only build ProjectA, you don't need to use this format. For example: Only when you need to build both ProjectA and ProjectB, but not build ProjectC... You can use command like:
msbuild xxx.sln /t:NotInSlnfolder:Build;NewFolder\InSolutionFolder:Build
Pay attention to the path when you use this format. Whether your project is in solution folder can affect the build result a lot ! And, the direct cause of your issue, this command's targets argument needs one ProjectName as input instead of ProjectName.csproj.
For Devenv command:
1.I always use VS2017 and VS2019,so I'm not certainly sure if VS2015's devenv related command has big difference from VS2017's or VS2019's. But according to details from this VS2017 document:
Commands that begin with devenv are handled by the devenv.com utility, which delivers output through standard system streams, such as stdout and stderr.
Alternatively, commands that begin with devenv.exe can use the same switches, but the devenv.com utility is bypassed. Using devenv.exe directly prevents output from appearing on the console.
I think that's why you don't see any message after execution of command. You should use devenv.com command to see the output in console. And it's by design that devenv.exe will prevents output from appearing on the console.
2.The following command builds the project CSharpWinApp, using the Debug project build configuration within MySolution.
devenv "%USERPROFILE%\source\repos\MySolution.sln" /build Debug /project "CSharpWinApp\CSharpWinApp.csproj" /projectconfig Debug
More details about devenv reference please check this document.
In addition:
1.Looks like you have one strange project structure. I checked your error message above and it seems your several projects(xx.csproj) are not under Solution(xx.sln) folder. Just a suggestion, the normal folder structure for VS2015 is always:
Solution folder
xx.sln
ProjectA folder
ProjectA.csproj
ProjectB folder
ProjectB.csproj
2.For most of the projects, build using msbuild is more powerful and convenient than build using devenv. So if you don't have special reason, I recommend using Msbuild, the build engine of VS.
Hope all above helps to resolve your issue and puzzle. Let me know if your issue persists:)
File "/Users/morel893/Desktop/env/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "projects_project" does not exist
LINE 1: ...ct"."technology", "projects_project"."image" FROM "projects_...

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.
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.
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.

Output Path and MSBuild

I have a solution with 9 projects. All references in each project have their CopyLocal property set to False.
When I build it from VS, none of these referenced binaries are copyed to the output build directory. Similarly, when I build using msbuild, I only see the project binaries and no references.
However, when I specify an output path in the msbuild command, some references are copied and I don't know why? Is there some setting I am forgetting to set? Has anyone seen this before?
When you build your application without setting the OutDir property, the files are copied to the path specified in project properties (Build\Output path). After this, there is another step that copies the referenced project output (*.dll file) to the OutDir of your application (*.exe). But if you set CopyLocal to false, this last step doesn't happen. Like this:
ProjectEXE\OutDir = c:\a\bin
ProjectDLL\OutDir = c:\b\bin
Pay attention to the fact that the two OutDir are different (and differently specified in your projects properties).
But when you set the OutDir using the command-prompt, you are setting both OutDir parameters to the same path. Still there is no final copy of the DLL to the same directory of your application, except for the fact that it is the same location you built the DLL and EXE first time. Like this:
msbuild yourSolution.sln /p:OutDir="c:\a\bin\"
ProjectEXE\OutDir = c:\a\bin
ProjectDLL\OutDir = c:\a\bin

Customize building VC++ in VS2010

I have a big C++ project and I need to do many steps in the building phase because I am building an application that is compatible with both 64 and 32, I have three projects:
proj1,Porj2,Proj3
and I need to do the following:
Exclude a cpp File from proj1 (32bit version)
Include a cpp file to proj1 (64bit version)
build proj1
build proj2
Execute output of proj2
Exclude a cpp File from proj3 (32bit version)
Include a cpp file to proj3 (64bit version)
Build proj3
Rename the exe that was built from proj3
Exclude a cpp File from proj1 (64bit version)
Include a cpp file to proj1 (32bit version)
still there are some other steps ... I was doing that manually and its frustrating, I found the I need to use MSBUILD but is it used for building native code ? and how can I perfrom these tasks ?
-Excluding and Including cpp files into projects
-Building proj
In Visual Studio 2010 and later, C++ projects use MSBuild.
Rather than excluding or including files based on the configuration, it would be simpler to use a preprocessor directive to conditionally compile the contents of the file. E.g., wrap the entire contents of the file in:
#ifdef MY_32BIT_BUILD_MACRO
// Source file contents here
#endif
And likewise with a macro for 64-bit builds. When using Visual C++, you can use the _M_IX86 and _M_X64 predefined macros to detect whether you are compiling for x86 or x64, respectively.
Alternatively, you could add a Condition property to the ClCompile item for the particular source file in the project file, and have it only included in the build when certain properties are set. I think that conditional compilation within the source file is a better option, though, unless you have complex rules that you need to use to determine whether to include a file or not.
In your solution, you can set project dependencies to ensure that one project is built before another. Right-click the solution, select Properties, and browse to Common Properties -> Project Dependencies. Dependencies can also be specified in a project file.
You can execute the output of a build by using a post-build task. Right-click the project, select Properties, and browse to Configuration Properties -> Build Events. The Post-Build event can be used to execute a command when the build has completed.
Rather than renaming an executable after build, it's easier to just have the build produce an executable with the right name. In the Project properties, under Configuration Properties -> General, the Target Name property can be used to set the name of the primary build output.

How do I compile a single source file within an MSVC project from the command line?

I'm about to start doing some benchmarking/testing of our builds, and I'd like to drive the whole thing from a command line. I am aware of DevEnv but am not convinced it can do what I want.
If I could have a single file built within a single project, I'd be happy.
Can this be done?
The magical incantation is as follows. Note that this has only been tested with VS 2010 - I have heard this is the first version of Visual Studio with this capability:
The Incantation
<msbuild> <project> <settings> <file>
Where
msbuild is a path to MSBuild.exe. Usually this should be set up for you by the VS2010 bat file so the right one will end up in your PATH, but if not I found one at C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe
project is the path to the vcxproj file within which your source file resides.
settings include the following:
/p:Configuration="Debug" // or whatever your Configuration is
/p:Platform=x64 // or x86
/t:ClCompile // to specify specifically you're looking to compile the file
file is actually another setting:
/p:SelectedFiles="path_to_file"
Notes
For <project> I had to specify a project (vcxproj) file instead of a solution (sln) file. The sln I would have used has multiple projects within it, so there would have been extra work to go that route anyhow (if it can even be done).
For the /p:Platform=x64 setting, there are several environment variables that pivot on what platform you are targeting (x64 v. x86) so make sure you set those up properly via Visual Studio's vcvarsall.bat.
Regarding path_to_file in the SelectedFiles parameter, this path must be the path as specified in the project file. If the path does not match the path used in the project file to reference the source, it doesn't seem to work.

Resources