Skip to content

Commit fb9186b

Browse files
committed
Build libicu v74.2 statically w/ SQLCipher to enable ICU
The SQLCipher that we build against, v4.10 compiles specifically against a version of SQLite that uses libicu 74.2 (it uses the versioned functions, e.g. uregex_setText_74) hence the slightly older version whereas the latest libicu version is v78.
1 parent 83b3b14 commit fb9186b

3 files changed

Lines changed: 243 additions & 5 deletions

File tree

cmake/StaticBuild.cmake

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
set(LIBICU_VERSION 74_2)
2+
set(LIBICU_DASH_VERSION 74-2)
3+
set(LIBICU_MIRROR https://github.com/unicode-org/icu/releases/download/release-${LIBICU_DASH_VERSION} CACHE STRING "libicu download mirror(s)")
4+
set(LIBICU_SOURCE icu4c-${LIBICU_VERSION}-src.tgz)
5+
set(LIBICU_HASH SHA512=e6c7876c0f3d756f3a6969cad9a8909e535eeaac352f3a721338b9cbd56864bf7414469d29ec843462997815d2ca9d0dab06d38c37cdd4d8feb28ad04d8781b0 CACHE STRING "libicu source hash")
6+
7+
include(ExternalProject)
8+
set(DEPS_DESTDIR ${CMAKE_BINARY_DIR}/static-deps)
9+
set(DEPS_SOURCEDIR ${CMAKE_BINARY_DIR}/static-deps-sources)
10+
set(DEPS_CMAKE_MODS ${DEPS_DESTDIR}/cmake-static-modules)
11+
file(MAKE_DIRECTORY ${DEPS_CMAKE_MODS})
12+
list(INSERT CMAKE_MODULE_PATH 0 ${DEPS_CMAKE_MODS})
13+
14+
include_directories(BEFORE SYSTEM ${DEPS_DESTDIR}/include)
15+
16+
file(MAKE_DIRECTORY ${DEPS_DESTDIR}/include)
17+
18+
function(expand_urls output source_file)
19+
set(expanded)
20+
foreach(mirror ${ARGN})
21+
list(APPEND expanded "${mirror}/${source_file}")
22+
endforeach()
23+
set(${output} "${expanded}" PARENT_SCOPE)
24+
endfunction()
25+
26+
function(add_static_target target ext_target libname)
27+
add_library(${target} STATIC IMPORTED GLOBAL)
28+
add_dependencies(${target} ${ext_target})
29+
target_link_libraries(libquic_static_deps INTERFACE ${target})
30+
set_target_properties(${target} PROPERTIES
31+
IMPORTED_LOCATION ${DEPS_DESTDIR}/lib/${libname}
32+
)
33+
if(ARGN)
34+
target_link_libraries(${target} INTERFACE ${ARGN})
35+
endif()
36+
endfunction()
37+
38+
set(libicu_cflags "${libicu_cflags} -O2")
39+
set(libicu_cxxflags "${libicu_cxxflags} -O2")
40+
set(cross_host "")
41+
if(CMAKE_CROSSCOMPILING)
42+
if(APPLE AND NOT ARCH_TRIPLET AND APPLE_TARGET_TRIPLE)
43+
set(ARCH_TRIPLET "${APPLE_TARGET_TRIPLE}")
44+
endif()
45+
set(cross_host "--host=${ARCH_TRIPLET}")
46+
endif()
47+
48+
set(deps_cc ${CMAKE_C_COMPILER})
49+
set(deps_cxx ${CMAKE_CXX_COMPILER})
50+
if(ANDROID)
51+
set(android_toolchain_suffix linux-android)
52+
set(android_compiler_suffix linux-android${ANDROID_PLATFORM_LEVEL})
53+
if(CMAKE_ANDROID_ARCH_ABI MATCHES x86_64)
54+
set(cross_host "--host=x86_64-linux-android")
55+
set(android_compiler_prefix x86_64)
56+
set(android_compiler_suffix linux-android${ANDROID_PLATFORM_LEVEL})
57+
set(android_toolchain_prefix x86_64)
58+
set(android_toolchain_suffix linux-android)
59+
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES x86)
60+
set(cross_host "--host=i686-linux-android")
61+
set(android_compiler_prefix i686)
62+
set(android_compiler_suffix linux-android${ANDROID_PLATFORM_LEVEL})
63+
set(android_toolchain_prefix i686)
64+
set(android_toolchain_suffix linux-android)
65+
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES armeabi-v7a)
66+
set(cross_host "--host=armv7a-linux-androideabi")
67+
set(android_compiler_prefix armv7a)
68+
set(android_compiler_suffix linux-androideabi${ANDROID_PLATFORM_LEVEL})
69+
set(android_toolchain_prefix arm)
70+
set(android_toolchain_suffix linux-androideabi)
71+
elseif(CMAKE_ANDROID_ARCH_ABI MATCHES arm64-v8a)
72+
set(cross_host "--host=aarch64-linux-android")
73+
set(android_compiler_prefix aarch64)
74+
set(android_compiler_suffix linux-android${ANDROID_PLATFORM_LEVEL})
75+
set(android_toolchain_prefix aarch64)
76+
set(android_toolchain_suffix linux-android)
77+
else()
78+
message(FATAL_ERROR "unknown android arch: ${CMAKE_ANDROID_ARCH_ABI}")
79+
endif()
80+
set(deps_cc "${ANDROID_TOOLCHAIN_ROOT}/bin/${android_compiler_prefix}-${android_compiler_suffix}-clang")
81+
set(deps_cxx "${ANDROID_TOOLCHAIN_ROOT}/bin/${android_compiler_prefix}-${android_compiler_suffix}-clang++")
82+
endif()
83+
84+
if(CMAKE_C_COMPILER_LAUNCHER)
85+
set(deps_c "${CMAKE_C_COMPILER_LAUNCHER} ${deps_cc}")
86+
endif()
87+
88+
if(CMAKE_CXX_COMPILER_LAUNCHER)
89+
set(deps_cxx "${CMAKE_CXX_COMPILER_LAUNCHER} ${deps_cxx}")
90+
endif()
91+
92+
set(apple_cflags_arch)
93+
set(apple_cxxflags_arch)
94+
set(apple_ldflags_arch)
95+
if(APPLE AND CMAKE_CROSSCOMPILING)
96+
if(cross_host MATCHES "^(.*-.*-)ios([0-9.]+)(-.*)?$")
97+
set(cross_host "${CMAKE_MATCH_1}darwin${CMAKE_MATCH_2}${CMAKE_MATCH_3}")
98+
endif()
99+
if(cross_host MATCHES "^(.*-.*-.*)-simulator$")
100+
set(cross_host "${CMAKE_MATCH_1}")
101+
endif()
102+
103+
set(apple_arch)
104+
if(ARCH_TRIPLET MATCHES "^(arm|aarch)64.*")
105+
set(apple_arch "arm64")
106+
elseif(ARCH_TRIPLET MATCHES "^x86_64.*")
107+
set(apple_arch "x86_64")
108+
else()
109+
message(FATAL_ERROR "Don't know how to specify -arch for GMP for ${ARCH_TRIPLET} (${APPLE_TARGET_TRIPLE})")
110+
endif()
111+
112+
set(apple_cxxflags_arch " -arch ${apple_arch}")
113+
if(CMAKE_OSX_DEPLOYMENT_TARGET)
114+
if (SDK_NAME)
115+
set(apple_ldflags_arch " -m${SDK_NAME}-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
116+
elseif(CMAKE_OSX_DEPLOYMENT_TARGET)
117+
set(apple_ldflags_arch " -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
118+
endif()
119+
endif()
120+
set(apple_ldflags_arch "${apple_ldflags_arch} -arch ${apple_arch}")
121+
122+
if(CMAKE_OSX_SYSROOT)
123+
foreach(f c cxx ld)
124+
set(apple_${f}flags_arch "${apple_${f}flags_arch} -isysroot ${CMAKE_OSX_SYSROOT}")
125+
endforeach()
126+
endif()
127+
elseif(cross_host STREQUAL "" AND CMAKE_LIBRARY_ARCHITECTURE)
128+
set(cross_host "--build=${CMAKE_LIBRARY_ARCHITECTURE}")
129+
endif()
130+
131+
# Builds a target; takes the target name (e.g. "readline") and builds it in an external project with
132+
# target name suffixed with `_external`. Its upper-case value is used to get the download details
133+
# (from the variables set above). The following options are supported and passed through to
134+
# ExternalProject_Add if specified. If omitted, these defaults are used:
135+
set(build_def_DEPENDS "")
136+
set(build_def_PATCH_COMMAND "")
137+
set(build_def_CONFIGURE_COMMAND ./configure ${cross_host} --disable-shared --prefix=${DEPS_DESTDIR} --with-pic
138+
"CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" ${cross_extra})
139+
set(build_def_BUILD_COMMAND make)
140+
set(build_def_INSTALL_COMMAND make install)
141+
set(build_def_BUILD_BYPRODUCTS ${DEPS_DESTDIR}/lib/lib___TARGET___.a ${DEPS_DESTDIR}/include/___TARGET___.h)
142+
set(build_dep_TARGET_SUFFIX "")
143+
144+
function(build_external target)
145+
set(options TARGET_SUFFIX DEPENDS PATCH_COMMAND CONFIGURE_COMMAND BUILD_COMMAND INSTALL_COMMAND BUILD_BYPRODUCTS)
146+
cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "${options}")
147+
foreach(o ${options})
148+
if(NOT DEFINED arg_${o})
149+
set(arg_${o} ${build_def_${o}})
150+
endif()
151+
endforeach()
152+
string(REPLACE ___TARGET___ ${target} arg_BUILD_BYPRODUCTS "${arg_BUILD_BYPRODUCTS}")
153+
154+
set(externalproject_extra)
155+
if(NOT CMAKE_VERSION VERSION_LESS 3.24)
156+
# Default in cmake 3.24+ is to not extract timestamps for ExternalProject, which breaks pretty
157+
# much every autotools package (which thinks it must reconfigure) because timestamps got
158+
# updated).
159+
list(APPEND externalproject_extra DOWNLOAD_EXTRACT_TIMESTAMP ON)
160+
endif()
161+
162+
string(TOUPPER "${target}" prefix)
163+
expand_urls(urls ${${prefix}_SOURCE} ${${prefix}_MIRROR})
164+
ExternalProject_Add("${target}${arg_TARGET_SUFFIX}_external"
165+
DEPENDS ${arg_DEPENDS}
166+
BUILD_IN_SOURCE ON
167+
PREFIX ${DEPS_SOURCEDIR}
168+
URL ${urls}
169+
URL_HASH ${${prefix}_HASH}
170+
DOWNLOAD_NO_PROGRESS ON
171+
PATCH_COMMAND ${arg_PATCH_COMMAND}
172+
CONFIGURE_COMMAND ${arg_CONFIGURE_COMMAND}
173+
BUILD_COMMAND ${arg_BUILD_COMMAND}
174+
INSTALL_COMMAND ${arg_INSTALL_COMMAND}
175+
BUILD_BYPRODUCTS ${arg_BUILD_BYPRODUCTS}
176+
${externalproject_extra}
177+
)
178+
endfunction()
179+
180+
if(CMAKE_CROSSCOMPILING)
181+
if(ARCH_TRIPLET STREQUAL x86_64-w64-mingw32)
182+
set(cross_host mingw64)
183+
set(openssl_extra_env RC=${CMAKE_RC_COMPILER})
184+
elseif(ARCH_TRIPLET STREQUAL i686-w64-mingw32)
185+
set(cross_host mingw)
186+
set(openssl_extra_env RC=${CMAKE_RC_COMPILER})
187+
elseif(ANDROID)
188+
set(openssl_extra_opts -D__ANDROID_API__=${ANDROID_PLATFORM_LEVEL} no-asm)
189+
set(openssl_extra_env "ANDROID_NDK_ROOT=${CMAKE_ANDROID_NDK}" "PATH=${ANDROID_TOOLCHAIN_ROOT}/bin:$ENV{PATH}")
190+
set(deps_CFLAGS "${deps_CFLAGS} --sysroot=${ANDROID_TOOLCHAIN_ROOT}/sysroot")
191+
if(CMAKE_ANDROID_ARCH_ABI MATCHES x86_64 OR CMAKE_ANDROID_ARCH_ABI MATCHES x86)
192+
# NOTE: Sysroot isn't sufficient to find the asm/ folder sitting in the host-tagged folder
193+
# /usr/lib/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/linux/types.h:9:10: fatal error: 'asm/types.h' file not found
194+
# At
195+
# /usr/lib/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android/asm/
196+
if(CMAKE_ANDROID_ARCH_ABI MATCHES x86_64)
197+
set(deps_CFLAGS "${deps_CFLAGS} -I${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/include/x86_64-linux-android")
198+
else()
199+
set(deps_CFLAGS "${deps_CFLAGS} -I${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/include/i686-linux-android")
200+
endif()
201+
endif()
202+
endif()
203+
endif()
204+
205+
build_external(libicu
206+
LOG_CONFIGURE ON
207+
LOG_BUILD ON
208+
LOG_OUTPUT_ON_FAILURE ON
209+
CONFIGURE_COMMAND
210+
./source/configure ${cross_host} --enable-static
211+
--disable-shared --disable-icu-config --disable-strict --disable-dyload --disable-icuio
212+
--disable-tests --disable-samples --with-data-packaging=static
213+
--prefix=${DEPS_DESTDIR} CC=${deps_cc} CXX=${deps_cxx}
214+
C_FLAGS=${apple_cflags_arch}${libicu_cflags}
215+
CXXFLAGS=${apple_cxxflags_arch}${libicu_cxxflags}
216+
BUILD_BYPRODUCTS
217+
${DEPS_DESTDIR}/lib/libicudata.a
218+
${DEPS_DESTDIR}/lib/libicui18n.a
219+
${DEPS_DESTDIR}/lib/libicutest.a
220+
${DEPS_DESTDIR}/lib/libicutu.a
221+
${DEPS_DESTDIR}/lib/libicuuc.a
222+
)
223+
add_static_target(libicu::libicudata libicu_external libicudata.a)
224+
add_static_target(libicu::libicui18n libicu_external libicui18n.a)
225+
add_static_target(libicu::libicutest libicu_external libicutest.a)
226+
add_static_target(libicu::libicutu libicu_external libicutu.a)
227+
add_static_target(libicu::libicuuc libicu_external libicuuc.a)
228+
229+
add_library(libicu::libicu INTERFACE IMPORTED GLOBAL)
230+
add_dependencies(libicu::libicu libicu_external)
231+
set_target_properties(libicu::libicu PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${DEPS_DESTDIR}/include)
232+
target_link_libraries(libicu::libicu INTERFACE libicu::libicui18n libicu::libicuuc libicu::libicudata)

external/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ simdutf_subdir()
149149
libsession_static_bundle(simdutf)
150150

151151
if(ENABLE_DATABASE)
152+
function(do_static_deps)
153+
include(../cmake/StaticBuild.cmake)
154+
endfunction()
155+
156+
do_static_deps()
152157
libsession_system_or_submodule(OPENSSL openssl openssl>=3.5.4 openssl-cmake)
153158
libsession_system_or_submodule(SQLCIPHER sqlcipher sqlcipher>=4.12.0 sqlcipher-cmake)
154159
endif()

external/sqlcipher-cmake/CMakeLists.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ file(MAKE_DIRECTORY ${SQLCIPHER_INCLUDEDIR})
1010

1111
# NOTE: Detect if openssl is being built locally for libsession, if so this build step depends on
1212
# that first before proceeding
13-
set(sqlcipher_depends)
14-
if (NOT APPLE AND TARGET openssl_external)
15-
set(sqlcipher_depends openssl_external)
13+
set(sqlcipher_depends libicu_external)
14+
if (TARGET openssl_external)
15+
set(sqlcipher_depends ${sqlcipher_depends} openssl_external)
1616
endif()
1717

1818
set(sqlcipher_cflags "${sqlcipher_cflags} -O2")
@@ -113,8 +113,8 @@ elseif(cross_host STREQUAL "" AND CMAKE_LIBRARY_ARCHITECTURE)
113113
set(cross_host "--build=${CMAKE_LIBRARY_ARCHITECTURE}")
114114
endif()
115115

116-
set(sqlcipher_ldflags "")
117-
set(sqlcipher_cflags "${sqlcipher_cflags} -DSQLITE_HAS_CODEC -DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown")
116+
set(sqlcipher_ldflags "-L${LIBICU_LIBDIR} -licudata")
117+
set(sqlcipher_cflags "${sqlcipher_cflags} -DSQLITE_HAS_CODEC -DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown -DSQLITE_ENABLE_ICU")
118118

119119
if(APPLE)
120120
set(sqlcipher_cflags "${sqlcipher_cflags} -DSQLCIPHER_CRYPTO_CC")
@@ -147,6 +147,7 @@ set_target_properties(sqlcipher::sqlcipher PROPERTIES
147147
INTERFACE_INCLUDE_DIRECTORIES ${SQLCIPHER_INCLUDEDIR}
148148
)
149149
target_compile_definitions(sqlcipher::sqlcipher INTERFACE SQLITE_HAS_CODEC)
150+
target_link_libraries(sqlcipher::sqlcipher INTERFACE libicu::libicu)
150151
if(APPLE)
151152
target_link_libraries(sqlcipher::sqlcipher INTERFACE "-framework Security" "-framework Foundation" "-framework CoreFoundation")
152153
else()

0 commit comments

Comments
 (0)