Paul
Paul

Reputation: 2728

Why won't a CMake-generated Makefile find an external library?

I'm attempting to use CMake for the first time and meeting with little success. My CMakeLists.txt is:

# Sets the version of CMake that is required.
cmake_minimum_required(VERSION 2.8.10)

# Name of the project.
project(QTCODERLIB)

# Adds common directories to the build.
include_directories(/usr/local/include)
link_directories(/usr/local/lib)

# Check for header files that we depend on.
include(CheckIncludeFiles)
check_include_files(libavcodec/avcodec.h HAVE_AVCODEC_H)

# Adds all of the source files.
file(GLOB SOURCE RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cxx)

# Builds a library named `qtcoder` from source.
add_library(qtcoder SHARED ${SOURCE})

# Links the library against third-party dependencies.
target_link_libraries(qtcoder avcodec)

My test.cxx file is:

#include "config.h"
#include <libavcodec/avcodec.h>

void f(void) {
  avcodec_register_all();
}

cmake . && make VERBOSE=1 results in this:

/usr/local/Cellar/cmake/2.8.10.1/bin/cmake -H/Users/phowes/Personal/QTCoder/QTCoderLib -B/Users/phowes/Personal/QTCoder/QTCoderLib --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/Cellar/cmake/2.8.10.1/bin/cmake -E cmake_progress_start /Users/phowes/Personal/QTCoder/QTCoderLib/CMakeFiles /Users/phowes/Personal/QTCoder/QTCoderLib/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make -f CMakeFiles/qtcoder.dir/build.make CMakeFiles/qtcoder.dir/depend
cd /Users/phowes/Personal/QTCoder/QTCoderLib && /usr/local/Cellar/cmake/2.8.10.1/bin/cmake -E cmake_depends "Unix Makefiles" /Users/phowes/Personal/QTCoder/QTCoderLib /Users/phowes/Personal/QTCoder/QTCoderLib /Users/phowes/Personal/QTCoder/QTCoderLib /Users/phowes/Personal/QTCoder/QTCoderLib /Users/phowes/Personal/QTCoder/QTCoderLib/CMakeFiles/qtcoder.dir/DependInfo.cmake --color=
make -f CMakeFiles/qtcoder.dir/build.make CMakeFiles/qtcoder.dir/build
/usr/local/Cellar/cmake/2.8.10.1/bin/cmake -E cmake_progress_report /Users/phowes/Personal/QTCoder/QTCoderLib/CMakeFiles 1
[100%] Building CXX object CMakeFiles/qtcoder.dir/test.cxx.o
/usr/bin/c++   -Dqtcoder_EXPORTS -fPIC -I/usr/local/include    -o CMakeFiles/qtcoder.dir/test.cxx.o -c /Users/phowes/Personal/QTCoder/QTCoderLib/test.cxx
Linking CXX shared library libqtcoder.dylib
/usr/local/Cellar/cmake/2.8.10.1/bin/cmake -E cmake_link_script CMakeFiles/qtcoder.dir/link.txt --verbose=1
/usr/bin/c++   -dynamiclib -Wl,-headerpad_max_install_names   -o libqtcoder.dylib -install_name /Users/phowes/Personal/QTCoder/QTCoderLib/libqtcoder.dylib CMakeFiles/qtcoder.dir/test.cxx.o  -L/usr/local/lib -lavcodec 
Undefined symbols for architecture x86_64:
  "avcodec_register_all()", referenced from:
      f() in test.cxx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [libqtcoder.dylib] Error 1
make[1]: *** [CMakeFiles/qtcoder.dir/all] Error 2
make: *** [all] Error 2

Both the object file and the library are compiled as 64-bit:

$ lipo -info CMakeFiles/qtcoder.dir/test.cxx.o
Non-fat file: CMakeFiles/qtcoder.dir/test.cxx.o is architecture: x86_64

$ lipo -info /usr/local/lib/libavcodec.dylib
Non-fat file: /usr/local/lib/libavcodec.dylib is architecture: x86_64

The function exists in the library:

$ nm /usr/local/lib/libavcodec.dylib | grep avcodec_register_all
0000000000033c01 T _avcodec_register_all

What am I doing wrong here?

Upvotes: 2

Views: 1084

Answers (2)

Ryan Maloney
Ryan Maloney

Reputation: 552

The avcodec libary is a C library and looking at your cmake output you are compiling for CXX. This question addresses how to handle precisely that scenario: g++ Linking Error on Mac while compiling FFMPEG

Upvotes: 2

Tom Kerr
Tom Kerr

Reputation: 10720

Usually you'd use find_package to do these sorts of heavy lifting tasks. CMake ships with a lot of modules by default, but sometimes you have to download one for less used projects.

Here is some documentation on how to find libraries.

Here is their contrived example of what you'd expect to see.

cmake_minimum_required(VERSION 2.8)
project(helloworld)
add_executable(helloworld hello.c)
find_package (BZip2)
if (BZIP2_FOUND)
  include_directories(${BZIP_INCLUDE_DIRS})
  target_link_libraries (helloworld ${BZIP2_LIBRARIES})
endif (BZIP2_FOUND)

From simple web searches it isn't clear to me that CMake provides an AVCodec module. I found a few online:

https://github.com/arjanhouben/SDL_ffmpeg/blob/master/Findavcodec.cmake http://whispercast.org/trac/browser/trunk/cmake/FindLibAvCodec.cmake

I see most people using this library are interested in FFMPEG, which maybe is what you are interested too.

https://github.com/zinnschlag/openmw/blob/master/cmake/FindFFMPEG.cmake

If you do need to use one that you download, here are some instructions for how to use custom modoules.

Upvotes: 1

Related Questions