CMake cannot find a static library using relative file paths
Asked Answered
P

2

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?

Prettify answered 16/5, 2015 at 11:16 Comment(0)
A
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.
)
Abyssal answered 16/5, 2015 at 13:7 Comment(5)
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.Prettify
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. 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.Abyssal
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 :)Abyssal
As an alternative, you can always insert an additional find_library call 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.Extracanonical
Also don't forget to clear the cmake cache. Sometimes you need to do it manually to fixup configuration quirks.Docilla
T
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.

Testes answered 25/5, 2015 at 7:22 Comment(3)
I'm not downvoting since this should work, but the docs for link_directories discourage its use in favour of passing the full path to target_link_libraries.Abyssal
That didn't work for me. (Pretty sure that was among the things I had already tried, too.)Prettify
@Prettify 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.Practitioner

© 2022 - 2024 — McMap. All rights reserved.