Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release
or cat /etc/issue
on the board.
Remember that you can always refer to the Torizon Documentation, there you can find a lot of relevant articles that might help you in the application development.
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:
This article complies to the Typographic Conventions for Torizon Documentation.
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.
As an example, we will import Fuse Emulator Project to Torizon - http://fuse-emulator.sourceforge.net/
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:
Language | files | blank | comment | code |
---|---|---|---|---|
C | 273 | 20781 | 10310 | 87191 |
C/C++ Header | 136 | 2793 | 3104 | 5559 |
Perl | 23 | 1512 | 561 | 4401 |
m4 | 9 | 303 | 171 | 2766 |
make | 33 | 311 | 680 | 1236 |
Windows Resource File | 15 | 175 | 272 | 494 |
yacc | 1 | 51 | 23 | 245 |
lex | 1 | 40 | 21 | 101 |
Bourne Shell | 3 | 24 | 35 | 34 |
SUM: | 494 | 25990 | 15177 | 102027 |
It’s around 100k lines of code, so it can be reasonably considered a medium-size project.
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
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:
fuse-emulator-fuse
)fuse
)autotools-based project
as the project typetorizon
(default)debug
configurationbin/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.
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:
CONFIGURATION
panel.devpackages
to: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.
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:
tasks.json{ "label": "autoreconf_libspectrum", "command": "autoreconf", "type": "shell", "args": [ "--install", "--force" ], "options": { "cwd": "${workspaceFolder}/fuse-emulator-libspectrum" }, "problemMatcher": [], "group": "none" }, { "label": "configure_libspectrum", "command": "./configure", "type": "shell", "args": [ "--prefix", "${workspaceFolder}", "--host", "${command:torizon.ccpp.getHostTriplet}" ], "options": { "cwd": "${workspaceFolder}/fuse-emulator-libspectrum" }, "problemMatcher": [], "group": "none", "dependsOn": [ "autoreconf_libspectrum" ] }, { "label": "build_libspectrum", "command": "make", "type": "shell", "args": [ "install-strip" ], "problemMatcher": { "base": "$gcc" }, "options": { "cwd": "${workspaceFolder}/fuse-emulator-libspectrum", "env": { "CFLAGS": "-g", "CXXFLAGS": "-g" } }, "group": "build", "dependsOn": [ "configure_libspectrum" ] },
We also need to add build_libspectrum
as a dependency of our existing configure tasks:
tasks.json{ "label": "configure_debug", "command": "./configure", "type": "shell", "args": [ "--prefix", "/${command:torizon.getAppName}", "--enable-debug", "--host", "${command:torizon.ccpp.getHostTriplet}", ], "problemMatcher": [], "group": "none", "dependsOn": [ "autoreconf", "build_libspectrum" ] }, { "label": "configure_release", "command": "./configure", "type": "shell", "args": [ "--prefix", "/${command:torizon.getAppName}", "--host", "${command:torizon.ccpp.getHostTriplet}" ], "problemMatcher": [], "group": "none", "dependsOn": [ "autoreconf", "build_libspectrum" ] },
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.
tasks.json"version": "2.0.0", "options": { "env": { "PKG_CONFIG_PATH": "${env:PKG_CONFIG_PATH}:${workspaceFolder}/lib/pkgconfig" } }, "tasks": [
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.
Pressing Ctrl + B
will launch the build task, this should complete successfully.
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.
Note: 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:
tasks.json{ "detail": "deploy application to work folder", "label": "deploy", "command": "make", "args": [ "install" ], "type": "shell", "options": { "env": { "DESTDIR": "${workspaceFolder}/${config:torizon.appfolder}/work" } }, "group": "none", "dependsOn": [ "deploy_libspectrum" ] }, { "detail": "deploy libspectrum to work folder", "label": "deploy_libspectrum", "command": "install", "args": [ "-D", "-t", "${workspaceFolder}/${config:torizon.appfolder}/work/${command:torizon.getAppName}/lib", "lib/libspectrum.so.*" ], "type": "shell", "group": "none" }
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.
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:
Set the extrapackages
configuration property to add the runtime dependencies:
glib2.0 libaudiofile1 libgtk-3-0
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:
+
button near volumes
/tmp
as the key value, press Enter
to confirm/tmp
also as value, press enter to confirmTo learn more about adding volumes and bind-mounts using our Torizon extension, read the Torizon Best Practices Guide - Storing Data Permanently.
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:
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/#%application.appname%#/lib"
To learn more about setting environment variables using our Torizon extension, including an example, read the Torizon Best Practices Guide - Graphical User Interface (GUI).
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.
Read the blog post from May, 2021 Importing a Qt Project Into Torizon Using VS Code.