1

I've been struggling to understand why CMake does not compile my program anymore. I made a container for cross-compile a C++ program for Windows. The environment:

  • Fedora 31
  • cmake 3.17.4
  • x86_64-w64-mingw32-g++ 9.2.1
  • boost 1.69

The following code is my current cmake toolchain file for mingw:

set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PFX x86_64-w64-mingw32)

set(Boost_ARCHITECTURE -x64)
set(Boost_DEBUG ON)
set(Boost_INCLUDE_DIR /usr/${TOOLCHAIN_PFX}/sys-root/mingw/include)
set(Boost_LIBRARY_DIR /usr/${TOOLCHAIN_PFX}/sys-root/mingw/lib)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.69 REQUIRED)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/local/include -L/usr/local/lib")

set(CMAKE_C_COMPILER ${TOOLCHAIN_PFX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PFX}-g++)

set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PFX})

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

The building process interrupts when linking the executable. It produces:

/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lboost_thread-mt
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lboost_log-mt
/usr/lib/gcc/x86_64-w64-mingw32/9.2.1/../../../../x86_64-w64-mingw32/bin/ld: cannot find -lboost_system

What shocks me the most is that it used to build (no changes have been made to the environment) and boost is installed from RPM. Funny things is that if I omit -lboost_thread-mt, off course, it complains.

  • So, the linker says that it cannot find a library `boost_thread-mt`. Where this library is located on your system? You set `Boost_DEBUG`. Have you checked its output about location of libraries? There are also strange things about toolchain: 1. `find_package` is rarely called in the toolchain file, it should be called from `CMakeLists.txt`. 2. Directory `/usr/local/include` refers to the **host** system include directory. Using it for cross-compilation is usually wrong. The same is about `/usr/local/lib`. 3. Option `-L` is not a **compiler** flag, so shouldn't be added to `CMAKE_CXX_FLAGS`. – Tsyvarev Dec 15 '20 at 22:59
  • You're cross-building for Windows using MinGW-w64. On the other hand you say boost is installed via RPM. Are you sure you have Boost installed for Windows/MinGW-w64, and the RPM installed version is not just for your Linux platform? – Brecht Sanders Dec 16 '20 at 08:13
  • Hey thanks. Off course the `Boost_DEBUG` is there for a reason. Boost is correctly installed and it's root is where i specify `Boost_INCLUDE_DIR` since CMake alone isn't able to find it. The use of `/usr/local/include` might be wrong but the host is a Docker container which serves only as a building environment and I put some locally built deps there. Regarding tour second observation, it's true, but my `CMakeLists` is pretty long and messy and it's easier to operate on the toolchain. Plus when I build for Linux I do not have problems. – Michele Ferrari Dec 16 '20 at 08:21
  • @BrechtSanders off course boost is installed for `MinGW`, yes – Michele Ferrari Dec 16 '20 at 08:22
  • The call `find_package(Boost)` which you show doesn't have a COMPONENTS specification, so `boost_thread-mt` is not what is produced by this call. Nor this call adds link directories for Boost libraries. So, where `boost_thread-mt` is specified in your `CMakeLists.txt`? Are you sure that you correctly add link directories for Boost libraries? The preferred way for work with Boost `thread` library is specifying it as COMPONENTS: `find_package(Boost COMPONENTS thread REQUIRED)`, see [that answer](https://stackoverflow.com/a/41398161/3440745) as example. – Tsyvarev Dec 16 '20 at 08:38
  • `boost_thread-mt` is exactly located where I expect it to be. The path is `/usr/x86_64-w64-mingw32/sys-root/mingw/lib`, also the debug value of `_boost_LIBRARY_SEARCH_DIRS_RELEASE` is as follows: `/usr/x86_64-w64-mingw32/sys-root/mingw/lib;NO_DEFAULT_PATH;NO_CMAKE_FIND_ROOT_PATH`. To me it looks like I would expect it to be. I am not an expert but I would say this thing is configured in the right way. In fact it is, as I am writing I realized that the library has "-x64" appended. But isn't `set(Boost_ARCHITECTURE -x64)` used to avoid having to link aganinst `boost_thread-mt-x64`? – Michele Ferrari Dec 16 '20 at 09:04

1 Answers1

0

You are overwriting many variables that should be correctly set by find_package() such as Boost_LIBRARY_DIR.

Also, you don't specify any components with find_package, as would be the standard way, unless you just want to use the header-only part of boost.

Thus, you are using find_package boost in unsupported/unspecified ways which might have worked in the past, by chance, but broke later.

What definitely works on Fedora 36 is the following:

cmake_minimum_required(VERSION 3.0...3.22.1)
project(some_project CXX)

# work-around: FindBoost: Boost_ARCHITECTURE not detected on MinGW
# https://gitlab.kitware.com/cmake/cmake/-/issues/20587
if(MINGW)
    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
        set(Boost_ARCHITECTURE "-x64")
    else()
        set(Boost_ARCHITECTURE "-x32")
    endif()
endif()

# works with/without
set(Boost_USE_STATIC_LIBS ON)

# set(Boost_DEBUG ON)

set(Boost_USE_STATIC_LIBS ON)

find_package(Boost 1.54
    REQUIRED COMPONENTS
    system
    filesystem) # just an example, add what you need

add_executable(somebinary main.cc sometranslationunit.cc)
target_link_libraries(somebinary ${Boost_LIBRARIES})

Build with:

mkdir build-cross
cd build-cross
mingw64-cmake -DCMAKE_BUILD_TYPE=Debug .. # or whatever build type
mingw64-make somebinary
maxschlepzig
  • 35,645
  • 14
  • 145
  • 182