c++cmakeallegro5

Cannot find directory in context of main.cpp (Allegro with CMake)


I'm trying to create a library that links against allegro5 media library using CMake. And then, I want to use my library in an executable.

My directory structure is:

src
 |----core
        |------src
        |------tests
        |------CMakeLists.txt
 |----main.cpp
 |----CMakeLists.txt

The CMakeLists.txt file inside the core folder is:

set(MY_HEADERS #My header files here)
set(MY_SRC #My source files here)

add_library(MyLib ${MY_HEADERS} ${MY_SRC})
target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")

## Allegro Lib

set(ALLEGRO_DIR "${PROJECT_SOURCE_DIR}/packages/allegro5/include")

if(WIN32)
    file(GLOB ALLEGRO_LIB "${PROJECT_SOURCE_DIR}/packages/allegro5/windows/x86/lib/*.lib")
    add_library(Allegro SHARED IMPORTED)
    set_target_properties(Allegro PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES ${ALLEGRO_DIR}
        IMPORTED_IMPLIB ${ALLEGRO_LIB}
    )
    target_link_libraries(MyLib PRIVATE Allegro)
    file(GLOB ALLEGRO_DLL "${PROJECT_SOURCE_DIR}/packages/allegro5/windows/x86/bin/*.dll")
    foreach(dll ${ALLEGRO_DLL})
        add_custom_command(TARGET MyLib POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy
            ${dll} $<TARGET_FILE_DIR:MyLib>)
    endforeach()
endif()

Now in my, top level CMakeLists.txt is:

cmake_minimum_required(VERSION 3.15)

project(MyProject)
enable_testing()

add_subdirectory(core)
add_executable(MyGame main.cpp)
target_link_libraries(MyGame MyLib)

In my IDE (Visual Studio) I see that the include statement for "allegro5/allegro.h" in my source files is inside core folder is giving me the warning "Cannot find directory allegro5 in search paths ... in context of ../src/main.cpp".

When I build the project I get the errors:

Cannot open source file 'allegro5/allegro'
Cannot open include file 'allegro5/allegro.h': No such file or directory.

This error only happens if I reference MyLib in main.cpp. (My main does not have any code, just a hello world statement):

// #include "MyLib.hpp"

int main(int argc, const char *argv[])
{
    /*const auto engine = &MyLib::EngineManager::getInstance();
    engine->start();
    const auto display = &MyLib::DisplayManager::getInstance();

    auto displayConfig = DisplayConfig();
    displayConfig.fullscreen = false;
    const auto displayId = display->createDisplay(displayConfig);*/
}

I guess this has something to do with the visibility I'm setting somewhere? I can't quite figure out how to fix. Appreciate your help, thanks!

EDIT:

When PRIVATE to PUBLIC, I get the following linker error:

LNK2019 unresolved external symbol __imp_al_install_system referenced in function "public: static void __cdecl mylib::EngineManager::start(void)" (?start@EngineManager@mylib@@SAXXZ)   C:\Users\xxx\src\out\build\x64-Debug\src    C:\Users\xxx\src\out\build\x64-Debug\main.cpp.obj

Solution

  • The include directory for allegro5 is defined as ALLEGRO_DIR in your CMake:

    ${PROJECT_SOURCE_DIR}/packages/allegro5/include
    

    Therefore, with the #include "allegro5/allegro.h", the full path to the header file would be appended:

    ${PROJECT_SOURCE_DIR}/packages/allegro5/include/allegro5/allegro.h
    

    Be sure this path is correct and the file exists.

    In addition, you set the INTERFACE include directories on the imported Allegro target, but you link it to MyLib using the PRIVATE keyword. This means the usage requirements of Allegro are not propagated to the MyGame. You should use PUBLIC for this link step instead if you want the INTERFACE_INCLUDE_DIRECTORIES of Allegro to also be transitively propagated to MyGame:

        target_link_libraries(MyLib PUBLIC Allegro)
    

    CMake has a good example demonstrating this in their documentation.