- Cross-compilation of PCL using conan.
- Full integration in an Android example app.
- Ubuntu 22.04
- Android SDK 25
- conan 2.0.4
The setup also works on macOS 13.1, except building for ARMv8 fails because of an issue with the clang compiler.
apt install cmake git make python3
Install conan and ninja.
pip3 install conan ninja
Then, download the latest Android NDK from the Android website and unzip it.
After that, run conan profile detect
to detect the default profile and create
an Android compilation profile under ~/.conan2/profiles/android
with the
following contents:
include(default)
[settings]
os=Android
os.api_level=26
compiler=clang
compiler.version=14
compiler.libcxx=c++_static
compiler.cppstd=14
[conf]
tools.android:ndk_path=[ndk_path]
Replacing [ndk_path]
with the path at which you unzipped the downloaded
Android NDK.
To start cross-compilation, run the provided script passing along the desired target architecture:
./pcl-build-for-android.sh armv8|armv7|x86|x86_64 [shared]
Appending the option shared
will build shared libraries instead of static
ones.
Set in app/build.gradle the abiFilters depending for which architectures you have cross-compiled. The default setup is arm64-v8a:
android {
compileSdkVersion 28
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
}
ndk {
abiFilters "arm64-v8a"
}
}
...
E.g. set in app/build.gradle to support armeabi-v7a and emulator (x86_64):
android {
defaultConfig {
...
ndk {
abiFilters "armeabi-v7a", "x86_64"
}
}
...
Or to support all:
android {
defaultConfig {
...
ndk {
abiFilters "arm64-v8a", "armeabi-v7a", "x86_64"
}
}
...
Now you can run the app and you will see in Logcat:
I/bashbug.example: pointcloud has size 5
The CMake based example-app has conan fully integrated:
example-app/app/src/main
...
├── cpp
│ ├── cmake
│ │ └── conan.cmake
│ ├── CMakeLists.txt
│ ├── conanfile.txt
│ └── native-lib.cpp
...
conanfile.txt defines the project's dependency to PCL.
[requires]
pcl/1.9.1@pcl-android/stable
[generators]
cmake_paths
cmake_find_package
CMakeLists.txt includes cmake/conan.cmake which is a cmake integration of conan.
include(${CMAKE_SOURCE_DIR}/cmake/conan.cmake)
conan_cmake_run(CONANFILE conanfile.txt
PROFILE arm64-v8a
BASIC_SETUP
UPDATE
BUILD missing)
include(${CMAKE_CURRENT_BINARY_DIR}/conan_paths.cmake)
conan_cmake_run()
does two things:
- It parses the conanfile.txt what dependencies it should install.
- In conanfile.txt are two generators defined
cmake_paths
andcmake_find_package
.cmake_paths
creates conan_paths.cmake within the build folder. This adds to theCMAKE_MODULE_PATH
andCMAKE_PREFIX_PATH
the search path for the cross-compiled libraries.cmake_find_package
creates auto-generated Find*.cmake files within the build folder .externalNativeBuild/cmake/debug/arm64-v8a
example-app/app/.externalNativeBuild
└── cmake
└── debug
└── arm64-v8a
...
├── conanbuildinfo.cmake
├── conanbuildinfo.txt
├── conaninfo.txt
├── conan_paths.cmake
├── Findandroid-toolchain.cmake
├── Findboost.cmake
├── Findeigen.cmake
├── Findflann.cmake
├── Findlz4.cmake
├── Findpcl.cmake
├── graph_info.json
├── lib
│ └── libnative-lib.so
└── rules.ninja
This Find*.cmake files resolve find_package
calls in CMakeLists.txt of cross-compiled libraries and provide targets like pcl::pcl
:
find_package(pcl REQUIRED)
add_library(native-lib SHARED native-lib.cpp)
find_library(log-lib log)
target_link_libraries(native-lib
PUBLIC
${log-lib}
pcl::pcl
)