Use a single Visual Studio solution to build both

2019-01-21 03:59发布

问题:

I've got an x86 Visual Studio solution with many project files in it. Some of the DLLs are designed to work as plug-ins to other applications on a user's system. We're expanding some of the DLLs to be able to support 64-bit applications. What I'd like to do is setup the solution/projects so that just hitting "Build" will build both the x86 and x64 versions of those DLLs. 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 DLLs generated.

Here's a couple of the modifications that I've tried to a test project, but 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 to the path specified in the original project. There's no 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.

回答1:

We do something similar to build core assemblies for .NET CF. Try this:

<Target Name="AfterBuild">
    <MSBuild Condition=" '$(Platform)' == 'x86' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
</Target>


回答2:

Importing project is 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 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.



回答3:

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 dlls so they can debug with them, and that you have a separate build process if you're actually deploying the dlls?



回答4:

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.



回答5:

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



回答6:

Perhaps I've missed the point of this discussion. Using Visual Studio, go to the Build/Configuration Manager. In the Active Solution Platform drop down, select "new...", a New Solution Platform dialog appears. Select x64 and accept the default Copy From. Close the Dialog and the Configuration Manager. Now open the Build/Batch Build. Check those configurations you want to build and build them. You will find the x64 build executables separate from the Win32 execs. You can verify that these are what was intended by right clicking on the execs and selecting Properties, select the Compatibility tab. In the dropdown window you can check to see what operating systems the exec 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.



回答7:

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"


回答8:

I ran into this problem with a project running in VS2008 XP (32-bit) and also VS2010 7 (64-bit). The solution I used was to use the $(PROGRAMFILES) variable. It resolved correctly on both machines.