I have the following structure of projects/source:
MyProject
|-MyProject
| |-src
| | |-project.c
| |
| |-CMakeLists.txt
|
|-MyLibrary
|-include
| |-hello.h
|
|-src
| |-hello.c
|
|-CMakeLists.txt
MyProject/src/project.c includes MyLibrary/include/hello.h, which in turn includes libusb.h from the system (found using CMake).
And I am adding the libusb dependency in MyLibrary/CMakeLists.txt using the following code:
# Find libusb
find_package(LibUsb REQUIRED)
# Include libusb
include_directories(${LIBUSB_INCLUDE_DIR})
# Add dependencies
target_link_libraries(owi535 ${LIBUSB_LIBRARY})
However when compiling MyProject (which includes MyLibrary using add_subdirectory and target_link_libraries), I get an error stating libusb.h cannot be found.
I can compile MyLibrary on it's own, however compiling MyProject requires libusb.h to be in it's include path, which it is not.
Is there a way to make it so that by adding MyLibrary as a dependency, MyProject pulls libusb.h through it? This would mean that I don't need to repeat the find_package code for every project that includes MyLibrary.
The other issue I am having is similar; I am getting an error stating that there are Undefined symbols when calling libusb functions in MyLibrary when I compile MyProject, however when compiling MyLibrary on it's own, there are no errors.
Undefined symbols for architecture x86_64:
"_libusb_close", referenced from:
_my_close_method in libMyLibrary.a(hello.c.o)
"_libusb_exit", referenced from:
_my_exit_method in libMyLibrary.a(hello.c.o)
"_libusb_init", referenced from:
_my_init_method in libMyLibrary.a(hello.c.o)
"_libusb_open_device_with_vid_pid", referenced from:
_my_open_method in libMyLibrary.a(hello.c.o)
ld: symbol(s) not found for architecture x86_64
From the cmake documentation:
PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of <target>.
Targets may populate this property [INTERFACE_INCLUDE_DIRECTORIES] to publish the include directories required to compile against the headers for the target. Consuming targets can add entries to their own INCLUDE_DIRECTORIES property such as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the include directories specified in the interface of foo.
So, you need to use this in MyLibrary/CMakeLists.txt:
target_include_directories(MyLibrary PUBLIC ${LIBUSB_INCLUDE_DIR})
Related
I am having difficulty importing a python extension module that depends on a separate shared library that I am building via a separate build system. When I attempt to import the module, I get an undefined symbol error:
import ext_mod
ImportError: /ext_mod_path/ext_mod.so: undefined symbol: __mangled_func_name
This makes a certain amount of sense, since it's missing from the extension module shared library, as it's contained in the separate shared library.
$ nm /ext_mod_path/ext_mod.so | grep __mangled_func_name
U __mangled_func_name
But the extension module library can successfully find the shared common library:
$ ldd /ext_mod_path/ext_mod.so
libmodcommon.so => /user_lib_path/libmodcommon.so (0x...)
And the symbol is defined there
$ nm /user_lib_path/libmodcommon.so | grep __mangled_func_name
000000000002e750 T __mangled_func_name
Why can't the symbol be seen in ext_mod.so?
For reference, the linker command for the extension module is:
g++ -o ext_mod.so -shared -Wl,-rpath=/user_lib_path ext_mod.os -L/user_lib_path -lmodcommon
guys,
I am relatively new to CMake and now I have a bug that I don't understand. Actually I thought I had no problems understanding the terms static and shared library and the functions of CMake. But currently...
So in my project projB I wanna use a static_library from project projA. ProjA is already compiled, linked, installed and used on my board. For ProjB the linker cannot find the library "example".
My issue: for me, i doesn't make sense why projA can find the shared library, projB not.
The error code:
Linking main ....
ld: cannot find -lexample
error: ld returned 1 exit status
My folder structure of projA:
include/ ... *.h (e. g. file.h)
src/ ... *.c (e. g. file.c)
CMakeFiles.txt
The CMakeLists.txt-File of projA:
cmake_minimum_required(VERSION 3.7)
PROJECT(projA)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_definitions(-g -O)
include_directories (include)
file (GLOB SOURCE_FILES src/*.c)
add_library (example STATIC ${SOURCE_FILES})
target_include_directories(example PUBLIC ${SOURCE_DIR}/include)
install(TARGETS example ARCHIVE DESTINATION usr/lib)
So projA will be later a library-component which can be used in many other projects. That's the reason why the created library is not part of projB and why I wanna import/include the created example.a file in a lot of other projects. The static library example.a should be stored in usr/lib.
In my projB the folder structure looks like:
CMakeFiles.txt
main.c
.... *.c
In my main.c-File I try to include the library with #<file.h> which is a part of my created library example.
The CMakeFiles.text of ProjB containing following Code:
cmake_minimum_required(VERSION 3.7)
PROJECT(projB)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set (CMAKE_C_STANDARD 99)
set (CMAKE_CXX_STANDARD 14)
add_definitions(-g -O -fpermissive)
# build executable
file (GLOB SOURCES *.c )
add_executable (exe ${SOURCES})
# target_include_directories(exe PUBLIC ${CMAKE_SOURCE_DIR}/usr/lib)
# add_library(example SHARED IMPORTED)
# set_property(TARGET example PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/usr/libexample.a)
target_link_libraries (exe example pthread)
install (TARGETS exe RUNTIME DESTINATION usr/sbin)
An attempt to find the error is commented out. I also worked with find_library(), but the library "example" could not be found. Of course I also built the library example as a shared_library and searched for a .so, etc.
As you can see from my example, this is not real code (used in production), but a simplified description of my problem. I am more interested in the systematic. Wrong thinking?
Does anyone have any idea what else I can try or why it doesn't work?
Is it because they are different projects? I mean, the file exists on my system, but is not found ...
Thanks a lot for your help!
Greetings
Matthias
I'm building a small local C library for various utility functions, including one to download files via libcurl. I will be using this utils library in various other C applications, but I would like the libcurl details to be hidden from those applications.
I have two cmake projects, "localutils" and "daytrading". localutils is correctly linking to a specific version of libcurl and unit tests are succeeding. This project is being "installed" to /usr/local/lib/localutils and /usr/local/include/localutils. daytrading is finding the localutils library, but I'm seeing "Undefined symbols for architecture x86_64:" errors when building daytrading that refer to the libcurl functions being used.
====================[ Build | update | Debug ]==================================
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake --build /Users/adam/c/daytrading/cmake-build-debug --target update -- -j 2
[ 66%] Built target tradingdays
[ 66%] Built target symbols
[ 83%] Linking C executable ../bin/update
Undefined symbols for architecture x86_64:
"_curl_easy_cleanup", referenced from:
_download_file in libfiles.a(files.c.o)
"_curl_easy_init", referenced from:
_download_file in libfiles.a(files.c.o)
"_curl_easy_perform", referenced from:
_download_file in libfiles.a(files.c.o)
"_curl_easy_setopt", referenced from:
_download_file in libfiles.a(files.c.o)
"_curl_version_info", referenced from:
_download_file in libfiles.a(files.c.o)
"_zip_fclose", referenced from:
_extract_file in libfiles.a(files.c.o)
"_zip_fopen_index", referenced from:
_extract_file in libfiles.a(files.c.o)
"_zip_fread", referenced from:
_extract_file in libfiles.a(files.c.o)
"_zip_get_num_entries", referenced from:
_extract_file in libfiles.a(files.c.o)
"_zip_open", referenced from:
_extract_file in libfiles.a(files.c.o)
"_zip_stat_index", referenced from:
_extract_file in libfiles.a(files.c.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [../bin/update] Error 1
make[2]: *** [CMakeFiles/update.dir/all] Error 2
make[1]: *** [CMakeFiles/update.dir/rule] Error 2
make: *** [update] Error 2
localutils CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(localutils C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ../bin)
include_directories(
/usr/local/opt/curl/include/curl
/usr/local/include)
link_directories(
/usr/local/opt/curl/lib
/usr/local/lib)
add_library(types src/types/comparers.c src/types/dict.c src/types/list.c)
add_library(files src/files/files.c)
find_library(CURL_LIB curl PATH /usr/local/opt/curl/lib NO_DEFAULT_PATH)
find_library(ZIP_LIB zip PATH /usr/local/lib/libzip NO_DEFAULT_PATH)
target_link_libraries(files ${CURL_LIB} ${ZIP_LIB})
add_executable(runtests tests/run.c tests/ListTests.c tests/DictionaryTests.c tests/FileTests.c)
target_link_libraries(runtests types files)
set_target_properties(types PROPERTIES PUBLIC_HEADER "src/types/types.h;src/types/comparers.h;src/types/list.h;src/types/dict.h")
set_target_properties(files PROPERTIES PUBLIC_HEADER "src/files/files.h")
INSTALL(TARGETS types files
ARCHIVE DESTINATION /usr/local/lib/${PROJECT_NAME}
LIBRARY DESTINATION /usr/local/lib/${PROJECT_NAME}
PUBLIC_HEADER DESTINATION /usr/local/include/${PROJECT_NAME})
daytrading CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(daytrading C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ../bin)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
find_library(TYPES_LIB types PATH /usr/local/lib/localutils NO_DEFAULT_PATH)
find_library(FILES_LIB files PATH /usr/local/lib/localutils NO_DEFAULT_PATH)
add_library(symbols src/symbols.c)
add_library(tradingdays src/tradingdays.c)
add_executable(update src/update.c)
target_link_libraries(update symbols tradingdays ${TYPES_LIB} ${FILES_LIB})
I was hoping that all of those libcurl details would be compiled into the "files" library of localutils, and that daytrading wouldn't even be aware that libcurl was involved. So far, the only way I've been able to make anything compile is by adding the same references to libcurl (and libzip) to the daytrading CMakeLists.txt file as well, which I was hoping to avoid.
I'm probably misunderstanding something fundamental about linking in general, or cmake for that matter.
Why building static library (.a) doesn't give any error and works correctly:
$(LIBRARY): assertion.o
$(AR) $(OUTPUT_STATIC_LIB_DIR)/$(LIBRARY) $(OUTPUT_DIR)/assertion.o
Simultaneously, when building shared library (.so) gives me such error:
$(SHARED_LIBRARY): assertion.o
$(CC) $(CFLAGS) -shared -o $(OUTPUT_LIB_DIR)/$(SHARED_LIBRARY) $(OUTPUT_DIR)/assertion.o
Error message:
Undefined symbols for architecture x86_64:
"_float_cmp_func", referenced from:
The code of your library does refer to "_float_cmp_func", which needs to be found at run-time.
But static library is not expected to be a sufficient binary module, it is just collection of object code that is designed to be included into a later build/link steps (together with other object code and libraries).
In contrast, shared library is "ready-to-use" binary module, so its dependencies should be resolved at link stage. So in this case you should add into your link step some module(s) where "_float_cmp_func" is implemented
I try to compile the picoc project into xcode. No external libraries, just .c and .h files that I imported in the Command Line Tool C project.
All .c files compile without issue, but when XCode is linking, I get these messages:
Undefined symbols for architecture x86_64:
"_BasicIOInit", referenced from:
_PicocInitialise in platform.o
"_CStdOut", referenced from:
_PrintSourceTextErrorLine in platform.o
_PlatformVPrintf in platform.o
"_MathFunctions", referenced from:
_IncludeInit in include.o
"_MathSetupFunc", referenced from:
_IncludeInit in include.o
"_PicocPlatformScanFile", referenced from:
_IncludeFile in include.o
...
The command giving the error is the following:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -v -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -L/Users/laurent/Library/Developer/Xcode/DerivedData/Pico-dhfwbamkhiyphjcwuncbwjsyjlax/Build/Products/Debug -F/Users/laurent/Library/Developer/Xcode/DerivedData/Pico-dhfwbamkhiyphjcwuncbwjsyjlax/Build/Products/Debug -filelist /Users/laurent/Library/Developer/Xcode/DerivedData/Pico-dhfwbamkhiyphjcwuncbwjsyjlax/Build/Intermediates/Pico.build/Debug/Pico.build/Objects-normal/x86_64/Pico.LinkFileList -mmacosx-version-min=10.8 -o /Users/laurent/Library/Developer/Xcode/DerivedData/Pico-dhfwbamkhiyphjcwuncbwjsyjlax/Build/Products/Debug/Pico
The Pico.LinkFileList file contains properly the list of all necessary .o files.
As all the unfound functions are in the properly compiled .c files (and compiled as .o), what should I do to avoid these errors ?
Thanks.
Those symbols are in clibrary.c; you must have missed it from the list of source files to compile.
Your next question will doubtless be about libraries to link the executable with, and to solve that I would suggest you look at the Makefile.
Adding Pico to the Target Dependencies list worked for me after the same situation. (from Pico i mean the xcode project folder from where we have created library)
reference :
https://github.com/bulldog2011/pico
In case it can help someone, I found out that some #ifdef commands were excluding the functions to be compiled.