11

I'd like to play around with the Allegro library, but I can't seem to get my test project to link properly. To be exact, I'm getting cannot find -l<...> errors, where <...> is a file I specified using target_link_libraries. (See below for details.)

For the record, I'm not all that knowledgeable about the build process, and my usual approach to it is "click a button and hope an executable pops up, if not, resort to trial and error." I've found quite a lot of similar questions on here, but it seems that either the problems or the solutions are different from what I'm experiencing. I'm hoping for a definite "here's what you're doing wrong, and here's what to do instead".

That said, this is my project structure:

/include
/lib
/src
    main.cpp
CMakeLists.txt

The include and lib directories I copied from the Allegro binary package, and lib is where all the .a files reside.

Here's what my CMakeLists.txt says:

cmake_minimum_required(VERSION 3.2)
project(AllegroTest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -static-libgcc -static-libstdc++ -fpermissive")
add_definitions( -DALLEGRO_STATICLINK )

file(GLOB SOURCES src/*.cpp)
set(SOURCE_FILES ${SOURCES})
add_executable(AllegroTest ${SOURCE_FILES})

include_directories(include)

target_link_libraries(AllegroTest
    liballegro-5.0.10-static-mt.a
    liballegro_acodec-5.0.10-static-mt.a
    liballegro_audio-5.0.10-static-mt.a
    libvorbisfile-1.3.2-static-mt.a
    libvorbis-1.3.2-static-mt.a
    liballegro_color-5.0.10-static-mt.a
    liballegro_dialog-5.0.10-static-mt.a
    liballegro_font-5.0.10-static-mt.a
    liballegro_image-5.0.10-static-mt.a
    liballegro_memfile-5.0.10-static-mt.a
    liballegro_physfs-5.0.10-static-mt.a
    liballegro_primitives-5.0.10-static-mt.a
    liballegro_ttf-5.0.10-static-mt.a
    libdumb-0.9.3-static-mt.a
    libFLAC-1.2.1-static-mt.a
    libfreetype-2.4.8-static-mt.a
    libogg-1.2.1-static-mt.a
    libzlib-1.2.5-static-mt.a
    libopenal-1.14-static-mt.a
)

target_link_libraries(AllegroTest
    libgdiplus.a
    libuuid.a
    libkernel32.a
    libwinmm.a
    libpsapi.a
    libopengl32.a
    libglu32.a
    libuser32.a
    libcomdlg32.a
    libgdi32.a
    libshell32.a
    libole32.a
    libadvapi32.a
    libws2_32.a
    libshlwapi.a
)

And these are the errors I'm getting:

c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro-5.0.10-static-mt
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro_acodec-5.0.10-static-mt
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lallegro_audio-5.0.10-static-mt
<etc.>

I've tried specifying the path in every way imaginable — including combining it with the usage of link_directories(lib) — but nothing seems to have any effect.

The only thing that did work is specifying the absolute path (C:/Users/<...>/lib/liballegro-5.0.10-static-mt.a), but it occurs to me that this is far from the ideal way.

What mistake am I making here, and what's the recommended way to fix it?

Fraser
  • 74,704
  • 20
  • 238
  • 215
vvye
  • 1,208
  • 1
  • 10
  • 25

2 Answers2

9

The way I'd recommend is to use the absolute path. I'm not sure why you see this as far from ideal; it's trivial to achieve:

target_link_libraries(AllegroTest
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro-5.0.10-static-mt.a
    ${CMAKE_CURRENT_SOURCE_DIR}/lib/liballegro_acodec-5.0.10-static-mt.a
    etc.
)
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • I feel that with absolute paths the project would no longer be self-contained and instead rely on its environment. I suppose `CMAKE_CURRENT_SOURCE_DIR` is a way around that, so thanks for mentioning that. Is there really no way to work with truly relative paths, though? It seems to me like there should be. – vvye May 16 '15 at 13:15
  • 1
    I would have expected the `link_directories(lib)` to fix this to be honest, but the use of `link_directories` is discouraged - even in its [own documentation](http://www.cmake.org/cmake/help/v3.2/command/link_directories.html). It's very common to find instances of `CMAKE_SOURCE_DIR` and `CMAKE_CURRENT_SOURCE_DIR` - I think this is good practice actually. It saves you having to check docs for commands where you're not sure if they treat paths as relative to the source root or the build root. – Fraser May 16 '15 at 13:19
  • At least now I understand your reluctance if you'd thought you'd have to hard-code absolute paths from your own machine - that indeed should be avoided at all costs :) – Fraser May 16 '15 at 13:21
  • 1
    As an alternative, you can always insert an additional [`find_library` call](http://www.cmake.org/cmake/help/v3.2/command/find_library.html) that takes the hardcoded `${CMAKE_CURRENT_SOURCE_DIR}/lib/...` as a hint, along with a second hint that is customizable by the user. I personally like to set aside an environment variable that allows the user to inject a custom path for libraries which takes precedence over any hardcoded paths. – ComicSansMS May 18 '15 at 08:36
  • Also don't forget to clear the cmake cache. Sometimes you need to do it manually to fixup configuration quirks. – Montdidier May 25 '15 at 03:58
1

I've done similar things before, what I do is like this:

link_directories(lib)
target_link_libraries(my_target
    allegro-5.0.10-static-mt
    allegro_acodec-5.0.10-static-mt
    ...
)

notice that there are no leading lib and trailing .a.

Ziming Song
  • 1,176
  • 1
  • 9
  • 22
  • I'm not downvoting since this should work, but the [docs for `link_directories`](http://www.cmake.org/cmake/help/v3.2/command/link_directories.html) discourage its use in favour of passing the full path to `target_link_libraries`. – Fraser May 25 '15 at 10:49
  • That didn't work for me. (Pretty sure that was among the things I had already tried, too.) – vvye May 25 '15 at 11:57
  • @vvye It does work. But "The command will apply only to targets created after it is called. ". So put `link_directories` before `add_executable` solves your problem. – duleshi Sep 16 '15 at 02:53