diff --git a/asio/include/asio/detail/impl/posix_thread.ipp b/asio/include/asio/detail/impl/posix_thread.ipp index 7602377336..d1c1333c3f 100644 --- a/asio/include/asio/detail/impl/posix_thread.ipp +++ b/asio/include/asio/detail/impl/posix_thread.ipp @@ -3,6 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2024, BlackBerry Limited. Pavlo Kleymonov (pkleymonov at blackberry com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -47,6 +48,11 @@ std::size_t posix_thread::hardware_concurrency() { #if defined(_SC_NPROCESSORS_ONLN) long result = sysconf(_SC_NPROCESSORS_ONLN); + +#if defined(__QNX__) + result &= 0xFFFFFFFF; +#endif //defined(__QNX__) + if (result > 0) return result; #endif // defined(_SC_NPROCESSORS_ONLN) diff --git a/asio/include/asio/detail/socket_types.hpp b/asio/include/asio/detail/socket_types.hpp index cf4f746a44..2c1e0354bd 100644 --- a/asio/include/asio/detail/socket_types.hpp +++ b/asio/include/asio/detail/socket_types.hpp @@ -3,6 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2024, BlackBerry Limited. Pavlo Kleymonov (pkleymonov at blackberry com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -411,7 +412,13 @@ const int max_iov_len = IOV_MAX; // POSIX platforms are not required to define IOV_MAX. const int max_iov_len = 16; # endif -# define ASIO_OS_DEF_SA_RESTART SA_RESTART +// Note: QNX does not support SA_RESTART +// Therefore they are specifically excluded here. +# if defined(__QNX__) +# define ASIO_OS_DEF_SA_RESTART 0 +# else +# define ASIO_OS_DEF_SA_RESTART SA_RESTART +# endif # define ASIO_OS_DEF_SA_NOCLDSTOP SA_NOCLDSTOP # define ASIO_OS_DEF_SA_NOCLDWAIT SA_NOCLDWAIT #endif diff --git a/asio/qnx/.gitignore b/asio/qnx/.gitignore new file mode 100644 index 0000000000..7f50d71955 --- /dev/null +++ b/asio/qnx/.gitignore @@ -0,0 +1,6 @@ +# QNX Build Files +build/nto-aarch64-le/* +build/nto-x86_64-o/* +!build/Makefile +!build/nto-aarch64-le/GNUmakefile +!build/nto-x86_64-o/GNUmakefile diff --git a/asio/qnx/README.md b/asio/qnx/README.md new file mode 100644 index 0000000000..63c6210d4f --- /dev/null +++ b/asio/qnx/README.md @@ -0,0 +1,30 @@ +# Compile the port for QNX + +**NOTE**: QNX ports are only supported from a **Linux host** operating system + +### Install dependencies + +`sudo apt install automake` + +`sudo apt install pkg-config` + +### Switch to asio main folder + +`cd asio` + +### Generate GNU build tool ./configure and all needed Makefiles + +`./autogen.sh` + +### Setup QNX SDP environment + +`source /qnxsdp-env.sh` + +### Build examples and install asio headers into SDP + +`JLEVEL=$(nproc) make -C qnx/build install` + + +**All asio headers have to be installed to SDP** +* $QNX_TARGET/usr/include/asio/ +* $QNX_TARGET/usr/include/asio.hpp diff --git a/asio/qnx/build/Makefile b/asio/qnx/build/Makefile new file mode 100644 index 0000000000..1a7ac1e0fe --- /dev/null +++ b/asio/qnx/build/Makefile @@ -0,0 +1,3 @@ +LIST=OS CPU VARIANT +MAKEFILE=GNUmakefile +include recurse.mk diff --git a/asio/qnx/build/build-hooks b/asio/qnx/build/build-hooks new file mode 100644 index 0000000000..7dda99a0d8 --- /dev/null +++ b/asio/qnx/build/build-hooks @@ -0,0 +1,160 @@ +#!/bin/sh + +# +# QNX specific build configuration nested level +# +NESTED_LEVEL="../../.." + +# +# Setup of essential configuration parameters +# +function hook_preconfigure { +# +# QNX specific changes are covered by prediefined '__QNX__' +# For examples: "fd_passing_stream_server" and "fd_passing_stream_client" +# For the testsuites: unit/ip/multicast +# + CXXFLAGS="$CXXFLAGS -DASIO_HAS_PTHREADS -DASIO_HAS_STD_STRING_VIEW -DASIO_HAS_CONSTEXPR -DASIO_HAS_STD_FUTURE_CLASS" + +# +# Add socket library +# + LDFLAGS="$LDFLAGS -lsocket" + +# +# Distributive directory +# + DIST_BASE="${PWD}/${NESTED_LEVEL}" + +# +# Setup correct pathes for install and build make commands +# + configure_opts="--srcdir=${DIST_BASE}" + configure_opts="${configure_opts} --prefix=${INSTALL_ROOT_nto}/usr" + configure_opts="${configure_opts} --exec-prefix=${INSTALL_ROOT_nto}/${cpudir}/usr" +} + +# +# Adjust relative path to ./configure tool +# +function hook_configure { + ${NESTED_LEVEL}/configure \ + ${ac_host:+"--host=${ac_host}"} \ + ${ac_build:+"--build=${ac_build}"} \ + ${configure_opts} \ + ${ac_params:+${CC:+"CC=${CC}"}} \ + ${ac_params:+${CFLAGS:+"CFLAGS=-O2 ${CFLAGS}"}} \ + ${ac_params:+${CPPFLAGS:+"CPPFLAGS=${CPPFLAGS}"}} \ + ${ac_params:+${LDFLAGS:+"LDFLAGS=${LDFLAGS}"}} \ + ${ac_params:+${CXX:+"CXX=${CXX}"}} \ + ${ac_params:+${CXXFLAGS:+"CXXFLAGS=-O2 ${CXXFLAGS}"}} \ + ${ac_params:+${ac_autotools:+${ac_autotools}}} \ + || Error "configure failed"; +} + +function hook_premake { + if [ "${make_cmds}" == "check" ] && [ "${TARGET_SYSNAME}" == "nto" ]; then + echo "For target nto suppress tests execution." + echo "All tests have to be run on target system." + make_opts="${make_opts} TESTS=''" + fi +} + +function hook_postmake { + red="\033[0;31m" + grn="\033[0;32m" + yel="\033[1;33m" + blu="\033[1;34m" + cls="\033[0m" + base_build=$PWD + base_testsuite="src/tests" + base_script="run_testsuites.sh" + testsuite_log="test-suite.log" + testsuite_script=$base_testsuite/$base_script + testsuite_sdp_bin=${INSTALL_ROOT_nto}/${cpudir}/usr/bin/asio_tests + + # + # uninstall all asio test from SDP + # + if [ "${make_cmds}" == "uninstall" ] && [ -d ${testsuite_sdp_bin} ]; then + echo "we have to uninstall all asio tests" + (set -x; rm -rf ${testsuite_sdp_bin}) + fi + + # + # build and install all asio tests + # + if [ "${make_cmds}" == "check" ] && [ "${TARGET_SYSNAME}" == "nto" ] && [ "${SYSNAME}" == "linux" ]; then + if [ -d ${base_testsuite} ]; then + + echo "${blu}=========================================================================${cls}" + echo "${blu}Generate script to run testsuites for the ${cpu}${cls}" + echo "${blu}=========================================================================${cls}" + + echo "Remove old testsuite script ..." + #(set -x; - print each command before executing ) + (set -x; rm -f "$testsuite_script") + + echo "Looking for tests executables..." + testsuite_list=$(find . -type f -executable | sed -n "s/^\.\/src\/tests\/\(\S*\)$/\1/p") + + pkg_str=$(grep 'PACKAGE_STRING' Makefile | grep -oP '\d+\.\d+\.\d+' | head -1) + + echo "Creating testsuites script..." + echo "#!/bin/sh" > $testsuite_script || Error "Unexpected error during $testsuite_script initialization"; + echo "_pass=0" >> $testsuite_script || Error "Unexpected error during $testsuite_script initialization"; + echo "_fail=0" >> $testsuite_script || Error "Unexpected error during $testsuite_script initialization"; + echo "echo \"### Testsuites log file ###\" > $testsuite_log" >> $testsuite_script || Error "Unexpected error during $testsuite_script initialization"; + + + echo "Adding testsuites to the script:'$testsuite_script'..." + testsuite_number=0 + for v in ${testsuite_list}; do + testsuite_number=$((testsuite_number+1)); + echo "### Suite number: $testsuite_number" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "result=\$($v 2>&1)" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "if [ 0 -eq \$? ]; then" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo " _pass=\$((_pass+1))" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo " echo \"${grn}PASS${cls}:$v\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "else" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo " _fail=\$((_fail+1))" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo " echo \"${red}FAIL${cls}:$v\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "fi" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "echo \"### Testsuite:$v ###\" >> $testsuite_log" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "echo \"\${result}\" >> $testsuite_log" >> $testsuite_script || Error "Unexpected error during $testsuite_script update by testsuite:'$v'"; + echo "${blu}ADDED${cls}:$v"; + # + # install testsuite into SDP + # + _dest_folder="${testsuite_sdp_bin}/$(dirname $v)" + _source_test="src/tests/$v" + [ -d "${_dest_folder}" ] || (set -x; mkdir -p ${_dest_folder}) + (set -x; cp -f $_source_test $_dest_folder) + done + + echo "echo \"${grn}=========================================================================${cls}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"${grn}Testsuite summary for asio ${pkg_str}${cls}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"${grn}=========================================================================${cls}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"# TOTAL: ${testsuite_number}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"# ${grn}PASS${cls}: \${_pass}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"# ${red}FAIL${cls}: \${_fail}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "if [ 0 -eq \${_fail} ]; then" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"${grn}=========================================================================${cls}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "else" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "echo \"${red}\${_fail} fails see test log:$testsuite_log ${cls}\"" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + echo "fi" >> $testsuite_script || Error "Unexpected error during $testsuite_script update"; + + chmod +x $testsuite_script + + #(set -x; - print each command before executing ) + (set -x; cp -f $testsuite_script $testsuite_sdp_bin) + + echo "${blu}For asio ${pkg_str} total ${testsuite_number} testsuites were added into script:${testsuite_script}${cls}"; + echo "${blu}All testsuites were installed into '${testsuite_sdp_bin}'${cls}"; + echo "${blu}To run all tests please copy '${testsuite_sdp_bin}' to the target system and run test script '${testsuite_script}'${cls}"; + else + echo "${red}Error - base testsuite:'${base_build}/${base_testsuite}' for asio ${pkg_str} was not found!${cls}"; + exit 1; + fi + fi +} diff --git a/asio/qnx/build/nto-aarch64-le/GNUmakefile b/asio/qnx/build/nto-aarch64-le/GNUmakefile new file mode 100644 index 0000000000..d5e18a78d1 --- /dev/null +++ b/asio/qnx/build/nto-aarch64-le/GNUmakefile @@ -0,0 +1,6 @@ +ifndef QCONFIG +QCONFIG=qconfig.mk +endif +include $(QCONFIG) + +include $(MKFILES_ROOT)/qmake-cfg.mk diff --git a/asio/qnx/build/nto-x86_64-o/GNUmakefile b/asio/qnx/build/nto-x86_64-o/GNUmakefile new file mode 100644 index 0000000000..d5e18a78d1 --- /dev/null +++ b/asio/qnx/build/nto-x86_64-o/GNUmakefile @@ -0,0 +1,6 @@ +ifndef QCONFIG +QCONFIG=qconfig.mk +endif +include $(QCONFIG) + +include $(MKFILES_ROOT)/qmake-cfg.mk diff --git a/asio/qnx/test/README.md b/asio/qnx/test/README.md new file mode 100644 index 0000000000..85d65f4dfa --- /dev/null +++ b/asio/qnx/test/README.md @@ -0,0 +1,60 @@ +# Testing asio lib on QNX + +**NOTE**: QNX ports are only supported from a **Linux host** operating system + +asio lib normally wants to be tested on the same machine it was built on. This obviously doesn't work when cross-compiling for QNX. The gist is to build, then copy the whole asio lib source tree on a target. This will include all the relevant files and directory structure which asio lib expects when running its test suite. + +# Running the Test Suite + +### Install dependencies + +`sudo apt install automake` + +`sudo apt install pkg-config` + +### Switch to asio main folder + +`cd asio` + +### Generate GNU build tool ./configure and all needed Makefiles + +`./autogen.sh` + +### Setup QNX SDP environment + +`source /qnxsdp-env.sh` + +### Build and install all asio tests into SDP + +`JLEVEL=$(nproc) CPULIST=x86_64 make -C qnx/build check` + +### Then build your QNX image using mkqnximage and the following options: + +`export ASIO_ROOT=$PWD` + +`mkdir test_image && cd test_image` + +`mkqnximage --extra-dirs=$ASIO_ROOT/qnx/test/mkqnximage --clean --run --force --test-asio=$QNX_TARGET/x86_64/usr/bin/asio_tests` + +### Once the target has booted, the asio tests will be located in /data/asio: + +`cd /data/asio` + +`./run_testsuites.sh` + +### Test execution summary +`...` + +`=========================================================================` + +`Testsuite summary for asio 1.29.0` + +`=========================================================================` + +`# TOTAL: 346` + +`# PASS: 346` + +`# FAIL: 0` + +`=========================================================================` \ No newline at end of file diff --git a/asio/qnx/test/mkqnximage/opt_scripts/opt_test_asio b/asio/qnx/test/mkqnximage/opt_scripts/opt_test_asio new file mode 100755 index 0000000000..1804524247 --- /dev/null +++ b/asio/qnx/test/mkqnximage/opt_scripts/opt_test_asio @@ -0,0 +1,79 @@ +#!/bin/bash + +. ${TOOL_DIR}/functions + +function brief() +{ + echo "--test-asio=[no|]" +} + +function help() +{ + brief + cat < to the compiled asio tests tree, the full tree will be imported + on the target under /data/asio from which you can execute the asio test suite using: + + cd /data/asio/ + ./run_testsuites.sh + + NOTE: You must compile the asio source tree of the desired target before building + the vm image. + + The default is no. +EOF +} + +function validate() { + + if [ ${OPT_TEST_ASIO} != "no" ]; then + if [ ! -d "${OPT_TEST_ASIO}" ]; then + echo "Invalid asio source tree '${OPT_TEST_ASIO}'" + exit 1; + fi + else + exit 0; + fi +} + +function configure() +{ + rm -f output/option_files/*.opt_test_asio + if [ "$OPT_TEST_ASIO" != no ]; then + if [ "${OPT_VERBOSE}" == "yes" ]; then + echo "Building asio file list from ${OPT_TEST_ASIO}" + fi + + for f in $(find ${OPT_TEST_ASIO} -type f); do + echo "[perms=0755] asio/${f#${OPT_TEST_ASIO}/}=${f}" >> output/option_files/data_files.opt_test_asio + done; + + case ${OPT_ARCH} in + x86*) + ASIO_TEST_PREFIX="nto-${OPT_ARCH}-o"; + ;; + *aarch64*) + ASIO_TEST_PREFIX="nto-aarch64-le"; + ;; + esac + + # export asio options" + echo "ASIO_TEST_PREFIX=${ASIO_TEST_PREFIX}" >> output/option_files/ifs_env.opt_test_asio + + fi + + exit 0 +} + +case "$1" in + brief) + brief;; + help) + help;; + validate) + validate;; + configure) + configure;; + default) + echo no;; +esac diff --git a/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp b/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp index 229509f1c1..cc56b76303 100644 --- a/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp +++ b/asio/src/examples/cpp11/local/fd_passing_stream_client.cpp @@ -4,6 +4,7 @@ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2021 Heiko Hund (heiko at openvpn dot net) +// Copyright (c) 2024, BlackBerry Limited. Pavlo Kleymonov (pkleymonov at blackberry com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,6 +24,14 @@ #include #include +#if defined(__QNX__) + #undef CMSG_ALIGN + #define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + + #undef CMSG_SPACE + #define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr))) +#endif //defined(__QNX__) + using asio::local::stream_protocol; constexpr std::size_t max_length = 1024; diff --git a/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp b/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp index 5082185e75..9611db5b5f 100644 --- a/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp +++ b/asio/src/examples/cpp11/local/fd_passing_stream_server.cpp @@ -4,6 +4,7 @@ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2021 Heiko Hund (heiko at openvpn dot net) +// Copyright (c) 2024, BlackBerry Limited. Pavlo Kleymonov (pkleymonov at blackberry com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,6 +23,14 @@ #if defined(ASIO_HAS_LOCAL_SOCKETS) +#if defined(__QNX__) + #undef CMSG_ALIGN + #define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + + #undef CMSG_SPACE + #define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr))) +#endif //defined(__QNX__) + using asio::local::stream_protocol; class session diff --git a/asio/src/tests/unit/ip/multicast.cpp b/asio/src/tests/unit/ip/multicast.cpp index 4f0b3f45e1..c70c7d06b0 100644 --- a/asio/src/tests/unit/ip/multicast.cpp +++ b/asio/src/tests/unit/ip/multicast.cpp @@ -3,6 +3,7 @@ // ~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2024, BlackBerry Limited. Pavlo Kleymonov (pkleymonov at blackberry com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -146,17 +147,20 @@ void test() #if (defined(__MACH__) && defined(__APPLE__)) \ || defined(__FreeBSD__) \ || defined(__NetBSD__) \ - || defined(__OpenBSD__) + || defined(__OpenBSD__) \ + || defined(__QNX__) const ip::address multicast_address_v6 = ip::make_address("ff02::1%lo0", ec); #else // (defined(__MACH__) && defined(__APPLE__)) // || defined(__FreeBSD__) // || defined(__NetBSD__) // || defined(__OpenBSD__) + // || defined(__QNX__) const ip::address multicast_address_v6 = ip::make_address("ff01::1", ec); #endif // (defined(__MACH__) && defined(__APPLE__)) // || defined(__FreeBSD__) // || defined(__NetBSD__) // || defined(__OpenBSD__) + // || defined(__QNX__) ASIO_CHECK(!have_v6 || !ec); // join_group class. @@ -207,11 +211,11 @@ void test() if (have_v6) { -#if defined(__hpux) +#if defined(__hpux) || defined(__QNX__) ip::multicast::outbound_interface outbound_interface(if_nametoindex("lo0")); #else ip::multicast::outbound_interface outbound_interface(1); -#endif +#endif // defined(__hpux) || defined(__QNX__) sock_v6.set_option(outbound_interface, ec); ASIO_CHECK_MESSAGE(!ec, ec.value() << ", " << ec.message()); }