diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac2005ba..d22989fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,22 +14,28 @@ jobs: NDK_VERSION: "28.0.13004108" CMAKE_VERSION: "3.31.6" ANDROID_PLATFORM: "23" + RUST_VERSION: "1.92.0" steps: - name: Install build dependencies # android-actions/setup-android needs unzip # sdkmanager needs jre + # libime needs boost (build host tools) + # opencc needs python (scripts) + # libchewing needs rustup (build) + # libiconv needs gperf (build) run: | pacman -Syu --needed --noconfirm \ git unzip jre-openjdk \ ghc cabal-install haskell-shake haskell-aeson-pretty \ cmake extra-cmake-modules ninja \ - fmt boost \ - python opencc \ + boost \ + python \ + rustup \ gperf - name: Fetch source code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: # this only sync submodules specified in .gitmodules, # because we don't want recursive submodules in glog, librime, etc. @@ -41,6 +47,8 @@ jobs: git config --global --add safe.directory '*' # fetch libime submodule kenlm since it's not in .gitmodules git submodule update --init --recursive libime + # fetch libchewing-data submodule + git submodule update --init --recursive libchewing - name: Setup Android NDK uses: android-actions/setup-android@v3 @@ -50,6 +58,7 @@ jobs: - name: Build everything env: ANDROID_NDK_ROOT: ${{ env.ANDROID_HOME }}/ndk/${{ env.NDK_VERSION }} + RUST_VERSION: ${{ env.RUST_VERSION }} run: | # use archlinux's dynamic only ghc cabal configure --disable-library-vanilla --enable-shared --enable-executable-dynamic --ghc-options=-dynamic @@ -68,13 +77,14 @@ jobs: - name: Upload prebuilt to artifact if: github.event_name == 'pull_request' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: path: build/prebuilt.tar.zst + compression-level: 0 - name: Fetch fcitx5-android/prebuilt if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: path: prebuilt repository: fcitx5-android/prebuilt diff --git a/.gitmodules b/.gitmodules index 48ce823e..a8f29950 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,7 +27,7 @@ fetchRecurseSubmodules = false [submodule "marisa-trie"] path = marisa-trie - url = https://github.com/rime/marisa-trie + url = https://github.com/s-yata/marisa-trie [submodule "librime"] path = librime url = https://github.com/rime/librime diff --git a/Lua b/Lua index 3ed55a56..504ef66d 160000 --- a/Lua +++ b/Lua @@ -1 +1 @@ -Subproject commit 3ed55a56eaa05c9221f40b3c07d0e908eb1067b0 +Subproject commit 504ef66d500fa1fb4f1684b6617b01342eee704a diff --git a/OpenCC b/OpenCC index 556ed224..907bfcbb 160000 --- a/OpenCC +++ b/OpenCC @@ -1 +1 @@ -Subproject commit 556ed22496d650bd0b13b6c163be9814637970ae +Subproject commit 907bfcbbd3aae86ff04bc8eaca67c8af03108ddf diff --git a/README.md b/README.md index ec24784e..59eaa9a8 100644 --- a/README.md +++ b/README.md @@ -25,18 +25,21 @@ both can be installed with `sdkmanager` command line tool. ## Libraries -* boost: [moritz-wundke/Boost-for-Android](https://github.com/moritz-wundke/Boost-for-Android) -* libevent: [libevent/libevent](https://github.com/libevent/libevent/tree/release-2.1.12-stable) +* boost ([cmake build](https://github.com/boostorg/cmake)): [boostorg/boost](https://github.com/boostorg/boost) +* libuv: [libuv/libuv](https://github.com/libuv/libuv) * libintl-lite: [j-jorge/libintl-lite](https://github.com/j-jorge/libintl-lite) +* fmt: [fmtlib/fmt](https://github.com/fmtlib/fmt) +* fcitx5: [fcitx/fcitx5](https://github.com/fcitx/fcitx5) +* zstd: [facebook/zstd](https://github.com/facebook/zstd) * libime data: [fcitx/libime](https://github.com/fcitx/libime) -* lua: [walterschell/LuaCMake](https://github.com/walterschell/Lua) +* libime-jyutping data: [fcitx/libime-jyutping](https://github.com/fcitx/libime-jyutping) +* lua (cmake build): [walterschell/Lua](https://github.com/walterschell/Lua) * opencc: [BYVoid/OpenCC](https://github.com/BYVoid/OpenCC) -* spell-dict data: [fcitx/fcitx5](https://github.com/fcitx/fcitx5/blob/master/src/modules/spell/dict) -* anthy dict: [fujiwarat/anthy-unicode](https://github.com/fujiwarat/anthy-unicode) +* anthy-unicode: [fujiwarat/anthy-unicode](https://github.com/fujiwarat/anthy-unicode) * glog: [google/glog](https://github.com/google/glog) * yaml-cpp: [jbeder/yaml-cpp](https://github.com/jbeder/yaml-cpp) * leveldb: [google/leveldb](https://github.com/google/leveldb) -* marisa-trie: [rime/marisa-trie](https://github.com/rime/marisa-trie) +* marisa-trie: [s-yata/marisa-trie](https://github.com/s-yata/marisa-trie) * librime: [rime/librime](https://github.com/rime/librime) * librime-lua: [rime/librime-lua](https://github.com/hchunhui/librime-lua) * librime-octagram: [rime/librime-octagram](https://github.com/lotem/librime-octagram) diff --git a/anthy-unicode b/anthy-unicode index e63d1d67..924994ee 160000 --- a/anthy-unicode +++ b/anthy-unicode @@ -1 +1 @@ -Subproject commit e63d1d67caa95886076ac1f6033469e03b36c990 +Subproject commit 924994eebf13d87022ddcf07eac485f784c4e17d diff --git a/build.cfg b/build.cfg index e712285a..7186514a 100644 --- a/build.cfg +++ b/build.cfg @@ -32,8 +32,8 @@ py_table_sha256 = 42146ac97de6c13d55f9e99ed873915f4c66739e9c11532a34556badf9792c ## https://github.com/boostorg/boost/releases boost--cmake.tar.xz # boost -boost_version = 1.87.0 -boost_sha256 = 7da75f171837577a52bbf217e17f8ea576c7c246e4594d617bfde7fafd408be5 +boost_version = 1.90.0 +boost_sha256 = aca59f889f0f32028ad88ba6764582b63c916ce5f77b31289ad19421a96c555f ## https://github.com/fcitx/libime-jyutping/blob/master/data/CMakeLists.txt # jyutping dict diff --git a/fcitx5 b/fcitx5 index 7d716276..d3f45a07 160000 --- a/fcitx5 +++ b/fcitx5 @@ -1 +1 @@ -Subproject commit 7d71627695b49c06a4270f4d8106e84afb75cddb +Subproject commit d3f45a07335d4cdf7728ad02766e59d45f32f8a8 diff --git a/libchewing b/libchewing index 9be48513..a6a8fa4a 160000 --- a/libchewing +++ b/libchewing @@ -1 +1 @@ -Subproject commit 9be48513bc46bafa134eef4b2bfde6a533470d33 +Subproject commit a6a8fa4abd3f215e3ba89a7b61702eaf8ca68f5c diff --git a/libhangul b/libhangul index 154a5e0f..41c702f5 160000 --- a/libhangul +++ b/libhangul @@ -1 +1 @@ -Subproject commit 154a5e0f13aebc80a465336642a406d6ddfc06cf +Subproject commit 41c702f5d3581325b646ef6249f1f641b0427ae0 diff --git a/libime b/libime index c0e12b89..aa3ed007 160000 --- a/libime +++ b/libime @@ -1 +1 @@ -Subproject commit c0e12b8926f10d3d20bbb0d2e36648b67102ab89 +Subproject commit aa3ed0070f878b7d912ba2e8c6478b87ab5d960d diff --git a/libime-jyutping b/libime-jyutping index 7ad0e426..af6ac381 160000 --- a/libime-jyutping +++ b/libime-jyutping @@ -1 +1 @@ -Subproject commit 7ad0e426f9af2105033bd1afe52c0cb3057b127e +Subproject commit af6ac38153345718c182cc5e27e5a1c2662a6f16 diff --git a/libintl-lite b/libintl-lite index ba151460..edbb3064 160000 --- a/libintl-lite +++ b/libintl-lite @@ -1 +1 @@ -Subproject commit ba1514607d02ce3711d828e784a7e9e2bb25aa84 +Subproject commit edbb3064b2ee7ed42ffc5a4b9e0b8c3616d54cbf diff --git a/librime b/librime index 1c233581..de4700e9 160000 --- a/librime +++ b/librime @@ -1 +1 @@ -Subproject commit 1c23358157934bd6e6d6981f0c0164f05393b497 +Subproject commit de4700e9f6b75b109910613df907965e3cbe0567 diff --git a/librime-lua b/librime-lua index e3912a4b..68f9c364 160000 --- a/librime-lua +++ b/librime-lua @@ -1 +1 @@ -Subproject commit e3912a4b3ac2c202d89face3fef3d41eb1d7fcd6 +Subproject commit 68f9c364a2d25a04c7d4794981d7c796b05ab627 diff --git a/libthai b/libthai index 618e442c..e10e6af5 160000 --- a/libthai +++ b/libthai @@ -1 +1 @@ -Subproject commit 618e442c340cff089f29743d35392a6aba21a9fb +Subproject commit e10e6af55634a993e60e80521ab03b1947044f38 diff --git a/libuv b/libuv index 8fb9cb91..b556c062 160000 --- a/libuv +++ b/libuv @@ -1 +1 @@ -Subproject commit 8fb9cb919489a48880680a56efecff6a7dfb4504 +Subproject commit b556c0629d0fd250b5feefbc91b84c6f5e3dae48 diff --git a/marisa-trie b/marisa-trie index 773766d6..3e87d53b 160000 --- a/marisa-trie +++ b/marisa-trie @@ -1 +1 @@ -Subproject commit 773766d670a16ee2166f1087f8b67fa0235ea8d1 +Subproject commit 3e87d53b78e15f2f43783d5e376561a8c9722051 diff --git a/patches/libchewing.patch b/patches/libchewing.patch index cb719ae0..ca23a90d 100644 --- a/patches/libchewing.patch +++ b/patches/libchewing.patch @@ -1,50 +1,85 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index ae1d14b7..5d03df35 100644 +index 59e012d8..48dca4c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -1,2 +1,2 @@ --cmake_minimum_required(VERSION 3.24.0) -+cmake_minimum_required(VERSION 3.22.1) - project(libchewing LANGUAGES C) -@@ -216,8 +216,6 @@ if(WITH_RUST) - list(APPEND ALL_INC ${INC_DIR}/chewing_rs.h) - endif() - --add_subdirectory(doc) --add_subdirectory(data) +@@ -77,7 +77,7 @@ corrosion_import_crate(MANIFEST_PATH Cargo.toml CRATES chewing_capi) if(BUILD_TESTING) - add_subdirectory(tests) + corrosion_import_crate(MANIFEST_PATH Cargo.toml CRATES chewing_testhelper) endif() -@@ -228,14 +226,20 @@ add_library(common OBJECT +-corrosion_import_crate(MANIFEST_PATH Cargo.toml CRATES chewing-cli) ++corrosion_add_target_rustflags(chewing_capi "--remap-path-prefix=${PROJECT_SOURCE_DIR}=.") - src/porting_layer/src/asprintf.c - ) -+target_compile_options(common PRIVATE -+ "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=." -+) - target_compile_definitions(common PRIVATE -- CHEWING_DATADIR=\"${CMAKE_INSTALL_FULL_DATADIR}/libchewing\" -+ CHEWING_DATADIR=\"./libchewing\" + if(WITH_SQLITE3) + corrosion_set_features(chewing_capi FEATURES sqlite) +@@ -191,7 +191,7 @@ target_include_directories(libchewing ) - add_library(libchewing ${ALL_INC} src/chewing.c) - set_target_properties(libchewing PROPERTIES LINKER_LANGUAGE C) -+target_compile_options(libchewing PRIVATE -+ "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=." -+) - target_compile_definitions(libchewing PRIVATE -- CHEWING_DATADIR=\"${CMAKE_INSTALL_FULL_DATADIR}/libchewing\" -+ CHEWING_DATADIR=\"./libchewing\" + corrosion_set_env_vars(chewing_capi +- CHEWING_DATADIR=${CMAKE_INSTALL_FULL_DATADIR}/libchewing ++ CHEWING_DATADIR="./libchewing" ) - if(NOT WITH_RUST) - target_sources(common PRIVATE -@@ -288,6 +292,9 @@ if(NOT WITH_RUST) - ${SRC_DIR}/userphrase-hash.c - ) - endif() -+ target_compile_options(userphrase PRIVATE -+ "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=." -+ ) - target_link_libraries(libchewing - PRIVATE common - PRIVATE userphrase) + target_link_libraries(libchewing PRIVATE chewing_capi) + target_link_libraries(chewing_capi INTERFACE ${SQLite3_LIBRARIES}) +@@ -239,15 +239,17 @@ else() + ) + endif() + +-install(FILES ${ALL_INC} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/chewing) ++install(FILES ${ALL_INC} DESTINATION include/chewing) + install(FILES ${PROJECT_BINARY_DIR}/chewing.pc +- DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +-install(TARGETS libchewing ++ DESTINATION lib/pkgconfig) ++install(TARGETS chewing_capi + EXPORT libchewingTargets +- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +- INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) ++ ARCHIVE DESTINATION lib ++ INCLUDES DESTINATION include ++ LIBRARY DESTINATION lib ++ RUNTIME DESTINATION bin) ++install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libchewing_capi.a ++ DESTINATION lib) + + if(BUILD_DATA) + install( +@@ -261,7 +263,6 @@ if(BUILD_DATA) + ) + endif() + +-install(IMPORTED_RUNTIME_ARTIFACTS chewing-cli DESTINATION ${CMAKE_INSTALL_BINDIR}) + + # generate CMake Config files + include(CMakePackageConfigHelpers) +diff --git a/Cargo.toml b/Cargo.toml +index d546d772..448f6b1d 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -41,10 +41,10 @@ tempfile = "3.10.1" + + [profile.release] + lto = true +-opt-level = 3 ++opt-level = "s" + panic = "abort" + codegen-units = 1 +-debug = true ++debug = false + + [package.metadata.docs.rs] + features = ["sqlite"] +diff --git a/capi/Cargo.toml b/capi/Cargo.toml +index 517dd9e2..12fefb9e 100644 +--- a/capi/Cargo.toml ++++ b/capi/Cargo.toml +@@ -7,7 +7,7 @@ rust-version = "1.88" + edition = "2024" + + [lib] +-crate-type = ["rlib", "staticlib"] ++crate-type = ["staticlib"] + + [dependencies] + chewing = { version = "0.11.0", path = ".." } diff --git a/patches/libhangul.patch b/patches/libhangul.patch index 37945e0b..604a69b7 100644 --- a/patches/libhangul.patch +++ b/patches/libhangul.patch @@ -1,17 +1,17 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8aafe38..edc76dd 100644 +index afac588..7d11d94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -50,7 +50,6 @@ set(LIBHANGUL_LIBRARY_DIR "${CMAKE_INSTALL_LIBDIR}") - add_subdirectory(hangul) - add_subdirectory(data/hanja) +@@ -52,7 +52,6 @@ add_subdirectory(data/hanja) + if(ENABLE_EXTERNAL_KEYBOARDS) add_subdirectory(data/keyboards) + endif() -add_subdirectory(tools) add_subdirectory(po) if(BUILD_TESTING) diff --git a/hangul/CMakeLists.txt b/hangul/CMakeLists.txt -index 14fde95..399beb6 100644 +index cfda59b..d3a82b9 100644 --- a/hangul/CMakeLists.txt +++ b/hangul/CMakeLists.txt @@ -45,9 +45,9 @@ add_library(hangul diff --git a/patches/librime.patch b/patches/librime.patch index e5e70afb..99fa0858 100644 --- a/patches/librime.patch +++ b/patches/librime.patch @@ -1,14 +1,5 @@ -From 15a8b479e66ac597a0fca4bede8012f5bb9df151 Mon Sep 17 00:00:00 2001 -From: Rocka -Date: Tue, 12 Nov 2024 22:16:16 +0800 -Subject: [PATCH 1/2] set file-prefix-map to relative path - ---- - src/CMakeLists.txt | 2 ++ - 1 file changed, 2 insertions(+) - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 16082869..c4a5b5ca 100644 +index 8faa61f8..671622ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,6 +166,8 @@ if(BUILD_SHARED_LIBS) @@ -20,24 +11,8 @@ index 16082869..c4a5b5ca 100644 set_target_properties(rime-static PROPERTIES OUTPUT_NAME "rime" PREFIX "lib" ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) --- -2.47.0 - - -From 25608d1ea7a246b3ac4e7ccc02b1b6dfbb468869 Mon Sep 17 00:00:00 2001 -From: Rocka -Date: Tue, 12 Nov 2024 22:20:33 +0800 -Subject: [PATCH 2/2] Persist options to user.yaml in RimeSetOption - ---- - src/rime/engine.cc | 1 - - src/rime/engine.h | 2 ++ - src/rime/service.h | 8 ++++---- - src/rime_api_impl.h | 9 +++++++++ - 4 files changed, 15 insertions(+), 5 deletions(-) - diff --git a/src/rime/engine.cc b/src/rime/engine.cc -index 07aa6b7d..7360e0b5 100644 +index 4a54f64c..2efe0c93 100644 --- a/src/rime/engine.cc +++ b/src/rime/engine.cc @@ -52,7 +52,6 @@ class ConcreteEngine : public Engine { @@ -49,7 +24,7 @@ index 07aa6b7d..7360e0b5 100644 // implementations diff --git a/src/rime/engine.h b/src/rime/engine.h -index 2e1c8b81..94a6b500 100644 +index 6b51a68e..c5b8f7e4 100644 --- a/src/rime/engine.h +++ b/src/rime/engine.h @@ -16,6 +16,7 @@ namespace rime { @@ -68,8 +43,30 @@ index 2e1c8b81..94a6b500 100644 protected: Engine(); +diff --git a/src/rime/lever/deployment_tasks.cc b/src/rime/lever/deployment_tasks.cc +index 6e6ff895..fe111d55 100644 +--- a/src/rime/lever/deployment_tasks.cc ++++ b/src/rime/lever/deployment_tasks.cc +@@ -429,17 +429,6 @@ static bool ConfigNeedsUpdate(Config* config) { + } + + bool ConfigFileUpdate::Run(Deployer* deployer) { +- const path shared_data_path(deployer->shared_data_dir); +- const path user_data_path(deployer->user_data_dir); +- // trash deprecated user copy created by an older version of Rime +- path source_config_path(shared_data_path / file_name_); +- path dest_config_path(user_data_path / file_name_); +- path trash = user_data_path / "trash"; +- if (TrashDeprecatedUserCopy(source_config_path, dest_config_path, +- version_key_, trash)) { +- LOG(WARNING) << "deprecated user copy of '" << file_name_ +- << "' is moved to " << trash; +- } + // build the config file if needs update + the config(Config::Require("config")->Create(file_name_)); + if (ConfigNeedsUpdate(config.get())) { diff --git a/src/rime/service.h b/src/rime/service.h -index 2b3111af..95ca87dc 100644 +index a69ae741..9b3d4b16 100644 --- a/src/rime/service.h +++ b/src/rime/service.h @@ -44,11 +44,11 @@ class Session { @@ -89,7 +86,7 @@ index 2b3111af..95ca87dc 100644 string commit_text_; }; diff --git a/src/rime_api_impl.h b/src/rime_api_impl.h -index 7749ce98..b0200a67 100644 +index 30f4514f..c17d4794 100644 --- a/src/rime_api_impl.h +++ b/src/rime_api_impl.h @@ -17,6 +17,8 @@ @@ -101,7 +98,7 @@ index 7749ce98..b0200a67 100644 using namespace rime; -@@ -426,6 +428,13 @@ RIME_DEPRECATED void RimeSetOption(RimeSessionId session_id, +@@ -430,6 +432,13 @@ RIME_DEPRECATED void RimeSetOption(RimeSessionId session_id, if (!ctx) return; ctx->set_option(option, !!value); @@ -115,6 +112,3 @@ index 7749ce98..b0200a67 100644 } RIME_DEPRECATED Bool RimeGetOption(RimeSessionId session_id, --- -2.47.0 - diff --git a/patches/libuv.patch b/patches/libuv.patch index 2548c4f8..4e84bdfe 100644 --- a/patches/libuv.patch +++ b/patches/libuv.patch @@ -1,845 +1,110 @@ -From 0b34eef8cec4571aa9c92288ecfc544fbcb74463 Mon Sep 17 00:00:00 2001 +From 6abcdf44e338898e492f1d0a583534a32d7e3701 Mon Sep 17 00:00:00 2001 From: Rocka -Date: Tue, 12 Nov 2024 23:01:06 +0800 -Subject: [PATCH] android: revive support for api level 21 +Date: Sun, 25 Jan 2026 01:36:10 +0800 +Subject: [PATCH] android: disable ifaddrs stuff and fix build for sdk < 24 -reverts c8cbdbd and rebased to v1.49.2 --- - CMakeLists.txt | 4 + - Makefile.am | 2 + - include/uv/android-ifaddrs.h | 54 +++ - src/unix/android-ifaddrs.c | 713 +++++++++++++++++++++++++++++++++++ - src/unix/linux.c | 6 +- - 5 files changed, 778 insertions(+), 1 deletion(-) - create mode 100644 include/uv/android-ifaddrs.h - create mode 100644 src/unix/android-ifaddrs.c + include/uv/unix.h | 5 +++++ + src/unix/linux.c | 14 ++++++++++++++ + src/unix/tcp.c | 4 ++-- + 3 files changed, 21 insertions(+), 2 deletions(-) -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 28c6df256..3ec932e54 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -277,6 +277,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") - src/unix/random-getentropy.c - src/unix/random-getrandom.c - src/unix/random-sysctl-linux.c) -+ list(APPEND uv_defines LLONG_MAX=0x7fffffffffffffffLL) -+ if(ANDROID_PLATFORM_LEVEL LESS 24) -+ list(APPEND uv_sources -+ src/unix/android-ifaddrs.c) -+ endif() - endif() +diff --git a/include/uv/unix.h b/include/uv/unix.h +index 7c972026f..0ed1b512c 100644 +--- a/include/uv/unix.h ++++ b/include/uv/unix.h +@@ -137,6 +137,11 @@ typedef UV_PLATFORM_SEM_T uv_sem_t; + typedef pthread_cond_t uv_cond_t; + typedef pthread_key_t uv_key_t; - if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux") -diff --git a/Makefile.am b/Makefile.am -index f85a41316..31d4d040b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -406,7 +406,9 @@ libuv_la_SOURCES += src/unix/aix-common.c \ - endif - - if ANDROID -+uvinclude_HEADERS += include/uv/android-ifaddrs.h - libuv_la_CFLAGS += -D_GNU_SOURCE -+libuv_la_SOURCES += src/unix/android-ifaddrs.c - endif - - if CYGWIN -diff --git a/include/uv/android-ifaddrs.h b/include/uv/android-ifaddrs.h -new file mode 100644 -index 000000000..9cd19fec1 ---- /dev/null -+++ b/include/uv/android-ifaddrs.h -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 1995, 1999 -+ * Berkeley Software Design, Inc. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp -+ */ -+ -+#ifndef _IFADDRS_H_ -+#define _IFADDRS_H_ -+ -+struct ifaddrs { -+ struct ifaddrs *ifa_next; -+ char *ifa_name; -+ unsigned int ifa_flags; -+ struct sockaddr *ifa_addr; -+ struct sockaddr *ifa_netmask; -+ struct sockaddr *ifa_dstaddr; -+ void *ifa_data; -+}; -+ -+/* -+ * This may have been defined in . Note that if is -+ * to be included it must be included before this header file. -+ */ -+#ifndef ifa_broadaddr -+#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ -+#endif -+ -+#include -+ -+__BEGIN_DECLS -+extern int getifaddrs(struct ifaddrs **ifap); -+extern void freeifaddrs(struct ifaddrs *ifa); -+__END_DECLS -+ ++// we do not have pthread_barrier_init until Android API level 24 ++#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__ ++# undef PTHREAD_BARRIER_SERIAL_THREAD +#endif -diff --git a/src/unix/android-ifaddrs.c b/src/unix/android-ifaddrs.c -new file mode 100644 -index 000000000..4765cc06b ---- /dev/null -+++ b/src/unix/android-ifaddrs.c -@@ -0,0 +1,713 @@ -+/* -+Copyright (c) 2013, Kenneth MacKay -+Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016) -+All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without modification, -+are permitted provided that the following conditions are met: -+ * Redistributions of source code must retain the above copyright notice, this -+ list of conditions and the following disclaimer. -+ * Redistributions in binary form must reproduce the above copyright notice, -+ this list of conditions and the following disclaimer in the documentation -+ and/or other materials provided with the distribution. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+*/ -+ -+#include "uv/android-ifaddrs.h" -+#include "uv-common.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+typedef struct NetlinkList -+{ -+ struct NetlinkList *m_next; -+ struct nlmsghdr *m_data; -+ unsigned int m_size; -+} NetlinkList; -+ -+static int netlink_socket(pid_t *p_pid) -+{ -+ struct sockaddr_nl l_addr; -+ socklen_t l_len; -+ -+ int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); -+ if(l_socket < 0) -+ { -+ return -1; -+ } -+ -+ memset(&l_addr, 0, sizeof(l_addr)); -+ l_addr.nl_family = AF_NETLINK; -+ if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) -+ { -+ close(l_socket); -+ return -1; -+ } -+ -+ l_len = sizeof(l_addr); -+ if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0) -+ { -+ close(l_socket); -+ return -1; -+ } -+ *p_pid = l_addr.nl_pid; -+ -+ return l_socket; -+} -+ -+static int netlink_send(int p_socket, int p_request) -+{ -+ char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; -+ -+ struct nlmsghdr *l_hdr; -+ struct rtgenmsg *l_msg; -+ struct sockaddr_nl l_addr; -+ -+ memset(l_buffer, 0, sizeof(l_buffer)); -+ -+ l_hdr = (struct nlmsghdr *)l_buffer; -+ l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); -+ -+ l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); -+ l_hdr->nlmsg_type = p_request; -+ l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; -+ l_hdr->nlmsg_pid = 0; -+ l_hdr->nlmsg_seq = p_socket; -+ l_msg->rtgen_family = AF_UNSPEC; -+ -+ memset(&l_addr, 0, sizeof(l_addr)); -+ l_addr.nl_family = AF_NETLINK; -+ return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); -+} -+ -+static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) -+{ -+ struct sockaddr_nl l_addr; -+ struct msghdr l_msg; -+ -+ struct iovec l_iov; -+ l_iov.iov_base = p_buffer; -+ l_iov.iov_len = p_len; -+ -+ for(;;) -+ { -+ int l_result; -+ l_msg.msg_name = (void *)&l_addr; -+ l_msg.msg_namelen = sizeof(l_addr); -+ l_msg.msg_iov = &l_iov; -+ l_msg.msg_iovlen = 1; -+ l_msg.msg_control = NULL; -+ l_msg.msg_controllen = 0; -+ l_msg.msg_flags = 0; -+ l_result = recvmsg(p_socket, &l_msg, 0); -+ -+ if(l_result < 0) -+ { -+ if(errno == EINTR) -+ { -+ continue; -+ } -+ return -2; -+ } -+ -+ /* Buffer was too small */ -+ if(l_msg.msg_flags & MSG_TRUNC) -+ { -+ return -1; -+ } -+ return l_result; -+ } -+} -+ -+static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done) -+{ -+ size_t l_size = 4096; -+ void *l_buffer = NULL; -+ -+ for(;;) -+ { -+ int l_read; -+ -+ uv__free(l_buffer); -+ l_buffer = uv__malloc(l_size); -+ if (l_buffer == NULL) -+ { -+ return NULL; -+ } -+ -+ l_read = netlink_recv(p_socket, l_buffer, l_size); -+ *p_size = l_read; -+ if(l_read == -2) -+ { -+ uv__free(l_buffer); -+ return NULL; -+ } -+ if(l_read >= 0) -+ { -+ struct nlmsghdr *l_hdr; -+ for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) -+ { -+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) -+ { -+ continue; -+ } -+ -+ if(l_hdr->nlmsg_type == NLMSG_DONE) -+ { -+ *p_done = 1; -+ break; -+ } -+ -+ if(l_hdr->nlmsg_type == NLMSG_ERROR) -+ { -+ uv__free(l_buffer); -+ return NULL; -+ } -+ } -+ return l_buffer; -+ } -+ -+ l_size *= 2; -+ } -+} -+ -+static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) -+{ -+ NetlinkList *l_item = uv__malloc(sizeof(NetlinkList)); -+ if (l_item == NULL) -+ { -+ return NULL; -+ } -+ -+ l_item->m_next = NULL; -+ l_item->m_data = p_data; -+ l_item->m_size = p_size; -+ return l_item; -+} -+ -+static void freeResultList(NetlinkList *p_list) -+{ -+ NetlinkList *l_cur; -+ while(p_list) -+ { -+ l_cur = p_list; -+ p_list = p_list->m_next; -+ uv__free(l_cur->m_data); -+ uv__free(l_cur); -+ } -+} -+ -+static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid) -+{ -+ int l_size; -+ int l_done; -+ NetlinkList *l_list; -+ NetlinkList *l_end; -+ -+ if(netlink_send(p_socket, p_request) < 0) -+ { -+ return NULL; -+ } -+ -+ l_list = NULL; -+ l_end = NULL; -+ -+ l_done = 0; -+ while(!l_done) -+ { -+ NetlinkList *l_item; -+ -+ struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done); -+ /* Error */ -+ if(!l_hdr) -+ { -+ freeResultList(l_list); -+ return NULL; -+ } -+ -+ l_item = newListItem(l_hdr, l_size); -+ if (!l_item) -+ { -+ freeResultList(l_list); -+ return NULL; -+ } -+ if(!l_list) -+ { -+ l_list = l_item; -+ } -+ else -+ { -+ l_end->m_next = l_item; -+ } -+ l_end = l_item; -+ } -+ return l_list; -+} -+ -+static size_t maxSize(size_t a, size_t b) -+{ -+ return (a > b ? a : b); -+} -+ -+static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) -+{ -+ switch(p_family) -+ { -+ case AF_INET: -+ return sizeof(struct sockaddr_in); -+ case AF_INET6: -+ return sizeof(struct sockaddr_in6); -+ case AF_PACKET: -+ return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); -+ default: -+ return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); -+ } -+} -+ -+static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) -+{ -+ switch(p_family) -+ { -+ case AF_INET: -+ memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); -+ break; -+ case AF_INET6: -+ memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); -+ break; -+ case AF_PACKET: -+ memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); -+ ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; -+ break; -+ default: -+ memcpy(p_dest->sa_data, p_data, p_size); -+ break; -+ } -+ p_dest->sa_family = p_family; -+} -+ -+static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) -+{ -+ if(!*p_resultList) -+ { -+ *p_resultList = p_entry; -+ } -+ else -+ { -+ struct ifaddrs *l_cur = *p_resultList; -+ while(l_cur->ifa_next) -+ { -+ l_cur = l_cur->ifa_next; -+ } -+ l_cur->ifa_next = p_entry; -+ } -+} -+ -+static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) -+{ -+ struct ifaddrs *l_entry; -+ -+ char *l_index; -+ char *l_name; -+ char *l_addr; -+ char *l_data; -+ -+ struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); + -+ size_t l_nameSize = 0; -+ size_t l_addrSize = 0; -+ size_t l_dataSize = 0; -+ -+ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); -+ struct rtattr *l_rta; -+ for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) -+ { -+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); -+ switch(l_rta->rta_type) -+ { -+ case IFLA_ADDRESS: -+ case IFLA_BROADCAST: -+ l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); -+ break; -+ case IFLA_IFNAME: -+ l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); -+ break; -+ case IFLA_STATS: -+ l_dataSize += NLMSG_ALIGN(l_rtaSize); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ l_entry = uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); -+ if (l_entry == NULL) -+ { -+ return -1; -+ } -+ memset(l_entry, 0, sizeof(struct ifaddrs)); -+ l_entry->ifa_name = ""; -+ -+ l_index = ((char *)l_entry) + sizeof(struct ifaddrs); -+ l_name = l_index + sizeof(int); -+ l_addr = l_name + l_nameSize; -+ l_data = l_addr + l_addrSize; -+ -+ /* Save the interface index so we can look it up when handling the -+ * addresses. -+ */ -+ memcpy(l_index, &l_info->ifi_index, sizeof(int)); -+ -+ l_entry->ifa_flags = l_info->ifi_flags; -+ -+ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); -+ for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) -+ { -+ void *l_rtaData = RTA_DATA(l_rta); -+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); -+ switch(l_rta->rta_type) -+ { -+ case IFLA_ADDRESS: -+ case IFLA_BROADCAST: -+ { -+ size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); -+ makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); -+ ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; -+ ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; -+ if(l_rta->rta_type == IFLA_ADDRESS) -+ { -+ l_entry->ifa_addr = (struct sockaddr *)l_addr; -+ } -+ else -+ { -+ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; -+ } -+ l_addr += NLMSG_ALIGN(l_addrLen); -+ break; -+ } -+ case IFLA_IFNAME: -+ strncpy(l_name, l_rtaData, l_rtaDataSize); -+ l_name[l_rtaDataSize] = '\0'; -+ l_entry->ifa_name = l_name; -+ break; -+ case IFLA_STATS: -+ memcpy(l_data, l_rtaData, l_rtaDataSize); -+ l_entry->ifa_data = l_data; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ addToEnd(p_resultList, l_entry); -+ return 0; -+} -+ -+static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) -+{ -+ int l_num = 0; -+ struct ifaddrs *l_cur = *p_links; -+ while(l_cur && l_num < p_numLinks) -+ { -+ char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); -+ int l_index; -+ memcpy(&l_index, l_indexPtr, sizeof(int)); -+ if(l_index == p_index) -+ { -+ return l_cur; -+ } -+ -+ l_cur = l_cur->ifa_next; -+ ++l_num; -+ } -+ return NULL; -+} -+ -+static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) -+{ -+ struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); -+ struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); -+ -+ size_t l_nameSize = 0; -+ size_t l_addrSize = 0; -+ -+ int l_addedNetmask = 0; -+ -+ size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); -+ struct rtattr *l_rta; -+ struct ifaddrs *l_entry; -+ -+ char *l_name; -+ char *l_addr; -+ -+ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) -+ { -+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); -+ if(l_info->ifa_family == AF_PACKET) -+ { -+ continue; -+ } -+ -+ switch(l_rta->rta_type) -+ { -+ case IFA_ADDRESS: -+ case IFA_LOCAL: -+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); -+ if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) -+ { -+ /* Make room for netmask */ -+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); -+ l_addedNetmask = 1; -+ } -+ break; -+ case IFA_BROADCAST: -+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); -+ break; -+ case IFA_LABEL: -+ l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ l_entry = uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); -+ if (l_entry == NULL) -+ { -+ return -1; -+ } -+ memset(l_entry, 0, sizeof(struct ifaddrs)); -+ l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); -+ -+ l_name = ((char *)l_entry) + sizeof(struct ifaddrs); -+ l_addr = l_name + l_nameSize; -+ -+ l_entry->ifa_flags = l_info->ifa_flags; -+ if(l_interface) -+ { -+ l_entry->ifa_flags |= l_interface->ifa_flags; -+ } -+ -+ l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); -+ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) -+ { -+ void *l_rtaData = RTA_DATA(l_rta); -+ size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); -+ switch(l_rta->rta_type) -+ { -+ case IFA_ADDRESS: -+ case IFA_BROADCAST: -+ case IFA_LOCAL: -+ { -+ size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); -+ makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); -+ if(l_info->ifa_family == AF_INET6) -+ { -+ if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) -+ { -+ ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; -+ } -+ } -+ -+ /* Apparently in a point-to-point network IFA_ADDRESS contains -+ * the dest address and IFA_LOCAL contains the local address -+ */ -+ if(l_rta->rta_type == IFA_ADDRESS) -+ { -+ if(l_entry->ifa_addr) -+ { -+ l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; -+ } -+ else -+ { -+ l_entry->ifa_addr = (struct sockaddr *)l_addr; -+ } -+ } -+ else if(l_rta->rta_type == IFA_LOCAL) -+ { -+ if(l_entry->ifa_addr) -+ { -+ l_entry->ifa_dstaddr = l_entry->ifa_addr; -+ } -+ l_entry->ifa_addr = (struct sockaddr *)l_addr; -+ } -+ else -+ { -+ l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; -+ } -+ l_addr += NLMSG_ALIGN(l_addrLen); -+ break; -+ } -+ case IFA_LABEL: -+ strncpy(l_name, l_rtaData, l_rtaDataSize); -+ l_name[l_rtaDataSize] = '\0'; -+ l_entry->ifa_name = l_name; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) -+ { -+ unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); -+ unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); -+ unsigned char l_mask[16] = {0}; -+ unsigned i; -+ for(i=0; i<(l_prefix/8); ++i) -+ { -+ l_mask[i] = 0xff; -+ } -+ if(l_prefix % 8) -+ { -+ l_mask[i] = 0xff << (8 - (l_prefix % 8)); -+ } -+ -+ makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); -+ l_entry->ifa_netmask = (struct sockaddr *)l_addr; -+ } -+ -+ addToEnd(p_resultList, l_entry); -+ return 0; -+} -+ -+static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) -+{ -+ -+ int l_numLinks = 0; -+ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) -+ { -+ unsigned int l_nlsize = p_netlinkList->m_size; -+ struct nlmsghdr *l_hdr; -+ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) -+ { -+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) -+ { -+ continue; -+ } -+ -+ if(l_hdr->nlmsg_type == NLMSG_DONE) -+ { -+ break; -+ } -+ -+ if(l_hdr->nlmsg_type == RTM_NEWLINK) -+ { -+ if(interpretLink(l_hdr, p_resultList) == -1) -+ { -+ return -1; -+ } -+ ++l_numLinks; -+ } -+ } -+ } -+ return l_numLinks; -+} -+ -+static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) -+{ -+ for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) -+ { -+ unsigned int l_nlsize = p_netlinkList->m_size; -+ struct nlmsghdr *l_hdr; -+ for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) -+ { -+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket) -+ { -+ continue; -+ } -+ -+ if(l_hdr->nlmsg_type == NLMSG_DONE) -+ { -+ break; -+ } -+ -+ if(l_hdr->nlmsg_type == RTM_NEWADDR) -+ { -+ if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) -+ { -+ return -1; -+ } -+ } -+ } -+ } -+ return 0; -+} -+ -+int getifaddrs(struct ifaddrs **ifap) -+{ -+ int l_socket; -+ int l_result; -+ int l_numLinks; -+ pid_t l_pid; -+ NetlinkList *l_linkResults; -+ NetlinkList *l_addrResults; -+ -+ if(!ifap) -+ { -+ return -1; -+ } -+ *ifap = NULL; -+ -+ l_socket = netlink_socket(&l_pid); -+ if(l_socket < 0) -+ { -+ return -1; -+ } -+ -+ l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid); -+ if(!l_linkResults) -+ { -+ close(l_socket); -+ return -1; -+ } -+ -+ l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid); -+ if(!l_addrResults) -+ { -+ close(l_socket); -+ freeResultList(l_linkResults); -+ return -1; -+ } -+ -+ l_result = 0; -+ l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap); -+ if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1) -+ { -+ l_result = -1; -+ } -+ -+ freeResultList(l_linkResults); -+ freeResultList(l_addrResults); -+ close(l_socket); -+ return l_result; -+} -+ -+void freeifaddrs(struct ifaddrs *ifa) -+{ -+ struct ifaddrs *l_cur; -+ while(ifa) -+ { -+ l_cur = ifa; -+ ifa = ifa->ifa_next; -+ uv__free(l_cur); -+ } -+} + /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ + #if defined(_AIX) || \ + defined(__OpenBSD__) || \ diff --git a/src/unix/linux.c b/src/unix/linux.c -index 857a4ef8a..9deec0ef5 100644 +index ea3e2de03..298cf88b0 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c -@@ -37,7 +37,11 @@ +@@ -37,7 +37,10 @@ #include #include --#include -+# if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__ -+# include "uv/android-ifaddrs.h" -+# else -+# include -+# endif ++#define HAS_IFADDRS (!defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__) ++#if HAS_IFADDRS + #include ++#endif #include #include #include +@@ -56,6 +59,11 @@ + #include + #include + ++// ndk r28 does not have this definition: https://github.com/android/ndk/issues/2136 ++#if defined(__ANDROID__) && !defined(LLONG_MAX) ++# define LLONG_MAX 0x7fffffffffffffffLL ++#endif ++ + #ifndef __NR_io_uring_setup + # define __NR_io_uring_setup 425 + #endif +@@ -1941,6 +1949,8 @@ nocpuinfo: + + + static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { ++// disable ifaddrs stuff on Android ++#if HAS_IFADDRS + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) +@@ -1952,10 +1962,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { + if (ent->ifa_addr->sa_family == PF_PACKET) + return exclude_type; + return !exclude_type; ++#endif + } + + /* TODO(bnoordhuis) share with bsd-ifaddrs.c */ + int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { ++// disable ifaddrs stuff on Android ++#if HAS_IFADDRS + uv_interface_address_t* address; + struct sockaddr_ll* sll; + struct ifaddrs* addrs; +@@ -2042,6 +2055,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + freeifaddrs(addrs); + + return 0; ++#endif + } + + +diff --git a/src/unix/tcp.c b/src/unix/tcp.c +index 98970d752..c39cdb030 100644 +--- a/src/unix/tcp.c ++++ b/src/unix/tcp.c +@@ -31,7 +31,7 @@ + #include + + /* ifaddrs is not implemented on AIX and IBM i PASE */ +-#if !defined(_AIX) ++#if !defined(_AIX) || !defined(__ANDROID__) + #include + #endif + +@@ -228,7 +228,7 @@ static int uv__is_ipv6_link_local(const struct sockaddr* addr) { + static int uv__ipv6_link_local_scope_id(void) { + struct sockaddr_in6* a6; + int rv; +-#if defined(_AIX) ++#if defined(_AIX) || defined(__ANDROID__) + /* AIX & IBM i do not have ifaddrs + * so fallback to use uv_interface_addresses */ + uv_interface_address_t* interfaces; -- -2.47.0 +2.52.0 diff --git a/patches/marisa-tire.patch b/patches/marisa-tire.patch index d7309734..85ee41d5 100644 --- a/patches/marisa-tire.patch +++ b/patches/marisa-tire.patch @@ -1,12 +1,12 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index d89d928..6ba6a32 100644 +index b96374e..4f040d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -49,6 +49,7 @@ add_library(marisa - ${MARISA_SRC} +@@ -195,6 +195,7 @@ target_include_directories(marisa + PRIVATE + lib ) - +target_compile_options(marisa PRIVATE "-ffile-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.") - install(TARGETS marisa - EXPORT marisa-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + set_target_properties(marisa PROPERTIES + VERSION "${Marisa_VERSION}" + SOVERSION "${Marisa_VERSION_MAJOR}" diff --git a/patches/opencc-host.patch b/patches/opencc-host.patch new file mode 100644 index 00000000..27776dfe --- /dev/null +++ b/patches/opencc-host.patch @@ -0,0 +1,24 @@ +diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt +index 3b7057aa..f3eb802a 100644 +--- a/data/CMakeLists.txt ++++ b/data/CMakeLists.txt +@@ -130,7 +130,9 @@ foreach(DICT ${DICTS}) + FILES + ${DICT_GENERATED_DIR}/${DICT}.ocd2 + DESTINATION +- ${DIR_SHARE_OPENCC} ++ data ++ COMPONENT ++ data + ) + + set_directory_properties( +@@ -161,5 +163,7 @@ install( + FILES + ${CONFIG_FILES} + DESTINATION +- ${DIR_SHARE_OPENCC} ++ data ++ COMPONENT ++ data + ) diff --git a/patches/opencc.patch b/patches/opencc.patch index bfba681a..8ab60218 100644 --- a/patches/opencc.patch +++ b/patches/opencc.patch @@ -1,14 +1,54 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 1acb75a9..05198910 100644 +index c2e9dc70..fb9077d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -210,7 +210,8 @@ if(NOT USE_SYSTEM_MARISA) +@@ -79,10 +79,6 @@ endif() + + ######## Directory + +-set(LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE PATH "") +-if(CMAKE_INSTALL_LIBDIR MATCHES "lib64$") +- set(LIB_SUFFIX 64) +-endif() + + set (DIR_PREFIX ${CMAKE_INSTALL_PREFIX}) + set (DIR_INCLUDE ${DIR_PREFIX}/include) +@@ -215,19 +211,13 @@ if(NOT USE_SYSTEM_MARISA) message(STATUS "Use bundled marisa library.") add_subdirectory(deps/marisa-0.2.6) else() - find_library(LIBMARISA NAMES marisa) -+ find_package(marisa) -+ set(LIBMARISA marisa) - if (LIBMARISA) - message(STATUS "libmarisa found: ${LIBMARISA}") - else() +- if (LIBMARISA) +- message(STATUS "libmarisa found: ${LIBMARISA}") +- else() +- message(FATAL_ERROR "libmarisa not found.") +- endif() ++ find_package(Marisa REQUIRED) + endif() + + ######## Subdirectories + + add_subdirectory(src) + add_subdirectory(doc) +-add_subdirectory(data) + add_subdirectory(test) + + ######## Testing +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 227e6c65..9aed48d1 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -116,7 +116,7 @@ add_library(libopencc ${LIBOPENCC_SOURCES} ${LIBOPENCC_HEADERS}) + add_library(OpenCC::OpenCC ALIAS libopencc) + set_target_properties(libopencc PROPERTIES POSITION_INDEPENDENT_CODE ON) + source_group(libopencc FILES ${LIBOPENCC_SOURCES} ${LIBOPENCC_HEADERS}) +-target_link_libraries(libopencc marisa) ++target_link_libraries(libopencc Marisa::marisa) + target_include_directories(libopencc PUBLIC + $ + $ +@@ -206,4 +206,3 @@ endif() + + # Subdir + +-add_subdirectory(tools) diff --git a/src/Main.hs b/src/Main.hs index 34fd4398..3034a0e3 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -57,6 +57,7 @@ main = do libuvRule libintlLiteRule luaRule + hostOpenCCRule openccRule boostRule zstdRule @@ -64,6 +65,7 @@ main = do glogRule yamlCppRule leveldbRule + hostMarisaRule marisaRule librimeRule libhangulRule @@ -175,7 +177,8 @@ data ToolchainVersions = ToolchainVersions { prebuilderRev :: String, ndkVersion :: String, platformVersion :: Int, - cmakeVersion :: String + cmakeVersion :: String, + rustVersion :: String } instance A.ToJSON ToolchainVersions where @@ -184,7 +187,8 @@ instance A.ToJSON ToolchainVersions where [ fromString "prebuilder" A..= prebuilderRev, fromString "ndk" A..= ndkVersion, fromString "platform" A..= platformVersion, - fromString "cmake" A..= cmakeVersion + fromString "cmake" A..= cmakeVersion, + fromString "rust" A..= rustVersion ] getToolchainVersions :: Action ToolchainVersions @@ -198,4 +202,5 @@ getToolchainVersions = do pure $ dropWhileEnd (== ' ') ndkVersion | otherwise -> fail "Failed to parse Pkg.Revision" Nothing -> fail "Pkg.Revision not found in source.properties" + rustVersion <- fromMaybeM (fail "RUST_VERSION not set") (getEnv "RUST_VERSION") pure ToolchainVersions {..} diff --git a/src/Rules/Boost.hs b/src/Rules/Boost.hs index 0f108a98..67e29151 100644 --- a/src/Rules/Boost.hs +++ b/src/Rules/Boost.hs @@ -32,6 +32,8 @@ boostRule = do cmakeFlags = const [ "-DCMAKE_INSTALL_MESSAGE=NEVER", + -- install boost headers to parent directory, symlink it afterwards + "-DCMAKE_INSTALL_INCLUDEDIR=" <> "../include", "-DBOOST_EXCLUDE_LIBRARIES=" <> intercalate ";" @@ -69,26 +71,13 @@ boostRule = do "-DBOOST_IOSTREAMS_ENABLE_LZMA=OFF", "-DBOOST_IOSTREAMS_ENABLE_ZSTD=OFF", "-DBOOST_INSTALL_LAYOUT=system" - ] + ], + -- symlink headers for each abi to reduce size + postBuildEachABI = BuildActionABI $ \_ env -> + liftIO $ do + let includePath = buildEnvOutPrefix env "include" + whenM (doesPathExist includePath) $ removePathForcibly includePath + createDirectoryLink (".." "include") includePath } "boost" ~> do - env <- getAndroidEnv - -- since header files are the same regardless of abi - -- we take a random one - let abiList = getABIList env - firstAbi = head abiList - _ <- buildBoost $ WithAndroidEnv Boost env - liftIO $ do - getDirectoryFilesIO - (outputDir "boost" firstAbi "include" "boost") - ["//*"] - >>= mapM_ - ( \x -> - copyFileAndCreateDir (outputDir "boost" firstAbi "include" "boost" x) $ - outputDir "boost" "include" "boost" x - ) - forM_ abiList $ \a -> do - -- symlink headers for each abi to reduce size - let path = outputDir "boost" a "include" - whenM (doesPathExist path) $ removePathForcibly path - createDirectoryLink (".." "include") path + buildWithAndroidEnv buildBoost Boost diff --git a/src/Rules/Fcitx5.hs b/src/Rules/Fcitx5.hs index 8c221ac9..9bd7e5fc 100644 --- a/src/Rules/Fcitx5.hs +++ b/src/Rules/Fcitx5.hs @@ -69,7 +69,7 @@ hostFcitx5Rule = do -- ignore install errors Exit _ <- cmd "cmake" "--install" buildDir -- install "comp-spell-dict" manually - copyFile' (buildDir "src" "modules" "spell" "comp-spell-dict") $ hostPrefix "bin" "comp-spell-dict" + copyFile' (buildDir "bin" "comp-spell-dict") $ hostPrefix "bin" "comp-spell-dict" pure () -------------------------------------------------------------------------------- diff --git a/src/Rules/LibChewing.hs b/src/Rules/LibChewing.hs index 53216704..cb206bb5 100644 --- a/src/Rules/LibChewing.hs +++ b/src/Rules/LibChewing.hs @@ -23,23 +23,34 @@ libchewingRule = do useCMake $ (cmakeBuilder "libchewing") { preBuild = BuildAction $ \_ src -> do - -- CMakeLists is changed in last build + -- install rust toolchain + cmd_ Shell "rustup toolchain install $RUST_VERSION" + -- CMakeLists.txt changed in last build cmd_ (Cwd src) Shell "git checkout ." - -- skip data and shared lib - -- merge libuserphrase.a into libchewing.a - -- remove absolute path by CHEWING_DATADIR macro - -- remove absolute path by __FILE__ macro + -- disable data/doc, remove absolute path, optimize library size cmd_ (Cwd src) "git apply ../patches/libchewing.patch", - cmakeFlags = - const - [ "-DBUILD_SHARED_LIBS=OFF", - "-DBUILD_TESTING=OFF", - "-DWITH_SQLITE3=OFF", - "-DWITH_RUST=OFF" - ] + preBuildEachABI = BuildActionABI $ \_ env -> do + -- install rust target for this abi + let targetName = case (buildEnvABI env) of + "armeabi-v7a" -> "armv7-linux-androideabi" + "arm64-v8a" -> "aarch64-linux-android" + "x86" -> "i686-linux-android" + "x86_64" -> "x86_64-linux-android" + _ -> fail "Unknown Android ABI" + cmd_ "rustup" "target" "add" targetName, + cmakeFlags = + const + [ "-DBUILD_SHARED_LIBS=OFF", + "-DBUILD_TESTING=OFF", + "-DBUILD_DATA=OFF", + "-DBUILD_DOC=OFF", + "-DWITH_SQLITE3=OFF" + ] } "chewing-dict" ~> do + -- install rust + cmd_ Shell "rustup toolchain install $RUST_VERSION" let libchewingBuildHost = outputDir "libchewing-build-host" dictSrcDir = libchewingBuildHost "data" cmd_ (Cwd libchewingSrc) Shell "git checkout ." @@ -49,10 +60,9 @@ libchewingRule = do libchewingBuildHost "-G" "Ninja" - [ "-DBUILD_SHARED_LIBS=OFF", - "-DBUILD_TESTING=OFF", + [ "-DBUILD_TESTING=OFF", "-DWITH_SQLITE3=OFF", - "-DWITH_RUST=OFF" + "-DBUILD_DOC=OFF" ] libchewingSrc cmd_ @@ -60,14 +70,13 @@ libchewingRule = do "--build" libchewingBuildHost "--target" - [ "data", - "all_static_data" + [ "dict_chewing", + "misc" ] - copyFile' (dictSrcDir "dictionary.dat") (dictOutputDir "dictionary.dat") - copyFile' (dictSrcDir "index_tree.dat") (dictOutputDir "index_tree.dat") - copyFile' (dictSrcDir "pinyin.tab") (dictOutputDir "pinyin.tab") - copyFile' (dictSrcDir "swkb.dat") (dictOutputDir "swkb.dat") - copyFile' (dictSrcDir "symbols.dat") (dictOutputDir "symbols.dat") + copyFile' (dictSrcDir "dict" "chewing" "tsi.dat") (dictOutputDir "tsi.dat") + copyFile' (dictSrcDir "dict" "chewing" "word.dat") (dictOutputDir "word.dat") + copyFile' (dictSrcDir "misc" "swkb.dat") (dictOutputDir "swkb.dat") + copyFile' (dictSrcDir "misc" "symbols.dat") (dictOutputDir "symbols.dat") "libchewing" ~> do need ["chewing-dict"] diff --git a/src/Rules/LibUV.hs b/src/Rules/LibUV.hs index 004dc227..1a351432 100644 --- a/src/Rules/LibUV.hs +++ b/src/Rules/LibUV.hs @@ -28,8 +28,7 @@ libuvRule = do ], preBuild = BuildAction $ \_ src -> do cmd_ (Cwd src) "git checkout ." - cmd_ (Cwd src) "git clean -fd" - -- revive support for android api level 21 + -- disable tcp cmd_ (Cwd src) "git apply ../patches/libuv.patch" } "libuv" ~> buildWithAndroidEnv buildlibuv LibUV diff --git a/src/Rules/Marisa.hs b/src/Rules/Marisa.hs index 7b4988e2..66fd1db7 100644 --- a/src/Rules/Marisa.hs +++ b/src/Rules/Marisa.hs @@ -3,7 +3,11 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE TypeFamilies #-} -module Rules.Marisa (marisaRule) where +module Rules.Marisa + ( marisaRule, + hostMarisaRule, + ) +where import Base import CMakeBuilder @@ -14,6 +18,23 @@ data MarisaTrie = MarisaTrie type instance RuleResult MarisaTrie = () +hostMarisaRule :: Rules () +hostMarisaRule = do + "host-marisa" ~> do + marisaSrc <- liftIO $ canonicalizePath "marisa-trie" + let buildDir = outputDir "marisa-build-host" + let hostPrefix = outputDir "host" + cmd_ (Cwd marisaSrc) "git checkout ." + cmd_ + "cmake" + "-B" buildDir + "-G" "Ninja" + [ "-DCMAKE_INSTALL_PREFIX=" <> hostPrefix + ] + marisaSrc + cmd_ "cmake" "--build" buildDir + cmd_ "cmake" "--install" buildDir + marisaRule :: Rules () marisaRule = do buildMarisa <- diff --git a/src/Rules/OpenCC.hs b/src/Rules/OpenCC.hs index 0a39fadb..825edd85 100644 --- a/src/Rules/OpenCC.hs +++ b/src/Rules/OpenCC.hs @@ -4,7 +4,11 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} -module Rules.OpenCC (openccRule) where +module Rules.OpenCC + ( hostOpenCCRule, + openccRule, + ) +where import Base import CMakeBuilder @@ -15,6 +19,28 @@ data OpenCC = OpenCC type instance RuleResult OpenCC = () +hostOpenCCRule :: Rules () +hostOpenCCRule = do + "opencc-dict" ~> do + need [ "host-marisa" ] + openccSrc <- liftIO $ canonicalizePath "OpenCC" + let buildDir = outputDir "opencc-build-host" + let hostPrefix = outputDir "host" + cmd_ Shell ("echo " <> openccSrc) + cmd_ (Cwd openccSrc) "git checkout ." + cmd_ (Cwd openccSrc) "git apply ../patches/opencc-host.patch" + cmd_ + "cmake" + "-B" buildDir + "-G" "Ninja" + [ "-DCMAKE_INSTALL_PREFIX=" <> (outputDir "opencc"), + "-DCMAKE_FIND_ROOT_PATH=" <> hostPrefix, + "-DCMAKE_PREFIX_PATH=" <> hostPrefix + ] + openccSrc + cmd_ "cmake" "--build" buildDir "--target" [ "opencc_dict", "Dictionaries" ] + cmd_ "cmake" "--install" buildDir "--component" "data" + openccRule :: Rules () openccRule = do buildOpenCC <- @@ -37,35 +63,12 @@ openccRule = do "-DENABLE_BENCHMARK=OFF", "-DENABLE_DARTS=OFF", "-DUSE_SYSTEM_MARISA=ON", - "-Dmarisa_DIR=" <> (buildEnvOut "marisa" buildEnvABI "lib" "cmake" "marisa"), + "-DMarisa_DIR=" <> (buildEnvOut "marisa" buildEnvABI "lib" "cmake" "Marisa"), "-DUSE_SYSTEM_PYBIND11=OFF", "-DUSE_SYSTEM_RAPIDJSON=OFF", "-DUSE_SYSTEM_TCLAP=OFF" ] } "opencc" ~> do - need ["marisa"] - env <- getAndroidEnv - -- since dictionary files are the same regardless of abi - -- we take a random one - let abiList = getABIList env - firstAbi = head abiList - -- delete old data and symlinks - liftIO $ do - removePathForcibly $ outputDir "opencc" "data" - forM_ abiList $ \a -> removePathForcibly $ outputDir "opencc" a "share" "opencc" - buildOpenCC $ WithAndroidEnv OpenCC env - liftIO $ do - getDirectoryFilesIO - (outputDir "opencc" firstAbi "share" "opencc") - ["//*"] - >>= mapM_ - ( \x -> - copyFileAndCreateDir (outputDir "opencc" firstAbi "share" "opencc" x) $ - outputDir "opencc" "data" x - ) - forM_ abiList $ \a -> do - -- symlink dictionaries for each abi to reduce size - let dataPath = outputDir "opencc" a "share" "opencc" - whenM (doesPathExist dataPath) $ removePathForcibly dataPath - createDirectoryLink (".." ".." "data") dataPath + need [ "marisa", "opencc-dict" ] + buildWithAndroidEnv buildOpenCC OpenCC diff --git a/yaml-cpp b/yaml-cpp index f7320141..56e3bb55 160000 --- a/yaml-cpp +++ b/yaml-cpp @@ -1 +1 @@ -Subproject commit f7320141120f720aecc4c32be25586e7da9eb978 +Subproject commit 56e3bb550c91fd7005566f19c079cb7a503223cf