Skip to content

Commit 9dd3803

Browse files
committed
Decouple MultiBackend.cmake into a different file
1 parent 63dce22 commit 9dd3803

4 files changed

Lines changed: 96 additions & 120 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ option(MLN_USE_RUST "Use components in Rust" OFF)
2121
option(MLN_TEXT_SHAPING_HARFBUZZ "Use haffbuzz to shape complex text" ON)
2222
option(MLN_CREATE_AUTORELEASEPOOL "Create autoreleasepool in render loop" OFF)
2323
option(MLN_CREATE_AMALGAMATION "Create static amalgamation of core (requires amerge)" OFF)
24-
option(MLN_ANDROID_MULTI_BACKEND "Android only: build both OpenGL and Vulkan versions" OFF)
2524

2625
include(cmake/validate-backend-options.cmake)
2726
include(cmake/clang-tidy.cmake)
@@ -34,109 +33,12 @@ if(WIN32 AND NOT DEFINED ENV{MSYSTEM} AND NOT MLN_WITH_QT AND NOT CMAKE_SYSTEM_N
3433
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/platform/windows/custom-toolchain.cmake)
3534
endif()
3635

37-
if(MLN_ANDROID_MULTI_BACKEND)
38-
if(NOT ANDROID)
39-
message(FATAL_ERROR
40-
"MLN_ANDROID_MULTI_BACKEND is only supported on Android.")
41-
endif()
42-
43-
# Android: invoke the Android NDK CMakeLists twice via ExternalProject_Add
44-
# (once per backend) and surface the results to AGP as two distinct
45-
# add_library(SHARED) targets so both .so files end up in the AAR.
46-
# Reached via add_subdirectory(...) from the Android src/cpp CMakeLists,
47-
# whose project(MapLibreAndroid) is already in effect. We deliberately
48-
# avoid calling our own project() here so the add_library targets below
49-
# land in the AGP-invoked MapLibreAndroid root project — otherwise AGP's
50-
# cmake-server query doesn't see them.
51-
#
52-
# The OpenGL target's output filename is the default "maplibre" (i.e.
53-
# libmaplibre.so) so it matches the single-backend OpenGL AAR; Vulkan keeps
54-
# the "-vulkan" suffix to disambiguate.
55-
include(ExternalProject)
56-
57-
set(_multi_android_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/MapLibreAndroid/src/cpp)
58-
59-
set(_multi_forward_args
60-
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
61-
-DANDROID_ABI=${ANDROID_ABI}
62-
-DANDROID_PLATFORM=${ANDROID_PLATFORM}
63-
-DANDROID_NDK=${ANDROID_NDK}
64-
-DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN}
65-
-DANDROID_STL=${ANDROID_STL}
66-
-DANDROID_CPP_FEATURES=${ANDROID_CPP_FEATURES}
67-
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
68-
-DMLN_ANDROID_MULTI_BACKEND=OFF)
69-
70-
set(_multi_opengl_dir ${CMAKE_BINARY_DIR}/multi-opengl)
71-
set(_multi_vulkan_dir ${CMAKE_BINARY_DIR}/multi-vulkan)
72-
73-
set(_multi_android_lib_dir ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/MapLibreAndroid)
74-
75-
ExternalProject_Add(maplibre-opengl-build
76-
SOURCE_DIR ${_multi_android_source_dir}
77-
BINARY_DIR ${_multi_opengl_dir}
78-
CMAKE_ARGS
79-
${_multi_forward_args}
80-
-DMLN_WITH_OPENGL=ON
81-
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${_multi_opengl_dir}/lib
82-
"-DMLN_ANDROID_TOP_BINARY_DIR=${_multi_android_lib_dir}/${ANDROID_ABI}-opengl"
83-
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target maplibre
84-
INSTALL_COMMAND ""
85-
BUILD_ALWAYS 1)
86-
87-
ExternalProject_Add(maplibre-vulkan-build
88-
SOURCE_DIR ${_multi_android_source_dir}
89-
BINARY_DIR ${_multi_vulkan_dir}
90-
CMAKE_ARGS
91-
${_multi_forward_args}
92-
-DMLN_WITH_VULKAN=ON
93-
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${_multi_vulkan_dir}/lib
94-
"-DMLN_ANDROID_TOP_BINARY_DIR=${_multi_android_lib_dir}/${ANDROID_ABI}-vulkan"
95-
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target maplibre
96-
INSTALL_COMMAND ""
97-
BUILD_ALWAYS 1)
98-
99-
set(_multi_stub ${CMAKE_BINARY_DIR}/maplibre_multi_stub.cpp)
100-
file(WRITE ${_multi_stub}
101-
"extern \"C\" void maplibre_multi_backend_stub() {}\n")
102-
103-
add_library(maplibre-opengl SHARED ${_multi_stub})
104-
# Produce libmaplibre.so (not libmaplibre-opengl.so) so the OpenGL output
105-
# matches the single-backend OpenGL AAR's library name.
106-
set_target_properties(maplibre-opengl PROPERTIES OUTPUT_NAME maplibre)
107-
add_dependencies(maplibre-opengl maplibre-opengl-build)
108-
add_custom_command(TARGET maplibre-opengl POST_BUILD
109-
COMMAND ${CMAKE_COMMAND} -E copy
110-
${_multi_opengl_dir}/lib/libmaplibre.so
111-
$<TARGET_FILE:maplibre-opengl>
112-
VERBATIM)
113-
114-
add_library(maplibre-vulkan SHARED ${_multi_stub})
115-
add_dependencies(maplibre-vulkan maplibre-vulkan-build)
116-
add_custom_command(TARGET maplibre-vulkan POST_BUILD
117-
COMMAND ${CMAKE_COMMAND} -E copy
118-
${_multi_vulkan_dir}/lib/libmaplibre.so
119-
$<TARGET_FILE:maplibre-vulkan>
120-
VERBATIM)
121-
122-
# AGP's defaultConfig nativeTargets always lists "maplibre"; provide a
123-
# custom target so `cmake --build . --target maplibre` triggers both .so
124-
# builds.
125-
add_custom_target(maplibre DEPENDS maplibre-opengl maplibre-vulkan)
126-
127-
install(TARGETS maplibre-opengl maplibre-vulkan LIBRARY DESTINATION lib)
128-
129-
return()
130-
endif()
131-
13236
project("MapLibre Native" LANGUAGES CXX C)
13337

13438
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
13539
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER MapLibre)
13640

137-
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
138-
include(CTest)
139-
endif()
41+
include(CTest)
14042

14143
if(NOT CMAKE_BUILD_TYPE)
14244
set(CMAKE_BUILD_TYPE Release)

cmake/validate-backend-options.cmake

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@ endif()
1919
if (MLN_WITH_WEBGPU)
2020
math(EXPR backend_count "${backend_count} + 1")
2121
endif()
22-
if (MLN_ANDROID_MULTI_BACKEND)
23-
math(EXPR backend_count "${backend_count} + 1")
24-
endif()
2522

2623
if (backend_count EQUAL 0)
2724
message(FATAL_ERROR
2825
"You need to set a rendering backend. "
29-
"Set exactly one of: MLN_WITH_OPENGL, MLN_WITH_METAL, MLN_WITH_VULKAN, MLN_WITH_WEBGPU, or MLN_ANDROID_MULTI_BACKEND.")
26+
"Set exactly one of: MLN_WITH_OPENGL, MLN_WITH_METAL, MLN_WITH_VULKAN, or MLN_WITH_WEBGPU.")
3027
elseif (backend_count GREATER 1)
3128
message(FATAL_ERROR
3229
"Multiple rendering backends selected. "
33-
"Please enable only one of: MLN_WITH_OPENGL, MLN_WITH_METAL, MLN_WITH_VULKAN, MLN_WITH_WEBGPU, or MLN_ANDROID_MULTI_BACKEND.")
30+
"Please enable only one of: MLN_WITH_OPENGL, MLN_WITH_METAL, MLN_WITH_VULKAN, or MLN_WITH_WEBGPU.")
3431
endif()

platform/android/MapLibreAndroid/src/cpp/CMakeLists.txt

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,19 @@ cmake_minimum_required(VERSION 3.10)
22

33
project(MapLibreAndroid)
44

5-
# Always invoke the top-level CMakeLists. When MLN_ANDROID_MULTI_BACKEND=ON
6-
# (set by the Gradle multiBackend flavor via -D), the top-level handles the
7-
# dual-backend ExternalProject_Add setup, declares maplibre-opengl (output
8-
# libmaplibre.so) and maplibre-vulkan (output libmaplibre-vulkan.so) SHARED
9-
# targets, and returns from its scope. The matching `if` below then skips
10-
# this file's normal single-backend maplibre target.
11-
# MLN_ANDROID_TOP_BINARY_DIR is set by the multi-backend ExternalProject sub-builds
12-
# to give each backend (opengl/vulkan) its own isolated static library output dir,
13-
# preventing LTO object corruption when both sub-builds share the same arm64-v8a/ dir.
14-
# Single-backend builds (invoked directly by AGP) leave it unset and get the default.
15-
if(NOT DEFINED MLN_ANDROID_TOP_BINARY_DIR)
16-
get_filename_component(MLN_ANDROID_TOP_BINARY_DIR
17-
"${CMAKE_CURRENT_BINARY_DIR}/../../../../../${ANDROID_ABI}" ABSOLUTE)
18-
endif()
19-
add_subdirectory(../../../../../ ${MLN_ANDROID_TOP_BINARY_DIR})
20-
5+
# (a) Multi-flavor build is self-contained in MultiBackend.cmake and only entered for the
6+
# Gradle `multiBackend` flavor (which passes -DMLN_ANDROID_MULTI_BACKEND=ON). It never touches
7+
# the shared top-level CMakeLists; the single-backend path below is unaffected.
218
if(MLN_ANDROID_MULTI_BACKEND)
9+
include(${CMAKE_CURRENT_SOURCE_DIR}/MultiBackend.cmake)
2210
return()
2311
endif()
2412

13+
# (b) Build core into THIS configure's own build dir (was: ../../../../../${ANDROID_ABI}, an
14+
# out-of-tree path both multi sub-builds collided on). Each configure now has its own dir, so
15+
# the multi sub-builds isolate automatically -- no MLN_ANDROID_TOP_BINARY_DIR guard needed.
16+
add_subdirectory(../../../../../ ${CMAKE_CURRENT_BINARY_DIR}/maplibre-core)
17+
2518
set(CMAKE_CXX_STANDARD 20)
2619
set(CMAKE_CXX_STANDARD_REQUIRED ON)
2720

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Android multi-backend build (Gradle `multiBackend` flavor only).
2+
#
3+
# Builds libmaplibre.so (OpenGL) and libmaplibre-vulkan.so (Vulkan) by invoking this directory's
4+
# stock single-backend build twice via ExternalProject, and surfaces both to AGP as SHARED
5+
# targets so both .so land in the multiBackend AAR.
6+
#
7+
# Reached via include() from src/cpp/CMakeLists.txt while project(MapLibreAndroid) is in effect,
8+
# so the add_library targets below land in the AGP-invoked MapLibreAndroid project (AGP's CMake
9+
# file-API query only sees targets declared there) and CMAKE_CURRENT_SOURCE_DIR stays src/cpp.
10+
include(ExternalProject)
11+
12+
set(_src ${CMAKE_CURRENT_SOURCE_DIR}) # src/cpp -- the single-backend entry
13+
14+
# Forward the exact Android toolchain AGP handed this configure to each sub-build. Each sub-build
15+
# takes the single-backend path (MLN_ANDROID_MULTI_BACKEND=OFF) and builds core into its own
16+
# BINARY_DIR (see src/cpp/CMakeLists.txt edit (b)), so the two sub-builds isolate automatically.
17+
set(_fwd
18+
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
19+
-DANDROID_ABI=${ANDROID_ABI}
20+
-DANDROID_PLATFORM=${ANDROID_PLATFORM}
21+
-DANDROID_NDK=${ANDROID_NDK}
22+
-DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN}
23+
-DANDROID_STL=${ANDROID_STL}
24+
-DANDROID_CPP_FEATURES=${ANDROID_CPP_FEATURES}
25+
-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=${ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES}
26+
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
27+
-DMLN_ANDROID_MULTI_BACKEND=OFF)
28+
29+
# Distinct BINARY_DIR per backend => distinct core build dir => no shared static-lib / LTO dir.
30+
set(_gl ${CMAKE_BINARY_DIR}/multi-opengl)
31+
set(_vk ${CMAKE_BINARY_DIR}/multi-vulkan)
32+
33+
ExternalProject_Add(maplibre-opengl-build
34+
SOURCE_DIR ${_src}
35+
BINARY_DIR ${_gl}
36+
CMAKE_ARGS
37+
${_fwd}
38+
-DMLN_WITH_OPENGL=ON
39+
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${_gl}/lib
40+
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target maplibre
41+
INSTALL_COMMAND ""
42+
BUILD_ALWAYS 1)
43+
44+
ExternalProject_Add(maplibre-vulkan-build
45+
SOURCE_DIR ${_src}
46+
BINARY_DIR ${_vk}
47+
CMAKE_ARGS
48+
${_fwd}
49+
-DMLN_WITH_VULKAN=ON
50+
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${_vk}/lib
51+
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target maplibre
52+
INSTALL_COMMAND ""
53+
BUILD_ALWAYS 1)
54+
55+
# Surface both externally-built .so to AGP via stub SHARED targets whose output file is
56+
# overwritten with the real backend .so. AGP packages targets it builds; ExternalProject outputs
57+
# are opaque to it and IMPORTED targets aren't packaged -- hence this bridge.
58+
set(_stub ${CMAKE_BINARY_DIR}/maplibre_multi_stub.cpp)
59+
file(WRITE ${_stub} "extern \"C\" void maplibre_multi_backend_stub() {}\n")
60+
61+
add_library(maplibre-opengl SHARED ${_stub})
62+
# Produce libmaplibre.so (not libmaplibre-opengl.so) so the OpenGL output matches the
63+
# single-backend OpenGL AAR's library name.
64+
set_target_properties(maplibre-opengl PROPERTIES OUTPUT_NAME maplibre)
65+
add_dependencies(maplibre-opengl maplibre-opengl-build)
66+
add_custom_command(TARGET maplibre-opengl POST_BUILD
67+
COMMAND ${CMAKE_COMMAND} -E copy
68+
${_gl}/lib/libmaplibre.so
69+
$<TARGET_FILE:maplibre-opengl>
70+
VERBATIM)
71+
72+
add_library(maplibre-vulkan SHARED ${_stub}) # -> libmaplibre-vulkan.so
73+
add_dependencies(maplibre-vulkan maplibre-vulkan-build)
74+
add_custom_command(TARGET maplibre-vulkan POST_BUILD
75+
COMMAND ${CMAKE_COMMAND} -E copy
76+
${_vk}/lib/libmaplibre.so
77+
$<TARGET_FILE:maplibre-vulkan>
78+
VERBATIM)
79+
80+
# AGP's defaultConfig nativeTargets always lists "maplibre"; provide a custom target so
81+
# `cmake --build . --target maplibre` triggers both .so builds.
82+
add_custom_target(maplibre DEPENDS maplibre-opengl maplibre-vulkan)
83+
84+
install(TARGETS maplibre-opengl maplibre-vulkan LIBRARY DESTINATION lib)

0 commit comments

Comments
 (0)