Switch between Debug and Release Library in cmake programmatically for vcpkg installed libraries - cmake

I have successfully compiled my C++ program but I am a getting linker error
(default)\Catch2.lib(catch_stringref.cpp.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
After reading the post I realized this is due to improper library selection by library (using release mode library while my application is in debug mode) hence I printed the path to catch2 library
CMake Code
find_library(CATCH2_LIBRARY catch2)
message ("CATCH2_LIBRARY : ${CATCH2_LIBRARY}")
target_link_libraries(${PROJECT_NAME} ${CATCH2_LIBRARY})
returned
CATCH2_LIBRARY : D:/vcpkg/installed/x64-windows/lib/Catch2.lib
instead of
D:/vcpkg/installed/x64-windows/debug/lib/Catch2d.lib
I wish to know how can I make the cmake look into the debug directory (for libraries) when I am building in debug mode and vice versa.
Kindly note in Debug Mode the library is Catch2d.lib and in release mode it is Catch2.lib.
Library Paths
Release Library Path : D:\vcpkg\installed\x64-windows\lib\Catch2.lib
Debug Library Path : D:\vcpkg\installed\x64-windows\debug\lib\Catch2d.lib
This is continuation of my first cmake usage saga carried forward from here

What you are most likely interested in, is something that's called a generator expression. This allows you to define specific flags/names/suffixes/prefixes etc. based on the specified configuration.
They usually look something like this:
target_link_libraries(foobar PRIVATE Catch2$<$<CONFIG:Debug>:d>)
When running cmake with the Debug configuration it will add a d at the end of Catch2

Related

Dependencies between Android native modules (prefab) fail to build

Our Android application consists of 40-some Android Library Modules (ALMs), each of which also builds a C++ shared library with externalNativeBuild and CMake. So far we had the dependencies between these libs set up like this:
The dependent ALM references the dependency ALM with api project(':lib')
The dependent CMake script references the dependency .so with add_library(SHARED IMPORTED lib) and set_target_properties(lib PROPERTIES IMPORTED_LOCATION ...) and a relative path.
Recently we had to upgrade to the latest Android API version. This started off a cascade because now we were getting deprecated warnings in code generated by the navigation-ktx library, but upgrading that requires upgrading Gradle and the Android Gradle plugin. After that I started getting errors like liblib.so, needed by 'project', missing and no known rule to make it.
It looks like the latest Gradle parallelizes build tasks more heavily, and this means the dependent CMake/Ninja builds are being started concurrently with their dependencies, resulting in this error because the dependency is not yet built. I figured out that what we were doing was not entirely supported, but there is a "supported" way to do that now, so I refactored our entire build to use Prefab.
Now I started getting other errors, alternating between:
1.
C++ build system [prefab] failed while executing ...
Usage: prefab [OPTIONS] PACKAGE_PATH...
Error: Invalid value for "PACKAGE_PATH": Directory ... is not readable.
ld: error: undefined symbol ...
I looked into build/intermediates and found that in the 2nd case, the cmake config script was generated incorrectly: instead of add_library(lib::lib SHARED IMPORTED ) it had add_library(lib::lib INTERFACE IMPORTED) like it it was a header only library, and there was no IMPORTED_LOCATION set in the file.
What am I doing wrong and what should I do to unbreak our build?
It looks like the toolchain support for prefab interdependencies within a project is not quite finished. Others are reporting the same kind of errors at https://issuetracker.google.com/issues/265544858:
This appears to be a race condition with generating prefab cmake files.
It says in https://issuetracker.google.com/issues/221231432 that the header-only cmake config is generated to satisfy Android Studio's IDE features (completion, etc.) before the library is actually built.
Treat as-yet-unconfigured modules as if they are Header-only libraries for Android Studio purposes. This works because Android Studio doesn't care about linker flags for the purposes of providing language services.

librsvg - cmake module debug mode appends a suffix

I'm trying to get a native Windows build working in which we depend on librsvg-2. It's correctly installed through vcpkg. We usually build with cmake and have made a custom module to find this library. This works great in the unix world, but not within Windows and targeting either a Debug build or a Release build (from visual studio). This is due to the fact the actual lib file gets suffixed with a d on Windows.
This is our FindLibRSVG.cmake
include(LibFindMacros)
libfind_package(LibRSVG Cairo)
libfind_package(LibRSVG GDK-PixBuf)
libfind_pkg_detect(LibRSVG librsvg-2.0
FIND_PATH librsvg/rsvg.h PATH_SUFFIXES librsvg-2 librsvg-2.0
FIND_LIBRARY rsvg-2
)
libfind_process(LibRSVG)
To get the build working on Windows i have to specify a flag to our cmake command like this:
cmake .. -DLibRSVG_LIBRARY=./vcpkg_installed/x64-windows/debug/lib/rsvg-2.40d.lib
Do note the d at the end of the library.
I know there is a cmake module SelectLibraryConfigurations available but i'm not quite sure how to use this properly.
What i'd like to achieve is to be able to build in debug mode without having to provide this flag.
Note: The LibFindMacros implementation can be found here

How to create debug and release versions of libraries

I'm releasing a library which will be able to install headers and .a libraries for reuse. I would like users to be able to link either to release or debug builds of the lib if they so desire. I know that I can use DEBUG_POSTFIX like in Create a directory based on Release/Debug build type in CMake. My question is how do the users differentiate between the two? They would still put target_link_libraries(mylib), so I don't understand how a debug build would be chosen.
If MyLibTargets.cmake is correctly made they don't specify between the two. MyLibTargets.cmake should properly set IMPORTED_CONFIGURATIONS and IMPORTED_LOCATION_<CONFIG> for the target mylib. Then Debug maps to the Debug location and Release maps to the Release location. This is done automatically using the export command for multi-configuration generator. It's not really any different how a multi-configuration generator chooses Debug / Release libraries for any regular library target.

Mark CMake package as required by some targets, not others

I have a CMake file that contains a target that depend on a package, namely Java, as well a target that dose not require Java.
I would like to be able to build the not-requiring-java target w/o requiring java.
add_executable(nojava_targ "")
add_executable(java_targ "")
The trouble is once CMake sees the requiring-java-project on a machine w/o Java, CMake errors out, refusing to build the Makefile. This prevents the not-requiring-java target from building even though it doesn't need java.
find_package(JNI COMPONENTS Development)
target_include_directories( java_targ PRIVATE
${JTARG_INCLUDES}
${JNI_INCLUDE_DIRS})
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
/mnt/src/prjx/JAVA_INCLUDE_PATH
used as include directory in directory /mnt/src/prjx/
Is there some way to signal to CMake that this package is required, but only by some targets?
find_package will set JNI_FOUND to true if it finds the package, so add any Java-target
commands only if JNI_Found is true. Something like this:
find_package(JNI COMPONENTS Development)
if(JNI_FOUND)
add_executable(java_targ java_targ.cpp)
target_include_directories(java_targ PRIVATE
${JTARG_INCLUDES}
${JNI_INCLUDE_DIRS})
endif()

VS10 always links to SUBSYSTEM:WINDOWS; CMake+SDL+GLEW

I'm just trying to set up a simple project that shall be able to compile on every platform, that is supported by CMake. I started my project on a Win7-system and wrote a little main.cpp that includes SDL.h and GL/glew.h. The style of the main-function is simple c++:
int main(int, char**) {}
In my CMakeLists.txt I call find_package(SDL) and find_package(GLEW). The CMake-part works well, so I just opened the vs10-solution-file and tried to compile when I get the LNK2019:
error LNK2019: unresolved external symbol main referenced in function __tmainCRTStartup
This would mean that I chose the wrong subsystem, doesn't it? But if I simply toggle the subsystem from CONSOLE to WINDOWS and back the problem still exists. Has CMake set a hidden option for that? How can I compile my simple program in vs10?
I had this problem tonight. I'm using CMake to create an MSVC project to build my GLFW app. Of course, the age-old trick for getting rid of the console window if you're using MSVC by itself is to go in to the properties and set "Subsystem" to "Windows" and "Entry Point" to mainCRTStartup, which corresponds to adding the /SUBSYSTEM:WINDOWS /ENTRY:"mainCRTStartup" flags to link.exe, but CMake doesn't provide an easy way to do that.
If you just do a straight-up add_executable() command, you'll get /SUBSYSTEM:CONSOLE /ENTRY:"mainCRTStartup" being passed to the linker.
If you do an add_executable(exename WIN32 ...), you'll get /SUBSYSTEM:WINDOWS.
Gaah! Either option gets us halfway there!
I poked through the .cmake files that CMake ships with (fwiw, I'm using CMake 2.8.10 and Visual Studio 2012 Express), and discovered that the variable that seems to control the /SUBSYSTEM and /ENTRY flags is called CMAKE_CREATE_WIN32_EXE. So to set both parts, we just have to change that variable. Here's what I ended up with, which did the trick:
if(MSVC)
set(CMAKE_CREATE_WIN32_EXE "/SUBSYSTEM:WINDOWS /ENTRY:\"mainCRTStartup\"")
endif(MSVC)
Hope that helps someone else.