I want to use CMake to create a simple static library Maths
, and then link to that library to create a simple executable Alpha
.
Here's my directory structure:
/Maths
/build
/
/CMakeLists.txt
/maths.cpp
/maths.h
/Alpha
/build
/
/CMakeLists.txt
/main.cpp
And here are the contents of those files:
* CMakeLists.txt (for Maths) *
cmake_minimum_required(VERSION 2.6)
project(Maths)
add_library(maths STATIC maths.cpp)
* maths.cpp *
int Double(int x)
{
int y = x * 2;
return y;
}
* maths.h *
int Double(int x);
* CMakeLists.txt (for Alpha) *
cmake_minimum_required(VERSION 2.8)
project(Alpha)
add_executable(alpha main.cpp ../Maths/maths.h)
target_link_libraries(maths ../Maths/build/libmaths.a)
* main.cpp *
#include <iostream>
#include "maths.h"
using namespace std;
int main()
{
int x = 5;
int y = Triple(x);
cout << "The answer = " << y << endl;
return 0;
}
So, I enter the directory /Maths/build
, and run cmake ..
. Then, I run make
. This creates the library file libmaths.a
in the directory /Maths/build
.
Then, I enter the directory /Alpha/build
, and run cmake ..
. Then, I run make
. However, this gives me the error message:
/usr/bin/ld: cannot find -lmaths
Why can make not find the library file that I just created?
I also tried copyiing libmaths.a
and maths.h
into the directory /Alpha
, and changing Alpha's CMakeLists.txt to:
cmake_minimum_required(VERSION 2.8)
project(Alpha)
add_executable(alpha main.cpp maths.h)
target_link_libraries(maths libmaths.a)
But this gave the same error.
To add a library in CMake, use the add_library() command and specify which source files should make up the library. Rather than placing all of the source files in one directory, we can organize our project with one or more subdirectories. In this case, we will create a subdirectory specifically for our library.
CMakeLists. txt is placed at the root of the source tree of any application, library it will work for. If there are multiple modules, and each module can be compiled and built separately, CMakeLists. txt can be inserted into the sub folder.
link_directories([AFTER|BEFORE] directory1 [directory2 ...]) Adds the paths in which the linker should search for libraries. Relative paths given to this command are interpreted as relative to the current source directory, see CMP0015 . The command will apply only to targets created after it is called.
This tells CMake that the RUNTIME file (. dll) should be installed to bin , the LIBRARY file (. so) should be installed to lib , and the ARCHIVE (. lib) file should be installed to lib/myproject .
The essential problem here is that libmaths.a
is not placed in one of the default linker directories.
The bigger problem is that you passed libmaths.a
to target_link_libraries
in the first place.
This is bad for several reasons, but the most obvious is that it's completely non-portable. A different compiler toolchain might use a different ending than .a
for static libraries, so you won't be able to build there. Also, should you ever decide to switch to dynamic linking in the future, it means refactoring your existing CMake scripts.
The proper solution is to not pass hardcoded filenames to target_link_libraries
. There are two roads that you can take to avoid this.
Use a find script. Essentially, you call find_library(MY_MATHLIB maths [...])
and then do target_link_libraries(alpha ${MY_MATHLIB})
instead. This will determine the absolute path of the .a
file in a portable way and pass that to the linker. The biggest disadvantage of this approach is that the .a
file must already be there for the find call to succeed. So if you want to build maths
after running the CMake for alpha
or build it as part of alpha
, this won't work.
Since both libraries are under your control, consider using CMake's packaging mechanism. This is by far the most convenient approach for building, but unfortunately also the most difficult to set up. If you are willing to spend some time digging through the CMake docs and experimenting with the build, I encourage you to give it a try, but if you just want something that works quickly, you might want to stick with option 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With