138

I have a small project with a Makefile which I'm trying to convert to CMake, mostly just to get experience with CMake. For purposes of this example, the project contains a source file (C++, though I don't think the language is particularly relevant) and a static library file which I've copied from elsewhere. Assume for argument's sake that the source code to the library is unavailable; I only have the .a file and the corresponding header.

My handmade Makefile contains this build rule:

main: main.o libbingitup.a
    g++ -o main main.o libbingitup.a

which works fine. How do I tell CMake to reproduce this? Not literally this exact makefile, of course, but something that includes an equivalent linking command. I've tried the obvious but naive ways, like

add_executable(main main.cpp libbingitup.a)

or

add_executable(main main.cpp)
target_link_libraries(main libbingitup.a)

as well as various things with link_directories(.) or add_library(bingitup STATIC IMPORTED) etc. but nothing so far that results in a successful linkage. What should I be doing?


Version details: CMake 2.8.7 on Linux (Kubuntu 12.04) with GCC 4.6.3

David Z
  • 128,184
  • 27
  • 255
  • 279

4 Answers4

158

CMake favours passing the full path to link libraries, so assuming libbingitup.a is in ${CMAKE_SOURCE_DIR}, doing the following should succeed:

add_executable(main main.cpp)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a)
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • 2
    Great, that works, thanks! It seems a little hackish to have to put in the full path explicitly here, but I guess that's just the CMake way... – David Z Dec 29 '12 at 04:10
  • 4
    I agree it seems like overkill here, but explicitly specifying the full path pays dividends if you have multiple different versions of the same lib installed. – Fraser Dec 29 '12 at 04:16
  • 1
    Amazing, as usual! In my case, solved a problem of libraries depending on another built dynamic library which was depending on a static library: the depending libraries were also trying to link to this static library. – Antonio Nov 04 '15 at 15:45
  • 2
    How does main know about the include directories? – ManuelSchneid3r Mar 30 '16 at 13:00
  • 5
    You'd need to use [`target_include_directories`](https://cmake.org/cmake/help/v3.5/command/target_include_directories.html) or [`include_directories`](https://cmake.org/cmake/help/v3.5/command/include_directories.html) (the former is the preferred way as it's more specific). – Fraser Mar 30 '16 at 13:13
  • @Fraser: That makes no sense. Include directories are for the compiler, and contain header files. This is a library file, for the linker. Different tool, different type of file. – MSalters Sep 05 '17 at 12:38
  • 1
    @MSalters I was answering the comment above mine rather than the OP when I mentioned `target_include_directories` - I agree that it makes no sense to pass library files in that call. – Fraser Sep 06 '17 at 13:33
  • Don't forget to add any other dependences (e.g. shared libraries like pthreads) that `libbingitup.a` depends on! – Anastasios Andronidis Nov 26 '21 at 20:10
42

If you don't want to include the full path, you can do

add_executable(main main.cpp)
target_link_libraries(main bingitup)

bingitup is the same name you'd give a target if you create the static library in a CMake project:

add_library(bingitup STATIC bingitup.cpp)

CMake automatically adds the lib to the front and the .a at the end on Linux, and .lib at the end on Windows.

If the library is external, you might want to add the path to the library using

link_directories(/path/to/libraries/)
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • 3
    And if there are .a and .so files with the same name how you specify you want to link against the .a or the .so in this case? – George Oct 18 '19 at 07:15
  • 4
    @George: You can't. If you have both types present, include the full name of the file you want to link against. – Cris Luengo Oct 18 '19 at 16:35
28

I found this helpful...

http://www.cmake.org/pipermail/cmake/2011-June/045222.html

From their example:

ADD_LIBRARY(boost_unit_test_framework STATIC IMPORTED)
SET_TARGET_PROPERTIES(boost_unit_test_framework PROPERTIES IMPORTED_LOCATION /usr/lib/libboost_unit_test_framework.a)
TARGET_LINK_LIBRARIES(mytarget A boost_unit_test_framework C)
stu
  • 8,461
  • 18
  • 74
  • 112
  • 4
    What about INCLUDE_DIRECTORIES? – kyb Jun 07 '19 at 11:07
  • 1
    This only works if the library is part of the cmake build, but foreign ones this does not work – daparic Apr 01 '20 at 11:44
  • 1
    the question says "the project contains a source file (C++, though I don't think the language is particularly relevant) and a static library file which I've copied from elsewhere." – stu Apr 02 '20 at 17:04
1

I want to add to the other comments, the project name is the first argument. I had a project called cmakecompile and i wanted to add libusb to it, the code is as follows,

add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")

the project had just only a main.c file, the first parameter in target_link_libraries is the name of your project and the second parameter is the path of the library.

Note that may help: Since i am compiling under windows, i had to install msys2 because the library you have has to be compiled with the same compiler. For example if you get libusb and try to use it in a qt-creator project, it will not work and you may get unreferenced functions, therefore i had to install msys2 and install libusb from inside msys2, install make and create a QT Cmake project and compile from Qt creator using the msys2 make.

The full cmakelists.txt is as follow

cmake_minimum_required(VERSION 3.5)

project(cmakecompile LANGUAGES C)

add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")
Sherif O.
  • 506
  • 4
  • 15
  • This seems to be saying basically the same thing as [Fraser's answer](https://stackoverflow.com/a/14078232/56541). If you meant to expand on that other answer with additional information, could you clarify what you meant to add and why you found it to be necessary? – David Z Mar 07 '21 at 22:35
  • I am adding other details, which is important, such as which path to follow if this is for qt and not visual studio. Also what is the minimum cmake content needed for it to get it compiled. I remember i struggled once 2d days to find these information and that is why i provide it for the community. – Sherif O. Mar 08 '21 at 08:25
  • Thanks @DrlSherifOmran for showing the explicit directory form. – EndsOfInvention Jul 26 '21 at 20:25