Reputation: 24171
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.
Upvotes: 6
Views: 21037
Reputation: 4626
Use a 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 the top-level CMakeLists.txt instead of the individual subdirectory ones
Upvotes: 3
Reputation: 54777
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.
Upvotes: 5