Reference integration#
After building the scrample binary for the qnx x86 image, we can now run it inside the reference qnx image for the x86 platform.
The reference integration repository already provides a reference qnx image.
This image is intentionally minimal and contains only the essential tooling in the IFS image.
For more details of the qnx reference image in Eclipse S-CORE, refer to the reference integration README.md.
To create an ifs image, qnx_ifs bazel rule in qnx_qemu/build/BUILD file is used:
qnx_ifs(
name = "init",
build_file = "init.build",
srcs = [
"system.build",
":scripts",
":configs",
],
visibility = [
"//:__pkg__"
],
)
The snippet above defines an ifs image named init.
The build_file attribute points to the init.build script, which acts as the entry point for the ifs image. It defines the image content and the initial start-up steps.
For more information, refer to the official QNX OS Image Build Files documentation.
The init.build file also includes system.build file, which is used - among other things - to deploy local files to the ifs image, as shown in the example below for the dhcp.conf
# DHCP client configuration
[perms=644] /etc/dhcpcd.conf = configs/dhcpcd.conf # DHCP client configuration file
This is where we need to add our scrample application binary and its runtime configuration. Before doing so, we must first add the scrample binary as a dependency of the ifs image.
The first step is to update the MODULE.bazel file with the dependency to the scrample module and all modules it depends on.
Next, we need to extend .bazelrc file with the compiler settings needed to build these modules.
Both steps follow the same pattern described earlier in the Building source code chapter. Once all dependencies are set up, we can add our scrample binary as dependency of the ifs_image target in the qnx_qemu/build/BUILD:
1qnx_ifs(
2 name = "init",
3 build_file = "init.build",
4 srcs = [
5 "system.build",
6 ":scripts",
7 ":configs",
8 "@score_scrample//src:scrample",
9 "//scrample_integration:etc_configs",
10 ],
11 ext_repo_maping = {
12 "SCRAMPLE_PATH": "$(location @score_scrample//src:scrample)",
13 },
14 visibility = [
15 "//:__pkg__"
16 ],
17)
In lines 8 and 9, we add the dependencies for the scrample binary and scrample runtime config.
Because the scrample_binary target is defined in the scrample bazel module, we must reference it explicit using the scrample module prefix @score_scrample.
The scrample runtime configuration is located in reference_integration repository and includes the IPC services definition file and logging config file.
As shown in the scrample runtime config BUILD file, we use the bazel function export_files to make files available to the external qnx tool mkifs, which is triggered by q*nx_ifs()* in the background.
For the same reason, we declare in line 12 the path to the built scrample binary as the environment variable SCRAMPLE_PATH. (Remember: all targets from other modules are rebuilt in the context of the current module’s configuration.) This allows as to reference the binary during mkifs execution. Finally, we add the scrample artifact to the system.build file file, as shown below:
[perms=777] /etc/logging.json = scrample_integration/etc/logging.json
[perms=777] /etc/mw_com_config.json = scrample_integration/etc/mw_com_config.json
[perms=777] /scrample = ${SCRAMPLE_PATH}
This copies the artifacts to their final location in the ifs image on the target. Now we are ready to build the ifs image, start qemu and to test our application. First, we start qemu, which will also build the ifs image in the background. According to the QEMU tutorial in the reference integration repository, run the following command:
bazel run --config=x86_64-qnx //:run_qemu
If everything was successfull, you should see following output:
[INFO] [QEMU] IP address set to: 169.254.158.190
[INFO] [QEMU] ---> DHCP configuration completed successfully
[INFO] [QEMU] ---> Network configuration completed
[INFO] [QEMU] ---> Setting hostname
[INFO] [QEMU] Hostname set to: Qnx_S-core
[INFO] [QEMU] ---> adding /tmp_discovery folder
Now we can run the scrample binary. It supports two modes: one for sending data and one for receiving it. Start two processes in different modes to let them communicate with each other
/scrample -n 10 -t 100 -m send & ./scrample -n 5 -t 100 -m recv
You can find the explanation of all command-line arguments in the scrample main.cpp file. If everything works correctly, you should now see output indicating that the two processes are communicating with each other. It should look similar to the following:
[INFO] [test_scrample] 2025/11/10 07:53:49.1229574 145754 000 ECU1 IPBR lola log info verbose 2 No explicit applicationID configured. Falling back to using process UID. Ensure unique UIDs for applications using mw::com.
[INFO] [test_scrample] 2025/11/10 07:53:49.1229574 145754 000 ECU1 IPBR lola log info verbose 2 No explicit applicationID configured. Falling back to using process UID. Ensure unique UIDs for applications using mw::com.
[INFO] [test_scrample] 2025/11/10 07:53:49.1229578 145784 000 ECU1 IPBR lola log info verbose 10 Calculated sizes of shm-objects for service_id:instance_id 6432 : 1 are as follows:
[INFO] [test_scrample] QM-Ctrl: 1736 , ASIL_B-Ctrl: 0 , Data: 109984
[INFO] [test_scrample] 2025/11/10 07:53:49.1229580 145811 000 ECU1 IPBR lola log info verbose 2 Successfully created offer path /tmp_discovery/mw_com_lola/service_discovery/6432/1
[INFO] [test_scrample] 2025/11/10 07:53:50.1230079 150796 000 ECU1 IPBR lola log info verbose 2 Successfully created offer path /tmp_discovery/mw_com_lola/service_discovery/6432/1
[INFO] [test_scrample] score/MapApiLanesStamped: Running as proxy, looking for services
[INFO] [test_scrample] score/MapApiLanesStamped: Found service, instantiating proxy
[INFO] [test_scrample] score/MapApiLanesStamped: Subscribing to service
[INFO] [test_scrample] score/MapApiLanesStamped: Received sample: 4
[INFO] [test_scrample] score/MapApiLanesStamped: Received sample: 5
[INFO] [test_scrample] score/MapApiLanesStamped: Proxy received valid data
[INFO] [test_scrample] score/MapApiLanesStamped: Cycle duration 100ms
[INFO] [test_scrample] score/MapApiLanesStamped: Received sample: 6
[INFO] [test_scrample] score/MapApiLanesStamped: Proxy received valid data
[INFO] [test_scrample] score/MapApiLanesStamped: Cycle duration 100ms
[INFO] [test_scrample] score/MapApiLanesStamped: Received sample: 7
[INFO] [test_scrample] score/MapApiLanesStamped: Proxy received valid data
[INFO] [test_scrample] score/MapApiLanesStamped: Cycle duration 100ms
[INFO] [test_scrample] score/MapApiLanesStamped: Received sample: 8
By the way, the same workflow is implemented as one of our integration tests, which you can run with the following command
bazel test --config=qemu-integration --test_output=streamed //:test_scrample_qemu