Search code examples
c++cmakeconan

Travis CI reports linker errors for gcc-7 for a Vulkan project


I have a problem with my CMake + conan setup which causes linker errors in Travis CI:

https://travis-ci.org/github/inexorgame/vulkan-renderer/builds/674840008

There are a lot of undefined references which means that the linker can't find the library files somehow. It can't find spdlog so the linker error is not Vulkan specific.

My conanfile.pysetup looks like this:

from conans import ConanFile, CMake

class InexorConan(ConanFile):

    settings = (
        "os",
        "compiler",
        "build_type",
        "arch"
    )

    requires = (
        "benchmark/1.5.0",
        "glm/0.9.9.7",
        "gtest/1.10.0",
        "spdlog/1.5.0",
        "glfw/3.3.2@bincrafters/stable",
        "toml11/3.1.0",
        "imgui/1.75",
        "stb/20200203",
        "nlohmann_json/3.7.3",
    )

    generators = "cmake"

    def imports(self):
        # Copies all dll files from packages bin folder to my "bin" folder (win)
        self.copy("*.dll", dst="bin", src="bin")
        # Copies all dylib files from packages lib folder to my "lib" folder (macosx)
        self.copy("*.dylib*", dst="lib", src="lib") # From lib to lib
        # Copies all so files from packages lib folder to my "lib" folder (linux)
        self.copy("*.so*", dst="lib", src="lib") # From lib to lib

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

My CMakeLists.txt look like this:

cmake_minimum_required(VERSION 3.4)

project(inexor-vulkan-renderer)

file(
    GLOB_RECURSE source_files
    "src/*.hpp"
    "src/*.cpp"
    "tests/*.*"
    "benchmarks/*.*"
)

# Use the folder structure in source code directory as project structure in Visual Studio.
function(assign_source_group)
    foreach (source_files IN ITEMS ${ARGN})
        if (IS_ABSOLUTE "${source_files}")
            file(RELATIVE_PATH _source_rel "${CMAKE_CURRENT_SOURCE_DIR}" "${source_files}")
        else ()
            set(_source_rel "${source_files}")
        endif ()
        get_filename_component(_source_path "${_source_rel}" PATH)
        string(REPLACE "/" "\\" _source_path_msvc "${_source_path}")
        source_group("${_source_path_msvc}" FILES "${source_files}")
    endforeach ()
endfunction(assign_source_group)

set(NORMAL_SOURCE_FILES)
set(TEST_SOURCE_FILES)
set(BENCHMARK_SOURCE_FILES)

# Sort source files by tests and benchmarks.
foreach (file ${source_files})
    if (file MATCHES ".*_test.*")
        set(TEST_SOURCE_FILES ${TEST_SOURCE_FILES} ${file})
    elseif (file MATCHES ".*_benchmark.*")
        set(BENCHMARK_SOURCE_FILES ${BENCHMARK_SOURCE_FILES} ${file})
    else ()
        set(NORMAL_SOURCE_FILES ${NORMAL_SOURCE_FILES} ${file})
    endif ()
endforeach ()

if (NOT CMAKE_VERSION VERSION_LESS 3.7.0)
    message(STATUS "Using module to find Vulkan")
    find_package(Vulkan)
endif ()

# Dependency setup via conan.
# Download conan executer in case it does not exists.
if (NOT EXISTS "${CMAKE_CURRENT_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.14/conan.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/conan.cmake"
    )
endif ()

include(${CMAKE_CURRENT_BINARY_DIR}/conan.cmake)

conan_check(VERSION 1.19.1 REQUIRED)

conan_cmake_run(
    CONANFILE conanfile.py
    BASIC_SETUP
    BUILD outdated
    PROFILE default
    PROFILE_AUTO build_type
    KEEP_RPATHS
)

# Use the folder structure in source code directory as project structure in Visual Studio.
assign_source_group(${NORMAL_SOURCE_FILES})
assign_source_group(${TEST_SOURCE_FILES})
assign_source_group(${BENCHMARK_SOURCE_FILES})

add_executable(inexor-vulkan-renderer src/main.cpp ${NORMAL_SOURCE_FILES})
conan_target_link_libraries(inexor-vulkan-renderer)
target_compile_features(inexor-vulkan-renderer PRIVATE cxx_std_17)

target_include_directories(inexor-vulkan-renderer PRIVATE Vulkan::Vulkan)
target_link_libraries(inexor-vulkan-renderer Vulkan::Vulkan fmt spdlog)

# Use multiple threads to generate code.
if (MSVC)
    target_compile_options(inexor-vulkan-renderer PRIVATE "/MP")
endif ()

# Use root folder of the repository as working directory in Visual Studio debugger!
# Otherwise Visual Studio can't find any files like shaders or textures.
if (WIN32)
    set_property(TARGET inexor-vulkan-renderer PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif ()

file(
    GLOB_RECURSE NORMAL_SOURCE_FILES_WITHOUT_MAIN
    "src/vulkan-renderer/*"
)

add_executable(inexor-vulkan-renderer-tests ${NORMAL_SOURCE_FILES_WITHOUT_MAIN} ${TEST_SOURCE_FILES})
conan_target_link_libraries(inexor-vulkan-renderer-tests)
target_compile_features(inexor-vulkan-renderer-tests PRIVATE cxx_std_17)

target_include_directories(inexor-vulkan-renderer-tests PRIVATE Vulkan::Vulkan)
target_link_libraries(inexor-vulkan-renderer-tests Vulkan::Vulkan spdlog)

# Use root folder of the repository as working directory in Visual Studio debugger!
# Otherwise Visual Studio can't find any files like shaders or textures.
if (WIN32)
    set_property(TARGET inexor-vulkan-renderer PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif ()

if (MSVC)
    # Use multiple threads to compile the code.
    target_compile_options(inexor-vulkan-renderer-tests PRIVATE "/MP")
endif ()

add_executable(inexor-vulkan-renderer-benchmarks ${NORMAL_SOURCE_FILES_WITHOUT_MAIN} ${BENCHMARK_SOURCE_FILES})
conan_target_link_libraries(inexor-vulkan-renderer-benchmarks Vulkan::Vulkan spdlog)
target_compile_features(inexor-vulkan-renderer-benchmarks PRIVATE cxx_std_17)
target_include_directories(inexor-vulkan-renderer-benchmarks PRIVATE Vulkan::Vulkan)

target_include_directories(inexor-vulkan-renderer-benchmarks PRIVATE Vulkan::Vulkan)
target_link_libraries(inexor-vulkan-renderer-benchmarks spdlog gtest)

if (WIN32)
    set_property(TARGET inexor-vulkan-renderer-benchmarks PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif ()

# Use multiple threads to compile the code.
if (MSVC)
    target_compile_options(inexor-vulkan-renderer-benchmarks PRIVATE "/MP")
endif ()

This setup works for Visual Studio 2019. Maybe conan can't pass the libraries to the target?

conan_target_link_libraries(inexor-vulkan-renderer-tests)
target_link_libraries(inexor-vulkan-renderer-tests Vulkan::Vulkan spdlog)

This is my Travis setup:

os: linux
language: python
python: "3.7"
dist: xenial

os: linux
addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
    packages:
      - g++-7

before_script:
  - sudo apt-get install
  - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
  - sudo apt-get update -qq

install:
  - pip install conan
  - conan user
  - sudo apt-get install -qq g++-7
  - wget https://github.com/premake/premake-core/releases/download/v5.0.0-alpha11/premake-5.0.0-alpha11-linux.tar.gz?Human=true -O premake-5.0.0-alpha11-linux.tar.gz
  - tar -xzvf premake-5.0.0-alpha11-linux.tar.gz
  - sudo apt-get -qq update
  - sudo apt-get install -y libassimp-dev libglm-dev graphviz libxcb-dri3-0 libxcb-present0 libpciaccess0 cmake libpng-dev libxcb-dri3-dev libx11-dev libx11-xcb-dev libmirclient-dev libwayland-dev libxrandr-dev
  - export VK_VERSION=1.2.131.1
  - wget -O vulkansdk-linux-x86_64-$VK_VERSION.tar.gz https://sdk.lunarg.com/sdk/download/$VK_VERSION/linux/vulkansdk-linux-x86_64-$VK_VERSION.tar.gz
  - tar zxf vulkansdk-linux-x86_64-$VK_VERSION.tar.gz
  - export VULKAN_SDK=$TRAVIS_BUILD_DIR/$VK_VERSION/x86_64

script:
  - export CC=gcc-7
  - export CXX=g++-7
  - conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
  - conan install .
  - cmake -DCMAKE_BUILD_TYPE=Release .
  - cmake --build . --target inexor-vulkan-renderer
  - ctest .

notifications:
  email:
    recipients:
      - info@inexor.org
    on_success: change
    on_failure: always

I've been trying to fix this for several days now. I would appreciate it if someone could give me a hint.

Sincere regards Johannes.


Solution

  • Observe that your linker is looking for std::__cxx11::basic_string which belongs to libstdc++11. However, your conan profile is using libstdc++, which is incompatible, you can see it at the beginning of your log.

    You need to configure your conan profile using libstdc++11 instead:

    conan profile update settings.compiler.libcxx=libstdc++11 default 
    

    Further reading:

    https://docs.conan.io/en/latest/getting_started.html - Step 5

    https://docs.conan.io/en/latest/howtos/manage_gcc_abi.html