How can I disable TrackFileAccess via CMake? - cmake

My company uses CMake to manage their code. Some of my colleagues are on Linux, and I'm on Windows, using Visual Studio. Our code is organised into a number of libraries, which translates into a number of Visual Studio projects under one solution.
To speed up compilation, I'm trying to integrate clcache with my setup. To do this, I need to disable TrackFileAccess for every project in the solution as noted here.
So, to my understanding, I have to modify the CMake files to either either inject some XML into each library's .vcproj file, or to modify the parameters passed to msbuild.exe itself. I'm having a lot of trouble figuring out how to do either of these things.
To try invoking msbuild.exe with specific command line parameters, I found the variable CMAKE_MAKE_PROGRAM. I tried using it with SET(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} /p:TrackFileAccess=false" CACHE INTERNAL ""), but I can see from Process Explorer that msbuild.exe was not getting invoked with that argument.
I couldn't work out how I'd go about injecting XML into the .vcproj files, or if it can even be done with CMake. Is there actually a way to do it? Or would I instead need to perhaps write a script to run after CMake runs, to edit its output?
While we're at it, do I really need to edit every single .vcproj file, or could I perhaps edit something that each .vcproj will inherit?

Aha!
I did more digging, and I think I'm barking up the wrong tree with CMake. It turns out, I could edit C:\Users\me\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.x64.user.props and add in
<PropertyGroup Label="Globals">
<TrackFileAccess>false</TrackFileAccess>
</PropertyGroup>
and it works!

Related

Can I override the OutputPath of a project on the solution level from within the VS2015 IDE?

My goal is to override the OutputPath property on all projects in a solution to be $(SolutionDir)$(Configuration)\. I would like to set this from within the VS2015 IDE.
I don't want to change the OutputPath in the .csproj or .vcxproj files (I know how to do this and it's not my intention to make a permanent change to the project files). I just need a local change for the moment to build.
I know I can accomplish this from the command line in a Developer Command Prompt by setting /p:OutputPath=$(SolutionDir)$(Configuration)\ on msbuild. Ideally, would like to be able to do this from within the IDE. Is that possible?
I was able to set OutputPath in a Developer Command Prompt and then launch VS2015, open the solution, and build:
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
Typical way of doing this is to import the same msbuild file in each project, and set OutputPath in that imported file. Disadvantage: project files need to be modified, it's not 'from within VS'. Advantage: has to be done once only, works on commandline as well as in VS, works for everybody, is pretty flexible and extensible. For example you could override OuputPath based on whether or not a certain file is present on the system, or a certain environment variable, or hostname, etc.
The answer you gave also works, though is also not from within VS. But the biggest drawback for me is that if you give your project to someone else they won't have an overriden output path, i.e. such modifications cannot really be put in version control. Of course if that's what you are after than it's fine.

Modify website MSBuild options to include configuration in path

I'm in the process of updating an old solution from Visual Studio 2005 to Visual Studio 2015, and I'm trying to reproduce as much of our old kludgy behavior as we safely can to minimize the downstream effects. I'm currently running into an issue with the Website Property Pages and MSBuild.
The path here is mostly correct, except that we want the configuration used to be in the path as well. So a Debug build will go into E:\Projects\...\PrecompiledWeb\Debug\MyService and a Release build will go into E:\Projects\...\PrecompiledWeb\Release\MyService. Is this doable? Is there a variable I can insert to make that determination when building?
We're using msbuild against the containing solution file (via TeamCity if it matters, but I can replicate it without it).
Edit: I've found the Debug.AspNetCompiler.TargetPath and Release.AspNetCompiler.TargetPath paths in the solution, but if I change them to be separate, the Debug one overrides the Release one when I next open the dialog.
When MSBuild starts building the project, it takes one or several project files. This dialog takes it parameters from MSBuild project file (you can edit it either from Visual Studio, or simply in every text editor). The project should have the property, called $(Configuration). You can use it in your output variable:
<OutputPath>E:\Projects\...\PrecompiledWeb\$(Configuration)\MyService</OutputPath>
One thing you must aware of is that the property $(Configuration) must be declared before the $(OutputPath) property.

MSBuild task does not build solution file

I have a project file that should build another solution. I tried using the MSBuild task for this, like this:
<MSBuild Projects="MySolution.sln" Properties="Configuration=$(Configuration)"/>
I tried a lot of variants, like supplying hardcoded configuration, target Rebuild and so on. Building reports an error when I pass a wrong solution name, non-existing configuration or target and so on, so it definitely loads the solution and the project files. It exits relatively fast though and produces no output. According to documentation and examples, this should work though. I also tried passing an ItemGroup for the project, including project-specific properties as suggested by examples or in MSBuild - How to build a .NET solution file (in an XML task script) from pre-written command line commands , but that does not work either. It runs without error but no output.
When passing a list of project files instead (or a single project file), it builds correctly, but the problem is that dependencies between the projects are not properly resolved. At the end, I have to supply all project files in the solution and add them to the list, which is what I want to avoid.
So, why does solution building not work, even though it should? What is wrong here?
Is this a .net project? If so you probably need to pass in a platform as well as a configuration.
<MSBuild
Projects="MySolution.sln"
Targets="build"
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
If the project just contains web sites and libraries then the platform should be Any CPU if your solution just contains executables then x86 or x64 or if it's a mixture of different types of platform then you can use mixed platforms
To check what are available open the solution in Visual Studio, right click on the solution in solution explorer and select "Configuration Manager" you'll then have a drop down for "Active Solution Platforms"

How can I run the current version of a NuGet package executable from the MSBuild project file?

I have added the xunit.runners package to a solution. The current version is 1.9.1, so I have hard-coded the path to the executable in an MSBuild project file:
<StartAction>Program</StartAction>
<StartProgram>$(MSBuildProjectDirectory)\..\..\Packages\xunit.runners.1.9.1\tools\xunit.gui.clr4.exe</StartProgram>
<StartArguments>"$(MSBuildProjectDirectory)\$(OutPutPath)$(AssemblyName).dll"</StartArguments>
(Off-topic: with this configuration, F5 starts the xUnit GUI runner and I can debug specific unit tests.)
I know that everytime I update the Nuget package, I will forget to change the path. Changing the path is a minor nuisance, since I have to unload the project, edit the file, then reload the project.
How can I start the executable, regardless of the actual version of the package? Can I find the executable in the folder named xunit.runners.* using a wildcard in MSBuild, then use that as a property in the <StartProgram> element?
Edit:
Something like:
<ItemGroup>
<Runners Include="$(MSBuildProjectDirectory)\..\..\Packages\xunit.runners.*\tools\xunit.gui.clr4.exe" />
</ItemGroup>
Will give me all runners in #(Runners), sorted by version. How can I get one of them, preferably the last one?
For filtering you can build a custom task. It can even be inline http://msdn.microsoft.com/en-us/library/dd722601.aspx, were you can write the c# code you need to loop over the items and pick the right one. Then you can expose the chosen path in an output property that you then use to set the value of the StartProgram property.
This question shows a custom inline task that gets an item array and does stuff with it. You can probably start from there.
You'll need to use this task in a target that runs before the target that initiates the debugging.
With fsimonazzi's comment I ended up with this:
<PropertyGroup>
<Package>$([System.IO.Directory]::GetDirectories("$(MSBuildProjectDirectory)\\..\\..\\Packages\\", "xunit.runners.*").GetValue(0))</Package>
<StartAction>Program</StartAction>
<StartProgram>$(Package)\tools\xunit.gui.clr4.exe</StartProgram>
<StartArguments>"$(MSBuildProjectDirectory)\$(OutPutPath)$(AssemblyName).dll"</StartArguments>
</PropertyGroup>
Apparently, NuGet will guarantee there's only one version of the package.

allowDefinition='MachineToApplication' msbuild error

We have a ASP.NET MVC with 4-5 different build configurations. Whenever we change the build configuration, we need to delete the obj folder for the web project, since we get the 'allowDefinition='MachineToApplication' error. A pain, but we managed by deleting the folder in pre/post build events.
Now I need to configure our CI to build deployment packages. This means that I cannot delete the obj folder. Every time I compile e.g. with the following msbuild parameters
/p:CreatePackageOnPublish=true /p:DeployOnBuild=true
I recieve the error:
web.config(123): error ASPCONFIG: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
As far as I understand, the problem is that there's multiple .config files in the project - In our case, there's not. I could really use some help to find an explanation and find a permanent (no- hack) fix.
Edit:
This question is marked as a duplicate, but the corresponding answers and cause(s) in the 2 threads, are clearly different from each other. Not sure what is intended with this tag - I've read that particular post before posting this question, as it didn't answer my question. There's multiple causes for this error message. It is 'similar', but definitely not a duplicate!
There is a similar question here on SO with some good solutions for this issue.
The problem is that building a deployment package creates a copy of the web.config in a subfolder of /obj. That will normally be be cleared out if you do a rebuild or a clean. However, if you build a deployment package in one configuration (e.g. Debug) and then switch to another confguration (e.g. Release) the obj/Debug folder is not cleared out and the web.config file there causes problems.
The quick solution is to clean all configurations and then do a (re)build. Alternatively you could delete the /obj folder in your project.
To permanently resolve the issue you can either move the intermediate output (/obj) out of your project folder or modify the project to force a clean of all configurations on rebuild.
I too was deleting the obj folder until I had a conflict with a build script which required it. Catch-22, I used the accepted answer on the following SO link to move the location of the Obj folder to C:\Temp\BUILD. You have to do it per csproj file, but it is a great solution.
Here is the link: VisualStudio: How to save the obj folder somewhere else
Note that I am using a variable for the project name.
R:\Temp\Build\Debug\$(MSBuildProjectName)
I have the above line in both debug and release sections for all my projects, including class projects. My build path is a ram drive for speed. See this SO for more info: How to access macro variables within csproj file?
I just answered a similar question here. To recap, I ran into this problem in one of our MVC projects, and it was due to having the MvcBuildViews property in the project file set to true. Setting the property to false fixed the problem.
<MvcBuildViews>false</MvcBuildViews>
I also found this answer which outlines an alternative that does not require turning off view building.
I don't know that there is an "official" fix as it just seemed to start on multiple projects of mine for no reason that I can find in Visual Studio Premium 2012 (never happened in previous versions of VS).
As a work around to automate the deletion of the obj directory as others have said, similar to an answer by user Casual in this post VisualStudio: How to save the obj folder somewhere else, where unfortunately just moving the location of the obj folder didn't always seem to work.
Instead I added a few commands under Build Events in the Pre-build event command line:
rd "$(ProjectDir)obj" /S /Q
md "$(ProjectDir)obj"
md "$(ProjectDir)obj\Debug"
md "$(ProjectDir)obj\Release"
You can change/add/remove subfolders to match your custom build configurations using the line where buildConfigName matches the name of the build configuration you are using:
md "$(ProjectDir)obj\buildConfigName"
Hope this helps!
That error indicates that you are trying to something specific to an application at an IIS tree level that isn't defined as an application. For example if you try to do app-level functions in a web.config in a virtual directory, you will get that error. You need to find the path you are deploying to and make sure that it is defined in IIS as an application vs a folder or vdir.
Cleaning the solution (Right click Solution in VS, clean), worked for me.
I had the same error but with a deployed page.. Then realized my webserver's clock was set back to 2010 for some reason. set it to the correct date fix my problem
Clean your project
Remove the /obj folder (probably using publish and deploy? - there is a bug in it)
Althoug the problem is explained and solved in one way in the accepted answer, I wanted to show a solution which can be better for other cases. This solution has been included in some version of VS, but I can only say that I had the problem in VS 2013 Update 5. (See the "Beware" below, it could be fixed in this version, but not working only in my particular case).
I borrowed the soltuion from Error: allowDefinition='MachineToApplication' beyond application level on Visual Studio Connect.
The solution consist in including these lines to the web application project (.csproj file) which handle the deletion of the offedning intermediate files (which wans't a solution for the accepted answer, as he needed those intermediate files):
<!--Deal with http://connect.microsoft.com/VisualStudio/feedback/details/779737/error-allowdefinition-machinetoapplication-beyond-application-level,
we will need to clean up our temp folder before MVC project starts the pre-compile-->
<PropertyGroup>
<_EnableCleanOnBuildForMvcViews Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='' ">true</_EnableCleanOnBuildForMvcViews>
</PropertyGroup>
<Target Name="CleanupForBuildMvcViews" Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='true' and '$(MVCBuildViews)'=='true' " BeforeTargets="MvcBuildViews">
<ItemGroup>
<_PublishTempFolderNamesToCleanup Include="Database;TransformWebConfig;CSAutoParameterize;InsertAdditionalCS;ProfileTransformWebConfig;Package;AspnetCompileMerge" />
</ItemGroup>
<!--Force msbuild to expand all the wildcard characters so to get real file paths-->
<CreateItem Include="#(_PublishTempFolderNamesToCleanup->'$(BaseIntermediateOutputPath)**\%(identity)\**\*')">
<Output TaskParameter="Include" ItemName="_EvaluatedPublishTempFolderNamesToCleanup" />
</CreateItem>
<Delete Files="#(_EvaluatedPublishTempFolderNamesToCleanup)" />
</Target>
Beware: for some reason, probably because I included it myself in the project, my build target for building the views was named "BuildViews", instead of "MvcBuildViews", so I had to modify the BeforeTargets attribute accordingly.
This is not necessarily the exact same issue, and to be honest, probably down to pure lack of knowledge on my part, however I had this same error when:
I set up a standard asp.net new project actually just used for HTML5 stuff so nothing other than the usual project structure
I then (not thinking perhaps!) added a new WCF REST project (which actually was just another base asp.net project using very good examples from http://www.codeproject.com/Articles/128478/Consuming-WCF-REST-Services-Using-jQuery-AJAX-Call?fid=1597004&df=90&mpp=25&noise=3&prof=False&sort=Position&view=Quick&fr=26#xx0xx and http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx
The problem was I added the WCF REST project (#2) as a SUB-DIRECTORY of the main project (#1) and then tried to build! even if I cleaned the project of course.. I also made both projects use IISexpress because I thought there was an issue using the same port or something.
Of course the build process saw the web.config from #1 and then a sub-dir with another web.config #2..
I realise this probably should be a very basic understood gotcha and it has caught me out a while ago, however sometimes it's the simplest of mistakes that are a real pain!
Might help others... who perhaps haven't had their morning coffee..
tip 1: clean & then rebuild.
tip 2: just close VS and open again.
tip 3: the downloaded project may be inside another sub folder... open the folder which has you .net files.
c:/demo1/demo/ (all files)
You should have to open demo from vs... not demo1.
I have a somewhat a similar problem, i had the main config as Copy Always so it copied the config to the bin directory. When i republished the main project, i got the MachineToApplication error. So my solution was to just change the config to Do Not Copy and remove the extra configuration in the bin folder.