QNX SDP 8 Compiler flag `-lang-c++` now marked as deprecated

I’m testing my CMake project (v3.16 to support at least Ubuntu 20.04 LTS and later). With QNX8, there are new warnings saying that “cc: warning - lang-c++ is deprecated”.

This is documented by QNX at QNX Momentics IDE, which says:

“In addition, projects that use -lang-c++ should use -x c++ instead.”

I don’t seem to be able to modify the behaviour of the variable CMAKE_CXX_COMPILE_OBJECT or CMAKE_CXX_LINK_EXECUTABLE in a toolchain file (it appears to be ignored).

string(REPLACE "<CMAKE_CXX_COMPILER> -lang-c++" "<CMAKE_CXX_COMPILER> -xc++" CMAKE_CXX_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT})
string(REPLACE "<CMAKE_CXX_COMPILER> -lang-c++" "<CMAKE_CXX_COMPILER>" CMAKE_CXX_LINK_EXECUTABLE ${CMAKE_CXX_LINK_EXECUTABLE})

Seeing the file Modules/Compiler/QCC-CXX.cmake and modifying it there does fix the warning.

I could do a string replace, but my concern here is that if it is deprecated in QNX 8.0, what if a newer version of QNX makes this an error?

Is there a best practice, or a recommended way to write a toolchain file to properly handle this, that would be considered portable from CMake 3.16 and later?

My toolchain file for now contains (works with QNX 7.1 and QNX 8)

set(CMAKE_SYSTEM_NAME QNX)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(arch gcc_ntoaarch64le)

set(CMAKE_C_COMPILER qcc)
set(CMAKE_C_COMPILER_TARGET ${arch})
set(CMAKE_CXX_COMPILER q++)
set(CMAKE_CXX_COMPILER_TARGET ${arch})

The docs to use QCC is not correct, as the qnxsdp-env.sh doesn’t expose that on the path. But it does qcc and q++.

1 Like

Can you please test this branch (based on CMake 4.1 branch)?

I had a quick look at https://gitlab.kitware.com/ben.boeckel/cmake/-/commit/8e1e1b9cf46177aa9ea0db2184e2d0c181d5794d

Should there be an automatic check for the version if the variable is not set? For example, here are my macros at code.research/cmake/modules/research/qnx.cmake at master · jcurl/code.research · GitHub

I typically use the same toolchain file for QNX 7.1 as well as QNX 8.0 (I didn’t test it on QNX versions earlier than 7.1 though, as I have licenses).

Would you care to point me to instructions on how to best test within Ubuntu 22.04? Then it’s likely I can find time on the weekend.

Also, if I can’t upgrade CMake (QNX say they support Ubuntu 20.04/22.04/24.04, but obviously not in a CMake environment), what would be the best way to configure CMake to workaround without this patch?

I have to figure out how to test it myself actually since we lack CI for QCC at the moment. Unless you’re setting these variables manually in the toolchain file, you shouldn’t need to do anything once the diff is applied. I would try building CMake yourself and using it first. Once it is in a release, you can then download the prebuilt binaries and use them instead of the distro CMake.

I’ve verified that I got the warning without the commit and no warning with the change.

MR opened: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10992

Thanks. I was specifically asking if you can point to documentation so I can build cmake myself that confirms the change. Googling gives me how to build my own projects using cmake.

Can a test be implemented (even by my own project) that determines the compiler version before the code in the PR is run?

CMake builds itself with CMake (there’s a bootstrap step you can ignore if you already have a CMake build), so those instructions are still useful.

Can you provide your toolchain file?

That looks fine to me. When I tested, all I did was source the .sh file from the QNX install, set the CC=qcc and CXX=q++ envvars, and pass -DCMAKE_SYSTEM_NAME=QNX down. CMake uses the toolchain file to find the compiler path to use (and set up targeting like you do) and then it will do its introspection to find out things like:

  • what is the compiler ID (paths are not reliable)
  • version

and from there it will end up going through the logic I patched to create the command line to use the compiler at build time.

I’m not having any luck testing. I don’t want to overwrite my existing install, so I checked out commit 8e1e1b9cf46177aa9ea0db2184e2d0c181d5794d

Built

$ mkdir build && cd build
$ ../bootstrap --parallel=32 && make -j32
$ DESTDIR=~/source/cmake/install make install

Check it worked with version

$ ~/source/cmake/install/usr/local/bin/cmake --version
cmake version 4.1.0-rc4-g8e1e1b9

Building my project fails very early with:

$ ~/source/cmake/install/usr/local/bin/cmake -B . -S ../.. -DCMAKE_TOOLCHAIN_FILE=../../../toolchain/qcc_aarch64le.cmake
...
-- Check for working CXX compiler: /home/jcurl/qnx/qnx800/host/linux/x86_64/usr/bin/q++
-- Check for working CXX compiler: /home/jcurl/qnx/qnx800/host/linux/x86_64/usr/bin/q++ - broken
CMake Error at /home/jcurl/source/cmake/install/usr/local/share/cmake-3.31/Modules/CMakeTestCXXCompiler.cmake:73 (message):
  The C++ compiler

    "/home/jcurl/qnx/qnx800/host/linux/x86_64/usr/bin/q++"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: '/home/jcurl/source/code.research/qnx/build/qnx8/CMakeFiles/CMakeScratch/TryCompile-ldAfuy'
    
    Run Build Command(s): /home/jcurl/source/cmake/install/usr/local/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f Makefile cmTC_75374/fast
    /usr/bin/gmake  -f CMakeFiles/cmTC_75374.dir/build.make CMakeFiles/cmTC_75374.dir/build
    gmake[1]: Entering directory '/home/jcurl/source/code.research/qnx/build/qnx8/CMakeFiles/CMakeScratch/TryCompile-ldAfuy'
    Building CXX object CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o
    /home/jcurl/qnx/qnx800/host/linux/x86_64/usr/bin/q++ -Vgcc_ntoaarch64le -x c++    -Wp,-MD,CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o.d -Wp,-MT,CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o -Wp,-MF,CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o.d -o CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o -c /home/jcurl/source/code.research/qnx/build/qnx8/CMakeFiles/CMakeScratch/TryCompile-ldAfuy/testCXXCompiler.cxx
    Linking CXX executable cmTC_75374
    /home/jcurl/source/cmake/install/usr/local/bin/cmake -E cmake_link_script CMakeFiles/cmTC_75374.dir/link.txt --verbose=1
    CMakeFiles/cmTC_75374.dir/testCXXCompiler.cxx.o:1:1: error: stray '\177' in program
        1 | <U+007F>ELF<U+0002><U+0001><U+0001><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0001><U+0000><b7><U+0000><U+0001><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000>(<U+0002><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000><U+0000>@<U+0000><U+0000><U+0000><U+0000><U+0000>@<U+0000>
          | ^~~~~~~~

I’m suspecting I haven’t set up paths properly.

Note, I did the same with

$ export PATH=~/source/cmake/install/usr/local/bin:$PATH
$ cmake --version
cmake version 4.1.0-rc4-g8e1e1b9

Any hints on how to build and have side-by-side without removing the version my distro provides?

Same results with commit 59d2fdf8fc425cdf71fad613ba7107f06d93c424

Ah, I forgot about that; I side-stepped it by setting CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY. Something is getting confused and the compiler is reading the object file and expecting source code. Perhaps the link command should continue using -lang-c++?

I’ve updated the MR to just remove the -lang-c++ flag for linking.

That fixed so it will build. There is a regression when building QNX 7.1.0, so it doesn’t work as expected, so older versions of QNX may now break.

For example, it now also uses -x c++ for QNX 7.1.0. While it works, I’m pretty sure that QNX 6.5.0 doesn’t support this option (I don’t have QNX 6.5.0 or a project to test with).

$cmake --version
cmake version 4.1.0-rc4-g6845fa6
$ cmake -B . -S ../.. -DCMAKE_TOOLCHAIN_FILE=../../../toolchain/qcc_aarch64le.cmake

$ VERBOSE=1 make

cd /home/jcurl/source/code.research/qnx/build/qnx7/external/benchmark/src && /home/jcurl/qnx/qnx710/host/linux/x86_64/usr/bin/q++ -Vgcc_ntoaarch64le -x c++ -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_STEADY_CLOCK -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_QNX_SOURCE -I/home/jcurl/source/code.research/external/benchmark/include -I/home/jcurl/source/code.research/external/benchmark/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wconversion -Werror -Wsuggest-override -pedantic -pedantic-errors -fstrict-aliasing -Wno-deprecated-declarations -Wno-deprecated -Wstrict-aliasing -g -g -std=c++17 -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -O0 -Wp,-MD,CMakeFiles/benchmark.dir/check.cc.o.d -Wp,-MT,external/benchmark/src/CMakeFiles/benchmark.dir/check.cc.o -Wp,-MF,CMakeFiles/benchmark.dir/check.cc.o.d -o CMakeFiles/benchmark.dir/check.cc.o -c /home/jcurl/source/code.research/external/benchmark/src/check.cc

With CMake version 3.22.1, the same file shows:

[ 8%] Building CXX object external/benchmark/src/CMakeFiles/benchmark.dir/check.cc.o
cd /home/jcurl/source/code.research/qnx/build/qnx7/external/benchmark/src && /home/jcurl/qnx/qnx710/host/linux/x86_64/usr/bin/q++ -Vgcc_ntoaarch64le -lang-c++ -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_STEADY_CLOCK -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -D_QNX_SOURCE -I/home/jcurl/source/code.research/external/benchmark/include -I/home/jcurl/source/code.research/external/benchmark/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wconversion -Werror -Wsuggest-override -pedantic -pedantic-errors -fstrict-aliasing -Wno-deprecated-declarations -Wno-deprecated -Wstrict-aliasing -g -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -O0 -std=c++17 -Wp,-MD,CMakeFiles/benchmark.dir/check.cc.o.d -Wp,-MT,external/benchmark/src/CMakeFiles/benchmark.dir/check.cc.o -Wp,-MF,CMakeFiles/benchmark.dir/check.cc.o.d -o CMakeFiles/benchmark.dir/check.cc.o -c /home/jcurl/source/code.research/external/benchmark/src/check.cc

Hmm. That is unexpected. Could you log the CMAKE_CXX_COMPILER_VERSION CMake gets for your q++ there? I only have license access to 8.0.2.

You’re relying on the version of the compiler, which on QNX 7.1 reports (CMake 3.22.1, CMake 4.1.0-rc4-g6845fa6):

CMAKE_CXX_COMPILER_VERSION = 8.3.0

On QNX 8.0, reports:

 CMAKE_CXX_COMPILER_VERSION = 12.2.0

Please don’t do this for detecting the version of QNX. QNX can allow other compilers, not just GCC (qcc is a front-end wrapper, that might call GCC backend, or LLVM, or ICC, etc.).

My scripts used the variable CMAKE_SYSTEM_VERSION. This matches the description of the Operating system version we’re building for (e.g. 7.1.0 or 8.0.0).

Normally this variable isn’t set at all in my tests.

To get the CMAKE_SYSTEM_VERSION is a little tricky, it’s found in my repo at code.research/cmake/modules/research/qnx.cmake at c3cdd2e59c3fadb53218eccbf5da1f00a67ee6b9 · jcurl/code.research · GitHub

i.e. on 7.1.0 and earlier, it’s defined in the headers as _NTO_VERSION. On QNX 8.0 and later, it’s defined in the headers as __QNX__.

I’m not trying to detect the QNX version; this is specifically about q++ support and gcc should never see the code I’ve edited.

But if the compiler is not matching the system version, I’ll need to update the patch to check against 12.2.0. I’m not very familiar with QNX/qcc, so the toolchain not matching the advertised version in the installer was unexpected (though not surprising…macOS and Windows toolchain versioning is wonky too).

Thanks for testing!

In both 7.x and 8.x, qcc can be used to build C code and q++ can be used to build C++ code (similar to gcc and g++). As far as I can tell there is no need for the lang flag on either version, and therefore no need to detect the version.
Am I missing something?

Removing would be a good idea. I can test only this evening though with my project.

This seems to work well on QNX 7.1 and QNX 8.0.

# To include compiler feature detection
include(Compiler/GNU-CXX)

include(Compiler/QCC)
__compiler_qcc(CXX)

# If the toolchain uses qcc for CMAKE_CXX_COMPILER instead of QCC, the
# default for the driver is not c++.
set(CMAKE_CXX_COMPILE_OBJECT
  "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
set(CMAKE_CXX_LINK_EXECUTABLE
  "<CMAKE_CXX_COMPILER> <FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")

set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")