├── .gitignore ├── CMakeLists.txt ├── Readme.md ├── android-studio └── CMakeLists.txt ├── build.bat ├── open3d-android.config.cmake └── open3d-android.patch /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /install/ 3 | /.vscode/ 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6.0) 2 | project(superbuild NONE) 3 | 4 | # find Android NDK 5 | # Copied from SDK/cmake//android.toolchain.cmake 6 | if(NOT ANDROID_NDK) 7 | if(DEFINED ENV{ANDROID_NDK_HOME} 8 | AND IS_DIRECTORY "$ENV{ANDROID_NDK_HOME}") 9 | set(ANDROID_NDK "$ENV{ANDROID_NDK_HOME}") 10 | elseif(DEFINED ENV{ANDROID_HOME} 11 | AND IS_DIRECTORY "$ENV{ANDROID_HOME}/ndk-bundle") 12 | set(ANDROID_NDK "$ENV{ANDROID_HOME}/ndk-bundle") 13 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Linux 14 | AND IS_DIRECTORY "$ENV{HOME}/Android/Sdk/ndk-bundle") 15 | set(ANDROID_NDK "$ENV{HOME}/Android/Sdk/ndk-bundle") 16 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin 17 | AND IS_DIRECTORY "$ENV{HOME}/Library/Android/sdk/ndk-bundle") 18 | set(ANDROID_NDK "$ENV{HOME}/Library/Android/sdk/ndk-bundle") 19 | elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows 20 | AND IS_DIRECTORY "$ENV{LOCALAPPDATA}/Android/Sdk/ndk-bundle") 21 | set(ANDROID_NDK "$ENV{LOCALAPPDATA}/Android/Sdk/ndk-bundle") 22 | else() 23 | message(FATAL_ERROR "Android NDK unspecified.") 24 | endif() 25 | endif() 26 | file(TO_CMAKE_PATH "${ANDROID_NDK}" ANDROID_NDK) 27 | 28 | set(android_toolchain ${ANDROID_NDK}/build/cmake/android.toolchain.cmake) 29 | 30 | # this populates NDK_DEFAULT_ABIS 31 | include(${ANDROID_NDK}/build/cmake/abis.cmake) 32 | 33 | # git diff > open3d-android.patch 34 | # don't use PowerShell, it screws up encoding 35 | set(open3d_patch ${CMAKE_CURRENT_SOURCE_DIR}/open3d-android.patch) 36 | set(open3d_config ${CMAKE_CURRENT_SOURCE_DIR}/open3d-android.config.cmake) 37 | 38 | # setup build macros 39 | 40 | include(ExternalProject) 41 | find_package(Git REQUIRED) 42 | 43 | set(base "${CMAKE_BINARY_DIR}/CMakeExternals") 44 | # set base directory for external projects 45 | # CMake will figure out the source, build, etc. dirs automatically 46 | set_property(DIRECTORY PROPERTY EP_BASE ${base}) 47 | 48 | # Download Open3D once 49 | macro(fetch_open3d) 50 | ExternalProject_Add( 51 | open3d-fetch 52 | # no SOURCE_DIR, let CMake figure it out based on EP_BASE 53 | GIT_REPOSITORY https://github.com/intel-isl/Open3D.git 54 | GIT_TAG v0.7.0 55 | GIT_SHALLOW true 56 | PATCH_COMMAND ${GIT_EXECUTABLE} apply ${open3d_patch} 57 | # override default commands so CMake isn't invoked 58 | UPDATE_COMMAND "" 59 | CONFIGURE_COMMAND "" 60 | BUILD_COMMAND "" 61 | INSTALL_COMMAND "" 62 | ) 63 | endmacro() 64 | 65 | # Compile Open3D for a specific Android ABI 66 | macro(crosscompile_open3d abi) 67 | set(proj open3d-${abi}) 68 | # get the computed source dir 69 | ExternalProject_Get_property(open3d-fetch SOURCE_DIR) 70 | set(install_prefix ${CMAKE_INSTALL_PREFIX}/${proj}) 71 | ExternalProject_Add( 72 | ${proj} 73 | SOURCE_DIR ${SOURCE_DIR} 74 | # explicitly disable download since source dir is empty at config time 75 | DOWNLOAD_COMMAND "" 76 | DEPENDS open3d-fetch 77 | CMAKE_ARGS 78 | -DANDROID_ABI:STRING=${abi} 79 | -DCMAKE_TOOLCHAIN_FILE:FILEPATH=${android_toolchain} 80 | -DCMAKE_INSTALL_PREFIX:PATH=${install_prefix} 81 | -C ${open3d_config} 82 | ) 83 | endmacro() 84 | 85 | # download and build 86 | 87 | fetch_open3d() 88 | foreach(abi ${NDK_DEFAULT_ABIS}) 89 | crosscompile_open3d(${abi}) 90 | endforeach() 91 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Building Open3D core for Android 2 | 3 | CMake scripts for cross-compiling the core library of [Open3D](http://www.open3d.org/) for Android and linking to it with Android Studio. 4 | 5 | Tested with: 6 | 7 | - Windows 10 1809 8 | - CMake 3.14.1 9 | - Android Studio 3.4.1 with Gradle plugin 3.4.1 10 | - Bundled Android NDK r20 11 | - Open3D 0.7.0 12 | 13 | Should work on Linux hosts, too, but it's untested. 14 | 15 | ## Patches 16 | 17 | A lot of Open3D revolves around visualisation. Since that code relies on OpenGL and X11 (both of which don't exist on Android) I removed it from being compiled and included. The patches to its CMakeLists.txt can be found in [open3d-android.patch](open3d-android.patch). Essentially it: 18 | 19 | - prevents GLEW and GLFW from being built and linked 20 | - removes the Visualization and Tools modules 21 | 22 | The patch file itself was created with `git diff > open3d-android.patch`. 23 | 24 | ## Compiling 25 | 26 | You will need [Ninja](https://ninja-build.org/) on your system (and in the PATH variable). 27 | 28 | To cross-compile Open3D, simply: 29 | ``` 30 | mkdir build & cd build 31 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX=../install .. && cmake --build . 32 | ``` 33 | This downloads a specific revision of Open3D and compiles it for all supported NDK ABIs. 34 | 35 | - To change the version of Open3D change the `GIT_TAG` in the call to `ExternalProject_Add` for *open3d-fetch*. You may have to change Open3D's CMakeLists.txt's and create an updated patch file. 36 | - To specify an NDK path, call CMake with -DANDROID_NDK=path/to/ndk. By default it locates the NDK bundled with Android Studio. 37 | 38 | When it's finished, you'll find compiled versions for each Android ABI in the install folder. 39 | 40 | ## Linking 41 | 42 | To use the library in Android Studio, take a look at [the template CMakeLists.txt](android-studio/CMakeLists.txt). 43 | It defines a sample library that finds and links to Open3D. It requires two additional steps: 44 | 45 | 1. Set `OPEN3D_PATH` to the Open3D install. This can be done by [specifying an extra parameter to CMake](https://developer.android.com/ndk/guides/cmake#variables) in your build.gradle: 46 | ```groovy 47 | android { 48 | ... 49 | defaultConfig { 50 | ... 51 | externalNativeBuild { 52 | cmake { 53 | ... 54 | arguments "-DOPEN3D_PATH=path/to/Open3D/install" 55 | } 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | 2. Add the shared libraries. The template CMakeLists.txt copies the appropriate shared libraries to their own ABI folders under libs/ in the main source directory. To make Gradle find and package them, [add them to the source set](https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs): 62 | ```groovy 63 | android { 64 | ... 65 | sourceSets { 66 | main { 67 | jniLibs.srcDirs = ['libs'] 68 | } 69 | } 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /android-studio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(my-lib) 2 | 3 | set(SOURCE_FILES 4 | my-lib.cpp 5 | ) 6 | 7 | add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES}) 8 | 9 | # find and link Open3D 10 | 11 | # OPEN3D_PATH should be set in your build.grade like this: 12 | # (see https://developer.android.com/ndk/guides/cmake#variables) 13 | # 14 | # defaultConfig { 15 | # ... 16 | # externalNativeBuild { 17 | # cmake { 18 | # ... 19 | # arguments "-DOPEN3D_PATH=path/to/Open3D/install" 20 | # } 21 | # } 22 | # } 23 | 24 | if(NOT OPEN3D_PATH) 25 | message(FATAL_ERROR "Open3D path not specified") 26 | endif() 27 | 28 | set(open3d-abi-path ${OPEN3D_PATH}/open3d-${ANDROID_ABI}) 29 | 30 | # find lib/cmake/Open3D/Open3DConfig.cmake 31 | find_package(Open3D 0.7.0 # exact match required (major, minor, patch) 32 | REQUIRED 33 | PATHS ${open3d-abi-path} 34 | # don't look anywhere except in the path(s) we specify 35 | NO_DEFAULT_PATH 36 | # ignore the NDK CMAKE_FIND_ROOT_PATH, otherwise all search paths get prefixed with it 37 | NO_CMAKE_FIND_ROOT_PATH) 38 | 39 | # Open3D_LIBRARIES only contains "Open3D" when built as a shared lib 40 | # so we don't have to add 3rd party libs to the interface 41 | 42 | find_library(open3d-lib 43 | Open3D 44 | PATHS ${Open3D_LIBRARY_DIRS} 45 | NO_DEFAULT_PATH 46 | NO_CMAKE_FIND_ROOT_PATH) 47 | 48 | if(NOT open3d-lib) 49 | message(FATAL_ERROR "Open3D library not found") 50 | endif() 51 | 52 | # copy shared libraries to the libs folder 53 | # you'll need to add them to the source set so Gradle copies them: 54 | # (see https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs) 55 | 56 | # android { 57 | # ... 58 | # sourceSets { 59 | # main { 60 | # jniLibs.srcDirs = ['libs'] 61 | # } 62 | # } 63 | # } 64 | 65 | file(COPY ${open3d-lib} DESTINATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}) 66 | 67 | # Open3D gives us non-existing directories 68 | # CMake doesn't allow adding those as interface include directories 69 | foreach(dir ${Open3D_INCLUDE_DIRS}) 70 | if(NOT EXISTS ${dir}) 71 | list(REMOVE_ITEM Open3D_INCLUDE_DIRS ${dir}) 72 | endif() 73 | endforeach() 74 | 75 | add_library(Open3D SHARED IMPORTED) 76 | set_target_properties(Open3D PROPERTIES 77 | IMPORTED_LOCATION ${open3d-lib}) 78 | # You can't directly add interface properties to imported libraries on CMake < 3.11 79 | # Android Studio 3.4.1 ships with CMake 3.10.2 80 | # this is a workaround 81 | # (see https://gitlab.kitware.com/cmake/cmake/issues/15689) 82 | set_property(TARGET Open3D APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Open3D_INCLUDE_DIRS}) 83 | #target_include_directories(Open3D INTERFACE ${Open3D_INCLUDE_DIRS}) 84 | 85 | target_link_libraries(${PROJECT_NAME} PRIVATE Open3D) 86 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | mkdir build & cd build 2 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX=../install .. && cmake --build . 3 | cd .. 4 | -------------------------------------------------------------------------------- /open3d-android.config.cmake: -------------------------------------------------------------------------------- 1 | # http://www.open3d.org/docs/compilation.html 2 | 3 | set(BUILD_SHARED_LIBS ON CACHE BOOL "") 4 | set(WITH_OPENMP ON CACHE BOOL "") 5 | set(ENABLE_HEADLESS_RENDERING OFF CACHE BOOL "") 6 | set(BUILD_CPP_EXAMPLES OFF CACHE BOOL "") 7 | set(BUILD_UNIT_TESTS OFF CACHE BOOL "") 8 | 9 | # disable python bindings 10 | set(BUILD_PYBIND11 OFF CACHE BOOL "") 11 | set(BUILD_PYTHON_MODULE OFF CACHE BOOL "") 12 | set(BUILD_PYTHON_TUTORIALS OFF CACHE BOOL "") 13 | 14 | # build 3rd party dependencies from source 15 | set(BUILD_EIGEN3 ON CACHE BOOL "") 16 | set(BUILD_GLEW ON CACHE BOOL "") 17 | set(BUILD_GLFW ON CACHE BOOL "") 18 | set(BUILD_JPEG ON CACHE BOOL "") 19 | set(BUILD_JSONCPP ON CACHE BOOL "") 20 | set(BUILD_PNG ON CACHE BOOL "") 21 | set(BUILD_TINYFILEDIALOGS ON CACHE BOOL "") 22 | set(BUILD_QHULL ON CACHE BOOL "") 23 | 24 | # doesn't work for VS 25 | # see https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html 26 | # instead use: 27 | # cmake --build . --config Release 28 | set(CMAKE_BUILD_TYPE Release CACHE STRING "") 29 | -------------------------------------------------------------------------------- /open3d-android.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pezcode/open3d-core-android/3fdbc576ea91cc39a74a0a861f46d015c8a21db3/open3d-android.patch --------------------------------------------------------------------------------