Qt6 Android service with separate ".so" library and CMake - android

I have Qt 6.3 CMake-project that contains two subdirectories "app" and "service", i want include Android service .so library into result APK.
With qmake-project i can achieve this like that at app.pri:
contains(ANDROID_TARGET_ARCH, arm64-v8a) {
release: ANDROID_EXTRA_LIBS = $$OUT_PWD/../service/libservice_arm64-v8a.so
debug: ANDROID_EXTRA_LIBS = $$OUT_PWD/../service/libservice_arm64-v8a.so
}
with CMake i tried to set(QT_ANDROID_EXTRA_LIBS C:/workspace/build-test-Android_Qt_6_3_0_Clang_arm64_v8a-Debug/service/libservice_arm64-v8a.so)
at app->CMakeLists.txt and it has no effect.

Found that QT_ANDROID_EXTRA_LIBS is 'target property' and should be set via set_target_properties() then it adds .so into result.
set_target_properties(project_name PROPERTIES
QT_ANDROID_EXTRA_LIBS ${CMAKE_CURRENT_BINARY_DIR}/../service/libservice_${ANDROID_ABI}.so)

Related

libcrashpad_handler.so: library "libc++_shared.so" not found: needed by main executable

I followed the manual written by Bugsplat to build Crashpad for Android.
The build was successful and I got all necessary libraries. However I noticed that the prebuilt library libcrashpad_handler.so in Bugsplat's sample weighs about 26Mb. And mine is only 700Kb.
Moreover I got errors from linker when trying to catch signals from system.
/lib/arm64/libcrashpad_handler.so": library "libc++_shared.so" not found: needed by main executable
Is the instructions are not up-to-date on Bugsplat? Maybe there should be some extra_cflags passed to gn gen --args ?
Btw, I tried to include c++shared into apk with:
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
}
}
But i got no success to load it.
Really appreciate your assistance in building libcrashpad_handler.so.

Gradle with CMake Issue with git_describe

I did run into issue with running gradle with cmake.
This part of the code inside cmake file does not seem to work correctly
git_describe(GIT_DESCRIBE "--abbrev=7")
Because there is part of the code that depends on defined GIT_DESCRIBE and because git_describe fails block of that code does not gets execute. And I want to make it work as expected thus executing this block of code.
Here is the scheme of the Project:
-Root Dir of the Project:
-Submodule of git repo
-Rest of the files
Gradle File where it does set the Cmake (CMakeLists is contained inside of that submodule)
externalNativeBuild {
cmake {
path 'path/to/CMakeLists.txt'
}
}
It should work out of the box but when using this combination gradle + cmake it fails.
Running git describe --abbrev=7 in terminal shows the expected value.
I have replaced git_describe with execute_process
execute_process(COMMAND git describe --abbrev=7
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE)
This solved issue.

How to add/use GStreamer binary library with Qt C++ on Android?

I am attempting to use Gstreamer library on multiple platforms with my Qt project (for audio only). I already have it working on macOS with the binary files available online by just adding the framework to my .pro file:
LIBS += -F$$PWD/macOS/libs/ -framework GStreamer
INCLUDEPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/Headers
DEPENDPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/include
But now I want to use the binaries available at the same page for android. But because it is not "bundled" in a framework like on OS X I can't add it as easily. Furthermore the official explanations are made for a gradle build (which I don't know anything and don't use in Qt creator) and for use in Java. But, because I want to directly use the C API in Qt C++ I don't need JNI, and would like to directly use the library in my app like on OSX.
Thus, I tried to add the library like I would do it on any other linux, but recursively, since there is a multitude of library and header folders:
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
GSTREAMER_INCLUDE_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR = $$dirname(FILE)
if(!contains(INCLUDEPATH, $$BASEDIR)){
INCLUDEPATH += $$BASEDIR
}
}
GSTREAMER_DEPEND_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR_DEP = $$dirname(FILE)
if(!contains(DEPENDPATH, $$BASEDIR_DEP)){
DEPENDPATH += $$BASEDIR_DEP
}
}
GSTREAMER_LIB_FILES = $$files($$PWD/android/libs/gstreamer/arm64/lib/*.a, true)
for(FILE, GSTREAMER_LIB_FILES) {
BASENAME = $$basename(FILE)
LIBS += -l$$replace(BASENAME,\.a,)
}
}
But when I try the include
#include <gst/gst.h>
, it doesn't work and output 37 errors on unknown members of the global namespace related to time management like :
/Users/user/Library/Android/sdk/ndk/19.2.5345600/sources/cxx-stl/llvm-libc++/include/ctime:70:9: error: no member named 'asctime' in the global namespace
using ::asctime;
~~^
I really don't know how to use gstreamer and bundle it for android from the available official binaries and don't want to use any wrapper like qt-gstreamer (which isn't maintained by the way) or JNI.
Thanks for any help or input !

Limit CPU cores for ndkBuild with Cmake and Ninja

Before, when I was using ndkBuld for building native code on Android I was able to pass an argument to make to define a number of CPU cores to be used. If I wanted to utilize 4 cores I could add something like this
externalNativeBuild {
ndkBuild {
arguments "-j4", "APP_SHORT_COMMANDS=true"
abiFilters "armeabi-v7a"
}
}
Can somebody give an advice how can I do something similar with Cmake and Ninja? Is there some equivalent parameter for cmake configuration?
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static"
abiFilters getAbis()
}
}
Thanks.
controlling ninja parallelism
Ninja also support the same parameter:
$ ninja --help
usage: ninja [options] [targets...]
[...]
options:
[...]
-j N run N jobs in parallel [default=10, derived from CPUs available]
[...]
controlling ninja parallelism differentiating compile and link jobs
Now, if you want more granularity. For example, if you would like to limit the number of simultaneous link jobs, or compile jobs, or both.
Starting with CMake 3.11, it is now possible to limit the number of compile and/or link jobs.
You could then configure your project with these options:
-DCMAKE_JOB_POOL_COMPILE:STRING=compile
-DCMAKE_JOB_POOL_LINK:STRING=link
'-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'
Now, if your project end up spawning other child processed that are themselves building projects using ninja, you would have to:
use the fork of ninja that include Job Server support like it is done in make. Binaries are also available in the associated GitHub releases. See https://github.com/kitware/ninja#readme
make sure sub-project are also configured with the same -DCMAKE_JOB_ options
in the context of externalNativeBuild
This means you could try something like this:
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static -DCMAKE_JOB_POOL_COMPILE:STRING=compile -DCMAKE_JOB_POOL_LINK:STRING=link '-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'"
abiFilters getAbis()
}
}
I was able to fix this by adding:
if (PARALLEL_COMPILE_JOBS)
set(CMAKE_JOB_POOL_COMPILE compile_job_pool${CMAKE_CURRENT_SOURCE_DIR})
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" CMAKE_JOB_POOL_COMPILE ${CMAKE_JOB_POOL_COMPILE})
set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${CMAKE_JOB_POOL_COMPILE}=${PARALLEL_COMPILE_JOBS})
endif ()
if (PARALLEL_COMPILE_JOBS)
message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}: Limiting compiler jobs to ${PARALLEL_COMPILE_JOBS}")
endif ()
to my base CMakeLists.txt, and then in my build.gradle I added to cmake arguments: "-DPARALLEL_COMPILE_JOBS=8" to specify max 8 parallel clang++ compile processes. This works on current Android Studio cmake (3.10) and ninja (1.8.2) versions
I created a workaround: wrap the ninja executable used by Android Studio with a script that calls ninja with all given parameter plus "-j1" at the end.
Locate the ninja executable used by Android Studio. Something like, for example, somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
Rename it to something else, like ninja_orig
Create a shell script (and add execution permission to it) to replace the original ninja executable at somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja with the following content:
#!/bin/sh
somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja_orig $# -j1
Ok it seems it is a bug / missing feature in NDK. I've talked to some "NDK Googlers" and they were not able to help me either. Hopefully it will be supported in later versions of NDK / AS.
Here are the issues you can track the progress:
https://github.com/android-ndk/ndk/issues/983
and
https://issuetracker.google.com/issues/137878831

How to specify libraries only for Android platform build in .pro file?

I'm trying to use QtCreator (2.7.2) + QT (5.1.0) to build an application that runs on both desktop (Linux) and mobile (Android) platforms.
To achieve this, I need to use different pre-built libraries depending on the target platform.
How do I specify this in the .pro file?
The wizard only offers linux/mac/windows as platform choice like
unix:!mac {
message("* Using settings for Unix/Linux.")
LIBS += -L/path/to/linux/libs
}
I've tried
android {
message("* Using settings for Android.")
LIBS += -L/path/to/android/libs
}
But with both build targets only the unix:!mac gets executed/evaluated.
So my question is: How to detect the build target (called "Kits" now in QtCreator) in the .pro file and change library definitions accordingly?
I've so far only found out how to specify the platform (which seems to be the platform I'm building ON and not FOR) or the build variant RELEASE/DEBUG.
Other things I've found say I should prefix the LIB+= with the target platform like win32:LIB+=. But again, this won't work with android. Maybe I'm using a wrong syntax for the platform (android 4.2 on an arm-v7).
this works for me (Qt 5.3.2)
linux:!android {
message("* Using settings for Unix/Linux.")
LIBS += -L/path/to/linux/libs
}
android {
message("* Using settings for Android.")
LIBS += -L/path/to/android/libs
}
I'm using this in a .pro file, maybe it helps:
unix:!macx:
{
android:
{
INCLUDEPATH += "/usr/lib/boost/boost_1_47_0" \
inkscape
}
!android:
{
INCLUDEPATH += $$(BOOST_PATH) \
inkscape
}
}
macx:
{
INCLUDEPATH += "../../../../boost_1_54_0" \#$$(BOOST_PATH) \
inkscape
}

Categories

Resources