'How do I cross-compile Windows software using asio on Linux with CMake?

I wrote some software that uses a serial port to program a radio. It works just fine under Linux and I suspect it will also work well on Windows, but I'm having some problems compiling it for Windows on Linux. The project uses CMake and the non-Boost version of the asio library. I emphasize this to explain why neither boost-centric answers nor the tag apply here. I have written and use my own FindAsio.cmake file which I have under cmake/Modules in my project.

FindAsio.cmake

set(_x86 "(x86)")
file(GLOB _Asio_INCLUDE_DIRS
    "$ENV{ProgramFiles}/asio/*/include"
    "$ENV{ProgramFiles${_x86}}/asio/*/include"
    )
unset(_x86)

find_path(ASIO_INCLUDE_DIR
        NAMES
        asio.hpp
        PATHS
        ${_Asio_INCLUDE_DIRS}
        /usr/include
        /usr/local/include
        ${ASIO_ROOT}
)

if(ASIO_INCLUDE_DIR AND EXISTS "${ASIO_INCLUDE_DIR}/asio/version.hpp")
    file(STRINGS "${ASIO_INCLUDE_DIR}/asio/version.hpp" ASIO_H REGEX "^#define ASIO_VERSION [^/]*/")
    string(REGEX REPLACE "^.*ASIO_VERSION ([0-9]).*$" "\\1" ASIO_VERSION_MAJOR "${ASIO_H}")
    string(REGEX REPLACE "^.*ASIO_VERSION [0-9]([0-9][0-9][0-9]).*$" "\\1" ASIO_VERSION_MINOR "${ASIO_H}")
    string(REGEX REPLACE "^.*ASIO_VERSION [0-9][0-9][0-9][0-9]([0-9][0-9]).*$" "\\1" ASIO_VERSION_PATCH "${ASIO_H}")
    set(ASIO_VERSION "${ASIO_VERSION_MAJOR}.${ASIO_VERSION_MINOR}.${ASIO_VERSION_PATCH}")
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
    Asio
    DEFAULT_MSG
    ASIO_INCLUDE_DIR
)

When I use mingw64-cmake -DCMAKE_BUILD_TYPE=Release -S . -B winbuild I get an error,

CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Asio (missing: ASIO_INCLUDE_DIR)
Call Stack (most recent call first):
  /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  cmake/Modules/FindAsio.cmake:27 (find_package_handle_standard_args)
  src/CMakeLists.txt:2 (find_package)

Looking into it a bit more, it appears that mingw64 has its own include directory in /usr/x86_64-w64-mingw32/sys-root/mingw/include and, indeed, there is no asio.hpp file there. My package manager, dnf (I'm using a Fedora distro) has a number of packages, such as mingw64-boost but no mingw64-asio. I could use the boost version of asio, but would really rather not, since I don't actually need any of boost. The relevant portion of my src/CMakeLists.txt file is here:

src/CMakeLists.txt

find_package(Asio REQUIRED)
add_library(bc95xlt STATIC Channel.cpp Radio.cpp)
target_include_directories(bc95xlt PRIVATE ${ASIO_INCLUDE_DIR})
target_compile_definitions(bc95xlt PRIVATE ASIO_STANDALONE)

So my question is how to compile my code on Linux for Windows. Some ideas I had:

  1. download the source for asio and put the relevant portions in the mingw64 include tree
  2. create symlinks from the mingw64 include directory to the Linux version of asio which is already installed
  3. put a local copy of asio in my code tree

What's the way to do this that is easy to maintain?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source