@mobrowser/native 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,6 +62,14 @@ endif ()
62
62
 
63
63
  include(${PROJECT_ROOT_DIR}/node_modules/@mobrowser/native/cmake/Protobuf.cmake)
64
64
 
65
+ # Links protobuf and MoBrowser includes into an app library; called by templates.
66
+ function(mobrowser_configure_app_lib target)
67
+ target_link_libraries(${target} PUBLIC protobuf::libprotobuf)
68
+ target_include_directories(${target} PUBLIC
69
+ ${PROJECT_SOURCE_DIR}/src/native/gen
70
+ ${MOBROWSER_SDK_NATIVE_DIR}/include)
71
+ endfunction()
72
+
65
73
  # Create the shared library mobrowser_client with MoBrowser runtime
66
74
  add_library(${SHARED_LIB_NAME} SHARED
67
75
  ${GENERATED_SOURCES}
@@ -70,11 +78,15 @@ add_library(${SHARED_LIB_NAME} SHARED
70
78
 
71
79
  # Set up include paths for mobrowser_client
72
80
  target_include_directories(${SHARED_LIB_NAME} PRIVATE
73
- ${protobuf_SOURCE_DIR}/src
74
- ${absl_SOURCE_DIR}
75
- ${PROJECT_SOURCE_DIR}/native/gen
81
+ ${PROJECT_SOURCE_DIR}/src/native/gen
76
82
  ${MOBROWSER_SDK_NATIVE_DIR}/include
77
83
  ${MOBROWSER_SDK_DIR}/include)
78
84
 
79
- # Link mobrowser_lib into mobrowser_client
80
- target_link_libraries(${SHARED_LIB_NAME} PRIVATE ${STATIC_LIB_NAME} libprotobuf)
85
+ if (NOT MOBROWSER_USE_PREBUILT_PROTOBUF)
86
+ target_include_directories(${SHARED_LIB_NAME} PRIVATE
87
+ ${protobuf_SOURCE_DIR}/src
88
+ ${absl_SOURCE_DIR})
89
+ endif ()
90
+
91
+ # Link mobrowser_lib and protobuf into mobrowser_client
92
+ target_link_libraries(${SHARED_LIB_NAME} PRIVATE ${STATIC_LIB_NAME} protobuf::libprotobuf)
@@ -1,8 +1,3 @@
1
- include(FetchContent)
2
-
3
- set(FETCHCONTENT_QUIET OFF)
4
- set(BUILD_TESTING OFF)
5
-
6
1
  set(PROTOBUF_VERSION 33.2)
7
2
 
8
3
  if (NOT DEFINED PROTO_DIR)
@@ -29,43 +24,166 @@ if (NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 17)
29
24
  message(FATAL_ERROR "CMAKE_CXX_STANDARD must be set to 17 or higher before including MoBrowser.cmake")
30
25
  endif ()
31
26
 
27
+ include(${CMAKE_CURRENT_LIST_DIR}/ProtobufCompat.cmake)
28
+ include(${CMAKE_CURRENT_LIST_DIR}/ProtobufDownload.cmake)
29
+
32
30
  # ##############################################################################
33
- # Protobuf (with automatic Abseil fetching)
31
+ # Protobuf: a compatible prebuilt is downloaded by default, with FetchContent
32
+ # from source as the fallback.
33
+ #
34
+ # Policy is resolved by the MoBrowser CLI and forwarded as CMake cache variables:
35
+ # MOBROWSER_PROTOBUF_MODE=auto|prebuilt|fetch
36
+ # MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH=major|exact|family
34
37
  # ##############################################################################
35
- message(CHECK_START "Fetching Protobuf")
36
- list(APPEND CMAKE_MESSAGE_INDENT " ")
37
-
38
- # Abseil options
39
- set(ABSL_USE_SYSTEM_INCLUDES OFF CACHE BOOL "Treat Abseil headers as system includes (-isystem)")
40
- set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "Propagate C++ standard from consumers")
41
- set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "Enable install rules for Abseil")
42
- set(ABSL_BUILD_TESTING OFF CACHE BOOL "Build Abseil tests")
43
- set(ABSL_BUILD_TEST_HELPERS OFF CACHE BOOL "Build Abseil test helpers")
44
- set(ABSL_USE_EXTERNAL_GOOGLETEST ON CACHE BOOL "Use external GTest when needed")
45
- set(ABSL_FIND_GOOGLETEST OFF CACHE BOOL "Let Abseil find GTest on its own")
46
- set(ABSL_MSVC_STATIC_RUNTIME ON CACHE BOOL "Use static runtime with MSVC")
47
-
48
- # Protobuf options
49
- set(protobuf_BUILD_TESTS OFF CACHE BOOL "Do not build Protobuf tests")
50
- set(protobuf_BUILD_SHARED_LIBS OFF CACHE BOOL "Build Protobuf as static libs")
51
- set(protobuf_BUILD_EXPORT OFF CACHE BOOL "Do not export Protobuf CMake targets")
52
- set(protobuf_INSTALL OFF CACHE BOOL "Disable Protobuf install rules")
53
- set(protobuf_BUILD_LIBUPB ON CACHE BOOL "Build libupb for Protobuf")
54
- set(protobuf_MSVC_STATIC_RUNTIME ON CACHE BOOL "Use static runtime with MSVC")
55
- set(protobuf_FORCE_FETCH_DEPENDENCIES ON CACHE BOOL "Let Protobuf fetch Abseil and utf8_range")
56
- set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "Disable utf8_range install rules")
57
-
58
- FetchContent_Declare(
59
- Protobuf
60
- GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git"
61
- GIT_TAG "v${PROTOBUF_VERSION}"
62
- GIT_SHALLOW TRUE
63
- )
38
+ if (NOT DEFINED MOBROWSER_PROTOBUF_MODE)
39
+ set(MOBROWSER_PROTOBUF_MODE "auto" CACHE STRING
40
+ "Protobuf source selection: auto, prebuilt, or fetch")
41
+ endif ()
42
+
43
+ string(TOLOWER "${MOBROWSER_PROTOBUF_MODE}" MOBROWSER_PROTOBUF_MODE)
44
+
45
+ # Log policy flags so CMake does not warn about unused -D variables when the
46
+ # prebuilt path is compatible.
47
+ message(STATUS "MoBrowser protobuf policy: mode=${MOBROWSER_PROTOBUF_MODE}, "
48
+ "toolchainMatch=${MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH}")
49
+
50
+ # Bucket base for prebuilt protobuf, plus a persistent cache dir for extracted
51
+ # prefixes; both overridable via -D.
52
+ if (NOT DEFINED MOBROWSER_PROTOBUF_BUCKET_BASE)
53
+ set(MOBROWSER_PROTOBUF_BUCKET_BASE "https://storage.googleapis.com/mobrowser-runtime")
54
+ endif ()
55
+ if (NOT DEFINED MOBROWSER_PROTOBUF_CACHE_DIR)
56
+ if (DEFINED ENV{MOBROWSER_PROTOBUF_CACHE_DIR})
57
+ set(MOBROWSER_PROTOBUF_CACHE_DIR "$ENV{MOBROWSER_PROTOBUF_CACHE_DIR}")
58
+ else ()
59
+ set(MOBROWSER_PROTOBUF_CACHE_DIR "${CMAKE_BINARY_DIR}/.mobrowser-protobuf")
60
+ endif ()
61
+ endif ()
62
+
63
+ set(MOBROWSER_USE_PREBUILT_PROTOBUF FALSE)
64
+ set(MOBROWSER_PROTOBUF_SELECTED_ROOT "")
65
+ set(MOBROWSER_PROTOBUF_COMPAT_REASON "")
66
+
67
+ if (MOBROWSER_PROTOBUF_MODE STREQUAL "fetch")
68
+ message(STATUS "MOBROWSER_PROTOBUF_MODE=fetch; building protobuf via FetchContent")
69
+ else ()
70
+ mobrowser_protobuf_resolve(
71
+ "${PROTOBUF_VERSION}"
72
+ "${MOBROWSER_PROTOBUF_BUCKET_BASE}"
73
+ "${MOBROWSER_PROTOBUF_CACHE_DIR}"
74
+ "${MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH}"
75
+ _resolved_prefix
76
+ MOBROWSER_PROTOBUF_COMPAT_REASON)
77
+
78
+ if (NOT _resolved_prefix STREQUAL "")
79
+ # Authoritative compatibility gate on the extracted prefix's manifest.
80
+ mobrowser_protobuf_check(
81
+ "${_resolved_prefix}"
82
+ "${PROTOBUF_VERSION}"
83
+ _prebuilt_compatible
84
+ MOBROWSER_PROTOBUF_COMPAT_REASON)
85
+ if (_prebuilt_compatible)
86
+ set(MOBROWSER_USE_PREBUILT_PROTOBUF TRUE)
87
+ set(MOBROWSER_PROTOBUF_SELECTED_ROOT "${_resolved_prefix}")
88
+ message(STATUS "Using downloaded prebuilt protobuf from ${MOBROWSER_PROTOBUF_SELECTED_ROOT}")
89
+ endif ()
90
+ endif ()
91
+
92
+ if (NOT MOBROWSER_USE_PREBUILT_PROTOBUF)
93
+ if (MOBROWSER_PROTOBUF_MODE STREQUAL "prebuilt")
94
+ message(FATAL_ERROR
95
+ "MOBROWSER_PROTOBUF_MODE=prebuilt but no compatible prebuilt protobuf was available: ${MOBROWSER_PROTOBUF_COMPAT_REASON}")
96
+ elseif (MOBROWSER_PROTOBUF_MODE STREQUAL "auto")
97
+ message(STATUS "Prebuilt protobuf unavailable (${MOBROWSER_PROTOBUF_COMPAT_REASON}); falling back to FetchContent")
98
+ else ()
99
+ message(FATAL_ERROR "Unknown MOBROWSER_PROTOBUF_MODE: ${MOBROWSER_PROTOBUF_MODE}")
100
+ endif ()
101
+ endif ()
102
+ endif ()
103
+
104
+ if (MOBROWSER_USE_PREBUILT_PROTOBUF)
105
+ list(PREPEND CMAKE_PREFIX_PATH "${MOBROWSER_PROTOBUF_SELECTED_ROOT}")
106
+ find_package(Protobuf CONFIG REQUIRED)
107
+
108
+ # protoc is a host tool (toolchain-independent for codegen); prefer the one
109
+ # bundled in the SDK (same one the TS codegen uses), falling back to the
110
+ # downloaded prefix's protoc.
111
+ set(MOBROWSER_PROTOC "${MOBROWSER_SDK_DIR}/bin/protoc${CMAKE_EXECUTABLE_SUFFIX}")
112
+ if (NOT EXISTS "${MOBROWSER_PROTOC}")
113
+ set(MOBROWSER_PROTOC "${MOBROWSER_PROTOBUF_SELECTED_ROOT}/bin/protoc${CMAKE_EXECUTABLE_SUFFIX}")
114
+ endif ()
115
+ if (NOT EXISTS "${MOBROWSER_PROTOC}")
116
+ message(FATAL_ERROR "protoc not found (SDK bin or downloaded protobuf prefix)")
117
+ endif ()
118
+ message(STATUS "MOBROWSER_PROTOC: ${MOBROWSER_PROTOC}")
119
+
120
+ set(PROTOBUF_IMPORT_DIRS "${MOBROWSER_PROTOBUF_SELECTED_ROOT}/include" "${PROTO_DIR}")
121
+ else ()
122
+ include(FetchContent)
123
+
124
+ set(FETCHCONTENT_QUIET OFF)
125
+ set(BUILD_TESTING OFF)
126
+
127
+ message(CHECK_START "Fetching Protobuf")
128
+ list(APPEND CMAKE_MESSAGE_INDENT " ")
129
+
130
+ # Abseil options
131
+ set(ABSL_USE_SYSTEM_INCLUDES OFF CACHE BOOL "Treat Abseil headers as system includes (-isystem)")
132
+ set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "Propagate C++ standard from consumers")
133
+ set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "Enable install rules for Abseil")
134
+ set(ABSL_BUILD_TESTING OFF CACHE BOOL "Build Abseil tests")
135
+ set(ABSL_BUILD_TEST_HELPERS OFF CACHE BOOL "Build Abseil test helpers")
136
+ set(ABSL_USE_EXTERNAL_GOOGLETEST ON CACHE BOOL "Use external GTest when needed")
137
+ set(ABSL_FIND_GOOGLETEST OFF CACHE BOOL "Let Abseil find GTest on its own")
138
+ set(ABSL_MSVC_STATIC_RUNTIME ON CACHE BOOL "Use static runtime with MSVC")
139
+
140
+ # Protobuf options
141
+ set(protobuf_BUILD_TESTS OFF CACHE BOOL "Do not build Protobuf tests")
142
+ set(protobuf_BUILD_SHARED_LIBS OFF CACHE BOOL "Build Protobuf as static libs")
143
+ set(protobuf_BUILD_EXPORT OFF CACHE BOOL "Do not export Protobuf CMake targets")
144
+ set(protobuf_INSTALL OFF CACHE BOOL "Disable Protobuf install rules")
145
+ set(protobuf_BUILD_LIBUPB ON CACHE BOOL "Build libupb for Protobuf")
146
+ set(protobuf_MSVC_STATIC_RUNTIME ON CACHE BOOL "Use static runtime with MSVC")
147
+ set(protobuf_FORCE_FETCH_DEPENDENCIES ON CACHE BOOL "Let Protobuf fetch Abseil and utf8_range")
148
+ set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "Disable utf8_range install rules")
149
+
150
+ FetchContent_Declare(
151
+ Protobuf
152
+ GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git"
153
+ GIT_TAG "v${PROTOBUF_VERSION}"
154
+ GIT_SHALLOW TRUE
155
+ )
156
+
157
+ FetchContent_MakeAvailable(Protobuf)
158
+
159
+ list(POP_BACK CMAKE_MESSAGE_INDENT)
160
+ message(CHECK_PASS "fetched")
161
+
162
+ if (NOT TARGET protobuf::libprotobuf AND TARGET libprotobuf)
163
+ add_library(protobuf::libprotobuf ALIAS libprotobuf)
164
+ endif ()
64
165
 
65
- FetchContent_MakeAvailable(Protobuf)
166
+ set(PROTOBUF_IMPORT_DIRS "${protobuf_SOURCE_DIR}/src" "${PROTO_DIR}")
167
+ endif ()
66
168
 
67
- list(POP_BACK CMAKE_MESSAGE_INDENT)
68
- message(CHECK_PASS "fetched")
169
+ set(_decision_prefix "${MOBROWSER_PROTOBUF_SELECTED_ROOT}")
170
+ if (NOT MOBROWSER_USE_PREBUILT_PROTOBUF)
171
+ set(_decision_prefix "")
172
+ endif ()
173
+ set(_decision_manifest_key "")
174
+ if (MOBROWSER_USE_PREBUILT_PROTOBUF)
175
+ set(_manifest_ok FALSE)
176
+ mobrowser_protobuf_read_manifest("${MOBROWSER_PROTOBUF_SELECTED_ROOT}" _manifest_ok)
177
+ if (_manifest_ok)
178
+ set(_decision_manifest_key "${MOBROWSER_PROTOBUF_MANIFEST_TOOLCHAIN_KEY}")
179
+ endif ()
180
+ endif ()
181
+ mobrowser_protobuf_write_decision(
182
+ "${MOBROWSER_PROTOBUF_MODE}"
183
+ "${MOBROWSER_USE_PREBUILT_PROTOBUF}"
184
+ "${_decision_prefix}"
185
+ "${MOBROWSER_PROTOBUF_COMPAT_REASON}"
186
+ "${_decision_manifest_key}")
69
187
 
70
188
  # ##############################################################################
71
189
  # Protobuf code generation
@@ -74,9 +192,6 @@ message(CHECK_PASS "fetched")
74
192
  # Ensure output directory exists
75
193
  file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/src/native/gen")
76
194
 
77
- # Set proto paths for protoc command
78
- set(PROTOBUF_IMPORT_DIRS "${protobuf_SOURCE_DIR}/src" "${PROTO_DIR}")
79
-
80
195
  set(GENERATED_SOURCES)
81
196
  foreach (f IN LISTS PROTO_FILES)
82
197
  # Get file name without extension: foo/bar/baz.proto -> baz
@@ -106,15 +221,23 @@ endforeach()
106
221
 
107
222
  set(CC_NATIVEGEN_PLUGIN "${MOBROWSER_SDK_DIR}/bin/cc_nativegen${CMAKE_EXECUTABLE_SUFFIX}")
108
223
 
224
+ if (MOBROWSER_USE_PREBUILT_PROTOBUF)
225
+ set(_protoc_command "${MOBROWSER_PROTOC}")
226
+ set(_protoc_depend "${MOBROWSER_PROTOC}")
227
+ else ()
228
+ set(_protoc_command "$<TARGET_FILE:protoc>")
229
+ set(_protoc_depend protoc)
230
+ endif ()
231
+
109
232
  add_custom_command(
110
233
  OUTPUT ${GENERATED_SOURCES}
111
- COMMAND $<TARGET_FILE:protoc>
234
+ COMMAND "${_protoc_command}"
112
235
  ${PROTOC_ARGS}
113
236
  --cpp_out=${PROJECT_SOURCE_DIR}/src/native/gen
114
237
  --plugin=protoc-gen-rpc=${CC_NATIVEGEN_PLUGIN}
115
238
  --rpc_out=${PROJECT_SOURCE_DIR}/src/native/gen
116
239
  ${PROTO_FILES}
117
- DEPENDS ${PROTO_FILES} protoc ${CC_NATIVEGEN_PLUGIN}
240
+ DEPENDS ${PROTO_FILES} ${_protoc_depend} ${CC_NATIVEGEN_PLUGIN}
118
241
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
119
242
  COMMENT "Generating C++ sources from .proto files"
120
243
  VERBATIM
@@ -0,0 +1,545 @@
1
+ # Copyright (c) 2000-2026 TeamDev. All rights reserved.
2
+ # TeamDev PROPRIETARY and CONFIDENTIAL.
3
+ # Use is subject to license terms.
4
+
5
+ # Toolchain compatibility checks for MoBrowser prebuilt protobuf prefixes.
6
+
7
+ include_guard(GLOBAL)
8
+
9
+ # Version of the toolchain-key scheme; an artifact published under a different
10
+ # scheme is treated as incompatible (fall back to source).
11
+ set(MOBROWSER_PROTOBUF_KEY_SCHEME_VERSION 1)
12
+
13
+ if (NOT DEFINED MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH)
14
+ set(MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH "major" CACHE STRING
15
+ "Toolchain match policy: exact, major, or family (family skips major check for unknown compiler IDs only)")
16
+ endif ()
17
+
18
+ set(MOBROWSER_PROTOBUF_DECISION_FILE "${CMAKE_BINARY_DIR}/.mobrowser-protobuf-decision")
19
+
20
+ function(mobrowser_protobuf_write_decision MODE USED_PREBUILT PREFIX REASON MANIFEST_KEY)
21
+ if (USED_PREBUILT)
22
+ set(_used_prebuilt_json "true")
23
+ else ()
24
+ set(_used_prebuilt_json "false")
25
+ endif ()
26
+
27
+ string(REPLACE "\\" "\\\\" _prefix "${PREFIX}")
28
+ string(REPLACE "\\" "\\\\" _reason "${REASON}")
29
+ string(REPLACE "\\" "\\\\" _manifest_key "${MANIFEST_KEY}")
30
+ string(REPLACE "\"" "\\\"" _prefix "${_prefix}")
31
+ string(REPLACE "\"" "\\\"" _reason "${_reason}")
32
+ string(REPLACE "\"" "\\\"" _manifest_key "${_manifest_key}")
33
+
34
+ set(_payload "{\"mode\":\"${MODE}\",\"usedPrebuilt\":${_used_prebuilt_json},\"prefix\":\"${_prefix}\",\"reason\":\"${_reason}\",\"manifestToolchainKey\":\"${_manifest_key}\"}\n")
35
+ file(WRITE "${MOBROWSER_PROTOBUF_DECISION_FILE}" "${_payload}")
36
+ endfunction()
37
+
38
+ function(mobrowser_protobuf_read_manifest PREFIX OUT_OK)
39
+ set(_manifest_path "${PREFIX}/MOBROWSER_PROTOBUF.json")
40
+ if (NOT EXISTS "${_manifest_path}")
41
+ set(${OUT_OK} FALSE PARENT_SCOPE)
42
+ return()
43
+ endif ()
44
+
45
+ file(READ "${_manifest_path}" _json)
46
+
47
+ # ERROR_VARIABLE: a corrupt manifest falls back to source, not a fatal abort.
48
+ string(JSON _version ERROR_VARIABLE _e1 GET "${_json}" protobufVersion)
49
+ string(JSON _os ERROR_VARIABLE _e2 GET "${_json}" os)
50
+ string(JSON _arch ERROR_VARIABLE _e3 GET "${_json}" arch)
51
+ string(JSON _cpp_standard ERROR_VARIABLE _e4 GET "${_json}" cppStandard)
52
+ string(JSON _crt ERROR_VARIABLE _e5 GET "${_json}" crt)
53
+ string(JSON _build_type ERROR_VARIABLE _e6 GET "${_json}" buildType)
54
+ string(JSON _toolchain_key ERROR_VARIABLE _e7 GET "${_json}" toolchainKey)
55
+ string(JSON _compiler_id ERROR_VARIABLE _e8 GET "${_json}" compiler id)
56
+ string(JSON _compiler_version ERROR_VARIABLE _e9 GET "${_json}" compiler version)
57
+ string(JSON _compiler_major ERROR_VARIABLE _e10 GET "${_json}" compiler major)
58
+ string(JSON _stdlib_name ERROR_VARIABLE _e11 GET "${_json}" stdlib name)
59
+ if (_e1 OR _e2 OR _e3 OR _e4 OR _e5 OR _e6 OR _e7 OR _e8 OR _e9 OR _e10 OR _e11)
60
+ set(${OUT_OK} FALSE PARENT_SCOPE)
61
+ return()
62
+ endif ()
63
+ set(_stdlib_cxx11_abi "")
64
+ string(JSON _has_cxx11_abi ERROR_VARIABLE _cxx11_abi_err GET "${_json}" stdlib cxx11Abi)
65
+ if (NOT _cxx11_abi_err)
66
+ set(_stdlib_cxx11_abi "${_has_cxx11_abi}")
67
+ endif ()
68
+
69
+ set(_osx_deployment_target "")
70
+ string(JSON _has_osx ERROR_VARIABLE _osx_err GET "${_json}" osxDeploymentTarget)
71
+ if (NOT _osx_err AND NOT _has_osx STREQUAL "null")
72
+ set(_osx_deployment_target "${_has_osx}")
73
+ endif ()
74
+
75
+ set(_glibc "")
76
+ string(JSON _has_glibc ERROR_VARIABLE _glibc_err GET "${_json}" glibc)
77
+ if (NOT _glibc_err AND NOT _has_glibc STREQUAL "null")
78
+ set(_glibc "${_has_glibc}")
79
+ endif ()
80
+
81
+ set(_key_scheme "")
82
+ string(JSON _has_key_scheme ERROR_VARIABLE _key_scheme_err GET "${_json}" keySchemeVersion)
83
+ if (NOT _key_scheme_err)
84
+ set(_key_scheme "${_has_key_scheme}")
85
+ endif ()
86
+
87
+ set(MOBROWSER_PROTOBUF_MANIFEST_VERSION "${_version}" PARENT_SCOPE)
88
+ set(MOBROWSER_PROTOBUF_MANIFEST_OS "${_os}" PARENT_SCOPE)
89
+ set(MOBROWSER_PROTOBUF_MANIFEST_ARCH "${_arch}" PARENT_SCOPE)
90
+ set(MOBROWSER_PROTOBUF_MANIFEST_CPP_STANDARD "${_cpp_standard}" PARENT_SCOPE)
91
+ set(MOBROWSER_PROTOBUF_MANIFEST_CRT "${_crt}" PARENT_SCOPE)
92
+ set(MOBROWSER_PROTOBUF_MANIFEST_BUILD_TYPE "${_build_type}" PARENT_SCOPE)
93
+ set(MOBROWSER_PROTOBUF_MANIFEST_TOOLCHAIN_KEY "${_toolchain_key}" PARENT_SCOPE)
94
+ set(MOBROWSER_PROTOBUF_MANIFEST_COMPILER_ID "${_compiler_id}" PARENT_SCOPE)
95
+ set(MOBROWSER_PROTOBUF_MANIFEST_COMPILER_VERSION "${_compiler_version}" PARENT_SCOPE)
96
+ set(MOBROWSER_PROTOBUF_MANIFEST_COMPILER_MAJOR "${_compiler_major}" PARENT_SCOPE)
97
+ set(MOBROWSER_PROTOBUF_MANIFEST_STDLIB_NAME "${_stdlib_name}" PARENT_SCOPE)
98
+ set(MOBROWSER_PROTOBUF_MANIFEST_STDLIB_CXX11_ABI "${_stdlib_cxx11_abi}" PARENT_SCOPE)
99
+ set(MOBROWSER_PROTOBUF_MANIFEST_OSX_DEPLOYMENT_TARGET "${_osx_deployment_target}" PARENT_SCOPE)
100
+ set(MOBROWSER_PROTOBUF_MANIFEST_GLIBC "${_glibc}" PARENT_SCOPE)
101
+ set(MOBROWSER_PROTOBUF_MANIFEST_KEY_SCHEME "${_key_scheme}" PARENT_SCOPE)
102
+ set(${OUT_OK} TRUE PARENT_SCOPE)
103
+ endfunction()
104
+
105
+ function(mobrowser_protobuf_consumer_os OUT_OS)
106
+ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
107
+ set(${OUT_OS} "win32" PARENT_SCOPE)
108
+ elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
109
+ set(${OUT_OS} "darwin" PARENT_SCOPE)
110
+ elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
111
+ set(${OUT_OS} "linux" PARENT_SCOPE)
112
+ else ()
113
+ set(${OUT_OS} "${CMAKE_SYSTEM_NAME}" PARENT_SCOPE)
114
+ endif ()
115
+ endfunction()
116
+
117
+ function(mobrowser_protobuf_normalize_arch RAW_ARCH OUT_ARCH)
118
+ if (RAW_ARCH MATCHES "^(arm64|aarch64)$")
119
+ set(${OUT_ARCH} "arm64" PARENT_SCOPE)
120
+ elseif (RAW_ARCH MATCHES "^(x86_64|AMD64|amd64)$")
121
+ set(${OUT_ARCH} "x64" PARENT_SCOPE)
122
+ elseif (RAW_ARCH MATCHES "^(i[3-6]86|x86)$")
123
+ set(${OUT_ARCH} "x86" PARENT_SCOPE)
124
+ elseif (RAW_ARCH MATCHES "^(arm64|aarch64).*$")
125
+ set(${OUT_ARCH} "arm64" PARENT_SCOPE)
126
+ else ()
127
+ set(${OUT_ARCH} "unknown" PARENT_SCOPE)
128
+ endif ()
129
+ endfunction()
130
+
131
+ function(mobrowser_protobuf_consumer_arch OUT_ARCH)
132
+ set(_raw_arch "")
133
+
134
+ if (APPLE)
135
+ if (CMAKE_OSX_ARCHITECTURES)
136
+ list(GET CMAKE_OSX_ARCHITECTURES 0 _raw_arch)
137
+ else ()
138
+ set(_raw_arch "${CMAKE_SYSTEM_PROCESSOR}")
139
+ endif ()
140
+ elseif (WIN32)
141
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64|aarch64")
142
+ set(_raw_arch "arm64")
143
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
144
+ set(_raw_arch "x86_64")
145
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
146
+ set(_raw_arch "x86")
147
+ endif ()
148
+ else ()
149
+ set(_raw_arch "${CMAKE_SYSTEM_PROCESSOR}")
150
+ endif ()
151
+
152
+ if (_raw_arch STREQUAL "")
153
+ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
154
+ set(_raw_arch "x86_64")
155
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
156
+ set(_raw_arch "x86")
157
+ endif ()
158
+ endif ()
159
+
160
+ mobrowser_protobuf_normalize_arch("${_raw_arch}" _normalized_arch)
161
+ set(${OUT_ARCH} "${_normalized_arch}" PARENT_SCOPE)
162
+ endfunction()
163
+
164
+ function(mobrowser_protobuf_consumer_compiler_major OUT_MAJOR)
165
+ string(REGEX MATCH "^([0-9]+)" _match "${CMAKE_CXX_COMPILER_VERSION}")
166
+ if (_match)
167
+ set(${OUT_MAJOR} "${CMAKE_MATCH_1}" PARENT_SCOPE)
168
+ else ()
169
+ set(${OUT_MAJOR} "0" PARENT_SCOPE)
170
+ endif ()
171
+ endfunction()
172
+
173
+ function(mobrowser_protobuf_consumer_stdlib OUT_NAME OUT_CXX11_ABI)
174
+ set(_name "unknown")
175
+ set(_cxx11_abi "")
176
+
177
+ if (MSVC)
178
+ set(_name "msvc-stl")
179
+ elseif (APPLE)
180
+ set(_name "libc++")
181
+ elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
182
+ include(CheckCXXSourceCompiles)
183
+
184
+ # Clang can target libc++ or libstdc++. Probes must #error on the wrong
185
+ # branch: check_cxx_source_compiles sees only compilability, not returns.
186
+ check_cxx_source_compiles("
187
+ #include <string>
188
+ #if !defined(_LIBCPP_VERSION)
189
+ #error not libc++
190
+ #endif
191
+ int main() { return 0; }
192
+ " MOBROWSER_CONSUMER_STDLIB_LIBCXX)
193
+
194
+ if (MOBROWSER_CONSUMER_STDLIB_LIBCXX)
195
+ set(_name "libc++")
196
+ else ()
197
+ set(_name "libstdc++")
198
+
199
+ check_cxx_source_compiles("
200
+ #include <string>
201
+ #if !defined(_GLIBCXX_USE_CXX11_ABI) || !_GLIBCXX_USE_CXX11_ABI
202
+ #error not the new (cxx11) libstdc++ ABI
203
+ #endif
204
+ int main() { return 0; }
205
+ " MOBROWSER_CONSUMER_GLIBCXX_CXX11_ABI_1)
206
+ check_cxx_source_compiles("
207
+ #include <string>
208
+ #if !defined(_GLIBCXX_USE_CXX11_ABI) || _GLIBCXX_USE_CXX11_ABI
209
+ #error not the legacy libstdc++ ABI
210
+ #endif
211
+ int main() { return 0; }
212
+ " MOBROWSER_CONSUMER_GLIBCXX_CXX11_ABI_0)
213
+ if (MOBROWSER_CONSUMER_GLIBCXX_CXX11_ABI_1)
214
+ set(_cxx11_abi "1")
215
+ elseif (MOBROWSER_CONSUMER_GLIBCXX_CXX11_ABI_0)
216
+ set(_cxx11_abi "0")
217
+ endif ()
218
+ endif ()
219
+ endif ()
220
+
221
+ set(${OUT_NAME} "${_name}" PARENT_SCOPE)
222
+ set(${OUT_CXX11_ABI} "${_cxx11_abi}" PARENT_SCOPE)
223
+ endfunction()
224
+
225
+ function(mobrowser_protobuf_consumer_crt OUT_CRT)
226
+ if (NOT MSVC)
227
+ set(${OUT_CRT} "" PARENT_SCOPE)
228
+ return()
229
+ endif ()
230
+
231
+ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
232
+ set(_is_debug_config TRUE)
233
+ else ()
234
+ set(_is_debug_config FALSE)
235
+ endif ()
236
+
237
+ set(_runtime "${CMAKE_MSVC_RUNTIME_LIBRARY}")
238
+
239
+ # When unset (or explicitly empty) CMake defaults to the dynamic CRT
240
+ # (CMP0091: MultiThreaded$<$<CONFIG:Debug>:Debug>DLL).
241
+ if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY OR _runtime STREQUAL "")
242
+ if (_is_debug_config)
243
+ set(${OUT_CRT} "MultiThreadedDebugDLL" PARENT_SCOPE)
244
+ else ()
245
+ set(${OUT_CRT} "MultiThreadedDLL" PARENT_SCOPE)
246
+ endif ()
247
+ return()
248
+ endif ()
249
+
250
+ # Dynamic CRT if the value carries a DLL marker. Check this explicitly
251
+ # because "MultiThreadedDLL" contains the substring "MultiThreaded" and
252
+ # must not be misread as the static (/MT) runtime.
253
+ string(FIND "${_runtime}" "DLL" _dll_pos)
254
+ if (_dll_pos GREATER -1)
255
+ set(_dynamic TRUE)
256
+ else ()
257
+ set(_dynamic FALSE)
258
+ endif ()
259
+
260
+ # Debug CRT: a $<CONFIG:...> generator expression defers to the build type,
261
+ # while a plain literal (e.g. "MultiThreadedDebug") is authoritative.
262
+ if (_runtime MATCHES "\\$<")
263
+ set(_debug ${_is_debug_config})
264
+ elseif (_runtime MATCHES "MultiThreadedDebug")
265
+ set(_debug TRUE)
266
+ else ()
267
+ set(_debug FALSE)
268
+ endif ()
269
+
270
+ if (_debug AND _dynamic)
271
+ set(${OUT_CRT} "MultiThreadedDebugDLL" PARENT_SCOPE)
272
+ elseif (_debug)
273
+ set(${OUT_CRT} "MultiThreadedDebug" PARENT_SCOPE)
274
+ elseif (_dynamic)
275
+ set(${OUT_CRT} "MultiThreadedDLL" PARENT_SCOPE)
276
+ else ()
277
+ set(${OUT_CRT} "MultiThreaded" PARENT_SCOPE)
278
+ endif ()
279
+ endfunction()
280
+
281
+ # Detects the host glibc version on Linux (e.g. "2.35"); empty elsewhere or when
282
+ # it cannot be determined.
283
+ function(mobrowser_protobuf_consumer_glibc OUT_GLIBC)
284
+ set(_glibc "")
285
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
286
+ find_program(_getconf_exe getconf)
287
+ if (_getconf_exe)
288
+ execute_process(
289
+ COMMAND "${_getconf_exe}" GNU_LIBC_VERSION
290
+ OUTPUT_VARIABLE _getconf_out
291
+ ERROR_QUIET
292
+ RESULT_VARIABLE _getconf_rc
293
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
294
+ if (_getconf_rc EQUAL 0 AND _getconf_out MATCHES "([0-9]+\\.[0-9]+)")
295
+ set(_glibc "${CMAKE_MATCH_1}")
296
+ endif ()
297
+ endif ()
298
+ if (_glibc STREQUAL "")
299
+ find_program(_ldd_exe ldd)
300
+ if (_ldd_exe)
301
+ execute_process(
302
+ COMMAND "${_ldd_exe}" --version
303
+ OUTPUT_VARIABLE _ldd_out
304
+ ERROR_VARIABLE _ldd_err
305
+ RESULT_VARIABLE _ldd_rc)
306
+ if (_ldd_rc EQUAL 0 AND "${_ldd_out}${_ldd_err}" MATCHES "([0-9]+\\.[0-9]+)")
307
+ set(_glibc "${CMAKE_MATCH_1}")
308
+ endif ()
309
+ endif ()
310
+ endif ()
311
+ endif ()
312
+ set(${OUT_GLIBC} "${_glibc}" PARENT_SCOPE)
313
+ endfunction()
314
+
315
+ function(mobrowser_protobuf_compiler_major_compatible MATCH_POLICY MANIFEST_ID MANIFEST_MAJOR CONSUMER_MAJOR OUT_OK OUT_REASON)
316
+ if (MATCH_POLICY STREQUAL "exact")
317
+ if (NOT "${CONSUMER_MAJOR}" STREQUAL "${MANIFEST_MAJOR}")
318
+ set(${OUT_OK} FALSE PARENT_SCOPE)
319
+ set(${OUT_REASON} "compiler major mismatch (prebuilt ${MANIFEST_MAJOR}, consumer ${CONSUMER_MAJOR})" PARENT_SCOPE)
320
+ return()
321
+ endif ()
322
+ set(${OUT_OK} TRUE PARENT_SCOPE)
323
+ set(${OUT_REASON} "" PARENT_SCOPE)
324
+ return()
325
+ endif ()
326
+
327
+ # major / family: per-compiler-family rules (family is looser for unknown IDs).
328
+ if (MANIFEST_ID STREQUAL "MSVC")
329
+ if (CONSUMER_MAJOR LESS MANIFEST_MAJOR)
330
+ set(${OUT_OK} FALSE PARENT_SCOPE)
331
+ set(${OUT_REASON} "MSVC compiler too old (prebuilt ${MANIFEST_MAJOR}, consumer ${CONSUMER_MAJOR})" PARENT_SCOPE)
332
+ return()
333
+ endif ()
334
+ set(${OUT_OK} TRUE PARENT_SCOPE)
335
+ set(${OUT_REASON} "" PARENT_SCOPE)
336
+ return()
337
+ endif ()
338
+
339
+ # GNU / Clang / AppleClang: a newer consumer stays ABI-compatible with an
340
+ # older prebuilt of the same family, so require consumer >= prebuilt.
341
+ if (MANIFEST_ID MATCHES "GNU|Clang")
342
+ if (CONSUMER_MAJOR LESS MANIFEST_MAJOR)
343
+ set(${OUT_OK} FALSE PARENT_SCOPE)
344
+ set(${OUT_REASON} "compiler major too old (prebuilt ${MANIFEST_MAJOR}, consumer ${CONSUMER_MAJOR})" PARENT_SCOPE)
345
+ return()
346
+ endif ()
347
+ set(${OUT_OK} TRUE PARENT_SCOPE)
348
+ set(${OUT_REASON} "" PARENT_SCOPE)
349
+ return()
350
+ endif ()
351
+
352
+ if (MATCH_POLICY STREQUAL "family")
353
+ set(${OUT_OK} TRUE PARENT_SCOPE)
354
+ set(${OUT_REASON} "" PARENT_SCOPE)
355
+ return()
356
+ endif ()
357
+
358
+ if (NOT "${CONSUMER_MAJOR}" STREQUAL "${MANIFEST_MAJOR}")
359
+ set(${OUT_OK} FALSE PARENT_SCOPE)
360
+ set(${OUT_REASON} "compiler major mismatch (prebuilt ${MANIFEST_MAJOR}, consumer ${CONSUMER_MAJOR})" PARENT_SCOPE)
361
+ return()
362
+ endif ()
363
+
364
+ set(${OUT_OK} TRUE PARENT_SCOPE)
365
+ set(${OUT_REASON} "" PARENT_SCOPE)
366
+ endfunction()
367
+
368
+ function(mobrowser_protobuf_check_abseil PREFIX OUT_OK OUT_REASON)
369
+ set(_options_path "${PREFIX}/include/absl/base/options.h")
370
+ if (NOT EXISTS "${_options_path}")
371
+ set(${OUT_OK} FALSE PARENT_SCOPE)
372
+ set(${OUT_REASON} "Abseil options.h missing from prebuilt prefix" PARENT_SCOPE)
373
+ return()
374
+ endif ()
375
+
376
+ file(READ "${_options_path}" _absl_options)
377
+ # Accept 1 or 2 (auto resolves to std::string_view under C++17+); reject 0.
378
+ if (_absl_options MATCHES "#define ABSL_OPTION_USE_STD_STRING_VIEW ([0-9]+)")
379
+ set(_absl_view "${CMAKE_MATCH_1}")
380
+ else ()
381
+ set(_absl_view "")
382
+ endif ()
383
+ if (NOT (_absl_view STREQUAL "1" OR _absl_view STREQUAL "2"))
384
+ set(${OUT_OK} FALSE PARENT_SCOPE)
385
+ set(${OUT_REASON} "Abseil ABSL_OPTION_USE_STD_STRING_VIEW is '${_absl_view}', need 1 or 2" PARENT_SCOPE)
386
+ return()
387
+ endif ()
388
+
389
+ set(${OUT_OK} TRUE PARENT_SCOPE)
390
+ set(${OUT_REASON} "" PARENT_SCOPE)
391
+ endfunction()
392
+
393
+ function(mobrowser_protobuf_check PREFIX EXPECTED_PROTOBUF_VERSION OUT_COMPATIBLE OUT_REASON)
394
+ set(_compatible FALSE)
395
+ set(_reason "unknown incompatibility")
396
+
397
+ if (NOT EXISTS "${PREFIX}/lib/cmake/protobuf/protobuf-config.cmake")
398
+ set(_reason "prebuilt protobuf prefix is incomplete")
399
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
400
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
401
+ return()
402
+ endif ()
403
+
404
+ set(_manifest_ok FALSE)
405
+ mobrowser_protobuf_read_manifest("${PREFIX}" _manifest_ok)
406
+ if (NOT _manifest_ok)
407
+ set(_reason "MOBROWSER_PROTOBUF.json manifest is missing or invalid")
408
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
409
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
410
+ return()
411
+ endif ()
412
+
413
+ if (NOT "${MOBROWSER_PROTOBUF_MANIFEST_VERSION}" STREQUAL "${EXPECTED_PROTOBUF_VERSION}")
414
+ set(_reason "protobuf version mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_VERSION}, expected ${EXPECTED_PROTOBUF_VERSION})")
415
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
416
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
417
+ return()
418
+ endif ()
419
+
420
+ if (NOT "${MOBROWSER_PROTOBUF_MANIFEST_KEY_SCHEME}" STREQUAL "${MOBROWSER_PROTOBUF_KEY_SCHEME_VERSION}")
421
+ set(_reason "key scheme mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_KEY_SCHEME}, supported ${MOBROWSER_PROTOBUF_KEY_SCHEME_VERSION})")
422
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
423
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
424
+ return()
425
+ endif ()
426
+
427
+ mobrowser_protobuf_check_abseil("${PREFIX}" _abseil_ok _abseil_reason)
428
+ if (NOT _abseil_ok)
429
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
430
+ set(${OUT_REASON} "${_abseil_reason}" PARENT_SCOPE)
431
+ return()
432
+ endif ()
433
+
434
+ mobrowser_protobuf_consumer_os(_consumer_os)
435
+ mobrowser_protobuf_consumer_arch(_consumer_arch)
436
+ mobrowser_protobuf_consumer_compiler_major(_consumer_major)
437
+ mobrowser_protobuf_consumer_stdlib(_consumer_stdlib _consumer_cxx11_abi)
438
+ mobrowser_protobuf_consumer_crt(_consumer_crt)
439
+
440
+ if (NOT "${_consumer_os}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_OS}")
441
+ set(_reason "OS mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_OS}, consumer ${_consumer_os})")
442
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
443
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
444
+ return()
445
+ endif ()
446
+
447
+ if (NOT "${_consumer_arch}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_ARCH}")
448
+ set(_reason "architecture mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_ARCH}, consumer ${_consumer_arch})")
449
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
450
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
451
+ return()
452
+ endif ()
453
+
454
+ if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_COMPILER_ID}")
455
+ set(_reason "compiler family mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_COMPILER_ID}, consumer ${CMAKE_CXX_COMPILER_ID})")
456
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
457
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
458
+ return()
459
+ endif ()
460
+
461
+ mobrowser_protobuf_compiler_major_compatible(
462
+ "${MOBROWSER_PROTOBUF_TOOLCHAIN_MATCH}"
463
+ "${MOBROWSER_PROTOBUF_MANIFEST_COMPILER_ID}"
464
+ "${MOBROWSER_PROTOBUF_MANIFEST_COMPILER_MAJOR}"
465
+ "${_consumer_major}"
466
+ _major_ok
467
+ _major_reason)
468
+ if (NOT _major_ok)
469
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
470
+ set(${OUT_REASON} "${_major_reason}" PARENT_SCOPE)
471
+ return()
472
+ endif ()
473
+
474
+ if (NOT "${_consumer_stdlib}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_STDLIB_NAME}")
475
+ set(_reason "C++ standard library mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_STDLIB_NAME}, consumer ${_consumer_stdlib})")
476
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
477
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
478
+ return()
479
+ endif ()
480
+
481
+ if (MOBROWSER_PROTOBUF_MANIFEST_STDLIB_CXX11_ABI STREQUAL "0" OR MOBROWSER_PROTOBUF_MANIFEST_STDLIB_CXX11_ABI STREQUAL "1")
482
+ if (NOT "${_consumer_cxx11_abi}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_STDLIB_CXX11_ABI}")
483
+ set(_reason "libstdc++ _GLIBCXX_USE_CXX11_ABI mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_STDLIB_CXX11_ABI}, consumer ${_consumer_cxx11_abi})")
484
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
485
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
486
+ return()
487
+ endif ()
488
+ endif ()
489
+
490
+ if (DEFINED CMAKE_CXX_STANDARD)
491
+ if (CMAKE_CXX_STANDARD LESS MOBROWSER_PROTOBUF_MANIFEST_CPP_STANDARD)
492
+ set(_reason "C++ standard too low (need >= ${MOBROWSER_PROTOBUF_MANIFEST_CPP_STANDARD}, got ${CMAKE_CXX_STANDARD})")
493
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
494
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
495
+ return()
496
+ endif ()
497
+ endif ()
498
+
499
+ if (MSVC)
500
+ if (NOT "${_consumer_crt}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_CRT}")
501
+ set(_reason "MSVC runtime mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_CRT}, consumer ${_consumer_crt})")
502
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
503
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
504
+ return()
505
+ endif ()
506
+ if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "${MOBROWSER_PROTOBUF_MANIFEST_BUILD_TYPE}")
507
+ set(_reason "build type mismatch (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_BUILD_TYPE}, consumer ${CMAKE_BUILD_TYPE})")
508
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
509
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
510
+ return()
511
+ endif ()
512
+ endif ()
513
+
514
+ if (APPLE AND MOBROWSER_PROTOBUF_MANIFEST_OSX_DEPLOYMENT_TARGET)
515
+ if (DEFINED CMAKE_OSX_DEPLOYMENT_TARGET)
516
+ if (CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS MOBROWSER_PROTOBUF_MANIFEST_OSX_DEPLOYMENT_TARGET)
517
+ set(_reason "macOS deployment target too low (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_OSX_DEPLOYMENT_TARGET}, consumer ${CMAKE_OSX_DEPLOYMENT_TARGET})")
518
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
519
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
520
+ return()
521
+ endif ()
522
+ endif ()
523
+ endif ()
524
+
525
+ # Linux glibc floor: the prebuilt needs at least its build-time glibc. Fail
526
+ # closed when the manifest records a floor but the host's glibc is unknown.
527
+ if (_consumer_os STREQUAL "linux" AND NOT MOBROWSER_PROTOBUF_MANIFEST_GLIBC STREQUAL "")
528
+ mobrowser_protobuf_consumer_glibc(_consumer_glibc)
529
+ if (_consumer_glibc STREQUAL "")
530
+ set(_reason "glibc floor unverifiable (prebuilt ${MOBROWSER_PROTOBUF_MANIFEST_GLIBC}, consumer unknown)")
531
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
532
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
533
+ return()
534
+ endif ()
535
+ if (_consumer_glibc VERSION_LESS MOBROWSER_PROTOBUF_MANIFEST_GLIBC)
536
+ set(_reason "glibc too old (need >= ${MOBROWSER_PROTOBUF_MANIFEST_GLIBC}, consumer ${_consumer_glibc})")
537
+ set(${OUT_COMPATIBLE} FALSE PARENT_SCOPE)
538
+ set(${OUT_REASON} "${_reason}" PARENT_SCOPE)
539
+ return()
540
+ endif ()
541
+ endif ()
542
+
543
+ set(${OUT_COMPATIBLE} TRUE PARENT_SCOPE)
544
+ set(${OUT_REASON} "" PARENT_SCOPE)
545
+ endfunction()
@@ -0,0 +1,273 @@
1
+ # Copyright (c) 2000-2026 TeamDev. All rights reserved.
2
+ # TeamDev PROPRIETARY and CONFIDENTIAL.
3
+ # Use is subject to license terms.
4
+
5
+ # Resolves a prebuilt protobuf artifact from the configured bucket:
6
+ # derives the consumer toolchain key, reads the published index.json, selects a
7
+ # compatible artifact, and downloads + extracts it. All at configure time, using
8
+ # only CMake (file(DOWNLOAD)/file(SHA256)/cmake -E tar), so no external tooling
9
+ # is required. The caller runs the authoritative mobrowser_protobuf_check on the
10
+ # extracted prefix afterwards.
11
+
12
+ include_guard(GLOBAL)
13
+ include(${CMAKE_CURRENT_LIST_DIR}/ProtobufCompat.cmake)
14
+
15
+ # Slugifies a toolchain value: "+" -> "x", drop other non-alphanumerics,
16
+ # lowercase. libstdc++ -> libstdcxx, libc++ -> libcxx, msvc-stl -> msvcstl.
17
+ function(mobrowser_protobuf_slug VALUE OUT)
18
+ string(REPLACE "+" "x" _s "${VALUE}")
19
+ string(REGEX REPLACE "[^A-Za-z0-9]" "" _s "${_s}")
20
+ string(TOLOWER "${_s}" _s)
21
+ set(${OUT} "${_s}" PARENT_SCOPE)
22
+ endfunction()
23
+
24
+ function(mobrowser_protobuf_crt_slug CRT OUT)
25
+ if (CRT STREQUAL "MultiThreaded")
26
+ set(_s "mt")
27
+ elseif (CRT STREQUAL "MultiThreadedDLL")
28
+ set(_s "md")
29
+ elseif (CRT STREQUAL "MultiThreadedDebug")
30
+ set(_s "mtd")
31
+ elseif (CRT STREQUAL "MultiThreadedDebugDLL")
32
+ set(_s "mdd")
33
+ else ()
34
+ set(_s "")
35
+ endif ()
36
+ set(${OUT} "${_s}" PARENT_SCOPE)
37
+ endfunction()
38
+
39
+ # Computes the consumer's toolchain-key identity: the key-os segment ("win" for
40
+ # win32), arch, compiler slug, compiler major, and the trailing stdlib(+abi+crt)
41
+ # suffix. A published key is a match iff it equals
42
+ # "<oskey>-<arch>-<cslug>-<major>-<suffix>" for some numeric <major>.
43
+ function(mobrowser_protobuf_consumer_key OUT_OSKEY OUT_ARCH OUT_COMPILER_SLUG OUT_MAJOR OUT_STDLIB_SUFFIX)
44
+ mobrowser_protobuf_consumer_os(_os)
45
+ mobrowser_protobuf_consumer_arch(_arch)
46
+ mobrowser_protobuf_consumer_compiler_major(_major)
47
+ mobrowser_protobuf_consumer_stdlib(_stdlib _cxx11)
48
+ mobrowser_protobuf_consumer_crt(_crt)
49
+
50
+ if (_os STREQUAL "win32")
51
+ set(_oskey "win")
52
+ else ()
53
+ set(_oskey "${_os}")
54
+ endif ()
55
+
56
+ mobrowser_protobuf_slug("${CMAKE_CXX_COMPILER_ID}" _cslug)
57
+ mobrowser_protobuf_slug("${_stdlib}" _stdlib_slug)
58
+
59
+ set(_suffix "${_stdlib_slug}")
60
+ if (_stdlib STREQUAL "libstdc++")
61
+ if (_cxx11 STREQUAL "1")
62
+ set(_suffix "${_suffix}-cxx11")
63
+ elseif (_cxx11 STREQUAL "0")
64
+ set(_suffix "${_suffix}-cxx11-legacy")
65
+ endif ()
66
+ endif ()
67
+ if (NOT _crt STREQUAL "")
68
+ mobrowser_protobuf_crt_slug("${_crt}" _crt_slug)
69
+ if (NOT _crt_slug STREQUAL "")
70
+ set(_suffix "${_suffix}-${_crt_slug}")
71
+ endif ()
72
+ endif ()
73
+
74
+ set(${OUT_OSKEY} "${_oskey}" PARENT_SCOPE)
75
+ set(${OUT_ARCH} "${_arch}" PARENT_SCOPE)
76
+ set(${OUT_COMPILER_SLUG} "${_cslug}" PARENT_SCOPE)
77
+ set(${OUT_MAJOR} "${_major}" PARENT_SCOPE)
78
+ set(${OUT_STDLIB_SUFFIX} "${_suffix}" PARENT_SCOPE)
79
+ endfunction()
80
+
81
+ # Picks the newest compatible artifact from a parsed index.json. OUT_KEY is empty
82
+ # when nothing matches (OUT_REASON explains why).
83
+ function(mobrowser_protobuf_select_from_index INDEX_JSON OSKEY ARCH COMPILER_SLUG CONSUMER_MAJOR STDLIB_SUFFIX MATCH_POLICY OUT_URL OUT_SHA OUT_KEY OUT_REASON)
84
+ set(${OUT_URL} "" PARENT_SCOPE)
85
+ set(${OUT_SHA} "" PARENT_SCOPE)
86
+ set(${OUT_KEY} "" PARENT_SCOPE)
87
+
88
+ string(JSON _scheme ERROR_VARIABLE _scheme_err GET "${INDEX_JSON}" keySchemeVersion)
89
+ if (_scheme_err)
90
+ set(${OUT_REASON} "index.json has no keySchemeVersion" PARENT_SCOPE)
91
+ return()
92
+ endif ()
93
+ if (NOT "${_scheme}" STREQUAL "${MOBROWSER_PROTOBUF_KEY_SCHEME_VERSION}")
94
+ set(${OUT_REASON} "index key scheme ${_scheme} != supported ${MOBROWSER_PROTOBUF_KEY_SCHEME_VERSION}" PARENT_SCOPE)
95
+ return()
96
+ endif ()
97
+
98
+ string(JSON _count ERROR_VARIABLE _count_err LENGTH "${INDEX_JSON}" artifacts)
99
+ if (_count_err OR _count EQUAL 0)
100
+ set(${OUT_REASON} "index.json lists no artifacts" PARENT_SCOPE)
101
+ return()
102
+ endif ()
103
+
104
+ mobrowser_protobuf_consumer_glibc(_consumer_glibc)
105
+
106
+ set(_pat "^${OSKEY}-${ARCH}-${COMPILER_SLUG}-([0-9]+)-${STDLIB_SUFFIX}$")
107
+ set(_best_major -1)
108
+ set(_best_url "")
109
+ set(_best_sha "")
110
+ set(_best_key "")
111
+
112
+ math(EXPR _last "${_count} - 1")
113
+ foreach (_i RANGE ${_last})
114
+ string(JSON _key ERROR_VARIABLE _key_err GET "${INDEX_JSON}" artifacts ${_i} toolchainKey)
115
+ if (_key_err)
116
+ continue()
117
+ endif ()
118
+
119
+ if (NOT _key MATCHES "${_pat}")
120
+ continue()
121
+ endif ()
122
+ set(_cand_major "${CMAKE_MATCH_1}")
123
+
124
+ if (MATCH_POLICY STREQUAL "exact")
125
+ if (NOT _cand_major EQUAL CONSUMER_MAJOR)
126
+ continue()
127
+ endif ()
128
+ else ()
129
+ # major / family: the prebuilt must be same-or-older than the consumer.
130
+ if (_cand_major GREATER CONSUMER_MAJOR)
131
+ continue()
132
+ endif ()
133
+ endif ()
134
+
135
+ # glibc floor (Linux): fail closed when the host glibc is unknown.
136
+ string(JSON _glibc_floor ERROR_VARIABLE _gf_err GET "${INDEX_JSON}" artifacts ${_i} glibcFloor)
137
+ if (NOT _gf_err AND NOT _glibc_floor STREQUAL "null" AND NOT _glibc_floor STREQUAL "")
138
+ if (_consumer_glibc STREQUAL "")
139
+ continue()
140
+ endif ()
141
+ if (_consumer_glibc VERSION_LESS _glibc_floor)
142
+ continue()
143
+ endif ()
144
+ endif ()
145
+
146
+ # macOS deployment-target floor.
147
+ if (APPLE)
148
+ string(JSON _osx_floor ERROR_VARIABLE _of_err GET "${INDEX_JSON}" artifacts ${_i} osxDeploymentTarget)
149
+ if (NOT _of_err AND NOT _osx_floor STREQUAL "null" AND NOT _osx_floor STREQUAL "")
150
+ if (DEFINED CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS _osx_floor)
151
+ continue()
152
+ endif ()
153
+ endif ()
154
+ endif ()
155
+
156
+ if (_cand_major GREATER _best_major)
157
+ string(JSON _url ERROR_VARIABLE _url_err GET "${INDEX_JSON}" artifacts ${_i} url)
158
+ string(JSON _sha ERROR_VARIABLE _sha_err GET "${INDEX_JSON}" artifacts ${_i} sha256)
159
+ if (_url_err OR _sha_err)
160
+ continue()
161
+ endif ()
162
+ set(_best_major "${_cand_major}")
163
+ set(_best_url "${_url}")
164
+ set(_best_sha "${_sha}")
165
+ set(_best_key "${_key}")
166
+ endif ()
167
+ endforeach ()
168
+
169
+ if (_best_key STREQUAL "")
170
+ set(${OUT_REASON} "no compatible artifact for ${OSKEY}-${ARCH}-${COMPILER_SLUG}-*-${STDLIB_SUFFIX}" PARENT_SCOPE)
171
+ return()
172
+ endif ()
173
+
174
+ set(${OUT_URL} "${_best_url}" PARENT_SCOPE)
175
+ set(${OUT_SHA} "${_best_sha}" PARENT_SCOPE)
176
+ set(${OUT_KEY} "${_best_key}" PARENT_SCOPE)
177
+ set(${OUT_REASON} "" PARENT_SCOPE)
178
+ endfunction()
179
+
180
+ function(mobrowser_protobuf_download_and_extract URL SHA256 DEST_PREFIX OUT_OK OUT_REASON)
181
+ set(${OUT_OK} FALSE PARENT_SCOPE)
182
+ set(_archive "${DEST_PREFIX}.7z")
183
+ set(_staging "${DEST_PREFIX}.incomplete")
184
+
185
+ file(DOWNLOAD "${URL}" "${_archive}" STATUS _st SHOW_PROGRESS INACTIVITY_TIMEOUT 60)
186
+ list(GET _st 0 _code)
187
+ if (NOT _code EQUAL 0)
188
+ list(GET _st 1 _msg)
189
+ file(REMOVE "${_archive}")
190
+ set(${OUT_REASON} "download failed (${URL}): ${_msg}" PARENT_SCOPE)
191
+ return()
192
+ endif ()
193
+
194
+ file(SHA256 "${_archive}" _actual)
195
+ if (NOT _actual STREQUAL "${SHA256}")
196
+ file(REMOVE "${_archive}")
197
+ set(${OUT_REASON} "sha256 mismatch for ${URL} (expected ${SHA256}, got ${_actual})" PARENT_SCOPE)
198
+ return()
199
+ endif ()
200
+
201
+ # Extract into a staging dir and swap into place only on success, so an
202
+ # interrupted extract cannot leave a partial prefix that a later configure
203
+ # mistakes for a valid cache.
204
+ file(REMOVE_RECURSE "${_staging}" "${DEST_PREFIX}")
205
+ file(MAKE_DIRECTORY "${_staging}")
206
+ execute_process(
207
+ COMMAND "${CMAKE_COMMAND}" -E tar xf "${_archive}"
208
+ WORKING_DIRECTORY "${_staging}"
209
+ RESULT_VARIABLE _tar_rc
210
+ ERROR_VARIABLE _tar_err)
211
+ file(REMOVE "${_archive}")
212
+ if (NOT _tar_rc EQUAL 0)
213
+ file(REMOVE_RECURSE "${_staging}")
214
+ set(${OUT_REASON} "could not extract 7z archive (is 7z supported by this CMake's libarchive?): ${_tar_err}" PARENT_SCOPE)
215
+ return()
216
+ endif ()
217
+
218
+ file(RENAME "${_staging}" "${DEST_PREFIX}")
219
+
220
+ set(${OUT_OK} TRUE PARENT_SCOPE)
221
+ set(${OUT_REASON} "" PARENT_SCOPE)
222
+ endfunction()
223
+
224
+ # Top-level: resolve + download a compatible prebuilt for VERSION from BUCKET_BASE
225
+ # into CACHE_DIR. OUT_PREFIX is the extracted install prefix, or empty with
226
+ # OUT_REASON set when no compatible artifact could be obtained.
227
+ function(mobrowser_protobuf_resolve VERSION BUCKET_BASE CACHE_DIR MATCH_POLICY OUT_PREFIX OUT_REASON)
228
+ set(${OUT_PREFIX} "" PARENT_SCOPE)
229
+
230
+ mobrowser_protobuf_consumer_key(_oskey _arch _cslug _major _suffix)
231
+ if (_arch STREQUAL "unknown" OR _cslug STREQUAL "" OR _major STREQUAL "0")
232
+ set(${OUT_REASON} "could not determine the consumer toolchain key" PARENT_SCOPE)
233
+ return()
234
+ endif ()
235
+
236
+ file(MAKE_DIRECTORY "${CACHE_DIR}")
237
+ set(_index_url "${BUCKET_BASE}/downloads/protobuf/${VERSION}/index.json")
238
+ set(_index_file "${CACHE_DIR}/index-${VERSION}.json")
239
+ file(DOWNLOAD "${_index_url}" "${_index_file}" STATUS _st INACTIVITY_TIMEOUT 30)
240
+ list(GET _st 0 _code)
241
+ if (NOT _code EQUAL 0)
242
+ list(GET _st 1 _msg)
243
+ set(${OUT_REASON} "could not fetch ${_index_url}: ${_msg}" PARENT_SCOPE)
244
+ return()
245
+ endif ()
246
+ file(READ "${_index_file}" _index_json)
247
+
248
+ mobrowser_protobuf_select_from_index(
249
+ "${_index_json}" "${_oskey}" "${_arch}" "${_cslug}" "${_major}" "${_suffix}"
250
+ "${MATCH_POLICY}" _url _sha _key _sel_reason)
251
+ if (_key STREQUAL "")
252
+ set(${OUT_REASON} "${_sel_reason}" PARENT_SCOPE)
253
+ return()
254
+ endif ()
255
+
256
+ set(_prefix "${CACHE_DIR}/${VERSION}/${_key}")
257
+ if (EXISTS "${_prefix}/MOBROWSER_PROTOBUF.json")
258
+ message(STATUS "Reusing cached protobuf ${_key} at ${_prefix}")
259
+ set(${OUT_PREFIX} "${_prefix}" PARENT_SCOPE)
260
+ set(${OUT_REASON} "" PARENT_SCOPE)
261
+ return()
262
+ endif ()
263
+
264
+ message(STATUS "Downloading prebuilt protobuf ${_key}...")
265
+ mobrowser_protobuf_download_and_extract("${BUCKET_BASE}/${_url}" "${_sha}" "${_prefix}" _dl_ok _dl_reason)
266
+ if (NOT _dl_ok)
267
+ set(${OUT_REASON} "${_dl_reason}" PARENT_SCOPE)
268
+ return()
269
+ endif ()
270
+
271
+ set(${OUT_PREFIX} "${_prefix}" PARENT_SCOPE)
272
+ set(${OUT_REASON} "" PARENT_SCOPE)
273
+ endfunction()
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@mobrowser/native",
3
- "version": "2.11.0",
3
+ "version": "2.13.0",
4
4
  "description": "Configuration files for MōBrowser native integration",
5
5
  "main": "cmake/MoBrowser.cmake",
6
6
  "files": [
7
7
  "cmake/MoBrowser.cmake",
8
8
  "cmake/Platform.cmake",
9
9
  "cmake/Protobuf.cmake",
10
+ "cmake/ProtobufCompat.cmake",
11
+ "cmake/ProtobufDownload.cmake",
10
12
  "include",
11
13
  "internal"
12
14
  ],