CMake cannot find my library file
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 go into the directory /Maths/build
and run cmake ..
. Then I ran make
. This creates a library file libmaths.a
in the directory /Maths/build
.
Then I go into the directory /Alpha/build
and run cmake ..
. Then I ran make
. However, this gives me an error:
/usr/bin/ld: cannot find -lmaths
Why can't I find the library file I just created?
I also tried to copy libmaths.a
and maths.h
to directory /Alpha
and change Alpha 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.
source to share
The significant issue is that it libmaths.a
doesn't fit in one of the default linker directories. The big problem is what you moved libmaths.a
to target_link_libraries
.
This is bad for several reasons, but the most obvious one is that it is not completely portable. Another compiler toolchain might use a different end than .a
for static libraries, so you won't be able to build it. Also, if you ever decide to switch to dynamic linking in the future, it means reorganizing existing CMake scripts.
The correct solution is not to pass hard-coded filenames to target_link_libraries
. There are two paths you can take to avoid this.
-
Use find script. Essentially, you call
find_library(MY_MATHLIB maths [...])
and then executetarget_link_libraries(alpha ${MY_MATHLIB})
. This will figure out the absolute path of the file in a.a
portable way and pass it to the linker. The biggest disadvantage of this approach is that the file.a
must already be available for a successful search. So if you want to buildmaths
after running CMake for,alpha
or build it as a partalpha
, it won't work. -
Since both libraries are under your control, consider using the CMake packaging mechanism . This is by far the most user-friendly approach to build, but unfortunately also the hardest to set up. If you're willing to spend some time researching the CMake docs and experimenting with build, I recommend you give it a try, but if you just want something that works fast, you might want to stick with option 1.
source to share
Use CMakeLists.txt
in the root directory
/CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT( MyProject )
ADD_SUBDIRECTORY( Maths )
ADD_SUBDIRECTORY( Alpha )
in Alpha / CMakeLists.txt:
TARGET_LINK_LIBRARIES( alpha maths )
Run CMake on top level CMakeLists.txt instead of separate subdirectories
source to share