I have an external library here:
${PROJECT_SOURCE_DIR}/thirdparty/yaml-cpp/
It is made by a Makefile: thirdparty/Makefile. I am executing that makefile like so:
add_custom_target(
yaml-cpp
COMMAND make
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/thirdparty
)
I am then attempting to link the library, which builds to thirdparty/yaml-cpp/build/libyaml-cpp.a. This is the part that is not working:
target_link_libraries(load_balancer_node ${CMAKE_SOURCE_DIR}/thirdparty/yaml-cpp/build/libyaml-cpp.a)
I get the error:
Target "yaml-cpp" of type UTILITY may not be linked into another target.
One may link only to STATIC or SHARED libraries, or to executables with the
ENABLE_EXPORTS property set.
How do I execute that makefile and link the .a file?
So it makes sense that cmake can't figure out the dependencies here: it would have to parse the makefile and find the output. You have to tell it the output someone. Nearest I can figure, the best way to do this is to use a custom_command rather than a custom target:
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/thirdparty/yaml-cpp/build/libyaml-cpp.a
COMMAND make
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/thirdparty)
add_custom_target(
yaml-cpp
DEPENDS ${CMAKE_SOURCE_DIR}/thirdparty/yaml-cpp/build/libyaml-cpp.a)
...
add_dependencies(load_balancer_node yaml-cpp)
target_link_libraries(load_balancer_node ${CMAKE_SOURCE_DIR}/thirdparty/yaml-cpp/build/libyaml-cpp.a)
I was having linker troubles though (stupid windows machine), but cmake worked and made the libraries before trying to link.
Related
I want to iterate over all link libraries of a target target to build a list of all library binaries (static libraries) which target links to, e.g.
add_executable(exe main.cpp)
target_link_libraries(exe fmt::fmt otherExe)
We want a list of all library binary files (by using $<TARGET_LINKER_FILE:tgt>) for dependent targets fmt::fmt and otherExe to generate the apropriate CGO interface.go file with CFLAGS and LDFLAGS.
The thing is, its hard to write a loop in CMake to iterate over link dependencies of target since
properties like LINK_LIBRBARIES and INTERFACE_LINK_LIBRARIES are in general lists but might contain generator expressions, as in the case for interface library target fmt::fmt which comes from Conan where INTERFACE_LINK_LIBRARIES resolves to
$<$<CONFIG:Release>:CONAN_LIB::fmt_fmt_RELEASE;>. which contains a semicolon ";" which is then treated itself as a list with $<$<CONFIG:Release>:CONAN_LIB::fmt_fmt_RELEASE; and >.
This is due to that Conan adds the following
set_property(TARGET fmt::fmt
PROPERTY INTERFACE_LINK_LIBRARIES
$<$<CONFIG:Release>:${fmt_LIBRARIES_TARGETS_RELEASE}
${fmt_OBJECTS_RELEASE}> APPEND)
Anybody has a solution to this?
We found a solution by using the file-api of Cmake, we setup a "configure" add_custom_target in CMake which is a pyhton script which is reading the reply for the 'codemodel-v2' (file-api): parsing the JSON output file for the target of interest. Then
gathering all linker and compiler flags from this JSON and then configure a Go file with these flags.
Include files have been extracted by passing $<TARGET_PROPERTY:targetName,INCLUDE_DIRECTORIES> to the add_custom_command.
I am trying to make generate a shared library of an existing application, so that i can link it to gtest application.
My main applications cmake file looks like this:
project(audiodLib CXX C)
cmake_minimum_required(VERSION 2.8.7)
## Lets store all the source code in ${SOURCES}
file(GLOB SOURCES src/*.cpp src/controls/*.cpp src/controls/pulse/*.cpp src/modules/*.cpp src/product/*.cpp src/umi/*.cpp src/umi/modules/*.cpp src/umi/soundSettings/*.cpp src/utils/*.cpp utils/*.cpp pmtrace/*.c)
##Lets generate the library
##Please note, here instead of ${SOURCES} if i try to directly add source code, I always get
##an error saying that cmake could not find any *.cpp files
add_library(audiodLib SHARED ${SOURCES})
##Lets link it with libraries
target_link_libraries(audiodLib ${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
)
##Lets make this library availabel for other modules
install(TARGETS audiodLib LIBRARY DESTINATION ${WEBOS_INSTALL_LIBDIR})
After compilation, libaudiodLib.so is generated in /usr/lib directory.
And now if I try to access the audiodLib in my gtest code like this:
##${WEBOS_INSTALL_LIBDIR} = /usr/lib/
include_directories(${WEBOS_INSTALL_LIBDIR})
target_link_libraries(${GTEST_EXECUTABLE}
${WEBOS_GTEST_LIBRARIES}
${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
-laudiodLib
)
I get the following error:
cannot find -laudiodLib
The folder structure is as follows:
audiod/
CMakeList
|src
|tests
CMakelist
If someone can point out what I am doing wrong, it would be of great help. I am kind of stuck and clueless after spending 2-3 days on this.
Thank you so very much for offering me suggestions, and pointers, I was finally able to sove the problem.
Regarding library not found issue, I resolved it by rearranging the TARGET_LINK_LIBRARIES as follows:
target_link_libraries(audiod
audiodLib
${GLIB2_LDFLAGS}
${LUNASERVICE_LDFLAGS}
${PBNJSON_C_LDFLAGS}
${LUNAPREFS_LDFLAGS}
${POWERD_LDFLAGS}
${PMLOGLIB_LDFLAGS}
${NYXLIB_LDFLAGS}
${LIBPBNJSON_LDFLAGS}
${PULSE_LDFLAGS}
${LTTNG_UST_LDFLAGS}
${URCU_BP_LDFLAGS}
${PULSE_SIMPLE_LDFLAGS}
${WEBOSI18N_LDFLAGS}
pthread
rt
dl
-lsnapshot-boot
)
And how i resolved the BAD RPATH Error during do_package_qa, I have already answerd it here:
bitbake do_package_qa issue contains bad RPATH
I'm trying to make a plugin system for my application, and thus each plugin will need to link with my main application. This is fine on Linux and macOS, as I can just set the ENABLE_EXPORTS property of my executable target (set_target_properties(${PROJECT_NAME} PROPERTIES ENABLE_EXPORTS 1), and plugins will link just fine. On Windows however, clang++ yells at me that it can't find libws2editor.dll.a.
clang++.exe: error: no such file or directory: 'ws2editor/libws2editor.dll.a'
Upon looking over the CMake docs, it says "For DLL platforms an import library will be created for the exported symbols and then used for linking." - This import library file (presumably the .dll.a) never seems to be created though.
So how can I get the CMake build on Windows to create this file, or otherwise link with an executable?
Looks like I can use ar to generate the .a file for me, regardless of generator - plugins seem to link and load just fine when doing this. Awesome! :)
if(WIN32)
#Invoke ar to generate a .dll.a from the .obj files, required to link plugins
add_custom_command(TARGET ${PROJECT_NAME} PRE_LINK
COMMAND sh -c "${CMAKE_AR} cr lib${PROJECT_NAME}.dll.a $$(find . -name '*.obj' -printf '%p ')"
COMMENT "Generating lib${PROJECT_NAME}.dll.a for external linking"
)
#Also add the install command for libws2editor.dll.a
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${PROJECT_NAME}.dll.a DESTINATION bin)
endif(WIN32)
Is there any simple way to link at runtime a locally built library to a test with CMAKE?
For example:
enable_testing()
add_executable(Test test/Test.cpp)
target_link_libraries(Test -L../lib/libzmq/build/lib/ zmq)
add_test(
NAME TestClientZmq
COMMAND "LD_PRELOAD=../lib/libzmq/build/lib/libzmq.so Test")
Running the test will complain about the missing library at runtime:
error while loading shared libraries: libzmq.so.4.2.0: cannot open shared object file: No such file or directory
I can either:
Set LD_PRELOAD when running ctest
Write a wrapper script which does this and then calls the executable (what I have currently)
I would prefer to do everything in cmake though, since I think it's best to keep all this configuration in a single place to avoid bugs in the future.
Add
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
to your CMakeLists.txt. As explained in this wiki article.
After build, use the below command to make sure the RPATH is properly set:
objdump -x Test | grep RPATH
We ported our codebase to use CMake for build management some weeks ago. We realize now that there is a major problem when we are trying to Archive an application that depends on one (or several) library built in the same Xcode solution.
The linker fails because it cannot find the depended upon library (and the library is indeed not present where it is looking for it).
minimal example
Here is a minimal example producing the issue:
In CMakeLists.txt
##
## The library
##
project(library)
add_library(${PROJECT_NAME}
utils.h
utils.cpp
)
##
## The application
##
project(CocoaApp)
set(${PROJECT_NAME}_XIB
MainMenu.xib
)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE
AppDelegate.h
AppDelegate.mm
${${PROJECT_NAME}_XIB}
main.mm
)
target_link_libraries(${PROJECT_NAME} library "-framework Cocoa")
set_target_properties(${PROJECT_NAME} PROPERTIES
RESOURCE "${${PROJECT_NAME}_XIB}")
When generating an Xcode project from this simple CMake scripts, if trying to call Archive command, the compilation phase itself goes fine, but the linker phase fails with this error:
clang: error: no such file or directory: '<path_to_build_tree>/Release/libLibrary.a'
And there is indeed no libLibrary.a to be found in ${build_tree}/Release/. (If the library target was first compiled in Release, the file would already be there, but it is not viable as Archive should be self contained.)
Is this a bug ? Is there a workaround ?
Edit: setting ARCHIVE_OUTPUT_DIRECTORY on the lib
If ARCHIVE_OUTPUT_DIRECTORY is set for the Library target, then a file is indeed created in CMake's build_tree. Actually setting its value to "./" even places it where a 'normal' Release build would place the library.
The problem here is that the file that is placed in the build_tree is merely a soft link to the actual library (in ~/Library/Developer/Xcode/DerivedData/.../.../libLibrary.a). Instead, we would need that the "Archive" action builds the actual file here, exactly like a Release build would (or at least move it there when its done).