0

I am trying to install a custom library with CMake.

It consists of 2 'sub-libraries' and a main header file which includes the 'sub-libraries'.

I think it installs okay (The output looks like this:)

-- Configuring done
-- Generating done
-- Build files have been written to: /home/pi/Desktop/Projects/MaxLib/build
[ 20%] Building CXX object Geom/CMakeFiles/Geom.dir/Geom.cpp.o
[ 40%] Linking CXX shared library libGeom.so
[ 40%] Built target Geom
[ 60%] Building CXX object File/CMakeFiles/File.dir/File.cpp.o
[ 80%] Linking CXX shared library libFile.so
[ 80%] Built target File
[100%] Built target MaxLib
Install the project...
-- Install configuration: "Debug"
-- Installing: /usr/local/lib/libMaxLib.a
-- Installing: /usr/local/include/MaxLib.h
-- Installing: /usr/local/include/MaxLib/File.h
-- Installing: /usr/local/include/MaxLib/Geom.h

However, when I try to compile a program using it, I receive a number of "undefined reference to" errors. Where have I gone wrong?

The Main Header looks like:

#include "MaxLib/File.h"
#include "MaxLib/Geom.h"

It's CMakefile looks like this:

cmake_minimum_required(VERSION 3.5)

project(MaxLib)

add_library(${PROJECT_NAME}
    "${CMAKE_CURRENT_SOURCE_DIR}/MaxLib.h"
)

add_subdirectory(File)
add_subdirectory(Geom)
target_link_libraries(${PROJECT_NAME} File)
target_link_libraries(${PROJECT_NAME} Geom)

# Install Library
install (TARGETS ${PROJECT_NAME}
    LIBRARY DESTINATION lib)

# Install Main Header File
INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/MaxLib.h" DESTINATION include) # 
INSTALL(FILES ...) or install(DIRECTORY ...) 

# Build list of header files to install from other directorys. Root == "."
set(HEADER_DIRS "File" "Geom")
## Add Source Files from the other directories
foreach(DIR ${HEADER_DIRS})
    # Find all source files & append to list
    if(DIR STREQUAL ".")
        file(GLOB HEADER_FILES_IN_FOLDER *.h)
    else()
        file(GLOB HEADER_FILES_IN_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/${DIR}/*.h)
    endif()
    list(APPEND HEADER_FILES ${HEADER_FILES_IN_FOLDER})
endforeach()
# Install Header files
INSTALL(FILES ${HEADER_FILES} DESTINATION include/${PROJECT_NAME}) # INSTALL(FILES ...) or install(DIRECTORY ...) 

target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -g) 
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)

The 'sub-libraries's CMakefiles look like this:

project(Geom)

add_library(${PROJECT_NAME} SHARED
    ${CMAKE_CURRENT_SOURCE_DIR}/Geom.cpp
)

target_include_directories(${PROJECT_NAME}
    PUBLIC 
        ${CMAKE_CURRENT_SOURCE_DIR}
)

I am trying to include the library like this:

#include <MaxLib.h>

And I am adding -lMaxLib to its makefile

Edit:

A basic program like this:

#include <MaxLib.h>

int main() {
    float y1 = MaxLib::Geom::CleanAngle(7654);
}

Will produce the undefined reference error:

/usr/bin/ld: warning: libFile.so, needed by //usr/local/lib/libMaxLib.so, not found (try using -rpath or -rpath-link) // This shows when add_library marked SHARED
/usr/bin/ld: warning: libGeom.so, needed by //usr/local/lib/libMaxLib.so, not found (try using -rpath or -rpath-link) // This shows when add_library marked SHARED
/home/pi/Desktop/Projects/TestProgram/main.cpp:43: undefined reference to `MaxLib::Geom::CleanAngle(double)'
  • Despite you link MaxLib library with `Geom` and `File`, those libraries are NOT incorporated into MaxLib. Also, as MaxLib is a **static** library (`.a`), it doesn't remember linkage with other libraries. So if your program uses functions from Geom, it need to be **explicitly** linked to it, linkage with MaxLib is not sufficient. You may define MaxLib as a **shared** library (using SHARED keyword), so it will remember linkage. But in that case Geom and File should also be installed or somehow accessible when you link and run your program. – Tsyvarev Jun 04 '22 at 20:50
  • @Tsyvarev I have added SHARED to "add_library()" and it now is a ".so" but this doesn't seem to fix it. Is there something else I have missed? – Max Peglar-Willis Jun 04 '22 at 21:07
  • It depends on what exact "undefined reference to" you got, and where exactly these symbols are defined. Please, add **more details** about your error into the question post: the exact error message, the exact code which defines missed symbols and so on. In the current state we could only **guess** what is your problem. Ideally, we want a [mcve]. – Tsyvarev Jun 04 '22 at 21:39
  • @Tsyvarev I have updated the question. It seems to not find .so files for file and geom (which i have purposely not created), I was hoping that i could have the library static and only require a single MaxLib.so file? – Max Peglar-Willis Jun 04 '22 at 21:58
  • Have you read my [first comment](https://stackoverflow.com/questions/72502782/custom-cmake-library-what-have-i-done-wrong?noredirect=1#comment128077599_72502782) till the end? "But in that case Geom and File should also be installed or somehow accessible when you link and run your program." You cannot incorporate a shared libraries (`Geom` and `File`) into another library. – Tsyvarev Jun 04 '22 at 22:16
  • Sorry I am new to all this and it didn't really make sense to me before. So are you saying that you cannot have a single .so / .a file which you link to, regardless of whether the sub-libraries are shared or static? – Max Peglar-Willis Jun 04 '22 at 22:27
  • What I want is a single library I can link to, what is the best way to acheive this? – Max Peglar-Willis Jun 04 '22 at 22:34
  • You cannot combine **shared** libraries into the single one: https://stackoverflow.com/questions/915128/merge-multiple-so-shared-libraries. You can combine **static** libraries into the single one: https://stackoverflow.com/questions/37924383/combining-several-static-libraries-into-one-using-cmake. If you don't want `Geom` (and `File`) to be packed into a separate library file, then you could create it as `OBJECT` library, or don't create it at all. – Tsyvarev Jun 04 '22 at 23:01

0 Answers0