I am using the CMAKE_MSVC_RUNTIME_LIBRARY option so that MSVC uses /MTd
to statically link an executable.
CMakeLists.txt
cmake_minimum_required (VERSION 3.15 FATAL_ERROR)
cmake_policy(SET CMP0091 NEW)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
project ("cmaketoy")
find_package(GDAL REQUIRED)
add_executable (cmaketoy "cmaketoy.cpp" )
target_include_directories(cmaketoy PUBLIC ${GDAL_INCLUDE_DIR})
target_link_libraries(cmaketoy PRIVATE ${GDAL_LIBRARY})
cmaketoy.cpp
#include <iostream>
#include "gdal_priv.h"
int main() {
std::cout << "Hello CMake.\n";
GDALAllRegister();
return 0;
}
CMakeSettings.json (Visual Studio specific configuration)
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"environments": [
{ "GDAL_ROOT": "C:\\OSGeo4W64" }
]
}
]
}
Compiler output confirms that the MTd
option is being used:
[1/2] "C:\PROGRA~2\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\bin\HostX64\x64\cl.exe"
/nologo /TP -IC:\OSGeo4W64\include /DWIN32 /D_WINDOWS /GR /EHsc /Zi /Ob0 /Od /RTC1 -MTd
/showIncludes /FoCMakeFiles\cmaketoy.dir\cmaketoy.cpp.obj /FdCMakeFiles\cmaketoy.dir\ /FS -c ..\..\..\cmaketoy.cpp
[2/2] cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe"
-E vs_link_exe --intdir=CMakeFiles\cmaketoy.dir --rc="C:\PROGRA~2\Windows Kits\10\bin\10.0.18362.0\x64\rc.exe"
--mt="C:\PROGRA~2\Windows Kits\10\bin\10.0.18362.0\x64\mt.exe" --manifests -- "C:\PROGRA~2\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\bin\Hostx64\x64\link.exe"
/nologo CMakeFiles\cmaketoy.dir\cmaketoy.cpp.obj /out:cmaketoy.exe /implib:cmaketoy.lib /pdb:cmaketoy.pdb
/version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console
C:\OSGeo4W64\lib\gdal_i.lib kernel32.lib user32.lib gdi32.lib winspool.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
But when I run the exe, it tries to locate gdal300.dll
, which is not on the PATH
, and fails with
The program '[19452] cmaketoy.exe' has exited with code -1073741515 (0xc0000135) 'A dependent dll was not found'.
What modifications are needed to create a standalone, statically linked executable?
Update
Digging some more, this issue is not specific to CMake, but rather relates to the way the GDAL library is built in OS4GeoW. I get the same problem using a normal Visual Studio solution without CMake.
I had assumed I could statically link to gdal_i.lib
to create a standalone executable, but dumpbin /symbols gdal_i.lib
is just a stub library that accompanies gdal300.dll
(see here)
001 00000000 SECT2 notype External | __IMPORT_DESCRIPTOR_gdal300
See also this answer about the two types of .lib
file.