3

I have a C# project with two platforms: x86 and x64. This C# project depends on a native dll that must also be built as x86 or x64.

So far, I have successfully added cmake as a pre-build event to the .csproj of the C# project:

<Target Name="BeforeBuild">
    <Message Text="Building native library" />
    <Exec Command="cmake -DINSTALL_DIR=../bin/$(Platform)/$(Configuration) ../src/native" />
    <Exec Command="cmake --build . --target install" />
</Target>

This builds and copies the native dll to the output directory of the project, matching the selected configuration (e.g. bin/x86/Debug or bin/x64/Release).

If I use the x86 configuration in Visual Studio, then everything is fine. However, if I use the x64 configuration I get a failure, because the native library is still built as x86. In other words, I need to find a way to inform cmake to build a x64 binary when $(Platform) is 'x64'.

Is there a commandline switch to instruct cmake to built a x64 binary? I tried the -G and -T options, but they don't appear to support this (or I wasn't able to find the correct way to use them).

Ideas welcome!

Edit: I've managed to get a little bit closer by passing the $(VisualStudioVersion) property to cmake.

<PropertyGroup>
    <CMakeGenerator Condition="'$(OS)' == 'Windows_NT' and '$(Platform)' == 'x86'">-G"Visual Studio $(VisualStudioVersion)"</CMakeGenerator>
    <CMakeGenerator Condition="'$(OS)' == 'Windows_NT' and '$(Platform)' == 'AnyCPU'">-G"Visual Studio $(VisualStudioVersion) Win64"</CMakeGenerator>
    <CMakeGenerator Condition="'$(OS)' != 'Windows_NT'"></CMakeGenerator>
</PropertyGroup>
<Target Name="BeforeBuild">
    <Message Text="Building native library" />
    <Exec Command="cmake $(CMakeGenerator) -DINSTALL_DIR=../bin/$(Platform)/$(Configuration) ../src/native" />
    <Exec Command="cmake --build . --target install" />
</Target>

Unfortunately, $(VisualStudioVersion) returns a decimal number (e.g. 12.0 for VS2013), whereas cmake expects an integer (e.g. 12 for VS2013). If I can convert $(VisualStudioVersion) to an integer, then this should work! Can this be done?

Edit 2: solved!

MSBuild 4.0/4.5 adds property functions that can be used to modify properties. In this case, the following works perfectly:

<PropertyGroup>
    <CMakeVSVersion>$(VisualStudioVersion.Substring(0, $(VisualStudioVersion).IndexOf(".")))</CMakeVSVersion>
    <CMakeGenerator Condition="'$(OS)' == 'Windows_NT' and '$(Platform)' == 'x86'">-G"Visual Studio $(CMakeVSVersion)"</CMakeGenerator>
    <CMakeGenerator Condition="'$(OS)' == 'Windows_NT' and '$(Platform)' == 'AnyCPU'">-G"Visual Studio $(CMakeVSVersion) Win64"</CMakeGenerator>
    <CMakeGenerator Condition="'$(OS)' != 'Windows_NT'"></CMakeGenerator>
</PropertyGroup>
<Target Name="BeforeBuild">
    <Message Text="Building native library" />
    <Exec Command="cmake $(CMakeGenerator) -DINSTALL_DIR=../bin/$(Platform)/$(Configuration) ../src/native" />
    <Exec Command="cmake --build . --target install" />
</Target>

Hopefully someone might find this useful in the future!

The Fiddler
  • 2,726
  • 22
  • 28

1 Answers1

3

Unfortunately, the Visual Studio generators require the Visual Studio version to be explicitly specified for x64 builds. However, you should be able to make this work with the NMake generator:

<Target Name="BeforeBuild">
    <Message Text="Build native library" />
    <Exec Command="cmake -G&quot;NMake Makefiles&quot; -DINSTALL_DIR=../bin/$(Platform)/$(Configuration) ../src/native" />
    <Exec Command="cmake --build . --target install" />
</Target>

The NMake generator expects to find everything set up correctly on the command line (including path to the appropriate platform compiler), but that's taken care of by the target platform selected in the driving VS.

I don't have a way of testing it right now, so the actual syntax for the project file might differ, but the idea should work.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • I just tried this and I am hitting the [compiler cl not found](http://stackoverflow.com/questions/20887849/cmake-nmake-makefiles-compiler-cl-not-found-but-vs-12-generator-succeeds) issue. It appears that the cmd instance spawned by Visual Studio does not have cl in its path, which means this will not work... – The Fiddler Mar 07 '14 at 13:22
  • @TheFiddler :-( I tried this with VS2008 (using `set > vars.txt` as a pre-build command) and `cl` definitely was in the `PATH` (but that was a C++ project). Perhaps you could use `cmd /c "path/to/vcvars.bat" & cmake ...` as the command, and use an appropriate VS macro (or env. var) in the `path/to` part? – Angew is no longer proud of SO Mar 07 '14 at 13:29
  • Thanks, tt could be that my msbuild script is a C# project, not a C++ one. I'm trying a slightly different approach now (check my edit), but if that doesn't work out I'll try working with vcvars.bat. – The Fiddler Mar 07 '14 at 13:35
  • I'm accepting this answer, since it is a valid solution (as long as nmake is in your path) and it pointed me towards the solution I am using right now (use -G"Visual Studio $(VisualStudioVersion)"). – The Fiddler Mar 09 '14 at 17:14