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.
- 1. Platforms
- 2. Windows Portability
- 3. macOS portability
- 4. Linux portability
- 5. Configurations
- 6. Installers
In Quick start and New project we used Visual Studio 2019 to generate the NAppGUI solution. We understand by portability the ability to compile and debug our programs on platforms other than those that were written, without touching a single line of code. We understand by platform 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 such as Subversion or Git, although it could also be updated from an external memory.
- CMake: CMake will create a build project (or solution) from the source code using the scripts in
/prjdirectory 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.
In (Table 1) you have the complete list of supported platforms. In the folder
/lib for each project NAppGUI binaries must be present, depending on the platforms on which it should compile. CMake will recognize the contents of this folder and configure the solution in each case.
|sdk10_15_x64||Xcode 11.3||Intel x64||Catalina|
|sdk10_14_x64||Xcode 10.2.1||Intel x64||Mojave|
|sdk10_13_x64||Xcode 9.4.1||Intel x64||High Sierra|
|sdk10_12_x64||Xcode 8.3.3||Intel x64||Sierra|
|sdk10_11_x64||Xcode 7.3.1||Intel x64||El Capitan|
|sdk10_10_x64||Xcode 6.4||Intel x64||Yosemite|
|sdk10_9_x64||Xcode 6.2||Intel x64||Mavericks|
|sdk10_8_x64||Xcode 5.1.1||Intel x64||Mountain Lion|
|sdk10_7_x64||Xcode 4.6.3||Intel x64||Lion|
|sdk10_6_x64||Xcode 3.2.6||Intel x64||Snow Leopard|
|sdk10_6_x86||Xcode 3.2.6||Intel x86||Snow Leopard|
|gcc9_gtk3_x64||GCC 9.3/GTK 3.24||Intel x64||Ubuntu 20.04 LTS|
|gcc7_gtk3_x64||GCC 7.3.0||Intel x64||Ubuntu 18.04 LTS|
|gcc5_gtk3_x64||GCC 5.3.1||Intel x64||Ubuntu 16.04 LTS|
|gcc5_gtk3_x86||GCC 5.3.1||Intel x86||Ubuntu 16.04 LTS|
|gcc4_gtk3_x64||GCC 4.8.2||Intel x64||Ubuntu 14.04 LTS|
|gcc4_gtk3_x86||GCC 4.8.2||Intel x86||Ubuntu 14.04 LTS|
|gcc6_gtk3_arm||GCC 6.3.0||ARM||Raspbian 9.1 Strech|
2. Windows Portability
We can use any version of Visual Studio from 2005 to compile under Windows. As we saw on Quick start the first thing we have to do is launch CMake over the source code:
- Where is the source code:
- Where to build the binaries:
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 Cacheor 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).
2.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
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 (more details in Standard C library). 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.
2.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
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.
2.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
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.
|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|
SSE support is only disabled in 32-bit (x86) architectures. All 64-bit (x64) CPUs incorporate SSE2.
3. macOS portability
Compiling on Apple iMac, macBook and macMini follows the same philosophy as in Windows, we will only need CMake and Xcode. As we have already done in Windows, we open CMake and assign the directories:
- Where is the source code:
- Where to build the binaries:
/Users/fran/nappgui_build. Directory where the generated code will go.
[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
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
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.
3.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.
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 -p /Applications/Xcode.app/Contents/Developer
sudo xcode-select -s /Applications/Xcode8.app/Contents/Developer
sudo xcode-select -r
You must press CMake
[Generate]every time you use
xcode-selectso that your project updates the compiler change.
3.3. 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 13). From Xcode 10, you can not compile in this architecture (Figure 14).
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 15). 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 16).
4. Linux portability
In the Linux world, the
gcc compiler 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 team in Ubuntu, type the following commands:
1 2 3 4 5 6 7 8
sudo apt-get install gcc sudo apt-get install g++ sudo apt-get install make sudo apt-get install svn sudo apt-get install cmake cmake-qt-gui sudo apt-get install libgtk-3-dev sudo apt-get install libglu1-mesa-dev freeglut3-dev mesa-common-dev gsettings set org.gtk.Settings.Debug enable-inspector-keybinding true
The work methodology does not change at all. We open CMake, select the directories, press
[Configure] and then
[Generate] (Figure 17).
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:
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:
And if we are real hackers, we will be able to debug the programs directly from
gdb (Figure 18).
1 2 3
gdb ./die/Debug/Die (gdb) run ...
4.1. Eclipse CDT
Working directly with the terminal will give us the highest level of freedom possible to coding. With 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: Situate breakpoints, inspect the stack and variables, search for files within the code directory, multiple editions, mass searches, etc.
It is not imperative to use Eclipse. You can choose the editor/IDE you prefer.
The only difference is that we must use the generator
Eclipse CDT4 - Unix Makefiles in CMake (Figure 19) that in addition to
Makefile will create the files
.project needed to import the project into Eclipse.
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 20).
Some interesting Eclipse CDT options under
- Run/Debug->Launching->Terminate and Relaunch while launching.
NAppGUI supports the GCC compiler since version 4.3 (2008). Given the number of existing Linux distributions and that each one includes its own version of GCC, we will use Ubuntu as the reference operating system (Table 3).
It is possible to have several versions of GCC installed on the same machine and to alternate between them in a similar way as we did with
xcode-select, through utility
update-alternatives of Linux. We assume that we are in Ubuntu 18.04:
gcc --version gcc 7.4.0
sudo apt-get install gcc-6 g++-6
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.4.0 g++ --version g++ 7.4.0
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.
sudo apt-get install libgtk-3-dev
4.4. Linux 32bits
To compile 32bit applications from an Ubuntu 64bits system it is necessary to install the package
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.
4.5. ARM architecture
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 21). Both distributions are based on Debian, so we have GCC, CMake and Eclipse directly through
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 22).
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 23).
Unix make does not support multiple configurations. This forces us to enter the property
CMAKE_BUILD_CONFIG (Figure 24) to set the configuration in CMake before generating the
Makefile. We will have to press again
[Generate] for the new configuration to take effect.
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 25).
- Activate the
CMAKE_PACKAGEoption in the CMake panel.
- Set in
CMAKE_PACKAGE_PATHthe directory where the generated packages are to be saved.
- Select the type of packaging through the variable
CMAKE_PACKAGE_GENthat admits three values:
TGZ: Creates a compressed package
.tar.gzthat can be opened with any
.ziputility installed on the computer (Figure 26).
DragNDrop: (MacOS only). Create a
dmgdrive with a bundle
.appand a link to the
/Applications(Figure 27) folder.
NSIS: (Windows only). Create an installer using the Nullsoft scriptable install system (Figure 28) 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_PACKAGEonly when we are going to distribute. During the development process it is advisable to deactivate the checkbox.