I'm building a multi-architecture installer for a C++ program with NSIS. I'm using Visual Studio 2010. All is well except I don't know how to make the installer depend on the build for all architectures.
I have created a project to run makensis as a build step, and configured it to depend on all other projects in the solution. I'm currently building for Win32 and X86_64 architectures. The NSIS project is only built as a part of X86_64 configuration. But it packs files built in both X86_64 and Win32 configurations. Here lies the problem. If I build Win32 and then immediately X86_64, all is well. If I start with X86_64, the build fails because it can't find Win32 files. Worse, if I change some source code and rebuild only X86_64, the installer project will happily pick up out-of-date Win32 files without any indication of a problem.
Can I force a Win32 build from an X86_64 build, or do anything else to make this work?
I'm a Unix type, Windows is an alien world to me.
Any
As for "foolproof" solutions, if I understand you correctly:
- You have solution containing multiple projects (lets say
Test.sln
),
- You want to build this solution for several platforms,
- ... and use the MakeNSIS tool (I have no idea what that is) to create an installer packaging binaries built for all the platforms.
Please correct me if I am wrong. So, to achieve this task:
- I would completely drop the project you introduced (the one running MakeNSIS),
- Then would create
Test.msbuild
file such as the one below,
- Notice the
<Exec>
element, that is the place where you want to run you MakeNSIS,
- Then simply run the msbuild as
msbuild Test.msbuild
,
- Using this solution you would have all the projects from
Test.sln
first built for Win32
, then for x64
, and MakeNSIS would only be run afterwards.
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build" DependsOnTargets="Build_Win32;Build_x64">
<!-- Run whatever command you like, such as MakeNSIS .. ? -->
<Exec Command="notepad.exe" />
</Target>
<Target Name ="Build_Win32">
<MSBuild Projects="Test.sln" Properties="Configuration=Release;Platform=Win32" />
</Target>
<Target Name ="Build_x64">
<MSBuild Projects="Test.sln" Properties="Configuration=Release;Platform=x64" />
</Target>
</Project>
Please provide clarification to your actual question if the above isn't what you asked for.
EDIT:
After clarifying your request in the comment, I would propose following solution. I like the above solution with Test.msbuild
more, but here you go:
- Add new project
BuildInstaller
into your solution,
- In Configuration Manager uncheck the checkbox "Build" for this new project for all combinations of Configuration/Platform,
- Still in Configuration Manager, create new configuration, lets say Installers,
- For this new configuration, uncheck the "Build" checkbox for all the projects from the solution, except for the
BuildInstaller
,
- Now open the
BuildInstaller.vcxproj
in text editor and append the following snippet right before the closing </Project>
tag:
<ItemGroup>
<ProjectsToBuild Include="..\**\*.vcxproj" Exclude="..\**\BuildInstaller.vcxproj"/>
</ItemGroup>
<Target Name="Build" DependsOnTargets="Build_Win32;Build_x64">
<!-- Run whatever command you like, such as MakeNSIS .. ? -->
<Exec Command="notepad.exe" />
</Target>
<Target Name="Build_Win32">
<MSBuild Projects="@(ProjectsToBuild)" Properties="Configuration=Release;Platform=Win32" />
</Target>
<Target Name="Build_x64">
<MSBuild Projects="@(ProjectsToBuild)" Properties="Configuration=Release;Platform=x64" />
</Target>
- This way you effectively override the default build target,
- So now:
- Everytime you build for Release/Debug configuration, installer won't be built, that is preferred from many reasons,
- Everytime you build for Installers configuration, your new BuildInstaller.vcxproj will take over, will build both win32 and x64 binaries and in the end will run the custom command line executable. Of course binaries will be built using Release configuration which should be desired.
Initially I thought I could drop the <ItemGroup>
element and use Projects="..\Test.sln"
instead of Projects="@(ProjectsToBuild)"
as there should be no circular dependency (BuildInstaller.vcxproj is not built for Release) but the build took forever so there had to be some problem, weird...
Does this satisfy your needs?
I think you need to build Win32 configuration first and then 64bit configuration.
The makensis project should be built after both are finished (successfully!).
For example it is possible to call it from Post Build event (for 64bit configuration) or as separate project.
I am not sure whether your makensis project is based on Visual & Installer (http://www.visual-installer.com - sorry for little self promo :) or it is pure (text - batch) project included in VS Solution.
In both cases the Configuration manager in VS allows you to define the build order. The makensis project should be always the last so it can find all dependencies from previous configurations.
Also it is good to use relative path in makensis project - something like ${TARGET_PATH}
which will be defined for each configuration with different value.