149

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

5 Answers 5

166

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) 
Sign up to request clarification or add additional context in comments.

8 Comments

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...
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.
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.
How does main know about the include directories?
You'd need to use target_include_directories or include_directories (the former is the preferred way as it's more specific).
|
44

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/) 

2 Comments

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: You can't. If you have both types present, include the full name of the file you want to link against.
30

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) 

3 Comments

What about INCLUDE_DIRECTORIES?
This only works if the library is part of the cmake build, but foreign ones this does not work
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."
2

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") 

3 Comments

This seems to be saying basically the same thing as Fraser's answer. 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?
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.
Thanks @DrlSherifOmran for showing the explicit directory form.
1

Because cmake pass anything starts with a "-" directly to the compiler, for GCC, you can use the linker flag "-Wl,-Bstatic" to tell it to link static library explicitly. The "-Wl,-Bdynamic" in the end is necessary, gcc will try to static link everything else otherwise.

target_link_libraries(main -Wl,-Bstatic bingitup -Wl,-Bdynamic) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.