Search code examples
c++cmakepahoconan

Link PahoMqttCpp as a static library in CMake using Conan


I am working on a C++ web framework, oatpp to create REST APIs. Using the oatpp-starter project where the CMakeLists.txt looks like:

cmake_minimum_required(VERSION 3.1)

set(project_name my-project) ## rename your project here

project(${project_name})

set(CMAKE_CXX_STANDARD 11)

add_library(${project_name}-lib
        src/AppComponent.hpp
        src/controller/MyController.cpp
        src/controller/MyController.hpp
        src/dto/DTOs.hpp
)

## link libs

find_package(oatpp 1.2.5 REQUIRED)

target_link_libraries(${project_name}-lib
        PUBLIC oatpp::oatpp
        PUBLIC oatpp::oatpp-test
)

target_include_directories(${project_name}-lib PUBLIC src)

## add executables

add_executable(${project_name}-exe
        src/App.cpp
        test/app/MyApiTestClient.hpp)
target_link_libraries(${project_name}-exe ${project_name}-lib)
add_dependencies(${project_name}-exe ${project_name}-lib)

add_executable(${project_name}-test
        test/tests.cpp
        test/app/TestComponent.hpp
        test/app/MyApiTestClient.hpp
        test/MyControllerTest.cpp
        test/MyControllerTest.hpp
)

target_link_libraries(${project_name}-test ${project_name}-lib)
add_dependencies(${project_name}-test ${project_name}-lib)

set_target_properties(${project_name}-lib ${project_name}-exe ${project_name}-test PROPERTIES
        CXX_STANDARD 11
        CXX_EXTENSIONS OFF
        CXX_STANDARD_REQUIRED ON
)

enable_testing()
add_test(project-tests ${project_name}-test)

The executable I get after compiling this code runs successfully inside a container with same architecture. But when I add paho-mqtt library to the project, the executable does't run on the container because the shared library libpaho-mqttcpp3.so.1 not found: No such file or directory error.

I am adding the library using this configuration: Updated CMakeLists.txt :

cmake_minimum_required(VERSION 3.1)

set(project_name my-project) ## rename your project here

project(${project_name})

set(CMAKE_CXX_STANDARD 11)

add_library(${project_name}-lib
        src/AppComponent.hpp
        src/controller/MyController.cpp
        src/controller/MyController.hpp
        src/dto/DTOs.hpp
)

## link libs

find_package(oatpp 1.2.5 REQUIRED)

target_link_libraries(${project_name}-lib
        PUBLIC oatpp::oatpp
        PUBLIC oatpp::oatpp-test
)


## conan
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)

target_include_directories(${project_name}-lib PUBLIC src)

## add executables

add_executable(${project_name}-exe
        src/App.cpp
        test/app/MyApiTestClient.hpp)
target_link_libraries(${project_name}-exe ${project_name}-lib ${CONAN_LIBS})
add_dependencies(${project_name}-exe ${project_name}-lib)

add_executable(${project_name}-test
        test/tests.cpp
        test/app/TestComponent.hpp
        test/app/MyApiTestClient.hpp
        test/MyControllerTest.cpp
        test/MyControllerTest.hpp
)

target_link_libraries(${project_name}-test ${project_name}-lib ${CONAN_LIBS})
add_dependencies(${project_name}-test ${project_name}-lib)

set_target_properties(${project_name}-lib ${project_name}-exe ${project_name}-test PROPERTIES
        CXX_STANDARD 11
        CXX_EXTENSIONS OFF
        CXX_STANDARD_REQUIRED ON
)

enable_testing()
add_test(project-tests ${project_name}-test)

Here's the conanfile.txt

[requires]
paho-mqtt-cpp/1.2.0     # MQTT Client

[generators]
cmake

How to configure CMake to use Conan's downloaded PahoMqttCpp library to build a standalone project executable (using static library)


Solution

  • Here's what was happening: I configured CMakeLists.txt incorrectly to integrate with conan. Since I had paho-mqtt-cpp installed beforehand, the program was linking to installed libraries instead of those provided by conan.

    This CMakeLists.txt works for me:

    cmake_minimum_required(VERSION 3.1)
    set(PROJECT_NAME my-awesome-project)
    project(${PROJECT_NAME})
    
    set(CMAKE_CXX_STANDARD 14)
    
    ############################### CONAN SETUP BEGIN ##########################################
    if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
        message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
        file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.9/conan.cmake"
                "${CMAKE_BINARY_DIR}/conan.cmake")
    endif()
    include(${CMAKE_BINARY_DIR}/conan.cmake)
    conan_cmake_run(CONANFILE conanfile.txt BASIC_SETUP)
    ############################### CONAN SETUP END ############################################
    
    add_library(${PROJECT_NAME}-lib
            # controllers
            src/controller/StaticController.hpp
    
            # db
            src/db/DemoDb.hpp
    
            # mqtt
            src/mqtt/MqttCoroutine.hpp
            src/mqtt/MqttClient.hpp
    
            # dto
            src/dto/PageDto.hpp
            src/dto/StatusDto.hpp
            src/dto/DemoDto.hpp
    
            # services
            src/service/DemoService.cpp
            src/service/DemoService.hpp
    
            # base
            src/AppComponent.hpp
            src/DatabaseComponent.hpp
            src/ErrorHandler.cpp
            src/ErrorHandler.hpp)
    
    ## include directories
    target_include_directories(${PROJECT_NAME}-lib PUBLIC src)
    
    
    add_definitions(
            ## SQLite database file
            -DDATABASE_FILE="${CMAKE_CURRENT_SOURCE_DIR}/sql/db.sqlite"
    
            ## SQLite database test file
            -DTESTDATABASE_FILE="${CMAKE_CURRENT_SOURCE_DIR}/sql/test-db.sqlite"
    
            ## Path to database migration scripts
            -DDATABASE_MIGRATIONS="${CMAKE_CURRENT_SOURCE_DIR}/sql"
    
            ## my-awesome-project Service
            -DHOST="0.0.0.0"
            -DPORT=8080
    
            ## MQTT Broker
            -DMQTT_BROKER_URL="tcp://127.0.0.1:1883"
    )
    
    if(CMAKE_SYSTEM_NAME MATCHES Linux)
        find_package(Threads REQUIRED)
        target_link_libraries(${PROJECT_NAME}-lib INTERFACE Threads::Threads ${CMAKE_DL_LIBS})
    endif()
    
    ## add executables
    add_executable(${PROJECT_NAME}-exe src/App.cpp)
    target_link_libraries(${PROJECT_NAME}-exe ${PROJECT_NAME}-lib ${CONAN_LIBS})
    
    add_executable(${PROJECT_NAME}-test
            test/tests.cpp
            test/app/TestClient.hpp
            test/app/TestDatabaseComponent.hpp
            test/app/TestComponent.hpp
            test/DeviceControllerTest.hpp
            test/DeviceControllerTest.cpp)
    
    target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}-lib ${CONAN_LIBS})
    
    enable_testing()
    add_test(e2e-tests ${PROJECT_NAME}-test)
    
    

    Along with this conanfile.txt

    [requires]
    oatpp/1.2.5             # REST library
    oatpp-sqlite/1.2.5      # SQLite3 plugin
    paho-mqtt-cpp/1.2.0     # MQTT Client
    
    [generators]
    cmake
    

    Just use regular cmake command to generate Makefile. Then run make to get the executable.