0

I have am trying to link a precompiled so file to my executable in cmake. I'm not sure if I am misunderstanding how to use a shared library or not but I assumed that once I compile a shared library, any application can link to it and use it's functions. When compiling the executable, I get this error:

logger.h: No such file or directory
 #include "logger.h"
          ^~~~~~~~~~
compilation terminated.

Here is my cmake file for the executable

cmake_minimum_required(VERSION 2.8)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# set PROJECT home directory 
set(PROJECT_HOME "/opt/PROJECT")

# set the project name
project(ClServer)

# add the executable
add_executable(ClServer server.cpp)

add_library(logger SHARED IMPORTED libClLogger.so)

message ("Here")

set_target_properties(logger
PROPERTIES IMPORTED_LOCATION "#{PROJECT_HOME}/base"
)

target_link_libraries(ClServer
${Logger}
)

I've also tried using find_library and adding an absolute path to the shared library using target_link_libraries, but the same error occurs.

Here is my cmake file for the logger shared library:

cmake_minimum_required(VERSION 2.8)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# set Clamor home directory 
set(PROJECT_HOME "/opt/PROJECT")

# set the project name
project(ClLogger)

# set boost paths
set(Boost_NO_SYSTEM_PATHS TRUE)
if (Boost_NO_SYSTEM_PATHS)
    set(BOOST_ROOT "${PROJECT_HOME}/ext/Boost/boost_1_76_0")
    set(BOOST_LIBRARYDIR "${PROJECT_HOME}/ext/Boost/boost_1_76_0/stage/lib")
    set(BOOST_INCLUDEDIR "${PROJECT_HOME}/ext/Boost/boost_1_76_0")
endif (Boost_NO_SYSTEM_PATHS)

# provides the linker with the appropriate directories and components
find_package(Boost 1.76.0 COMPONENTS log log_setup thread filesystem system)
if(Boost_FOUND)
  include_directories(${BOOST_INCLUDEDIR})
  link_directories(${BOOST_LIBRARYDIR})
endif()

message (STATUS Boost_LIBRARIES:)
message (STATUS ${Boost_LIBRARIES})
message (STATUS BOOST_INCLUDEDIR:)
message (STATUS ${BOOST_INCLUDEDIR})

# add PROJECT source code libraries
add_library(ClLogger SHARED logger.cpp)

# link the appropriate libraries
target_link_libraries(ClLogger
libpthread.so.0
${Boost_LIBRARIES}
)

# redirect binaries to base folder
set_target_properties(ClLogger
    PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_HOME}/base"
    LIBRARY_OUTPUT_DIRECTORY "${PROJECT_HOME}/base"
    RUNTIME_OUTPUT_DIRECTORY "${PROJECT_HOME}/base"
)
Milos
  • 167
  • 1
  • 11
  • You need to add **include directory** which contains the required header (`logger.h`). You could do that either by "generic way", following on of the answers for [that question](https://stackoverflow.com/questions/13703647/how-to-properly-add-include-directories-with-cmake). Or you could do that via IMPORTED library target which you have, using property `INTERFACE_INCLUDE_DIRECTORY`, similar to [that question](https://stackoverflow.com/questions/25907478/possible-to-add-an-imported-library-to-target-link-libraries-that-takes-care-of). – Tsyvarev Aug 15 '21 at 11:52
  • Also note, that in CMake **targets** and **variables** are different things. Expression `${Logger}` dereferences `Logger` **variable** which you have never defined. Instead use `target_link_libraries(ClServer Logger)` for link with the IMPORTED **target**. – Tsyvarev Aug 15 '21 at 11:55

2 Answers2

0

After a bit of research and testing in my local machine,
i have updated my answer with the simple example tested on eclipse CDT and cmake in WSL2.(should work on any other environment fine ).
the following example should provide an answer to the question.

 cmake_test/
 ├── CMakeLists.txt
 ├── build
 ├── cmake_test.cpp
 └── **companyLibrary**
     ├── CMakeLists.txt
     ├── build
     ├── include
     │   └── Company.h
     └── src
         └── Company.cpp  

from the above project hierarchy companyLibrary is the one which generates the .so (shared Library), which will be used by cmake_test.cpp source file which is at the root level of the project.

cmake_test/companyLibrary/CMakeLists.txt

 cmake_minimum_required (VERSION 2.6)

 project (companyLibrary_test)
 set(CMAKE_BUILD_TYPE Release)

 #adding the header <.h> files into the project
 include_directories(include)

 file(GLOB SOURCES "src/*.cpp")

 add_library(testCompany SHARED ${SOURCES})

 install(TARGETS testCompany DESTINATION /usr/lib)  

this generates the .so file in this example (libtestCompany.so)

 sudo make install  

this will put .so file in /usr/lib folder

now this shared library will be used by the root project cmake_test.cpp file

cmake_test/CMakeLists.txt

cmake_minimum_required (VERSION 2.6)

project (cmake_test)

set ( PROJECT_LINK_LIBS libtestCompany.so )
link_directories( "/usr/lib" )
include_directories( "companyLibrary/include" )

add_executable( libtest cmake_test.cpp )
target_link_libraries( libtest ${PROJECT_LINK_LIBS} )  

add_executable and target_link_libraries should solve the problem as show above.

full source code availabe here on GitHub.

hope it helps :)

Abhishek D K
  • 2,257
  • 20
  • 28
  • This did not work, it produced the same error. Do I need to add something to cmake file that compiles the logger shared library or to the logger header file in order to allow it to be exported? I'm sure I am just missing something small – Milos Aug 15 '21 at 05:05
  • target_link_libraries(ClServer PRIVATE logger) – Abhishek D K Aug 15 '21 at 05:11
  • can you add the above statement and run again, let me know – Abhishek D K Aug 15 '21 at 05:11
  • This also did not solve it. I added the other cmake file for more context – Milos Aug 15 '21 at 05:20
  • @milos miladinov sorry , took more time to come with proper working example, hope it works as i tested it on my machine . – Abhishek D K Aug 21 '21 at 12:11
0

To consume a shared library, you need two things. First, shared library file and second public header file. Header file will get used in compilation stage and shared library file in linking stage. Error you are seeing is a compilation failure which says it failed to find header file "logger.h". Use target_include_directories in cmake of your executable to tell cmake where to look for header logger.h. Additionally if you want cmake to keep watch on logger.h modification, you can add logger.h as source file of your executable.

nkvns
  • 580
  • 3
  • 5