3

I'm new to building with CMake. I'm using Ubuntu and I have a .cpp file (say xyz.cpp located somewhere in ~/mydir) which links to three custom shared libraries (libA.so, libB.so & libC.so libraries). These three *.so files are located in /usr/local/lib.

I want to create a CMakeLists.txt to get this compiled. The below script throws errors like:

cmake_minimum_required(VERSION 3.11)
project(xyz VERSION 1.0.0 LANGUAGES C CXX)

# Set C standard to C11
set(CMAKE_C_STANDARD 11)

set(SOURCES src/xyz.cpp)

include_directories(/usr/local/include)

#For the shared library:

target_link_libraries(libA -L/usr/local/lib/)
target_link_libraries(libB -L/usr/local/lib/)
target_link_libraries(libC -L/usr/local/lib/)

target_link_libraries(xyz libA libB libC )
add_executable(xyz src/xyz.cpp)

ERROR:

CMake Error at CMakeLists.txt: (target_link_libraries):

   Cannot specify link libraries for target "libA" which is not built
   by this project.


 -- Configuring incomplete, errors occurred!
Kevin
  • 16,549
  • 8
  • 60
  • 74
codeLover
  • 3,720
  • 10
  • 65
  • 121
  • 2
    1) `target_link_libraries` should follow `add_executable`; 2) you don't need `target_link_libraries(libA...)` at all; 3) to add link directories, use `target_link_directories`. – Evg Apr 28 '20 at 19:13

1 Answers1

4

A couple important notes:

  1. The first argument to target_link_libraries() should be a valid CMake target, created by add_library() or add_executable(). Therefore, any target_link_libraries() call should be placed after the add_executable() call in your code.
  2. You only need one call to target_link_libraries() to link all of your *.so libraries to the executable. The first three calls are unnecessary (and invalid because libA, libB, and libC are all undefined). You should provide the full path to each of these libraries to ensure that the correct library is used.
  3. It is good practice to include the scoping argument in target_* calls, such as target_link_libraries(). This specifies whether the libraries are linked-to (PRIVATE), added to the link interface (INTERFACE), or both (PUBLIC). This distinction becomes more important as your CMake project grows to include more targets.

With these notes, and a few others commented below, your CMake file could look something like this:

cmake_minimum_required(VERSION 3.11)

# No need to specify C and CXX for LANGUAGES here, these are enabled by default!
project(xyz VERSION 1.0.0)

# Set C standard to C11
set(CMAKE_C_STANDARD 11)

set(SOURCES src/xyz.cpp)

include_directories(/usr/local/include)

# Define your executable target. You can pass in the SOURCES variable defined above.
add_executable(xyz ${SOURCES})

# Link the other libraries to your executable, using their full path.
# Note, the '-L' flag is not necessary.
target_link_libraries(xyz PRIVATE 
    /usr/local/lib/libA.so
    /usr/local/lib/libB.so
    /usr/local/lib/libC.so
)
Kevin
  • 16,549
  • 8
  • 60
  • 74