I am attempting to build for Windows XP using VS 2015 on Windows 10. Several parts of the code require us to link against Microsofts psapi.lib in this “cross compilation” case. I have attempted to
set (CMAKE_C_STANDARD_LIBRARIES “${CMAKE_C_STANDARD_LIBRARIES} psapi.lib”)
in a toolchain file but this does not work. Using
set (CMAKE_C_STANDARD_LIBRARIES_INIT “${CMAKE_C_STANDARD_LIBRARIES_INIT} psapi.lib”)
The best solution for your use case IMO is to just use target_link_libraries to explicitly link psapi.lib to whatever target contains the code needing it. Another alternative is the link_libraries command.
We are trying to keep platform specific aspects out of the code and out of the build specifications, e.g. cmake files as much as possible. To a large degree cmake supports this approach for us. Thanks to the cmake team for this.
Phrasing a dependency to a library that is only required on windows when “cross compiling” from Windows 10 to Windows XP in inner parts of the build specification did not exite me, so I looked for alternatives. The toolchain file seemed like a good idea for this purpose. Why I did not use link_libraries? It did not even occur to me that this would be allowed in a toolchain file. Also I found a reference to CMAKE_C_STANDARD_LIBRARIES and thought that it was intended for such a purpose.
link_libraries shouldn’t be called from a toolchain file. It might work, but it isn’t really meant for that. My suggestion was assuming you’d modify the project code.
You should be able to set CMAKE_C_STANDARD_LIBRARIES as a cache entry in the toolchain file with the complete list of libraries needed for that platform, including all the ones CMake normally adds by default.
One way that you can do this is to create your own add_library(project_settings INTERFACE) target that all of your targets link to. You can add psapi.lib here as well as any flags you’d like all targets to use as well.
What I did was to add psapi.dll to the existing content of CMAKE_C_STANDARD_LIBRARIES (see code in first post). This did not work. I also used CMAKE_C_STANDARD_LIBRARIES_INIT in this fashion without success. I think what happens is:
both the variables are empty during processing of the toolchain file.
the contents of the variables are overwritten by some part of cmake later. Maybe the code in ./share/cmake-3.17/Modules/Platform/Windows-MSVC.cmake is the “culprit”.
In my toolchain file I also use statements such as
set (CMAKE_C_FLAGS_INIT “${CMAKE_C_FLAGS_INIT} /D_USING_V110_SDK71_”)
Being able to set CMAKE_C_FLAGS_INIT in a toolchain file such that CMake’s builtin modules only append to it was added by commit a66004bee0 in CMake 3.7. A similar change could be made for CMAKE_C_STANDARD_LIBRARIES.
set (CMAKE_EXE_LINKER_FLAGS_INIT “${CMAKE_EXE_LINKER_FLAGS_INIT} psapi.lib”)
set (CMAKE_SHARED_LINKER_FLAGS_INIT “${CMAKE_SHARED_LINKER_FLAGS_INIT} psapi.lib”)
I do not really like either solution. On the other hand I do not like to compile for 32 Bit XP in 2020 either!
Sure. For reference, being able to set CMAKE_EXE_LINKER_FLAGS_INIT and friends in a toolchain file was added by commit 8a98cf6432 in CMake 3.7. I suggest using