CMake Environment Variables for QNX Toolchain

QNX QCC requires QNX_HOST and QNX_TARGET environment variables to be set.

I’m leveraging CPM.cmake to pull down the respective QNX toolchain. So I end up have a toolchain file like

CPMAddPackage(qnx-url@my-tag-7.0.0)

set(ENV{QNX_HOST} "${qnx_SOURCE_DIR}/qnx700/host/linux/x86_64")
set(ENV{QNX_TARGET} "${qnx_SOURCE_DIR}/qnx700/target/qnx7")

set(Qnx_QCC "$ENV{QNX_HOST}/usr/bin/qcc")

set(CMAKE_C_COMPILER ${Qnx_QCC})
# etc...

This succeeds in configuring. However, when I go to build I end up getting the error
cc: The QNX_HOST/QNX_TARGET environment variables must be set. Do I have any way to ensure the environment variable I set is seen when building? I realize the environment variable would typically be set up outside CMake (or perhaps in presets). However, given I’m using CMake to retrieve and resolve the dependency and the subsequent environment variable path, I would like to set it in CMake. Any options?

CMake (nor any process for that matter) can set environment variables in the parent process. That does indeed set QNX_HOST and QNX_TARGET during CMake’s run, but they are removed once CMake is done. There is no way to push environment variables into the build as build tools have no mechanism for CMake to use to do so.

Some alternatives:

  • set QNX_* in the calling environment outside of CMake so that it applies to the build as well; or
  • write wrapper scripts for the compiler that set it and then chain off to the real compiler

Thanks for the response.

Setting QNX_* outside of CMake in my situation is not ideal since it’s CMake that is specifying and retrieving the QNX installation.

Setting the compiler to something other than qcc seems to interfere with the ability for the toolchain to be recognized as QNX.

I tried setting the compiler launcher like so

set(CMAKE_CXX_COMPILER_LAUNCHER "QNX_HOST=${qnx_SOURCE_DIR}/rest/of/path};QNX_TARGET=${qnx_SOURCE_DIR}/rest/of/path" CACHE STRING "CXX Compiler Launcher for environment" FORCE)

Which almost works. However when I do similar for the CMAKE_CXX_LINKER_LAUNCHER, it seems to not like the format…

 /snap/cmake/955/bin/cmake -E cmake_link_script CMakeFiles/cmTC_b9191.dir/link.txt --verbose=1
    QNX_HOST=/home/foo/tools/qnx/qnx-v1.2/qnx700/host/linux/x86_64 QNX_TARGET=/home/foo/tools/qnx/qnx-v1.2/qnx700/target/qnx7 /home/foo/tools/qnx/qnx-v1.2/qnx700/host/linux/x86_64/usr/bin/qcc -Vgcc_ntoaarch64le_gpp -Wc,-isysroot,/home/foo/tools/qnx/qnx-v1.2/qnx700/target/qnx7 CMakeFiles/cmTC_b9191.dir/testCCompiler.c.o -o cmTC_b9191 
    Error running link command: No such file or directory
  1. However, if I use the --debug-trycompile option and manually run the contents of the link.txt it links correctly. Not sure if this is a limitation with the linker launcher?

  2. I did set environment variables briefly to see if I could get past configure. However, when I then try to build it looks like the CMAKE_CXX_COMPILER_LAUNCHER is not taking affect (while it is in cache). Can that not be set in a toolchain file?

You can do path/to/patched/scripts/bin/qcc which “fools” anything doing binary name-based detections. But CMake prefers to inspect the preprocessor symbols, so it shouldn’t be confused…

Yes, the cmake_link_script is not a POSIX shell and so does not understand the VAR=val cmd syntax; it is trying to run the command named QNX_HOST=… which is highly unlikely to exist.

I believe the piece that cared about the qcc name was find_package(Boost) when trying to find pre-built libraries compiled with qcc.

But with those suggestions I figured out an option that should work well with the wrapper script. Thanks for the help!

CPMAddPackage(qnx-url@my-tag-7.0.0)

set(QNX_HOST "${qnx_SOURCE_DIR}/qnx700/host/linux/x86_64")
set(QNX_TARGET "${qnx_SOURCE_DIR}/qnx700/target/qnx7")
set(QNX_QCC "${QNX_HOST}/usr/bin/qcc")

# Generate qcc wrapper script which sets required QNX_HOST & QNX_TARGET
set(QNX_QCC_WRAPPER "${CMAKE_BINARY_DIR}/qcc")
configure_file(${CMAKE_CURRENT_LIST_DIR}/qcc.in ${QNX_QCC_WRAPPER}
    FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
)

set(CMAKE_C_COMPILER ${QNX_QCC_WRAPPER })
set(CMAKE_CXX_COMPILER ${QNX_QCC_WRAPPER})
# continued QNX toolchain settings from cmake-toolchains documentation

# qcc.in contents
#/!bin/bash
# qcc wrapper script
# This script works around QNX expecting QNX_TARGET and QNX_HOST to be set in the environment
# and allows CMake to change QNX_TARGET & QNX_HOST depending on what version of qnx is
# retrieved by CPM.

# Note, $@ needs to be wrapped in quotes to ensure arguments
# are passed directly to qcc.
# https://stackoverflow.com/questions/10067266/when-should-i-wrap-quotes-around-a-shell-variable

QNX_HOST=@QNX_HOST@ QNX_TARGET=@QNX_TARGET@ @QNX_QCC@ "$@"