How to Import a C/C++ Application to Torizon
If you have an existing project and you want to migrate it to Torizon, you may wonder if there are any specifics or guides on how to do it. This article selects existing open-source C/C++ projects that are not necessarily commonly used on embedded and shows how to import them in Torizon, using the Visual Studio Code Extension for Torizon to build and debug them.
In this article, we will show some "tricks" and ways to work around build and runtime issues. The applications chosen as samples are medium-sized open source applications that may match the size of a typical customer's application on embedded devices.
The information may not apply directly to your own scenario, but reading through the article should give you good hints about how to handle different issues you may experience. Keep in mind that there are various frameworks to build a C/C++ project, for instance, the Makefiles, autotools, cmake, or even invoking the compiler directly. If the framework you use is not described, please contact us as want to know more about your requirements.
To illustrate the process of importing a C++ application to Torizon, the following example will be covered in this article:
- Autotools example: Fuse emulator for the Sinclair Zx-Spectrum
This article complies with the Typographic Conventions for Torizon Documentation.
- A computer on module with Torizon installed.
- Visual Studio Code Extension for Torizon installed in your host PC.
- Read the article Torizon Best Practices Guide.
- Read the article How to do C/C++ Development on Torizon.
- Build a hello world using your C/C++ framework, starting from our templates.
Guided Example: Autotools - Fuse Emulator
To illustrate the process of importing a C++ application to Torizon, we will show the process of importing a project written in C to Torizon. As an example, we will import the Fuse emulator project.
Fuse is an emulator for the Sinclair Zx-Spectrum, a home computer that was very popular in the 80s. It is written in C and has a UI developed with Gtk. Debian already provides packages for Fuse but in this article we will ignore them and show how to build it from source code.
Most of the features are encapsulated in a library named libspectrum. These are the stats of the full codebase (fuse and libspectrum) generated by cloc:
|Windows Resource File||15||175||272||494|
It’s around 100k lines of code, so it can be reasonably considered a medium-size project.
Download the Source-Code
Download fuse source-code using Git:
$ git clone https://git.code.sf.net/p/fuse-emulator/fuse fuse-emulator-fuse
You will also build libspectrum, as it will be useful to have both codebases during debugging. Clone it inside the folder where we downloaded fuse:
$ cd fuse-emulator-fuse
$ git clone https://git.code.sf.net/p/fuse-emulator/libspectrum fuse-emulator-libspectrum
If you are working on a Windows PC you must ensure that all files are using unix-style line ending (LF) and not the Windows one (CRLF). To convert all files to Unix line ending you may use WSL. Open a prompt by running wsl.exe, cd to the folder where you stored the code and run:
find -type f | grep -Fv ".git" | xargs dos2unix
Import the Application Using the VS Code Extension for Torizon
The first operation required to migrate fuse to Torizon is creating a configuration for it, this can be done with the “Import an existing C/C++ application" command of the VS code extension. You can follow those steps:
- Open the fuse base source folder (
- Define the application name (
autotools-based projectas the project type
- Select one of the Wayland-based platforms (in the sample we will use the 32-bit)
- Select user as
- Provide the relative path (
bin/fuse) where main executable binary will be installed into.
The extension creates a build container, reloads VSCode and runs inside this container using the Remote-containers extension from Microsoft.
At this point the only original source file that has been changed is .gitignore. The extension adds ignore entries for its working folders, making it easy to add the configuration files to your Git repository.
After opening the folder, Visual Studio will execute the configuration tasks, and this will generate an error:
checking for LIBSPECTRUM... no
configure: error: in `/workspaces/fuse-emulator-fuse':
configure: error: The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables LIBSPECTRUM_CFLAGS
and LIBSPECTRUM_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See `config.log' for more details
The terminal process terminated with exit code: 1
We are going to solve this issue in the coming steps.
Add Build Dependencies
Fuse uses some external libraries, so those should be added to the SDK and runtime containers to be able to build and run it. Fuse can use GTK+, SDL, libsvga or native X11 for its UI. GTK is the default option, so it will be built using that library, which also makes it relatively easy to run it using Wayland. To learn more about adding build and runtime dependencies, we recommend you to read the correspondig sections on How to do C/C++ Development on Torizon and C/C++ Development and Debugging on TorizonCore Using Visual Studio Code.
After searching inside the documentation (README and INSTALL mostly) you can get a list of development libraries: glib, audiofile and gtk-3. Some tools are needed during build (yacc and flex), so additional packages will have to be installed inside the SDK container. Keep in mind that this process depends on the project you are migrating to Torizon: sometimes the dependencies are clearly stated in the project documentation, other times you will have to either adopt a trial and error approach where you build the project and fix the errors, or read the source code and understand what libraries and tools are used.
You need to find the matching development packages for the corresponding version of Debian that the Torizon Container is based from - for instance Debian Bullseye for Torizon 5. Searching on packages.debian.org is usually one of the easiest ways; another possibility is to run a Debian Containers for Torizon in interactive mode and use a command-line tool as
apt-cache search combined with
grep to filter the results. Ensure that you install the right version for the architecture you choose, either armhf or arm64 (we will use armhf in this sample).
You can change our configuration:
- Select Torizon icon in the Visual Studio Code activity bar.
- Go to the
- Set the property
libglib2.0-dev:armhf libaudiofile-dev:armhf libgtk-3-dev:armhf bison flex
After this operation, Visual Studio Code will ask you if you want to rebuild the SDK container and add the new packages. Make sure that all files in the editor are saved before proceeding, and select the option to rebuild and reload the SDK container. After rebuild you'll get the same error from the configuration task, but don't worry, it's going to be fixed soon.
Configure the Build Tasks
Having to build libspectrum makes it a bit more complex because we must configure the Torizon project to build it before building the main Fuse codebase.
When using autotools you need to first configure the build, generating the actual makefiles, and then build it using
make. Those steps are defined in every project Visual Studio Code tasks, in .vscode/tasks.json. By default, the extension generates two tasks named configure_debug and configure_release, both depending on the
autoreconf task, that generates the configure script.
Having libspectrum in the picture requires that you define some additional tasks to configure and build it. You may also have to define debug and release variants, but at the moment we keep it simple and focus on a single configuration:
We also need to add
build_libspectrum as a dependency of our existing configure tasks:
You'll also have to configure pkgconfig to search into libspectrum build folder to find the .pc file describing the newly build library. To do this you have to configure an environment variable. This can be done by adding an "options" entry at the beginning of tasks.json.
Visual Studio Code won't automatically reload tasks, so you have to open the command palette and run the task
Developer: Reload Window command to reload the editor and run your new tasks.
Ctrl + B will launch the build task, this should complete successfully.
Configure the Deployment Tasks
Now you need to prepare the application for deployment. The Torizon extension requires that all the files used by the application are deployed under a subfolder under appconfig_*/work.
During debug those files are copied to the device directly, so there is no need to rebuild the debug container, and during release those files are added inside the release container.
The regular deploy task relies on the
make install command. This won’t deploy libspectrum, so we will need to create an additional task for this:
"detail": "deploy application to work folder",
"detail": "deploy libspectrum to work folder",
You will have to execute the command
Developer: Reload Window again to reload tasks.json.
If you run the
deploy task, everything we need to run fuse should be under appconfig_0/work/fuse-emulator-fuse. The directory name may be different if you changed application name during configuration or added other Torizon platform configurations to the project.
Add Runtime Dependencies
The application is ready to be deployed, but what runtime dependencies do you need to run it? You need to first configure the container that will host it with the required libraries. To learn more about adding build and runtime dependencies, we recommend you to read the correspondig sections on How to do C/C++ Development on Torizon and C/C++ Development and Debugging on TorizonCore Using Visual Studio Code.
Please notice that:
- We are not installing -dev packages, those are required for development, we just install the binaries required at runtime.
- The container is a native Arm32/Arm64 container, so we don’t need to specify the architecture of our packages.
extrapackages configuration property to add the runtime dependencies:
glib2.0 libaudiofile1 libgtk-3-0
Enable the Application to Access the Wayland Socket
Selecting a Wayland-based platform grants that the Wayland compositor is executed when our application run. Since the Wayland compositor container will also be downloaded, on first run it may take a few minutes.
To communicate with the compositor the application needs to access the Wayland socket under /tmp. We need to add /tmp to the volumes in our application configuration:
- press the
/tmpas the key value, press
/tmpalso as value, press enter to confirm
To learn more about adding volumes and bind-mounts using our Torizon extension, read the Torizon Best Practices Guide - Storing Data Permanently.
Set the Shared Libraries Path (LD LIBRARY PATH)
libspectrum will be deployed in the /lib subfolder of fuse directory, we have to add this to the LD_LIBRARY_PATH environment variable. To set environment variables, you can use the
env configuration property and set it to:
To learn more about setting environment variables using our Torizon extension, including an example, read the Torizon Best Practices Guide - Graphical User Interface (GUI).
Update MIME Database
There is another issue, discovered while debugging the application, that is related to Gtk. You’ll have to run the
update-mime-dabase tool to be able to load icons. Since those icons are used in the app menus, a failure on load will prevent fuse from running.
We can execute extra commands after our packages have been installed in the target container using the
buildcommands property. Set it to:
RUN update-mime-database /usr/share/mime
Now you can set a breakpoint (main entry point is in fuse.c) and press
F5 to deploy and run the application. Learn more about deploy, debug and release, among other topics, in the article Visual Studio Code Extension for Torizon.
Guided Example: Qt 5 - Serial Studio
Read the blog post from May, 2021 Importing a Qt Project Into Torizon Using VS Code.