qmake to Cmake transition: syntax for external librairies - cmake

For a specific project I am moving out of qmake and now have to use cmake.
My path are the following:
Source : ~/Projects/Project
External static library (OSVR in this instance) paths : ~/osvr/lib/ , ~/osvr/include/osvr /osvr/include/jsoncpp
Using qmake, the linking part to that library used to be:
INCLUDEPATH += /usr/include
LIBS += -L$$PWD/../../osvr/lib/ -losvrClientKit -losvrClient -losvrCommon -losvrUtil -ljsoncpp
INCLUDEPATH += $$PWD/../../osvr/include/
INCLUDEPATH += $$PWD/../../jsoncpp/include/
DEPENDPATH += $$PWD/../../osvr/lib/
Now I need to use cmake, but the library is not linked to:
The relevant part of my cmake.txt:
set(OSVR_DIR /home/pilou/osvr)
set(OSVR_INCLUDE_DIR /home/pilou/osvr/include/osvr/ClientKit)
find_library(OSVR_LIBRARIES ${OSVR_DIR}/lib)
[...]
target_link_libraries(myexec ${QT_LIBRARIES} ${OSVR_LIBRARIES} )
target_include_directories(myexec PUBLIC include ${OSVR_DIR}/include )
Which doesn't work...
A little help would be lovely as I am not too sure about how:
to ensure the external include folder is scanned
to link to my 3 libraries osvrClientKit osvrClient osvrCommon.
As a matter of fact I am also interested in a good explanation.
Thanks in advance.
EDIT : Thanks to the reply from ComicSansMs and for the posterity, the working Cmake syntax :
set(OSVR_DIR /home/pilou/osvr)
set(OSVR_INCLUDE_DIR /home/pilou/osvr/include)
find_library(OSVR_CLIENT_KIT_LIBRARY osvrClientKit HINTS ${OSVR_DIR}/lib)
find_library(OSVR_CLIENT_LIBRARY osvrClient HINTS ${OSVR_DIR}/lib)
find_library(OSVR_COMMON_LIBRARY osvrCommon HINTS ${OSVR_DIR}/lib)
find_library(OSVR_UTIL_LIBRARY osvrUtil HINTS ${OSVR_DIR}/lib)
find_library(JSONCPP_LIBRARY jsoncpp HINTS ${OSVR_DIR}/lib/x86_64-linux-gnu)
set(OSVR_LIBRARIES ${OSVR_CLIENT_KIT_LIBRARY} ${OSVR_CLIENT_LIBRARY} ${OSVR_COMMON_LIBRARY} ${OSVR_UTIL_LIBRARY} ${JSONCPP_LIBRARY})
and down the track:
target_link_libraries(myExec ${QT_LIBRARIES} ${OSVR_LIBRARIES} )
target_include_directories(myExec PUBLIC include ${OSVR_INCLUDE_DIR} )

Your use of find_library looks wrong.
Check out the manpage for find_library. You have to give the name of the library you want to find as an argument. You can optionally provide additional hints where to find that library:
find_library(OSVR_COMMON_LIBRARY osvrCommon
HINTS ${OSVR_DIR}/lib)
Note that you will need one separate find_library call for each library! Since your libraries seem to have interdependencies, the correct way to model them in CMake is to also add an imported target per library and then model the interdependencies on those targets correctly.
If you don't feel comfortable doing that yet, you can also add all the find libraries to a single OSVR_LIBRARIES variable in the correct order and then depend on that:
find_package(OSVR_COMMON_LIBRARY ...)
find_package(OSVR_CLIENT_LIBRARY ...)
find_package(OSVR_CLIENTKIT_LIBRARY ...)
...
set(OSVR_LIBRARIES ${OSVR_CLIENTKIT_LIBRARY} ${OSVR_CLIENT_LIBRARY} ${OSVR_COMMON_LIBRARY} ...)
target_link_libraries(myexec ${QT_LIBRARIES} ${OSVR_LIBRARIES})
Note though that this approach is quite fragile with regards to future changes and should in general be avoided in favor of the imported targets.
Also, be sure that you actually have proper error handling mechanisms in place for the case that your find calls do not actually find anything.

Related

How to combine STM32 HAL library with CMake, as it need file from project it linked to [duplicate]

i have recently switched my stm32 project to CMake to be independent on IDE. Root repository (application) contains multiple submodules (HAL, FreeRTOS etc.) and its CMakeLists.txt includes explicitly every single used file:
set(EXECUTABLE ${PROJECT_NAME}.elf)
add_executable(${EXECUTABLE}
# Own sources
src/main.c
src/SEGGER_SYSVIEW_Config_FreeRTOS.c
src/startup_stm32h723zgtx.s
src/stm32h7xx_hal_timebase_tim.c
src/system_stm32h7xx.c
# Base CMSIS and HAL library
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
#long list of HAL c files there...
# FreeRTOS library
lib-freertos/croutine.c
lib-freertos/event_groups.c
lib-freertos/list.c
lib-freertos/queue.c
lib-freertos/stream_buffer.c
lib-freertos/tasks.c
lib-freertos/timers.c
lib-freertos/portable/GCC/ARM_CM7/r0p1/port.c
lib-freertos/trace/Sample/FreeRTOSV10/SEGGER_SYSVIEW_FreeRTOS.c
lib-freertos/trace/SEGGER/Syscalls/SEGGER_RTT_Syscalls_GCC.c
lib-freertos/trace/SEGGER/SEGGER_RTT_ASM_ARMv7M.S
lib-freertos/trace/SEGGER/SEGGER_RTT_printf.c
lib-freertos/trace/SEGGER/SEGGER_RTT.c
lib-freertos/trace/SEGGER/SEGGER_SYSVIEW.c
)
target_include_directories(${EXECUTABLE}
PRIVATE
include
src
lib-hal/stm32h7xx/CMSIS/Include
lib-hal/stm32h7xx/CMSIS/Device/ST/STM32H7xx/Include
lib-hal/stm32h7xx/STM32H7xx_HAL_Driver/Inc
lib-freertos/include
lib-freertos/trace/Config
lib-freertos/trace/SEGGER
lib-freertos/trace/Sample/FreeRTOSV10/
lib-freertos/portable/GCC/ARM_CM7/r0p1
)
This solution works but i know it is not a sustainable approach. So i tried to create library in lib-hal and lib-freertos submodules, specifying their sources and includes
add_library(lib-hal-stm32h7xx)
target_include_directories(lib-hal-stm32h7xx
PUBLIC
CMSIS/Include
CMSIS/Device/ST/STM32H7xx/Include
STM32H7xx_HAL_Driver/Inc
PRIVATE
STM32H7xx_HAL_Driver/Src
)
target_sources(lib-hal-stm32h7xx
PRIVATE
STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c
STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
#long list of HAL c files there...
)
and then using
add_subdirectory(lib-hal/stm32h7xx)
add_subdirectory(lib-freertos)
and
target_link_library(${EXECUTABLE} lib-freertos lib-hal-stm32h7xx)
to "import" submodules into application project. But when building the executable, gcc cannot access files stm32h7xx_hal_conf.h and FreeRTOSConfig.h which are located in root directory include. I do not want to put configuration headers into submodules because they are used in multiple projects with different configurations. Is it possible to somehow extend already specified directory search scope for library after adding it into parent project?
File structure of project:
-src
-include (configuration for lib-hal and lib-freertos included there)
-lib-hal
-includes...
-sources...
-lib-freertos
-includes...
-sources...
Thanks in advance for response.
As Tsyvarev mentioned in the comments, you can modify the properties of the target in your project. To keep things clean, I usually create a function for this and place it in a separate file.
Tip: you can also add source files to the target. In case of FreeRTOS, you could add architecture-specific files, in case all your projects don't run on the same MCU family.
function(configure_freertos target_name)
target_sources(${target_name}
PRIVATE
lib-freertos/portable/GCC/ARM_CM7/r0p1/port.c
)
target_include_directories(${target_name}
PUBLIC
include
lib-freertos/portable/GCC/ARM_CM7/r0p1
)
endfunction()

CMake set per configuration linker flag

As the title states, is there a 'neat' way to set per configuration linker flag? It is not possible for me to use target_link_options() since I'm trying to link into a static library. Ideally, what I would want to achieve is to set Visual Studio's Librarian -> Additional Dependencies and Additional Library Directories and achieve the same result in XCode as well.
Here is what I've achieved so far:
set(LIB_LINKS_RUNTIME
${Vulkan_LIBRARIES}
${CMAKE_SOURCE_DIR}/bin/$<CONFIGURATION>/SDL2maind.lib
${CMAKE_SOURCE_DIR}/bin/$<CONFIGURATION>/SDL2d.lib
${CMAKE_SOURCE_DIR}/bin/$<CONFIGURATION>/imgui.lib
)
foreach(lib ${LIB_LINKS_RUNTIME})
set (CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${lib}")
endforeach()
According to https://cmake.org/cmake/help/latest/prop_tgt/STATIC_LIBRARY_OPTIONS.html STATIC_LIBRARY_OPTIONS property does the trick
set_property(TARGET Runtime PROPERTY STATIC_LIBRARY_OPTIONS ${LIB_LINKS_RUNTIME})

Don't reference all vendored libraries shipped with cocoapods

Situation
I have a static Library Project which references a few other static Libraries.
To distribute my (company internal) Library I added a podspec file.
I added the third party libraries to the vendored_libraries like this:
spec.vendored_libraries = "dependencies/libraries/**/*.a"
and the libraries command like this:
spec.libraries = "AfariaSLL", "ClientHubSLL", "Connectivity", "CoreServices", "Datavault", "E2ETrace", "Logger", "MAFLogger", "MAFLogonManagerNG", "MAFLogonUING", "MAFUIComponents", "MAFUIHelper", "Parser", "PerformanceLib", "Request", "sqlcipher", "crypto", "MAFFormatters", "MAFLocaleAwareControls", "MAFZipHelper", "ssl", "xml2", "stdc++", "z"
When i install the pod to one of my projects, the *.a files are copied as expected and referenced within the Pods.debug.xcconfig and Pods.release.xcconfig files like this:
OTHER_LDFLAGS = -ObjC -all_load -stdlib=libstdc++ -l"AfariaSLL" -l"ClientHubSLL" -l"Connectivity" -l"CoreServices" -l"Datavault" -l"E2ETrace" -l"Logger" -l"MAFFormatters" -l"MAFLocaleAwareControls" -l"MAFLogger" -l"MAFLogonManagerNG" -l"MAFLogonUING" -l"MAFUIComponents" -l"MAFUIHelper" -l"MAFZipHelper" -l"Parser" -l"PerformanceLib" -l"Pods-SBBSMPLib" -l"Request" -l"crypto" -l"sqlcipher" -l"ssl"
Until here everything works fine.
Problem
Not every Project needs all of the vendored libraries. So I tried to just reference the required libraries like this:
spec.libraries = "AfariaSLL", "ClientHubSLL", "Connectivity", "CoreServices", "Datavault", "MAFLogonManagerNG", "MAFLogonUING", "MAFUIComponents", "Request"
and hoped that it would have an impact to the OTHER_LDFLAGS. But unfortunately the OTHER_LDFLAGS remains the same. Even when i completely remove the spec.libraries line the OTHER_LDFLAGS don't change.
Summary
How can i achieve that the third party libraries are copied to the projects but not all are referenced within the OTHER_LDFLAGS?
Thank you so much!
the simplest solution I tried (and worked - but ist nowhere documented) is to create different podspec files for the possible scenarios. That means: different spec.vendored_libraries definitions for the different goals

Compiling and Llnking to used modules in external directory Compaq Fortran command prompt

I've already asked a similar question, here:
Linking to modules in external directory Compaq Visual Fortran command prompt
And I thought that the first answer was correct (that is, in the manual they say you can simply specify the path name before the module), but after deleting the temporary files in my library folder, this approach seemed to stop working. Trying with the /include[:path] approach, here is my .bat file:
df /include:..\FORTRAN_LIB\ __constants
myIO griddata_mod myfdgen myDiff magneticField /exe:magneticField
And an error is returned saying:
__constants
myIO
griddata_mod
myfdgen
myDiff
magneticField
f90: Severe: No such file or directory
... file is '__constants'
Again, I apologize that this question is VERY specific, but it seems like it should be simple and does not work at all.
p.s. Originally, I was using:
df ..\FORTRAN_LIB\__constants ..\FORTRAN_LIB\myIO
..\FORTRAN_LIB\griddata_mod ..\FORTRAN_LIB\myfdgen
..\FORTRAN_LIB\myDiff magneticField /exe:magneticField
But, as I've said, it stopped working after I deleted the temporary files in my FORTRAN_LIB folder. Also note, these .bat files used only one line, I've broken them into several lines just for readability. I would prefer using the /include[:path] option since that seems like a better solution.
Okay, so I think I figured out a workaround at the very least. I understood that the /include[:dir] specifies to search in "dir" for included files. But it seemed from documentation, that this also specifies to search for USEd modules but that doesn't seem to be the case.
My program now looks like this:
include '..\FORTRAN_LIB\__constants.f90'
include '..\FORTRAN_LIB\computeError.f90'
include '..\FORTRAN_LIB\griddata_mod.f90'
include '..\FORTRAN_LIB\myfdgen.f90'
include '..\FORTRAN_LIB\myDiff.f90'
include '..\FORTRAN_LIB\myIO.f90'
program magneticField
use constants
use computeError_mod
use griddata_mod
use myfdgen_mod
use myDiff_mod
use myIO_mod
implicit none
...
And my DF command like this:
df magneticField /exe:magneticField
And everything seems to work fine. It would be nicer to have the /include[:dir] option, but so long I'm able to reach in a separate directory, I'm satisfied. If anyone can find a better solution I'll switch the checkmark. I hope this helps with anyone else who was confused like me.

How to organize cmake file hierarchy with multiple optional dependencies

I have a C++ project with a core which is basically self-contained but with a lot of interfaces to third party codes that a user may or may not want to compile. We build the code using CMake and I am now trying to organize the code a bit better.
The solution I came up with is to add to the top CMakeLists.txt file a set of options which determine whether a dependent package should be located or not.
option(WITH_FOO "Compile the interface to Foo, if found" ON)
option(REQUIRE_FOO "Require that the Foo interface to be compiled" OFF)
option(WITH_BAR "Compile the interface to Bar, if found" ON)
option(REQUIRE_BAR "Require that the Bar interface to be compiled" OFF)
...
if(WITH_FOO)
if(REQUIRE_FOO)
find_package(Foo REQUIRED)
else(REQUIRE_FOO)
find_package(Foo)
endif(REQUIRE_FOO)
else(WITH_FOO)
set(FOO_FOUND FALSE)
endif(WITH_FOO)
if(WITH_BAR)
if(REQUIRE_BAR)
find_package(Bar REQUIRED)
else(REQUIRE_BAR)
find_package(Bar)
endif(REQUIRE_BAR)
else(WITH_BAR)
set(BAR_FOUND FALSE)
endif(WITH_BAR)
Then in the the CMakeLists.txt files in the subdirectories, there will be statements such as:
if(BAR_FOUND)
add_subdirectory(bar_interface)
endif(BAR_FOUND)
I don't particularly like this solution, partly because it is very verbose and partly because I feel that there should be some more standardized way of doing this. Is anyone aware of a better, more maintainable solution?
Have a look at the following standard CMake modules:
FeatureSummary - Macros for generating a summary of enabled/disabled features
CMakeDependentOption - Macro to provide an option dependent on other options
Examples of using FeatureSummary (from manual):
option(WITH_FOO "Help for foo" ON)
add_feature_info(Foo WITH_FOO "The Foo feature provides very cool stuff.")
find_package(LibXml2)
set_package_properties(LibXml2 PROPERTIES DESCRIPTION "A XML processing library." URL "http://xmlsoft.org/")
set_package_properties(LibXml2 PROPERTIES TYPE RECOMMENDED PURPOSE "Enables HTML-import in MyWordProcessor")
set_package_properties(LibXml2 PROPERTIES TYPE OPTIONAL PURPOSE "Enables odt-export in MyWordProcessor")
feature_summary(WHAT ALL)