Closed nmgwddj closed 1 month ago
Hi @nmgwddj
I'd probably recommend trying to use the new build system integrations, that includes some explicit Android integrations:
android_ndk
package. Just install the AndroidNDK in your system, as they detail in their setup instructions.conan new hello/0.1 --template=cmake_lib
[settings]
os=Android
os.api_level=23
arch=x86_64
compiler=clang
compiler.version=9
compiler.libcxx=c++_shared
build_type=Release
[conf]
tools.android:ndk_path=/your/path/to/your/ndk/installation
You might need to adapt some of the above values to your NDK installation
conan create . --profile:host=profile_host --profile:build=default
That would be a good starting point. Then from there, I would try to use the NDK from a tool_require
, but I suggest doing that later.
Thanks to @memsharded for your patient reply, I can successfully compile a hello package and a test program through the example you gave. But when I apply these in my existing project, I still can't finish cross-compiling.
First of all, in this case, I am not a package maker, and some Conan center packages are referenced in my existing CMake project. We will not make this CMake project into a Conan package, we just hope that the current CMake project can be compiled under different platforms (the practice of other platforms is to introduce conan.cmake to automatically perform the conan install process by passing different profiles)
I have installed the NDK and specified the absolute path of the profile in the host profile
[settings]
arch=armv8
compiler=clang
compiler.libcxx=libc++
compiler.version=14
os=Android
os.api_level=21
[conf]
tools.android:ndk_path=/Users/admin/Library/Android/sdk/ndk/23.1.7779620
The conanfile.py
of my current CMake project is as follows:
from conans import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class NebaseConan(ConanFile):
name = "conan-cross-platform-build"
author = "Dylan <2894220@gmail.com>"
description = "An example of a C++ app cross-platform build by Conan"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
exports_sources = "*"
def requirements(self):
self.requires("jsoncpp/1.9.5")
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
I simply cited a jsoncpp
as an example, then created a buil
directory and executed conan install
in the build directory
conan install .. --profile:build=default --profile:host=/Users/admin/Documents/temporary/conan-cross-platform-build/.profiles/android-armv8 --build=missing
Then I get the error below, is there any step I'm missing?
Configuration (profile_host):
[settings]
arch=armv8
compiler=clang
compiler.libcxx=libc++
compiler.version=14
os=Android
os.api_level=21
[options]
[build_requires]
[env]
[conf]
tools.android:ndk_path=/Users/admin/Library/Android/sdk/ndk/23.1.7779620
Configuration (profile_build):
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=apple-clang
compiler.libcxx=libc++
compiler.version=13.1
os=Macos
os_build=Macos
[options]
[build_requires]
[env]
CFLAGS=-fvisibility=hidden -fvisibility-inlines-hidden -mmacosx-version-min=10.13
CXXFLAGS=-fvisibility=hidden -fvisibility-inlines-hidden -mmacosx-version-min=10.13
jsoncpp/1.9.5: WARN: Package binary is corrupted, removing: 0a745a0fa934c8048a9bc8af0ba9e3afefff82ff
conanfile.py (conan-cross-platform-build/None): Installing package
Requirements
jsoncpp/1.9.5 from 'conancenter' - Cache
Packages
jsoncpp/1.9.5:0a745a0fa934c8048a9bc8af0ba9e3afefff82ff - Build
Cross-build from 'Macos:x86_64' to 'Android:armv8'
Installing (downloading, building) binaries...
jsoncpp/1.9.5: WARN: Build folder is dirty, removing it: /Users/admin/.conan/data/jsoncpp/1.9.5/_/_/build/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff
jsoncpp/1.9.5: Copying sources to build folder
jsoncpp/1.9.5: Building your package in /Users/admin/.conan/data/jsoncpp/1.9.5/_/_/build/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff
jsoncpp/1.9.5: Generator cmake created conanbuildinfo.cmake
jsoncpp/1.9.5: Aggregating env generators
jsoncpp/1.9.5: Calling build()
CMake Error at /usr/local/Cellar/cmake/3.21.3_1/share/cmake/Modules/Platform/Android-Determine.cmake:207 (message):
Android: Neither the NDK or a standalone toolchain was found.
Call Stack (most recent call first):
/usr/local/Cellar/cmake/3.21.3_1/share/cmake/Modules/CMakeDetermineSystem.cmake:160 (include)
CMakeLists.txt:2 (project)
CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
jsoncpp/1.9.5:
jsoncpp/1.9.5: ERROR: Package '0a745a0fa934c8048a9bc8af0ba9e3afefff82ff' build failed
jsoncpp/1.9.5: WARN: Build folder /Users/admin/.conan/data/jsoncpp/1.9.5/_/_/build/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff
ERROR: jsoncpp/1.9.5: Error in build() method, line 74
cmake = self._configure_cmake()
while calling '_configure_cmake', line 69
self._cmake.configure(build_folder=self._build_subfolder)
ConanException: Error 1 while executing cd '/Users/admin/.conan/data/jsoncpp/1.9.5/_/_/build/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff/build_subfolder' && cmake -G "Unix Makefiles" -DCMAKE_SYSTEM_NAME="Android" -DCMAKE_SYSTEM_VERSION="21" -DCMAKE_ANDROID_ARCH_ABI="arm64-v8a" -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM="android-21" -DANDROID_TOOLCHAIN="clang" -DANDROID_STL="libc++" -DCONAN_IN_LOCAL_CACHE="ON" -DCONAN_COMPILER="clang" -DCONAN_COMPILER_VERSION="14" -DCONAN_LIBCXX="libc++" -DBUILD_SHARED_LIBS="OFF" -DCMAKE_INSTALL_PREFIX="/Users/admin/.conan/data/jsoncpp/1.9.5/_/_/package/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff" -DCMAKE_INSTALL_BINDIR="bin" -DCMAKE_INSTALL_SBINDIR="bin" -DCMAKE_INSTALL_LIBEXECDIR="bin" -DCMAKE_INSTALL_LIBDIR="lib" -DCMAKE_INSTALL_INCLUDEDIR="include" -DCMAKE_INSTALL_OLDINCLUDEDIR="include" -DCMAKE_INSTALL_DATAROOTDIR="share" -DCONAN_CMAKE_POSITION_INDEPENDENT_CODE="ON" -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY="ON" -DCONAN_EXPORTED="1" -DJSONCPP_WITH_TESTS="False" -DJSONCPP_WITH_WARNING_AS_ERROR="False" -DJSONCPP_WITH_CMAKE_PACKAGE="False" -DJSONCPP_WITH_STRICT_ISO="False" -DJSONCPP_WITH_PKGCONFIG_SUPPORT="False" -DBUILD_STATIC_LIBS="True" -DJSONCPP_WITH_EXAMPLE="False" -DBUILD_OBJECT_LIBS="False" -Wno-dev '/Users/admin/.conan/data/jsoncpp/1.9.5/_/_/build/0a745a0fa934c8048a9bc8af0ba9e3afefff82ff'
Hi @nmgwddj
First of all, in this case, I am not a package maker, and some Conan center packages are referenced in my existing CMake project. We will not make this CMake project into a Conan package, we just hope that the current CMake project can be compiled under different platforms (the practice of other platforms is to introduce conan.cmake to automatically perform the conan install process by passing different profiles)
I think the main issue you are finding is that existing packages in ConanCenter are using the old build system integrations, they haven't upgraded yet to the new ones (CMakeDeps and CMakeToolchain
), so this functionality of cleanly cross-compiling to Android without any special thing besides specifying the path to the NDK in the conf
will not work in those recipes yet.
The good news is that recipes in ConanCenter will need to upgrade to the new build systems integrations, because that is necessary for Conan 2.0, which is already in alpha, will get into beta soon. It will take some time, but this is a priority for the following months.
Looking forward to the transformation of Conan 2.0 and old packages. Before that, I can choose to install locally and specify CONAN_CMAKE_TOOLCHAIN_FILE to temporarily satisfy the cross-compilation.
But it is worth mentioning that the introduction of android_ndk
in tool_requires is a very good solution, which does not require CI Agent to actively install NDK to the local environment, and the directory where different developers install NDK may also be inconsistent. Manually specify tools.android:ndk_path
The way might be a step backwards, so hopefully you guys will consider this situation.
Thanks again for your patient reply.
But it is worth mentioning that the introduction of android_ndk in tool_requires is a very good solution, which does not require CI Agent to actively install NDK to the local environment, and the directory where different developers install NDK may also be inconsistent. Manually specify tools.android:ndk_path The way might be a step backwards, so hopefully you guys will consider this situation.
Yes, absolutely, we like this approach. My recommendations above was in order to eliminate moving parts while checking what is working and what not. Once the tooling and integration is there, adding the ndk as a tool_requires
is very doable and convenient. It basically needs to define something like a self.conf_info.define("tools.android:ndk_path", self.package_folder)
in order to inject its path into the consumers and it will work. But that change in the ConanCenter package won't work until the consumer packages modernize themselves, so it hasn't happened yet. But we will certainly support it.
My solution how to use conan 2.0 and tool_requires for android-ndk. The trick is to use enviroment variable ANDROID_NDK_ROOT in cmake generated toolchain file. Here is host profile for conan.
[settings]
arch=armv7
arch_build=x86_64
build_type=Release
compiler=clang
compiler.libcxx=c++_shared
compiler.version=12
os=Android
os.api_level=21
[build_requires]
android-ndk/r23
[options]
[env]
CONAN_RUN_TESTS=False
CONAN_CMAKE_GENERATOR=Ninja
[conf]
tools.android:ndk_path=$ENV{ANDROID_NDK_ROOT}
tools.cmake.cmaketoolchain:system_processor=armv7-a
Hi @sbellus
Thanks for the trick of $ENV{ANDROID_NDK_ROOT}
, it might indeed work if you have the env-var defined.
Recall also that as Conan profiles in 2.0 are jinja templates, it is also possible:
[conf]
tools.android:ndk_path={{os.getenv("ANDROID_NDK_ROOT")}}
Also, a clarification about the above for other readers: The section [env]
and env-vars like CONAN_RUN_TESTS
and CONAN_CMAKE_GENERATOR
do not work in Conan 2.0, only 1.X.
Hi @memsharded
The ANDROID_NDK_ROOT
is set by build requirement android-ndk
automatically (in host profile).
Does conan parse profile at time when build requirement is already applied?
If not the tools.android:ndk_path={{os.getenv("ANDROID_NDK_ROOT")}}
will not work.
The android-ndk
could define self.conf_info.define("tools.android:ndk_path", self.package_folder...)
or something like that, directly, and then you wouldn't need to define it in profiles or anywhere else.
I am closing this ticket as resolved, now that we even have a docs example in https://docs.conan.io/2/examples/cross_build/android/ndk.html. Please create new updated tickets if necessary if there is any further question. Thanks!
In the official documentation, I found the following link: https://docs.conan.io/en/latest/integrations/cross_platform/android.html#using-android-ndk-package-tool-require, through which I learned that android-ndk can be referenced through
tool_requires
. The documentation states that when we use this package, the toolchain file and the variables required by CMake are generated. But when I executeconan install
and then pass CMake includeconanbuildinfo.cmake
, I get the following error when I execute CMake initialization:Obviously, Android NDK related environment variables are not injected into CMake. Then I saw in the description of the android-ndk package that
CMakeDeps
andCMakeToolchain
need to be specified in generators, but when I After setting up both generators and doingconan install
I get the following error:I've been tossing around for days, and I haven't been able to find a solution by constantly searching for issues, google, conan index example, etc.
The requirements are very simple. I hope to manage NDK through conan tool requires, and correctly inject various environment variables and toolchain information of NDK into my existing CMakeLists.txt and then perform cross-compilation. Because I have implemented various cross-compilation scenarios for Windows, macOS, Linux, and iOS through the existing Conan capabilities, and now it is only Android, I am very distressed.
Can someone give a complete example and tell me how to use it?