1

Summary

The following scenario is given:

  • A C++ application is built either via Visual Studio 15 (2017) directly, or by using a script which in turn calls cmake directly.
  • We ran into trouble with the linker which was curious, since cmake -G "Visual Studio 15 Win64" is specified
  • Further inspection of the CMakeCache.txt has shown that the 32Bit linker is still used first for some reason: CMAKE_LINKER:FILEPATH=D:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx86/x64/link.exe (note the Hostsx86 part. This is where a Hostsx64 should be)
  • Additionally there is an unrelated link.exe which is provided by a Git installation (OS is Win10). This executable is selected from path apparently, when the 32Bit VS link.exe fails
  • The build process is successful when building from Visual Studio

So essentially what is observed is:

Visual Studio seems to use the 32Bit linker during the compilation process, despite cmake -G "Visual Studio 15 Win64" being set when generating the project files. Then the 32Bit linker runs out of heap space and so the process reattempted with the usage of the 64Bit linker. However to find said linker the system path is checked and the link.exe supplied by the Git installation is found first. At this point this linker is supplied with the source directory and parameters, but as it is a different application the build process then fails.

So far there is only speculation on my end as to why Visual Studio is able to compile and link successfully. Current guess is that Visual Studio checks some default locations before checking path and so the correct 64Bit link.exe is found. This in turn allows the build and link process to finish successfully.

Attempted solutions

So I checked some ways to resolve this issue:

  • Checked the CMakeCache.txt, the used linker is set there and it is the 32Bit version: CMAKE_LINKER:FILEPATH=D:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx86/x64/link.exe. Changing this before attempting compilation and linkage works.
  • Checked the environment variables, then inserted the proper link.exe path (i.e. D:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx64/x64/link.exe) into the Path, so that it is found before the one supplied by the Git installation is found. This works.
  • Attempted to generate project files via CMake using cmake -G "Visual Studio 15" -A x64 $src -B "build64" -T host=x64. This does not work.

The problem with the solutions that work is, that they both require an explicit path to correct linker to be set in order to be able to compile via script. In addition the CMakeCache.txtis generated during the build procedure, so setting it half-way through means the build process as a whole could not be executed.

Question

Is it at all possible to to configure CMake prior to executing the build pipeline via cmake call, so that the 64Bit linker at the location D:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx86/x64/link.exe is used without explicitely setting this path somewhere (e.g. via CMake parameter during the cmake -G call)?

Otherwise our contributors have to apply individualized solutions and set these paths individually on their systems. I am trying to find a solution where our script, which calls cmake -G as well as the cmake-build call after that is already configured so that the 64Bit linker is used from the get go and the 32Bit linker is omitted.

Another related option is likely a CMake toolchain file: CMake: specifying build toolchain

However this still requires setting a path manually. The 32Bit linker is found automatically though, is there no way to set the 64Bit linker automatically without providing an explicit path?

Thank you in advance, any input is welcome.

Koenigsberg
  • 1,726
  • 1
  • 10
  • 22
  • 1
    Adding `-T host=x64` to the command line should select the linker from the x64 installation. – vre Aug 23 '21 at 11:22
  • This is one of the solutions attempted. The build failed. When I checked the log I saw the 32Bit linker path was still being selected. – Koenigsberg Aug 23 '21 at 11:23
  • 1
    Did you cleared the CMakeCache.txt file after trying the various options? I use `-T host=x64` by default and never saw such a behaviour. – vre Aug 23 '21 at 11:25
  • Yes. I just tested with a completely wiped build-folder, re-checked whether this parameter is set and made sure no `CMakeCache.txt` existed. Then reran the process using `cmake -G "Visual Studio 15" -A x64 $src -B "build64" -T host=x64`. The path in the newly generated `CMakeCache.txt` once again points to `Hostx86` rather than `Hostx64`. I am at a loss. – Koenigsberg Aug 23 '21 at 11:29
  • 1
    What CMake version are you using? I use the cmake command line as follows `cmake -B build64 -S -G "Visual Studio 15 2017" -A x64 -T host=x64` in that order with CMake 3.21.1 successfully. BTW what is `$src` supposed to be replaced with? – vre Aug 23 '21 at 11:35
  • CMake version is `3.15.3`. `$src` is a placeholder for the project folder. Subfolder of this project folder are among others the `src` source folder and the `build` build folder. The `CMakeLists.txt` is located in `$src`. It is also noteworthy that this pipeline was working previously. It is only with recent changes that it started breaking - the simple reason being that heap issues were not encountered before. However solving the excessive heap usage is sadly a different story as it will require much more time. – Koenigsberg Aug 23 '21 at 11:40
  • I don't remember if options after the source dir are not properly recognized or the sourcedir needs to be the last element on the command line but can you try replacing `$src` with `-S $src`? – vre Aug 23 '21 at 11:44
  • They seem to be properly recognized. I ran the `cmake -G` call now outside of the scripts and when done this way, then the proper linker path is set. My current suspicion is, that our pipeline has a second `cmake -G` in one of the sub-scripts it calls which then overrides the files generated with the proper `cmake -G` call. – Koenigsberg Aug 23 '21 at 11:50
  • 1
    Either way, I think you are a 100% right with your assumption of `-T host=x64` to be the required solution. The reason it doesn't work when I set these parameters seems to be due to some intricacies with our pipeline rather than the general principle. I am working now to verify that. Will update when done. – Koenigsberg Aug 23 '21 at 11:51
  • 1
    @vre I was able to confirm these suspicions. There was a "shadow"-pipeline active in this build process. Essentially a second call in a sub-script was overriding the correct files and this resulted in false generated project data. It works now with the `-T` parameter as desired. Thank you for your support! – Koenigsberg Aug 23 '21 at 14:36

0 Answers0