AuroraLinkingLibs
Description
The application is an example of linking libraries in various ways on the Aurora OS. The main goal is to demonstrate how to link static and dynamic libraries in all available application build systems for the Aurora OS. The application includes the ability to check the connection of three custom-written libraries: a static library, a implicit dynamic library, and a explicit dynamic library.
Build status:
Table of Contents
- Table of Contents
- Detailed description
- Compatibility
- Build features
- Branch info
- Install and Build
- Screenshots
- Usage options
- Project Structure
- Terms of Use and Participation in Development
Detailed description
There are three main ways to link any library:
-
Take the library sources and integrate them directly into your project. This is the simplest method, but in this case the library will be rebuilt every time. And this can greatly reduce the speed of building the application.
-
Use static libraries that are linked during application compilation. They are in files with the extension
*.a
-
Use dynamic libraries that are connected during application runtime. They are in files with the extension
*.so
Next, we will show how to collect and connect libraries for all the methods described above on two build systems - qmake
and cmake
Creating a library
For example, let's make the same library containing a single function that displays the sum of two numbers.
void print_add(int a, int b) {
qDebug() << a << " + " << b << " = " << a + b;
}
Next, we need the corresponding *.pro
and CMakeLists.txt
files, which will configure the qmake
and cmake
builds respectively.
For qmake:
TEMPLATE = lib
TARGET = add
SOURCES += add.cpp \
HEADERS += add.h \
this code will build a dynamic library with a *.so
file. To build a static one, you need to add a config after specifying the target:
TEMPLATE = lib
TARGET = add
CONFIG += staticlib
SOURCES += add.cpp \
HEADERS += add.h \
To build for the target, you need to go to Aurora IDE, make a dummy spec file in the rpm directory and start the build. The assembly will fail, but the library will be assembled and we will get what we need.
Next for cmake:
cmake_minimum_required(VERSION 3.0)
project(add)
# Find the Qt5 package
find_package(Qt5 COMPONENTS Core REQUIRED)
# Add the source files to the executable
add_library(add STATIC
add.cpp
add.h
)
# Include the header files
target_include_directories(add PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Link against the Qt5 libraries
target_link_libraries(add PRIVATE
Qt5::Core
)
For a dynamic library, replace STATIC
with SHARED
Building the library
There are two ways to build the library: through the IDE and through the terminal
Building via IDE
-
In the case of
qmake
, it is enough to write a dummy spec file, which will describe how to build the rpm package. We start the assembly through the IDE. It will fail because... There will be nothing to load into rpm, but the library will be assembled. And we will get the desired*.a
or*.so
file. -
In the case of
cmake
this will not work and you need to make a template application in which this library will be connected accordingly:
add_subdirectory(<library directory>)
Build via terminal
-
Assembly within a specific target. Login to docker/virtualbox on port 2222 with the command:
ssh -p 2222 -i "aurora-path"/vmshare/ssh/private_keys/sdk mersdk@localhost
Where "aurora-path" - path to the Aurora SDK installation directory
-
Checking installed targets:
sdk-assistant list
-
Go to target
as user:
sb2 -t AuroraOS-4.0.2.303-base-armv7hl -m sdk-build
as root:
sb2 -t "$target" -m sdk-install -R
Accordingly, we change the target AuroraOS-4.0.2.303-base-armv7hl to the desired one. We go to the build directory and execute the commands as if we were building as on regular Linux.
-
For
qmake
:mkdir build cd build qmake .. make
or call qmake of a specific target
qmake <name>.pro
-
For
cmake
:mkdir build cd build cmake .. make
Linking the library to the application
Let's look at each of the ways to connect the library:
Building with sources
In this case, you can simply copy the library source files into the project and add them to the target via add_executable
or SOURCE +=
for cmake
and qmake
respectively.
Building with sources (alternative)
You can directly call the library build during assembly and connect it. To do this, use the following commands:
-
For
cmake
:add_subdirectory(<directory>)
-call an assembly in a subdirectory
target_include_directories(${PROJECT_NAME} PRIVATE <directory> )
-add include pathes from directory
target_link_libraries(${PROJECT_NAME} <library name> )
-to link a static library file
-
For
qmake
:SUBDIRS += "directory path"
-call an assembly in a subdirectory
INCLUDEPATH += "path to .h files"
-add include pathes from directory
LIBS += -L"library path" -l"library name"
-to link a static library file
Adding a static library.
The static library has a .a
extension and is included in the project at build time. To do this you need:
-
Specify where to get function/class declarations from For cmake
include_directories
For qmakeINCLUDEPATH +=
-
Specify where to get the compiled library sources from For cmake
target_link_libraries
For qmakeLIBS += -L$$OUT_PWD/../<library path> -l<library name>
There are no more requirements, because... The library sources are already inside the executable file
Dynamic library
The dynamic library is connected while the application is running. There are two types of dynamic library linking: explicit and implicit linking.
Implicit dynamic linking of a dynamic library
Everything is identical to the static library, but the *.so
library file must be supplied along with the executable file
To do this, we indicate in the .spec
file so that it is copied to the desired directory. Example for the mul
and sub
libraries:
mkdir %{buildroot}/%{_datadir}/%{name}/lib/
cp -rf $PWD/mul/libmul.so* %{buildroot}/%{_datadir}/%{name}/lib/
cp -rf $PWD/sub/libsub.so* %{buildroot}/%{_datadir}/%{name}/lib/
%define __requires_exclude ^(libadd.*|libsub.*|libmul.*).*$
%define __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$
In AuroraOS, a path like /usr/share/{package_name}/lib/*
is standard for the libraries required for the application.
If there is no library in the specified path, the application will not start
Explicitly linking a dynamic library
It is not necessary to specify paths for declarations and for libraries. It is connected using the QLibrary
class. Example:
QLibrary myLib("/usr/share/ru.auroraos.qmake_libraries/lib/libmul.so");
if (myLib.load()) {
typedef void (*MyFunction)(int, int);
MyFunction myFunction = (MyFunction) myLib.resolve("print_mul");
if (myFunction) {
qDebug() << "Function resolved successfully";
// Call the function
myFunction(2, 3);
} else {
qDebug() << "Failed to resolve function";
}
} else {
qDebug() << "Failed to load library";
}
Because QLibrary
searches required function by name, you need to add following line to the library code:
#define DLL_PUBLIC __attribute__ ((visibility("default")))
extern "C" DLL_PUBLIC <your function>
This was done because, due to the presence of function overloading in C++, the name of the function in the library and the actual name by which the function will be searched in the SO file will be different. extern "C" specifies that the name must match.
To search for a library, you need to specify the full path, but this can be avoided by adding our library to ldconfig
.
Compatibility
The application works correctly starting with Aurora OS 5.x.x and higher.
Build features
This project contains two subprojects, each of which contains an identical application but with different build systems. In cmake_libraries, the project is built using the CMakeLists.txt file. In qmake_libraries, the project is built using the file ru.auroraos.qmake_libraries.pro.
Branch info
Install and Build
The project is built in the usual way using the Aurora SDK. Documentation to build.
Screenshots
Usage options
Calling a Function from the Library
-
Click on one of the options, after which a function from the library will be executed and a transition to the results screen will occur.
-
After the message about successful execution, you can go back.
Exploring Ways to Link Libraries
From the source code of this project, you can learn how to link various libraries for the build systems CMake and QMake:
-
static
-
dynamic with explicit linking
-
dynamic with implicit linking
Project Structure
The project has a standard C++ and QML based application structure for the Aurora OS.
-
The application using qmake employs the qmake build system.
-
The application using cmake employs the cmake build system.
CMake Project Structure
The project has a standard structure for C++ and QML applications for the Aurora OS.
- CMakeLists.txt the file describes the project structure for the cmake build system.
- icons the directory contains application icons for supported screen resolutions.
- add the directory contains sources of static library which linking to app
- sub the directory contains sources of dynamic library which linking implicit to app
- mul the directory contains sources of dynamic library which linking explicit to app
-
qml the directory contains the QML source code and user interface resources.
- cover the directory contains implementations of application covers.
- icons the directory contains additional user interface icons.
- pages the directory contains application pages.
- cmake_libraries.qml the file provides the application window implementation.
-
rpm the directory contains the rpm package build settings.
- cmake_libraries.spec the file is used by the rpmbuild tool.
-
src the directory contains C++ source code.
- main.cpp the file is the entry point to the application.
- translations the directory contains the user interface translation files.
- ru.auroraos.cmake_libraries.desktop the file defines the display and startup options for the application.
QMake Project Structure
The project has a standard structure for C++ and QML applications for the Aurora OS.
- add the subproject contains sources of static library which linking to app
- sub the subproject contains sources of dynamic library which linking implicit to app
- mul the subproject contains sources of dynamic library which linking explicit to app app the subproject describes the application itself and has the following structure:
- app.pro the file describes the project structure for the qmake build system.
- icons the directory contains application icons for supported screen resolutions.
-
qml the directory contains the QML source code and user interface resources.
- cover the directory contains implementations of application covers.
- icons the directory contains additional user interface icons.
- pages the directory contains application pages.
- qmake_libraries.qml the file provides the application window implementation.
-
rpm the directory contains the rpm package build settings.
- qmake_libraries.spec the file is used by the rpmbuild tool.
-
src the directory contains C++ source code.
- main.cpp the file is the entry point to the application.
- translations the directory contains the user interface translation files.
Terms of Use and Participation in Development
The project source code is provided under license, which allows its use in third-party applications.
The Participant Agreement governs the rights granted by the participants to the Open Mobile Platform Company.
Participant information is listed in the AUTHORS file.
The Code of Conduct is the current set of rules of the Open Mobile Platform Company, which communicates the expectations for interaction between community members when communicating and working on projects.