I have downloaded the myTODO Azure sample application and when trying to run it locally I am receiving the following very puzzling error message.
The item "..\MyTodo.WebUx\MyTodo.WebUx.csproj" in item list
"ProjectReferenceWithConfiguration" does not define a value for metadata "Configuration".
In order to use this metadata, either qualify it by specifying %(ProjectReferenceWithConfiguration.Configuration),
or ensure that all items in this list define a value for this metadata.
C:\Program Files (x86)\MSBuild\Microsoft\Cloud Service\1.0\Visual Studio 10.0\Microsoft.CloudService.targets
Below is an extractfrom the MyToDo.WebUX.csproj file, what do I change?
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
I had an issue today where MSBuild was giving me an almost identical error:
The item "xxx.csproj" in item list "ProjectReferenceWithConfiguration" does not define a value for metadata "Name".
Fortunately, I had another Azure service that was compiling correctly, so I was able to search out the differences. It turned out that in the solution that was working, MyService.ccproj (the Azure Service project) was compiling before xxx.csproj. In the solution that was failing, xxx.csproj was compiling first. When I specified the dependencies such that xxx.csproj compiled after MyService.ccproj, it started working.
I'm not sure exactly what's going on here, or what it is about xxx.csproj that makes it so it has to come after. If I figure it out I'll update, but maybe this will help you.
UPDATE: It seems like maybe Azure does not like it if you specify anything besides an Azure Role project as a dependency on the service project. I made it so MyWebRole.csproj was dependent on xxx.csproj, instead of MyService.ccproj being dependent on xxx.csproj, and it worked.
To get the web project to convert, remove the following from the element: "{603c0e0b-db56-11dc-be95-000d561079b0};"
That sample is out of date though ... you can use it to look at the tests project, but to get a more up to date vs2008 version of the majority of that project's code, try downloading the source to this lab: DeployingApplicationsinWindowsAzure.
The Source link is in the upper right corner. If you look at the end folder for the 3 exercise you will find a more up to date version of this project ... however I don't think the complete solution is there so you'll have to compare it to the one you linked to above.
... I haven't compared the projects myself so I don't know what is missing between the lab version and the one on code gallery.
Related
I wanted to use two configurations in my Visual Studio 2019 C++ project, lets say I wanted to rename Debug to Debug-A and add a new configuration called Debug-B based on Debug-A.
Debug-A and Debug-B differ only by one define symbol, lets say one has SYMBOL_A and another has SYMBOL_B.
Currently, I don't care about Release and anything other than x64.
It works corretly until I add a NuGet package (for example fmt). Then, when I try to compile, I get undefined symbol linker errors. Just like fmtd.lib was not included, if I include it manually (or change the project configuration name to Debug), the issue is gone.
I know the reason why NuGet includes it if my project configuration is named Debug. Look at the nuget package targets file (packages/fmt.7.0.1/build/fmt.targets) - lib files are hardcoded to $(Configuration) being either Debug or Release.
As far as I know, all NuGet C++ packages are built this way.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<Link>
<AdditionalDependencies>fmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
<AdditionalDependencies>fmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<Link>
<AdditionalDependencies>fmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
<AdditionalDependencies>fmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<!-- ... -->
</Project>
I know I can manually link the libs, but fmt was just an example, I use a lot of packages and manually linking will become an issue quite fast.
Is there any way to use the quick selection of preprocessor symbols provided by active solution configuration (the toolbar dropdown) and still be able to use NuGet properly? For example parsing the nuget files with fake $(Configuration) variable. Using $(Platform) (x86, x64 etc.) is impossible, library include path is depending on it's hardcoded value too.
Sample project with this bug.
If, as you mentioned, the NuGet Packages’ lib files are hardcoded, then we may need to find solutions from other sides, for example .vcxproj file or MSBuild.
I didn’t find any directly properties/parameters/ways which meet your requirements. But, is it possible to keep the Debug name, I mean, leave it named Debug not Debug-A or Debug-B, and then switch to use different Configurations by using other methods. Imagine there is a Debug configuration file(DebugB)(maybe DebugB related things are set in this file) excluded in the project and the project currently use another Debug configuration(DebugA), and during the build, the project will exactly use DebugA configuration. To switch, do something, or add a code line in .vcxproj file to include the file which contains DebugB configuration, and then let the DebugB configuration cover the DebugA configuration.
So, for covering the properties/items of .vcproj file. Perhaps customize build works.
Hope above could give you a little help.
I have a bunch of C++ projects (.vcxproj) for VS2017, which produce dynamic libraries (DLL), which are handled like "plugins" (i.e. they are loaded dynamically by the application).
Occasionally I want to change the produced DLLs names based on some list in text file (the format may be changed):
ProjName1;DLL1
ProjName2;DLL2
...
The first column specifies the project name ($(ProjectName)) and the second is for desired DLL name ($(TargetName)).
I want this file to be parsed at build-time, so each read DLL name goes into $(OutputFile) of the appropriate project.
For instance, ProjName1.vcxproj will have following fragment (at build time):
<Link>
<OutputFile>$(OutDir)DLL1$(TargetExt)</OutputFile>
</Link>
I guess, certain capabilities of msbuild can be utilized for this (e.g., ReadLinesFromFile task and FindInList task), but I'm not sure how to put these pieces together).
There are some examples of such automation to consider, though I doubt they are relevant to .vcxproj format:
MSBuild ReadLinesFromFile all text on one line
Read text file and split every line in MSBuild
Used ReadLinesFromFile to make version in separate file
The straightforward approach is to modify content of each .vcxproj-file to match the list (either manually, or with some script).
Are there any other options?
Update 1: I've managed to implement a partial solution, which is based on a separate file with DLL name (module name) for each project (refer to Property Functions for more hints).
With property sheets it was easy in my case to 'inject' the fix into all projects:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildProjectDirectory)\_MODULE.name')">
<ModuleName>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\_MODULE.name'))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
Though it works quite good, the approach doesn't meet my needs perfectly - I'd like to have all module names in one file.
After some investigations and tryouts I've finally managed to make a working solution for my case. Basically it is built on top of my previous partial solution by using magic powers of Regex. The hint how to handle regex in my context was found in another answer to similar question.
I've also tuned the list format a bit to my taste:
DLL1=ProjName1
DLL2=ProjName2
...
I've placed the changes in the property sheet, so they can be easily picked up by all dependent projects:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<PropertyGroup Condition="exists('$(MSBuildThisFileDirectory)..\_MODULES.txt')">
<ModulesNames>$([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\_MODULES.txt'))</ModulesNames>
<ModuleName>$([System.Text.RegularExpressions.Regex]::Match($(ModulesNames), '\W?(\w*)\W?=\W?$(MSBuildProjectName)\W?').get_Groups().get_Item(1))</ModuleName>
<TargetName>$(ModuleName)</TargetName>
</PropertyGroup>
...
</Project>
If the project isn't listed in _MODULES.txt, its $(TargetName) isn't affected.
If you see $(ModuleName) in the project settings, then everything is tuned correctly:
The solution seems to work fine except for one minor drawback: the build system (VS2017 v.15.9.15) is quite "lazy" in detecting changed in _MODULES.txt while the solution is open, so you'll have to close it and reopen. And chances are high the rebuild will be needed after you change the list.
I have a single desktop app project in Visual Studio which need to be built with a number of different app icons. I have added support for this in the project-file like so:
<PropertyGroup>
<ApplicationIcon Condition=" $(DefineConstants.Contains('OTHER_VERSION')) ">Other.ico</ApplicationIcon>
<ApplicationIcon Condition=" !$(DefineConstants.Contains('OTHER_VERSION')) ">Standard.ico</ApplicationIcon>
</PropertyGroup>
Now, how do I configure my project to build both these versions automatically at the same time, without having to execute the build twice and change build constants in between? Is it even possible?
The simplest way would be to create a copy of your project file, modify the build configuration however you want (output path, Assembly Name, etc...) add this modified project file to your solution and build. It will look like you have two projects in your solution, but they will reference the same files.
Your other option would be to simply write your own build script that calls msbuild passing a different configuration on each call which will result in multiple builds being created.
Another solution could be to create a post build action to copy the output executable and edit the icon from executable. This is possible in opening exceutable file with Visual Studio (Open->File...->Select "Executable Files" type) then it must be possible with code or script.
cf this question
I read about using these mechanisms in Brian Kretzler’s book and this example posted by Adam Badura, in particular.
Following Badura’s example (which he notes “Cleaning/Rebuilding does remove the file as expected as well.”) I have:
<PropertyGroup>
⋮
<CleanDependsOn>QtClean;$(CleanDependsOn)</CleanDependsOn> <!-- doesn't work -->
⋮
</PropertyGroup>
at top-level (direct child of the document root element).
When I use the IDE menu to Clean Solution, the QtClean Target is not performed. The Message task I included within it does not appear, and the expected effect of the RemoveDir task is not observed (nor are any error messages).
Why would this not work?
This should run using the latest VS2017 feature enhancement Directory.Build.Targets.
Insert the following in a file with the name Directory.Build.Targets at the root folder in trunk of your repository. MSBuild, while loading your .sln, will automatically load your customized Directory.Build.Targets file.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Inject a custom target into Clean by extending CleanDependsOn -->
<PropertyGroup>
<CleanDependsOn> $(CleanDependsOn); CustomAfterClean </CleanDependsOn>
</PropertyGroup>
<Target Name="CustomAfterClean" Condition="$(ProjectName) == 'XXXMyProjectXXX'" >
<!--- my custom clean up -->
</Target>
</Project>
I've learned that <CleanDependsOn> doesn't work because it's overwritten (not appended to) by Microsoft.Common.Targets, which is pulled in at the bottom of a project file. Thus, it cannot be extended by statements within the meaty center of the project file or property sheets as normally included. The “extension targets” are included at the end of the project file, after the normal common targets.
However, the <CppCleanDependsOn> property is extended (not overwritten without including the previous value) everywhere it is used.
One general answer to “Why would this not work?” is that global variables are evil. You have to understand the temporal proximity of the variable (“property”), as it may get changed again before it is read, or read before you are setting it.
According to this it should be possible to reference projects outside solution and have it working in VS and command line but not TFS.
Unfortunately, when I've tried to partition my solution this way, it didn't work neither in VS2010/devenv nor in msbuild.
In both cases the error was:
The OutputPath property is not set for project 'Common.csproj'.
Please check to make sure that you have specified a valid combination
of Configuration and Platform for this project. Configuration='Debug'
Platform='AnyCPU'. This error may also appear if some other project
is trying to follow a project-to-project reference to this project,
this project has been unloaded or is not included in the solution, and
the referencing project does not build using the same or an equivalent
Configuration or Platform.
However, current Platform is "x86" and no matter which platform and configuration I set in VS or msbuild it's always trying Debug|AnyCPU. In case of msbuild if I set /p:OutputPath=bin\x86\Debug it propagates to child projects correctly.
Is this a bug, can I work-around it ?
UPDATE
Found the bug in MS Connect. Unfortunately closed as Won't Fix :(
UPDATE 2
Found workaround: set ShouldUnsetParentConfigurationAndPlatform=false. Both on command line for msbuild and in project file (before any imports) to fix Visual Studio.
If I understand the problem correctly, it's actually because the AssignProjectConfiguration target is not correctly setting the configuration / platform properties for those projects.
If you know what their configurations and platforms should be, you could always just inject a target to run right after the AssignProjectConfiguration target, and override the SetConfiguration and SetPlatform properties on each item representing an unresolved (meaning not part of the solution configuration) inter-project reference.
For some stupid reason, the Microsoft-provided target stores the list of unresolved project references in the same collection as the resolved ones (but nowhere else), which leaves you with 2 options:
Just set each project's properties manually (ie. hard-coding via a dynamic ItemGroup element inside your injected target).
Call the AssignProjectConfiguration task yourself from your injected target, collect the unassigned outputs to assign them all a default configuration / platform of your choosing.
Either way, once you have your list of correctly configured project references, you can simply replace the unresolved items in the ProjectReferenceWithConfiguration item group with their manually modified counterparts (using another dynamic ItemGroup element with a Remove and then an Include).
Mind you, I wouldn't do things the way you are doing them. If you want to split your product into several solutions, then I would just have each solution publish shared outputs into a common staging area and have .proj scripts to link them together. I've learnt the hard way that command-line-style MSBuild and inside-VS-style MSBuild do not mix (they have made some odd compromises to ensure interoperability with non-MSBuild project systems, of which the whole AssignProjectConfiguration-with-VS-provided-solution-config-XML process is one).
I encountered something similar in VS2012. For me, it was related to the ShouldUnsetParentConfigurationAndPlatform property of the AssignProjectConfiguration target being set to true during the build. This resulted in "GlobalPropertiesToRemove = Configuration;Platform" which caused the Configuration and Platform properties to be cleared for the project reference.
I was able to see this occurring by looking in the Build output window after setting Tools -> Options -> Projects and Solutions -> Build and Run -> MSBuild project build output verbosity -> Diagnostic.
With a blank Configuration/Platform, this caused the following line in some of my projects to match, resulting in Debug assemblies in the project output even in a Release build:
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
The solution was to modify those csproj files to specify Release as the configuration to use when the Configuration variable was empty/blank:
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>