Undefined symbols linking to framework CMake - c

When compiling/statically linking a project of mine, I get the following error (in this case with OpenAL, I've tried other audio libraries such as PulseAudio and get similar errors):
Undefined symbols for architecture x86_64:
"_alcCaptureCloseDevice", referenced from:
_ad_close in libsphinxbase.a(ad_openal.c.o)
"_alcCaptureOpenDevice", referenced from:
_ad_open_dev in libsphinxbase.a(ad_openal.c.o)
"_alcCaptureSamples", referenced from:
_ad_read in libsphinxbase.a(ad_openal.c.o)
"_alcCaptureStart", referenced from:
_ad_start_rec in libsphinxbase.a(ad_openal.c.o)
"_alcCaptureStop", referenced from:
_ad_stop_rec in libsphinxbase.a(ad_openal.c.o)
"_alcGetIntegerv", referenced from:
_ad_read in libsphinxbase.a(ad_openal.c.o)
ld: symbol(s) not found for architecture x86_64
You can find the CMakeLists.txt in the link to the project, but I think the error lies within its dependency (despite it compiling just fine and generating a x86_64 architecture library). Here is the dependency's main CMakeLists.txt:
#
# Initial CMake and project setup
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
SET(PROJECT_NAME sphinxbase)
PROJECT(${PROJECT_NAME})
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
SET_DIRECTORY_PROPERTIES(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/build-data)
#
# Setup compiler flags
#
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE CACHE Release FORCE)
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=gnu11 -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=gnu11 -O3")
#
# Final project settings
#
configure_file("${CMAKE_SOURCE_DIR}/include/sphinx_config.h.in" "${CMAKE_SOURCE_DIR}/include/sphinx_config.h")
INCLUDE_DIRECTORIES(include)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(test EXCLUDE_FROM_ALL)
ADD_LIBRARY(${PROJECT_NAME} STATIC
$<TARGET_OBJECTS:libsphinxad>
$<TARGET_OBJECTS:fe>
$<TARGET_OBJECTS:feat>
$<TARGET_OBJECTS:lm>
$<TARGET_OBJECTS:util>
$<TARGET_OBJECTS:sphinx_adtools>
$<TARGET_OBJECTS:sphinx_cepview>
$<TARGET_OBJECTS:sphinx_fe>
$<TARGET_OBJECTS:sphinx_jsgf2fsg>
$<TARGET_OBJECTS:sphinx_lmtools>
)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIBS})
I'm setting ${LIBS} in the libsphinxad object folder:
include_directories(${CMAKE_SOURCE_DIR}/include/sphinxbase)
if (WIN32)
set(SOURCES ${SOURCES} ad_win32.c)
endif ()
find_package(PulseAudio)
if (PULSEAUDIO_FOUND)
set(SOURCES ${SOURCES} ad_pulse.c)
set(LIBS ${PULSEAUDIO_LIBRARIES} CACHE INTERNAL "libs")
endif()
find_package(OSS)
if (OSS_FOUND)
set(SOURCES ${SOURCES} ad_oss.c )
endif()
find_package(OpenAL)
if (OPENAL_FOUND)
set(SOURCES ${SOURCES} ad_openal.c)
set(LIBS ${OPENAL_LIBRARY} CACHE INTERNAL "libs")
include_directories(${OPENAL_INCLUDE_DIR})
endif()
find_package(ALSA)
if (ALSA_FOUND)
set(SOURCES ${SOURCES} ad_alsa.c)
set(LIBS ${ALSA_LIBRARIES} CACHE INTERNAL "libs")
endif()
add_library(libsphinxad OBJECT ${SOURCES})
As you can see, I'm linking to the OpenAL framework. Here is the path that CMake is sending into TARGET_LINK_LIBRARIES that gives the error above:
/System/Library/Frameworks/OpenAL.framework
It looks like I'm doing things correctly, so I'm somewhat confused. I've tried adding -framework flags and adding linking to other libraries such as CoreAudio and Foundation to no avail. Any suggestion?
I have gotten the project to build without error linking to the dynamic library, but for my purposes I need to link the library statically.

Related

How to include header files in external library in CMake

I have a C application which is running on Raspberry Pi 3 and currently, I have to build it on PI with Cmake. I am trying to build it on Ubuntu machine. I have added a CMAKE_TOOLCHAIN_FILE as described here.
I could run cmake. -DCMAKE_TOOLCHAIN_FILE without any problem but the "make" command is not successful and it can not find a header file inside one of the external library: "mirsdrapi-rsp". The error message is:
fatal error: mirsdrapi-rsp.h: No such file or directory
#include "mirsdrapi-rsp.h"
^
compilation terminated.
I have created a folder named "lib" and have put the "libmirsdrapi-rsp.so" file inside it.
my CMakeLists.txt is as below:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -v -g -D_XOPEN_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -v ")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-v")
set (SDR_API_PATH ${CMAKE_SOURCE_DIR}/lib)
include_directories (include ${SDR_API_PATH})
include_directories("${CMAKE_SOURCE_DIR}/lib")
find_library(mirslocation NAMES mirsdrapi-rsp HINTS ${SDR_API_PATH} NO_CMAKE_FIND_ROOT_PATH)
message(STATUS ${mirslocation})
add_library(mirs STATIC IMPORTED)
set_target_properties(mirs PROPERTIES IMPORTED_LOCATION ${mirslocation})
target_link_libraries (raspberryPiDaemon mirs)
target_link_libraries(raspberryPiDaemon m)
Cmake is printing the right path of the library mirsdrapi-rsp while running "find_library" and as I mentioned I am getting the error message just while running "make" command and not "cmake" command.
My content of CMAKE_TOOLCHAIN_FILE is as below:
# Define our host system
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Define the cross compiler locations
SET(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
# Define the sysroot path for the RaspberryPi distribution in our tools folder
SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/SET)
# Use our definitions for compiler tools
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Search for libraries and headers in the target directories only
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
add_definitions(-Wall -std=c11)
Anybody knows how I can add the header file from mirsdrapi-rsp library to include path?
I guess that you're setting include_directories to the wrong path (it is set 2 times to ${CMAKE_SOURCE_DIR}/lib which must be the folder of libraries not the header files). Check again the correct location of the missing header file.
More precisely: you need to find the path of mirsdrapi-rsp.h and let CMake know it just like for find_library:
find_path(MIRSDRAPI_INCLUDE_DIRS NAMES mirsdrapi-rsp.h PATHS {proper-location})
if (MIRSDRAPI_INCLUDE_DIRS)
target_include_directories(raspberryPiDaemon PRIVATE ${MIRSDRAPI_INCLUDE_DIRS})
endif()
In addition, you can set the INTERFACE_INCLUDE_DIRECTORIES property to the library like this:
set_property(TARGET mirsdrapi-rsp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MIRSDRAPI_INCLUDE_DIRS})
This way, target_include_directories might be unnecessary and target_link_directories should be enough.

cmake 3.9 target_link_libraries to static imported library failed. Same CMakefile works with CMake 2.8.12

I have the following CMakefile works well with CMake 2.8.12 but failed after upgrade to 3.9:
add_library(extlib STATIC IMPORTED GLOBAL)
set_property( TARGET extlib PROPERTY IMPORTED_LOCATION ${EXTERNAL_LIB_DIR}/extlib.a )
add_executable( myApp myApp.cpp )
target_link_libraries( myApp extlib)
cmake generates Makefile. But make failed:
/usr/bin/ld: ../../ext/lib/extlib.a(extlib.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
I run make VERBOSE=1 showing the following:
/usr/bin/c++ -rdynamic CMakeFiles/myApp.dir/myApp.cpp.o -o myApp -Wl,-rpath,/root/myApp/ext/lib ../../ext/lib/extlib.a
extlib.a is linked as a shared library.
The CMakefile has no problem with 2.8.12.
What do I need to modify to make it work in 3.9?
Thanks!

Which library should I include in CLion to enable readline

I'm using CLion on El Capitan. Now I need to use the readline and add_history function in my project. But the linker complains those below down.
Undefined symbols for architecture x86_64:
"_add_history", referenced from:
_main in lisp_3.c.o
"_readline", referenced from:
_main in lisp_3.c.o
ld: symbol(s) not found for architecture x86_64
I can tackle it by adding a -ledit flag when compiling it manually or linking the libedit.tbd in Xcode but CLion uses CMake. So I don't know which library should I add to the CMakeLists.txt.
It's the first time I have used CMake to build a project. And I could only follow what he did in this question How to include C static libraries in CMAKE project on MAC OS X
cmake_minimum_required(VERSION 3.3)
project(test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(SOURCE_FILES read.c)
add_executable(test ${SOURCE_FILES})
find_library(readline_lib /* what can I place here?*/)
set(frameworks ${readline_lib})
target_link_libraries(test ${frameworks})
a link to a tar of the readline library is available at: <https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html>
or more directly from: <git.savannah.gnu.org/cgit/readline.git/snapshot/readline-master.tar.gz>
I think the history functions come with the readline library.
Add this line to your CMakeLists.txt:
target_link_libraries(yourprojectname /usr/lib/x86_64-linux-gnu/libreadline.so)
I solved the same problem using:
target_link_libraries(test edit)
You need your program test to link against editline lib not readline
And below is the minimal CMakeList.txt file to compile it
cmake_minimum_required(VERSION 3.3)
project(test C)
set(SOURCE_FILES read.c)
add_executable(test ${SOURCE_FILES})
target_link_libraries(test edit)

How to use shared lib for static with cmake

I'm beginner with CMake and i would to compile my project with it.
I have the following CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (rt)
include_directories ("${PROJECT_BINARY_DIR}/src/")
include_directories ("${PROJECT_BINARY_DIR}/src/hook")
include_directories ("${PROJECT_BINARY_DIR}/src/light")
include_directories ("${PROJECT_BINARY_DIR}/src/move")
include_directories ("${PROJECT_BINARY_DIR}/src/object/inter")
include_directories ("${PROJECT_BINARY_DIR}/src/object/normal")
include_directories ("${PROJECT_BINARY_DIR}/src/option")
include_directories ("${PROJECT_BINARY_DIR}/src/parsing")
include_directories ("${PROJECT_BINARY_DIR}/src/ray")
include_directories ("${PROJECT_BINARY_DIR}/src/render")
include_directories ("${PROJECT_BINARY_DIR}/src/shadow")
include_directories ("${PROJECT_BINARY_DIR}/src/utils")
include_directories ("${PROJECT_BINARY_DIR}/lib/minilibx")
file(GLOB hook
"*.h"
"*.c"
)
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.c)
#set (EXTRA_LIBS ${EXTRA_LIBS} ${X11_LIBRARIES} m)
add_executable (rt ${SRC_FILES})
target_link_libraries (rt ${EXTRA_LIBS} X11 Xext m ${PROJECT_BINARY_DIR}/lib/libmlx.a)
But when I run make, my static library minilibx won't compile. with errors that all the functions from the X11 and Xext libraries are undefined.
make VERBOSE=1 result:
Linking C executable rt
/usr/bin/cmake -E cmake_link_script CMakeFiles/rt.dir/link.txt --verbose=1
/usr/bin/cc CMakeFiles/rt.dir/src/move/translation.c.o CMakeFiles/rt.dir/src/move/rotation.c.o CMakeFiles/rt.dir/src/light/light.c.o CMakeFiles/rt.dir/src/option/option.c.o CMakeFiles/rt.dir/src/option/file_option.c.o CMakeFiles/rt.dir/src/render/render.c.o CMakeFiles/rt.dir/src/hook/control.c.o CMakeFiles/rt.dir/src/ray/eye.c.o CMakeFiles/rt.dir/src/ray/ray.c.o CMakeFiles/rt.dir/src/utils/my_strlen.c.o CMakeFiles/rt.dir/src/utils/my_strncpy.c.o CMakeFiles/rt.dir/src/object/inter/plan.c.o CMakeFiles/rt.dir/src/object/inter/cone.c.o CMakeFiles/rt.dir/src/object/inter/cylinder.c.o CMakeFiles/rt.dir/src/object/inter/sphere.c.o CMakeFiles/rt.dir/src/object/inter/tore.c.o CMakeFiles/rt.dir/src/object/normal/plan.c.o CMakeFiles/rt.dir/src/object/normal/cone.c.o CMakeFiles/rt.dir/src/object/normal/cylinder.c.o CMakeFiles/rt.dir/src/object/normal/sphere.c.o CMakeFiles/rt.dir/src/parsing/scene.c.o CMakeFiles/rt.dir/src/parsing/file_access.c.o CMakeFiles/rt.dir/src/parsing/str_tool.c.o CMakeFiles/rt.dir/src/shadow/shadow.c.o CMakeFiles/rt.dir/src/main.c.o -o rt -rdynamic -lX11 -lXext -lm lib/libmlx.a
and this is an example of errors:
lib/libmlx.a(mlx_init.o): In function mlx_int_deal_shm':
mlx_init.c:(.text+0x2a): undefined reference toXShmQueryVersion'
mlx_init.c:(.text+0x104): undefined reference to `XShmPixmapFormat'
How do I solve the undefined reference errors?
I have solved the problem, the order of libs are not correct.
I just link my lib before another lib. Et voilĂ  :)
target_link_libraries (rt ${EXTRA_LIBS} ${PROJECT_BINARY_DIR}/lib/libmlx.a X11 Xext m)
CMake uses target_link_libraries to specify which libraries you link against.
In you case, it seems like you're linking against the correct libraries (target_link_libraries (rt ${EXTRA_LIBS} X11 Xext m ${PROJECT_BINARY_DIR}/lib/libmlx.a)), so my bet is they are not found.
Try running:
make VERBOSE=1
This will give you the gcc output. Paste the last couple of gcc instructions it generates here and we'll see why it didn't find your libs.

CMake: Static and dynamic linking based on BUILD_TYPE

I am developing a small simulation software that depends on two libraries, the GSL and the libconfig. As a build system, I use CMake. For both the GSL and libconfig, I found cmake files and copied them into the cmake/ directory of my project.
The scenario is the following: I want the project to have several different build types, like debug, release, etc., but also a custom one called cluster, which adds -static to the GCC flags and links against the .a libraries of the GSL and the libconfig, which I assume exist.
My CMakeLists.txt looks like this so far:
# version
SET(PACKAGE_VERSION "1.0")
SET(PACKAGE_NAME "INTERFACE")
PROJECT(interface C CXX)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# dirs -----------------------------------------------------
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
FIND_PACKAGE(GSL REQUIRED)
INCLUDE_DIRECTORIES(${GSL_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${GSL_LIBRARIES})
FIND_PACKAGE(LibConfig REQUIRED)
INCLUDE_DIRECTORIES(${LIBCONFIG_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${LIBCONFIG_LIBRARIES})
CONFIGURE_FILE("res/config.h.in" "config.h")
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
SET_DIRECTORY_PROPERTIES(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "config.h"
)
# compilation ----------------------------------------------
ADD_EXECUTABLE( interface
interface.c interface.h config.h
helpers.c
output.c
lattice.c
genetic.c
)
# optional CFLAGS
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99")
SET(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math")
SET(CMAKE_C_FLAGS_CLUSTER "-O3 -ffast-math -static")
SET(CMAKE_C_FLAGS_DEBUG "-g")
SET(CMAKE_C_FLAGS_PROFILE "-g -ffast-math -pg")
TARGET_LINK_LIBRARIES(interface m ${LIBS})
# installation --------------------------------------------
INSTALL(TARGETS interface DESTINATION bin)
This adds the -static to the compiler, when I use -DCMAKE_BUILD_TYPE=cluster. The thing is, that it still links against the .so versions of the libs, which causes gcc to throw errors. At least the FindLibConfig.cmake scripts sets both a LIBCONFIG_LIBRARY and a LIBCONFIG_STATIC_LIBRARY variable, which I could use.
What is the most elegant or smart way to reach my goal?
Acording to cmake documentation, cmake uses the variable BUILD_SHARED_LIBS to determine the default for add_library().
If you set to ON cmake will assume all add_library() call will be as
add_library(target SHARED lib1 lib2 ...)
For example something like -DBUILD_SHARED_LIBS=ON on the cmake command line may do what you are asking.
I solved it like this:
The User can specify an additional variable -DSTATIC_LINKING=TRUE. Then, the script looks like this. (Only the important parts for the static linking and compilation are shown!)
# determine, whether we want a static binary
SET(STATIC_LINKING FALSE CACHE BOOL "Build a static binary?")
# do we want static libraries?
# When STATIC_LINKING is TRUE, than cmake looks for libraries ending
# with .a. This is for linux only!
IF(STATIC_LINKING)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
ENDIF(STATIC_LINKING)
# set -static, when STATIC_LINKING is TRUE and set LINK_SEARCH_END_STATIC
# to remove the additional -bdynamic from the linker line.
IF(STATIC_LINKING)
SET(CMAKE_EXE_LINKER_FLAGS "-static")
SET_TARGET_PROPERTIES(surface PROPERTIES
LINK_SEARCH_END_STATIC 1)
ENDIF(STATIC_LINKING)

Resources