How to target both Win32 and x64 platforms with ONLY one set of solution/project files? - visual-studio-2010

I'm trying to migrate a multiple-project from VC++2005 to VC++2010, and I also need to port this application from Win32 to x64 platform.
I know that a project file could contain settings for both platforms, but it requires that I have to manully change the platfrom setting for each project say if I want to build for x64.
What I want to do is to have ONLY one set of solution/project files that could target both of these platforms, and with some kind of simple switch I can choose what platform I am building now.
Is there such a way? Or do I have to maintain two sets of solution/projects files, one for each platform, so that if I want to build for x64, I can only open the solution file for x64, and if I want to build for Win32, I have to open the solution file for Win32?

You can use the "Configuration Manager" in Visual Studio 2010 to make multiple configurations for your solution and project files.
In the menu bar of VS 2010, go to "Build" --> "Configuration Manager..."

Let's say you've the platform property which duplicates in each project file:
<Platform>x86</Platform>
You can extract this property from ALL project file in a single CommonProperties.properties file:
<?xml version="1.0" encoding="utf-8" ?>
<Project
ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Default">
<PropertyGroup>
<Platform>x86</Platform>
</PropertyGroup>
</Project>
And then just import it in ALL project files:
<Import Project="CommonProperties.properties" />
EDIT: Multiple platform support
<Platform Condition="'$(Platform)' == 'Win32'">x86</Platform>
<Platform Condition="'$(Platform)' == 'x64'">x64</Platform>
Useful links:
Property Element
MSBuild Conditional Constructs

Related

How do I use a specific version of the F# compiler in MSBuild projects?

I have some F# project files generated using visual studio.
On my computer, which has several F# versions installed, it seems to pick the latest one.
However, I want to use a specific F# compiler - the one installed using version 3.1.2.
How do I do so?
I'm using a similar setup, just that I'm consuming the F# compiler from its nuget package - this works nicer in shared build environments.
You will need a .props file to be included in all of your F# projects, I've called it fsharp_project.props. By changing that props file, you can update the compiler version for all of your F# projects. Its contents should be as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PackageRoot>C:\packages\Fsharp.Compiler.Tools.Nuget</PackageRoot>
<FscToolPath>$(PackageRoot)\tools</FscToolPath>
<FSharpVersion>v3.0</FSharpVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core">
<HintPath>$(PackageRoot)\tools\fsharp.core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
You need to adjust the path to your local version of the F# compiler, and also to the core libraries that you wish to use.
Then, modify your .fsproj file to consume that file as follows:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="C:\whereever\fsharp_project.props"/>
...
Further down in your .fsproj file you will see a reference of FSharp.Core.dll. Remove that - in the props file, there is already a reference to the version of the core libraries that come with the compiler.
Re-load your project and re-build, it will print out the full path of the fsc.exe that it is using.
As a side note: The same trick with .props files is also incredibly helpful for referencing the right version of FSharp.Core.dll in C# consumers of your F# code - that's a frequent source of runtime errors. Include a props file that only references FSharp.Core.dll in each .csproj, and you will be able to switch all C# projects to a new version of the core libraries by just updating the `.props' file.

Is there a way to global set the platform toolset to v110 on VS 2013?

I've been perusing through similar questions on stack overflow and could not find a specific or definitive enough answer to this question:
I am currently using MSVS 2013 Ultimate, and have separately downloaded MS build tools 2013 as well. I am trying to install some npm modules that use the earlier platform toolset of MSBuild to compile and after following instructions from MSDN on how to Modify the Target Framework to a different platform, those did not help me successfully download the packages either. My current project is dealing with javascript and I'm not using visual studio in the near future, so I'm extremely flexible in terms of changing its configuration settings at the moment.
I am afraid that I'll have to resort to downloading VS 2012 in order to do this, unless someone found a clear cut alternative.
I am currently running everything on Windows 8 Enterprise x64.
Thanks in advance for all the help.
You can make use of the ImportBefore extension points for MsBuild: add propertysheets to
$(VCTargetsPath)\Platforms\$(Platform)\ImportBefore
and add properties to them forcing the PlatformToolset irregardless of what is set in the vcproj files. With VS2013 it is a bit more difficult to do this compared to VS2012 (I used this trick there to globally build everything using the v110_xp toolset) but it still works.
Suppose you are on a 64bit machine and want to override settings for all C++ projects for the Win32 platform, add a property sheet called override_platformtoolset.props (the name doesn't matter, as long as it ends with .props) to the directory C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\ImportBefore\Default with this content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PlatformToolSet>v110</PlatformToolSet>
<DefaultPlatformToolset>v110</DefaultPlatformToolset>
</PropertyGroup>
<Target Name="ShowOverrideInfo1" BeforeTargets="Build">
<Message Text="Overriding PlatformToolset!" Importance="high"/>
</Target>
</Project>
Then add another file called override_platformtoolset to C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\ImportBefore with this content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PlatformToolSet>v110</PlatformToolSet>
<ToolsetPropsFound>false</ToolsetPropsFound>
<MinSupportedVCTargetsVersion>v110</MinSupportedVCTargetsVersion>
</PropertyGroup>
<Target Name="ShowOverrideInfo2" BeforeTargets="Build">
<Message Text="Overriding PlatformToolset!" Importance="high"/>
</Target>
</Project>
The targets are just there to make sure you put the files in the correct location: if you build now, you should see the Overriding PlatformToolset! message twice (and see that cl.exe and link.exe are invoked from C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin). Else something is wrong.
If you wonder how/why this works inspect Microsoft.Cpp.Defaults.props and Microsoft.Cpp.props.props in C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120.

ExcludeFilesFromDeployment not working in Visual Studio 2013 Publish Web

I have a fairly straightforward MVC 5 project in Visual Studio 2013. I have successfully set up publishing via Web Deploy to the server. I want to exclude a certain file from deployment without having to preview/uncheck it every time I publish (I am publishing the Release build).
I have edited the .csproj file for the project to include the <ExcludeFilesFromDeployment> tag.
<Project...>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
<ExcludeFilesFromDeployment>Library-that-is-not-good-for-server.dll</ExcludeFilesFromDeployment>
</PropertyGroup>
But nothing changes/the file still needs to be unchecked for addition when I go to publish in VS2013.
I have also tried adding a bin\ in front of the library, just in case. Not to mention, a warning pops up for the element that says "The element 'PropertyGroup' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003' has invalid child element 'ExcludeFilesFromDeployment' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003'. ..."
Microsoft's documentation that I was able to find in searches regarding excluding files from deployment, and the ExcludeFilesFromDeployment tag, http://msdn.microsoft.com/en-us/library/ee942158(v=vs.110).aspx, claim that the instructions only apply to VS2012 and partially to VS2010. Does anyone know what has changed for VS2013 or what I am doing wrong?
You need to add it in the profileName.pubxml file.
profileName.pubxml file position is:
my project ----> Properties ----> PublishProfiles ---> profileName.pubxml
Example:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ExcludeFilesFromDeployment>
Library-that-is-not-good-for-server.dll
</ExcludeFilesFromDeployment>
''' ''''
You probably need to have the following definition also in the 'profileName'.pubxml file:
<DeleteExistingFiles>False</DeleteExistingFiles>
Please remove all files from your Temp publish location(normally obj\Release\Package\PackageTmp) after excluding some files or directories.

Run other than the DefaultTarget for a project configuration under Visual Studio 2010

I've a MSBuild target in my csproj to copy files and folders of my web application to a target path after build.
<Target Name="PublishToFileSystem" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
...
If I call MSBuild via command line with the target "PublishToFileSystem" everything works fine.
But now I want to "use" this target also for a special configuration in Visual Studio (like Release, Debug, ...).
How can I assign a configuration to another target than the DefaultTarget "Build" set in the project with DefaultTargets:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
Thanks, Konrad
Try to use AfterBuild target instead of PublishToFileSystem:
<Target Name="AfterBuild" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
or check Overriding Predefined Targets on MSDN
If you want to do this for a specific solution configuration and you're suffering from ciruclar dependencies as I was, the easiest thing I could come up with is writing your own Target to use as default target. That target starts other targets based on a condition on the configuration.
<Target Name="CustomBuild">
<CallTarget Targets="SignAndroidPackage" Condition="'$(Configuration)' == 'UITest'"/>
<CallTarget Targets="Build" Condition="'$(Configuration)' != 'UITest'"/>
</Target>
And then simply change the Default target at the top of the project definition to that CustomBuild target.
<Project DefaultTargets="CustomBuild" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
Here's an approach that might suit your need: run a custom msbuild target from VisualStudio
(this is trick #78 in the book MSBuild Trickery)

How can I use a single Visual Studio solution to build both x86 and x64 at the same time?

I've got an x86 Visual Studio solution with many project files in it. Some of the DLL files are designed to work as plug-ins to other applications on a user's system.
We're expanding some of the DLL files to be able to support 64-bit applications. I'd like to set up the solution/projects so that just hitting "Build" will build both the x86 and x64 versions of those DLL
files. The solution contains both C++ and C# projects.
I realize that "Batch Build" is capable of building both, though it would be more convenient if developers could just click the same button as they have previously and have all of the output DLL files generated.
Here are a couple of the modifications that I've tried to a test project, but that I haven't gotten to work:
I've tried modifying the <Target Name="AfterBuild"> to try:
<Target Name="AfterBuild" Condition=" '$(Platform)' == 'x86' ">
<PropertyGroup>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
But that results in the following error:
C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets(565,5): error MSB4006: There is a circular dependency in the target dependency graph involving target "Build".
I think my conditions will prevent infinite recursion, but I understand how MSBuild could not see it that way.
I've also tried:
<Project DefaultTargets="MyBuild86;MyBuild64" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
...
<Target Name="MyBuild86">
<PropertyGroup>
<Platform>x86</Platform>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
<Target Name="MyBuild64">
<PropertyGroup>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<CallTarget Targets="Build"/>
</Target>
But my DefaultTargets appears to be ignored from within the Visual Studio IDE.
Last, I've tried creating a separate project that imports the first project:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<OutputPath>..\$(Configuration)\x64\</OutputPath>
<ProjectGuid>{A885CAC3-2BBE-4808-B470-5B8D482CFF0A}</ProjectGuid>
</PropertyGroup>
<Import Project="BuildTest.csproj" />
</Project>
And this so far has shown the most promise. However, Visual Studio seems to ignore my OutputPath setting from this new project and instead outputs the EXE/DLL file to the path specified in the original project. There isn't any PropertyGroup block that I can see that is being executed in the original project to override this, so I'm not sure what's happening.
We do something similar to build core assemblies for .NET Compact Framework.
Try this:
<Target Name="AfterBuild">
<MSBuild Condition=" '$(Platform)' == 'x86' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
</Target>
Importing a project in such manner works for me in Visual Studio 2010:
TestProject64.vcxproj
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="TestProject.vcxproj" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B7D61F1C-B413-4768-8BDB-31FD464AD053}</ProjectGuid>
</PropertyGroup>
</Project>
TestProject64.vcxproj.filters
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="TestProject.vcxproj.filters" />
</Project>
TestProject.vcxproj has two configurations defined inside: Release|x86 and Release|x64. As you can see, TestProject64.vcxproj has only the Release|x64 configuration. Defining of at least one configuration in TestProject64.vcxproj is necessary, otherwise Visual Studio will not be able to add TestProject64.vcxproj to a solution.
Now it's possible to include both TestProject.vcxproj and TestProject64.vcxproj to the same solution and build Release|x86 and Release|x64 at the same time.
I think the best way of doing this is to invoke MSBuild from the command line. It shouldn't need editing of MSBuild files. Just run
msbuild myproj.sln /p:Configuration="Debug|Win32"
msbuild myproj.sln /p:Configuration="Debug|x64"
I assume that if a developer is using Visual Studio then they'll only be generating the DLL files so they can debug with them, and that you have a separate build process if you're actually deploying the DLL files.
For C++, and if it's a project whose files/settings don't change often, one way to do it is create two projects within the solution, with both projects referring to the same source files. Then, in x64 builds, set one project to build 64-bit and the other 32-bit. (In x86 builds, set one as 32-bit and turn off the other.)
We've been using this for a while and it works fine.
Of course, you have to be careful that any changes you make to one are also made to its copy. i.e. if you add/remove a file or change its build setting, you have to do it in two places. Source-code changes still only need to be done once, because there's still only one copy of each source file.
And, of course, you may decide that doing this is more complex/risky than switching away from using the IDE. In our case it's worked really well, though.
You are not going to be able to do this with the UI of Visual Studio. For this you will need to hack the MSBuild files.
Try this link from MSDN for MSBuild Overview
I would suggest to create a dummy C++ Makefile project and then invoke MSBuild twice from it:
msbuild myproj.sln /p:Configuration="Debug|Win32"
msbuild myproj.sln /p:Configuration="Debug|x64"
Perhaps I've missed the point of this discussion.
Using Visual Studio, go to menu Build → Configuration Manager. In the Active Solution Platform drop down, select "New...", and a New Solution Platform dialog appears. Select x64 and accept the default Copy From. Close the dialog and the Configuration Manager.
Now open menu Build → Batch Build. Check those configurations you want to build and build them. You will find the x64 build executables separate from the Win32 executable files.
You can verify that these are what was intended by right clicking on the executable files, selecting Properties, and select the Compatibility tab. In the dropdown window you can check to see what operating systems the executable file can be run in.
Obviously, there may be some other tweaking you might have to do to get all the output files in their proper places, but this method seem somewhat simpler than fooling with build than those described above.
I ran into this problem with a project running in Visual Studio 2008 (on Windows XP) (32-bit) and also Visual Studio 2010 (on Windows 7) (64-bit).
The solution I used was to use the $(PROGRAMFILES) variable. It resolved correctly on both machines.

Resources