Portability
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.
It's hard to write software that runs correctly and efficiently. So once a program works in one environment, you don't want to repeat much of the effort if you move it to a different compiler or processor or operating system. Ideally, it should need no changes whatsoever. Kernighan & Pike - The Practice of Programming.
By portability we understand the ability to compile and debug our programs on platforms other than those for which they were written, without having to touch a single line of code. We understand by platform as the combination of a compiler and a CPU architecture. For example, v142_x64
refers to Visual Studio 2019 and Intel 64bits. In (Figure 1) we see the different steps in the code migration process.

- Working copy: A copy of the project source code must exist on each machine. Normally this will be done through a version control system, as we have seen in GitHub integration.
- CMake: CMake will create a build project (or solution) from the source code using the scripts in
/prj
directory of the SDK distribution. This will be done fully automatically. - Build: Using Visual Studio, Xcode or GCC the solution will be compiled and the libraries and executables included in it will be generated.
- Run/Debug: Binaries can already be executed and debugged on the target platform.
1. Windows Portability
We can use any version of Visual Studio from 2005 to compile under Windows (Table 1). As we saw on Quick start the first thing we have to do is launch CMake over the source code:
Compiler | Platform | Minimum O.S. | |
![]() |
Visual Studio 2022 | v143_x64 (x86) | Vista |
![]() |
Visual Studio 2019 | v142_x64 (x86) | Vista |
![]() |
Visual Studio 2017 | v141_x64 (x86) | Vista |
![]() |
Visual Studio 2015 | v140_x64 (x86) | Vista |
![]() |
Visual Studio 2013 | v120_x64 (x86) | Vista |
![]() |
Visual Studio 2012 | v110_x64 (x86) | Vista |
![]() |
Visual Studio 2010 | v100_x64 (x86) | XP |
![]() |
Visual Studio 2008 | v90_x64 (x86) | XP |
![]() |
Visual Studio 2005 | v80_x64 (x86) | XP |
- Where is the source code:
C:\nappgui_sdk\src
. - Where to build the binaries:
C:\nappgui_build
. - Press
[Configure]
and[Generate]
.
The first time CMake will ask what version of Visual Studio we want to use (Figure 2) and that, obviously, we must have installed in the machine in question. The architecture selected by default can be changed from the same dialog (Figure 3).


Once we press [Open Project]
, we will have the project ready to compile. From Visual Studio Build->Build Solution
and debug Debug->Start Debugging
(Figure 4).

To change the Visual Studio version we have to clear the CMake cache File->Delete Cache
or change the destination directory: Where to build the binaries. It is possible to have different solutions from the same code in several directories, each with its own version of Visual Studio.
Starting with Visual Studio 2010, a dissociation occurs between the editor and the compiler. The term Plaform Toolset identifies the compiler, that can be used with more modern IDEs. If we do not indicate anything, CMake will use the toolset included by default in each version of VS, but it can be changed from Optional toolset to use. For example, we can combine Visual Studio 15 2017
with the VS2013 toolset v120_xp
(Figure 5).

v120_xp
with the editor of VS2017.1.1. Visual C++ Redistributable
By default, Visual Studio dynamically links the functions of the C library, which causes the .exe
may not work on machines that do not have the VC++
DLLs (Figure 6). This forces applications to include a copy of MSVCRT.dll
, VCRUNTIME.dll
, ... or install the famous Visual C ++ Redistributable packages to ensure the application can run smoothly.

NAppGUI uses a small set of the C library, and directly accesses the Windows API whenever possible. For this reason, all applications created with NAppGUI perform a static link (option /MT
) of the stdlib functions that need, avoiding dependencies at the expense of slightly increasing (a few Kb) the size of the final executable. This ensures that applications will run smoothly on all Windows machines without the need for additional DLLs and without having to install the VC++ Redistributable.
NAppGUI applications do not require the Visual C++ Redistributable. Neither do they use the MFC "Microsoft Foundation Classes" nor the .NET platform.
1.2. WindowsXP support
From VS2012, the Platform Toolset generates executables that are not compatible with WindowsXP. If we want our applications to run on this system, we must select the alternative toolset finished in _xp
: V141_xp
, V140_xp
, V120_xp
, V110_xp
. Or, v100
, v90
or v80
, that do support XP (Figure 7).
Support for WindowsXP has been permanently removed in Visual Studio 2019. Platform Toolset v142_xp does not exist.

NAppGUI does not work on Windows prior to XP or with Visual Studio prior to 2005.
1.3. SSE support
With the Pentium III, Intel incorporated an additional set of instructions for floating-point operations called SSE Streaming SIMD Extensions. This allows optimizing mathematical calculations at the cost of losing compatibility, since applications that use SSE will not work on Pentium II or earlier models. In NAppGUI the toolset have been reserved v80_x86
and v90_x86
of Visual Studio to create applications compatible with older processors (Table 2). From v100_x86
, SSE2 will be used in all the toolset.
Toolset | SSE | Minimum CPU |
v80_x86 | x87 (no SSE) | Pentium II/AMD K6 |
v90_x86 | SSE | Pentium III/AMD Duron |
v100_x86 | SSE2 | Pentium IV/AMD Sempron |
v110_x86 | SSE2 | Pentium IV/AMD Sempron |
... | SSE2 | ... |
SSE support is only disabled in 32-bit (x86) architectures. All 64-bit (x64) CPUs incorporate SSE2.
1.4. Command line
To work from the command line in Windows, open a developer console (Developer Command Prompt for VS...) and go to the build directory:
|
cmake -G "Visual Studio 16 2019" -A x64 -T v120 ../nappgui_sdk/src msbuild NAppGUI.sln /p:Configuration=Debug |
where cmake
will generate VS solution (*.sln) and msbuild
will compile it:
-G
is the compiler version (or generator in CMake slang).
|
-G "Visual Studio 17 2022" -G "Visual Studio 16 2019" -G "Visual Studio 15 2017" -G "Visual Studio 14 2015" -G "Visual Studio 12 2013" -G "Visual Studio 11 2012" -G "Visual Studio 10 2010" -G "Visual Studio 9 2008" -G "Visual Studio 8 2005" |
Support for Visual Studio 8 2005 was removed in CMake 3.12. You must use an older version of CMake if you are still using VS2005. NAppGUI DOES NOT work with versions prior to VS2005.
-A
is the Intel 32 or 64 bit architecture:
|
-A x64 -A Win32 |
NAppGUI does not offer support for another type of architecture in Windows: ARM, Itanium, etc.
-T
is the Platform Toolset. If you omit this parameter, the one included by default in the compiler will be taken.../nappgui_sdk/src
: You must indicate the relative path to the/src
directory of the SDK./p:Configuration=Debug
See Configurations.
|
-T v143 -T v142 -T v141 -T v140 -T v120 -T v110 // For XP compatibility -T v141_xp -T v140_xp -T v120_xp -T v110_xp -T v100 -T v90 -T v80 |
2. macOS portability
Compiling on Apple iMac, macBook and macMini follows the same philosophy seen above, we will only need CMake and Xcode from 3.2.6 version (Table 3). As we have already done in Windows, we open CMake and assign the directories:
- Where is the source code:
/Users/fran/nappgui_sdk/src
(or yourWORKING_DIR/nappgui/src
). - Where to build the binaries:
/Users/fran/nappgui_build
. Directory where the generated code will go.
Press [Configure]
. The first time CMake will ask us to select the compiler. Unlike Visual Studio, it only offers one option for Xcode (Figure 8). We accept, press [Generate]
and then [Open Project]
.

Compiler | Minimum O.S. | Platform | |
![]() |
Xcode 13.1 | Monterey | sdk12_0_x64 (arm) |
![]() |
Xcode 12.5.1 | Big Sur | sdk11_3_x64 (arm) |
![]() |
Xcode 11.7 | Catalina | sdk10_15_x64 |
![]() |
Xcode 10.3 | Mojave | sdk10_14_x64 |
![]() |
Xcode 9.4.1 | High Sierra | sdk10_13_x64 |
![]() |
Xcode 8.3.3 | Sierra | sdk10_12_x64 |
![]() |
Xcode 7.3.1 | El Capitan | sdk10_11_x64 |
![]() |
Xcode 6.4 | Yosemite | sdk10_10_x64 |
![]() |
Xcode 6.2 | Mavericks | sdk10_9_x64 |
![]() |
Xcode 5.1.1 | Mountain Lion | sdk10_8_x64 |
![]() |
Xcode 4.6.3 | Lion | sdk10_7_x64 |
![]() |
Xcode 3.2.6 | Snow Leopard | sdk10_6_x64 (x86) |
When opening the Xcode solution (NAppGUI.xcodeproj)
, we see the different projects that compose it, including Die and Dice. We select Die in the upper left drop-down and then press Play
or Product->Run
(Figure 9). This will compile the program and launch it in debug mode, where we can establish breakpoints to inspect the stack and the value of the variables.

2.1. Base SDK and Deployment Target
Each year, Apple releases a new version of macOS, which comes with a new SDK and the Xcode update that includes the SDK.
Base SDK is the version included in each new major version of Xcode, which matches the latest version of the macOS system on the market.
Apple has a much more restrictive policy than Microsoft regarding the applications compatibility with earlier versions of the operating system. By default, a program compiled with SDK 10.14 (macOS Mojave) will not work in the immediately previous macOS High Sierra (Figure 10).

To avoid this problem, and for applications to work in older macOS, the Deployment Target parameter exists. When using it, a macro will be activated thatavoid the new features of the Base SDK. This will allow the program to run in old versions at the expense, of course, of not having access to the latest iMac features. You can select the Deployment Target through CMake options list, after pressing [Configure]
(Figure 11).

Xcode 8 considers Deployment Target to be less than 10.9 obsolete (Figure 12). Use Xcode 7 if you want support for Mac OSX 10.8 Mountain Lion and earlier.

2.2. Multiple versions of Xcode
We have already seen that CMake only offers an option for Xcode, although it is possible to have several versions on the same machine, each within its own Xcode.app
bundle. There will always be a default Xcode in the system (the most recent) but it can be changed using the xcode-select
utility:
1 2 |
xcode-select -p /Applications/Xcode.app/Contents/Developer |
1 |
sudo xcode-select -s /Applications/Xcode8.app/Contents/Developer |
1 |
sudo xcode-select -r |
You must press CMake[Configure]
and[Generate]
every time you usexcode-select
so that your project updates the compiler change.
2.3. macOS ARM
In November 2020 Apple launches its new line of desktop and laptop computers (iMac, macBook and macMini) based on the Apple M1 processor with ARM architecture (Figure 13). Although they are capable of running programs compiled for Intel x64 using the Rosetta 2 program (Figure 14), the ideal would be to compile our applications for the new architecture in order to optimize the executables as much as possible.


NAppGUI supports the Apple ARM architecture through the sdk11_00_arm
package. You just have to select the arm64
option in CMAKE_ARCHITECTURE
(Figure 15).
You can compile M1 architecture from Intel x64 machines, but you will not be able to debug executables.
M1 architecture is only available for Big Sur system (macOS 11.0) and later.

2.4. macOS 32bits
Since the macOS High Sierra version, Apple has declared obsolete the architecture of 32 bits, issuing warnings to the users in the case of detecting executables i386
(Figure 16). From Xcode 10, you can not compile in this architecture (Figure 17).


Support for 32-bit applications has definitely removed in macOS Catalina, which only allows 64-bit applications to run.
This makes some sense since all models of Intel iMac incorporate 64-bit processors, with the exception of a few 2006 models in white polycarbonate that mounted the 32-bit Intel Core Duo (Figure 18). These iMac admitted at most the Mac OSX 10.6 Snow Leopard, being fundamental requirement from 10.7 Lion, the have a 64-bit CPU. To compile without problems in 32bits you have to use, at most, Xcode 6 (Figure 19).


2.5. Command line
In the same way that we saw in Windows, if you prefer to work from a terminal, go to the directory build.
|
cmake -G "Xcode" -DCMAKE_DEPLOYMENT_TARGET:STRING="11.0" -DCMAKE_ARCHITECTURE:STRING="arm64" ../nappgui_sdk/src xcodebuild NAppGUI.xcodeproj -configuration Debug |
where cmake
will generate the (*.xcodeproj) file and xcodebuild
will compile it:
-G
always"Xcode"
. Usexcode-select
to toggle if you have multiple versions installed.-DCMAKE_DEPLOYMENT_TARGET
. Minimum operating system to be supported.-DCMAKE_ARCHITECTURE
.arm64
,x64
,i386
.
|
"11.0" // Big Sur "10.15" // Catalina "10.14" // Mojave "10.13" // High Sierra "10.12" // Sierra "10.11" // El Capitan "10.10" // Yosemite "10.9" // Mavericks "10.8" // Mountain Lion "10.7" // Lion "10.6" // Snow Leopard |
NAppGUI does not support creating Apple's Fat binaries. You must indicate a single value in this field.
../nappgui_sdk/src
: You must indicate the relative path to the/src
directory of the SDK.-configuration
See Configurations.
3. Linux portability
In the Linux world, the gcc
compiler (Table 4) and the make
tool are used to generate the binaries, but there is no "official" development environment. To carry out an elementary configuration of our computer, type the following commands:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Development tools sudo apt-get install gcc sudo apt-get install g++ sudo apt-get install make sudo apt-get install cmake cmake-qt-gui // Development libraries sudo apt-get install libgtk-3-dev sudo apt-get install libglu1-mesa-dev freeglut3-dev mesa-common-dev sudo apt-get install libcurl4-openssl-dev // GTK Inspector (Ctrl+D when debugging) gsettings set org.gtk.Settings.Debug enable-inspector-keybinding true // Check system libraries version pkg-config --modversion gtk+-3.0 3.24.20 pkg-config --modversion libcurl 7.68.0 |
Minimum O.S. | Compiler | Toolkit | Platform | |
![]() |
Ubuntu 22.04 LTS | GCC 11.2.0 | GTK 3.24.33 | gcc11_gtk3_x64 |
![]() |
Ubuntu 20.04 LTS | GCC 9.3 | GTK 3.24.20 | gcc9_gtk3_x64 |
![]() |
Ubuntu 18.04 LTS | GCC 7.5 | GTK 3.22.30 | gcc7_gtk3_x64 |
![]() |
Ubuntu 16.04 LTS | GCC 5.4 | GTK 3.18.9 | gcc5_gtk3_x64 (x86) |
![]() |
Ubuntu 14.04 LTS | GCC 4.8.2 | GTK 3.10.8 | gcc4_8_gtk3_x64 (x86) |
![]() |
Ubuntu 12.04 LTS | GCC 4.6.3 | GTK 3.4.2 | gcc4_6_gtk3_x64 (x86) |
![]() |
Raspbian 10 Buster | GCC 8.3.0 | GTK 3.24.5 | gcc8_gtk3_arm |
![]() |
Raspbian 9.1 Strech | GCC 6.3.0 | GTK 3.22.11 | gcc6_gtk3_arm |
![]() |
Raspbian 8.0 Jessie | GCC 4.9.2 | GTK 3.14.5 | gcc4_9_gtk3_arm |
The work methodology does not change at all. We open CMake, select the directories, press [Configure]
and then [Generate]
(Figure 20).

In Linux we must use the CMake Unix Makefiles
generator, which will create a series of Makefile
scripts in /home/fran/nappgui_build
(or the binary directory that we have selected). These Makefile
contain the necessary commands to compile and link all the projects of the solution. We open a terminal and run make
:
make
.
1 2 3 4 5 6 7 8 |
cd /home/fran/nappgui_build make [ 15%] Building C object games/die/CMakeFiles/Die.dir/dgui.c.o [ 30%] Building C object games/die/CMakeFiles/Die.dir/die.c.o [ 45%] Building C object games/die/CMakeFiles/Die.dir/draw/ddraw.c.o [ 60%] Building C object games/die/CMakeFiles/Die.dir/resgen/all.c.o [ 75%] Linking CXX executable Debug/Die [ 95%] Built target Die |
Once the compilation is finished, we can launch the executables directly from the terminal:
1 |
./die/Debug/Die |
And if we are real hackers, we will be able to debug the programs directly from gdb
(Figure 21).
1 2 3 |
gdb ./die/Debug/Die (gdb) run ... |

You can also use CMake from the command line:
|
cmake -G "Unix Makefiles" -DCMAKE_ARCHITECTURE:STRING="x64" -DCMAKE_BUILD_CONFIG:STRING="Debug" ../nappgui_sdk/src make |
where cmake
will generate the Makefiles
and make
will compile:
-G
"Unix Makefiles"
if you are only going to use the terminal. There is the possibility of working with different IDEs in Linux, as we will see below.-DCMAKE_ARCHITECTURE
.x64
,i386
oarm
.-DCMAKE_BUILD_CONFIG
See Configurations.../nappgui_sdk/src
: You must indicate the relative path to the/src
directory of the SDK.
|
"CodeBlocks - Unix Makefiles" "CodeLite - Unix Makefiles" "Sublime Text 2 - Unix Makefiles" "Kate - Unix Makefiles" "Eclipse CDT4 - Unix Makefiles" |
3.1. GTK+3
Unlike Windows and macOS, in Linux you can create user interfaces using different libraries (or toolkits) with GTK and Qt being the two most famous. NAppGUI uses GTK+3 for the graphical part in Linux (see Dependencies), although in the future it is possible that it also incorporates support for Qt, since it is the basis of the KDE desktop system, used in Kubuntu.GTK+3 is found naturally in Ubuntu and many other distributions, although to compile it is necessary to install the developer version.
3.2. Multiple versions of GCC
Although each Linux distribution incorporates a "canonical" version of GCC, it is possible to have several installed on the same machine and switch between them in a similar way as we did on the mac with xcode-select
. For this we will use the Linux command update-alternatives
. We assume we are on Ubuntu 18.04 LTS:
1 2 |
gcc --version gcc 7.5.0 |
1 |
sudo apt-get install gcc-6 g++-6 |
1 2 |
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 50 --slave /usr/bin/g++ g++ /usr/bin/g++-6 |
1 2 3 4 5 |
sudo update-alternatives --set gcc /usr/bin/gcc-6 gcc --version gcc 6.5.0 g++ --version g++ 6.5.0 |
1 2 3 4 5 |
sudo update-alternatives --auto gcc gcc --version gcc 7.5.0 g++ --version g++ 7.5.0 |
3.3. Eclipse CDT
Working directly with the terminal will give us the highest level of freedom possible to coding. Just returning to the console and typing make
everything necessary will be re-compiled. However, the use of GDB
directly will be quite tedious, so we will make the leap to Eclipse CDT. This environment will allow us to program with a methodology similar to that of Visual Studio and Xcode: Enable breakpoints, inspect the stack and variables, search for files within the code directory, multiple editions, mass searches, etc.
The only difference is that we must use the generator Eclipse CDT4 - Unix Makefiles
in CMake that in addition to Makefile
will create the files .cproject
and .project
needed to import the project into Eclipse.
It is not imperative to use Eclipse. CMake supports various IDEs based on Makefiles (Figure 22).

Makefile
. We open Eclipse and we do File->Import->Existing Projects into Workspace
. A dialog box will appear where we indicate the build directory that we have configured in CMake (/home/fran/nappgui_build
). Eclipse will open the project placing a tree with all the files on the left and we'll compile with Project->Build All
. At the time of debugging (Die in this case) we will create a profile from Run->Debug Configurations->C/C++ Application
. We press [Search Project...]
and select Die from the drop-down list. Finally we press [Debug]
to debug the application interactively (Figure 23).

Some interesting Eclipse CDT options under Window->Preferences
.
- Run/Debug->Launching->Terminate and Relaunch while launching.
3.4. Linux 32bits
To compile 32bit applications from an Ubuntu 64bits system it is necessary to install the package multilib
:
1 |
sudo apt-get install gcc-multilib |
But now there are problems to perform cross-compilation that includes the GTK+ library, so it will not be possible to use the same development machine to generate in both architectures, as in Windows. Console applications or libraries that do not access GTK can be compiled in 32bits from a 64bit computer.
It is not possible to compile in 32bits from an Ubuntu system of 64bit applications that use GTK+3.
3.5. Linux ARM
The architecture ARM Advanced RISC Machine is the predominant in the market of embedded devices such as smartphones and tablets. Currently, NAppGUI does not offer support for the development of iOS/Android mobile applications, but for other types of boards that support versions of Linux ARM "desktop", such as the Raspberry PI with Raspbian. To carry our code to Raspberry Pi you have to follow the same steps as in Ubuntu Linux (Figure 24). Both distributions are based on Debian, so we have GCC, CMake and Eclipse directly through apt-get
.

4. Configurations
An NAppGUI application can be compiled in three different configurations, depending on the level of debugging we need.
- Debug: Includes debug information in the binaries and code optimizations are not performed. It is the version for the developer.
- Release: The debug information is removed and all possible optimizations are made. It is the version for the user.
- ReleaseWithAssert: It is the Release version, but leaving the statements active Asserts. It is aimed at the end user, but in cases where it is necessary to obtain detailed information of possible anomalies, at the cost of a decrease in the overall performance of the program.
Both Visual Studio and Xcode are multi-configuration environments, that is, we can alternate between them directly from the editor itself. In Visual Studio we have a drop-down at the top of the editor (Figure 25).

In Xcode is a bit more hidden. We make Product->Scheme->Edit Scheme
. A pop-up window will appear. We select Run->Info->Build Configuration
(Figure 26).

Unfortunately, Unix make
does not support multiple configurations. This forces us to enter the property CMAKE_BUILD_CONFIG
(Figure 27) to set the configuration in CMake before generating the Makefile
. We will have to press again [Configure]
and [Generate]
for the new configuration to take effect.

5. Installers
The last step, once a program has been created and refined, will be to create a package/installer that contains the executable and its possible dependencies, to distribute it comfortably to the final user. This packaging process has been automated in NAppGUI thanks to CPack, a utility included with CMake (Figure 28).

- Activate the
CMAKE_PACKAGE
option in the CMake panel. - Set in
CMAKE_PACKAGE_PATH
the directory where the generated packages are to be saved. - Select the type of packaging through the variable
CMAKE_PACKAGE_GEN
that admits three values: TGZ
: Creates a compressed package.tar.gz
that can be opened with any.zip
utility installed on the computer (Figure 29).DragNDrop
: (MacOS only). Create admg
drive with a bundle.app
and a link to the/Applications
(Figure 30) folder.NSIS
: (Windows only). Create an installer using the Nullsoft scriptable install system (Figure 31) utility. It is necessary to have installed the software NSIS (only to create the installer). The user who receives the package does not need to have such software installed.



Each package includes a copy of the license with which we are going to distribute the application. The content of it can be edited from the file /res/license.txt
included in the resources directory of each project.
Packaging a program is time consuming. Activate CMAKE_PACKAGE
only when we are going to distribute. During the development process it is advisable to deactivate the checkbox.