Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake cannot find my library file

Tags:

cmake

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.

like image 675
Karnivaurus Avatar asked Oct 06 '14 18:10

Karnivaurus


People also ask

How do I add a library to CMake project?

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.

Where is CMakeLists TXT located?

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.

What is Link_directories?

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.

Where do I put CMake file?

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 .


1 Answers

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.

  1. 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.

  2. 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.

like image 130
ComicSansMS Avatar answered Sep 18 '22 16:09

ComicSansMS