diff options
| author | Po Lu | 2024-04-22 16:27:30 +0800 |
|---|---|---|
| committer | Po Lu | 2024-04-22 16:30:15 +0800 |
| commit | 3bcdf010a9f2576bac0d7f23af70fa9dff81ef95 (patch) | |
| tree | 600a98286f5469579cf87dac7c920590b5af4082 | |
| parent | 4d9629b087fe6df941b553c6931b2f8996901e21 (diff) | |
| download | emacs-3bcdf010a9f2576bac0d7f23af70fa9dff81ef95.tar.gz emacs-3bcdf010a9f2576bac0d7f23af70fa9dff81ef95.zip | |
Generate Android shared library list automatically
* .gitignore: Ignore new generated files.
* cross/Makefile.in (src/Makefile): Remove leftover
specification of the source Gnulib directory.
* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_READELF): New
variable.
* java/Makefile.in (CONFIG_FILE, ALL_DEPENDENCIES, READELF)
(cf-stamp-1, cf-stamp): New variables and rules; compute the set
of library files in the order of loading and generate a file
with this information.
(ALL_CLASS_FILES): New variable; if builddir is not srcdir,
$($(CONFIG_FILE), $(CLASS_FILES)): Depend on EmacsConfig.java.
add generated files in the build directory.
(classes.dex): Adjust to match.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative)
<static initializer>: Load shared libraries from
EMACS_SHARED_LIBRARIES rather than a hard-coded list.
* m4/ndk-build.m4 (ndk_INIT): Search for readelf...
(ndk_CHECK_MODULES): ...and substitute its path as
NDK_BUILD_READELF.
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | cross/Makefile.in | 2 | ||||
| -rw-r--r-- | cross/ndk-build/ndk-build.mk.in | 1 | ||||
| -rw-r--r-- | java/Makefile.in | 91 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 52 | ||||
| -rw-r--r-- | m4/ndk-build.m4 | 11 |
6 files changed, 126 insertions, 35 deletions
diff --git a/.gitignore b/.gitignore index 29c571a3dcb..4098e2210b5 100644 --- a/.gitignore +++ b/.gitignore | |||
| @@ -66,6 +66,10 @@ java/org/gnu/emacs/*.class | |||
| 66 | # Built by `aapt'. | 66 | # Built by `aapt'. |
| 67 | java/org/gnu/emacs/R.java | 67 | java/org/gnu/emacs/R.java |
| 68 | 68 | ||
| 69 | # Built by `make'. | ||
| 70 | java/org/gnu/emacs/EmacsConfig.java | ||
| 71 | java/org/gnu/emacs/cf-stamp | ||
| 72 | |||
| 69 | # Built by `config.status'. | 73 | # Built by `config.status'. |
| 70 | java/AndroidManifest.xml | 74 | java/AndroidManifest.xml |
| 71 | 75 | ||
diff --git a/cross/Makefile.in b/cross/Makefile.in index 1e8daea6f91..575c6c4cb29 100644 --- a/cross/Makefile.in +++ b/cross/Makefile.in | |||
| @@ -140,7 +140,7 @@ src/Makefile: $(top_builddir)/src/Makefile.android | |||
| 140 | -e 's/\.\.\/admin\/charsets/..\/..\/admin\/charsets/g' \ | 140 | -e 's/\.\.\/admin\/charsets/..\/..\/admin\/charsets/g' \ |
| 141 | -e 's/^libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \ | 141 | -e 's/^libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \ |
| 142 | -e 's/libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \ | 142 | -e 's/libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \ |
| 143 | -e 's/-I\$$(top_srcdir)\/lib/-I..\/$(subst /,\/,$(srcdir))\/lib/g' \ | 143 | -e 's/-I\$$(top_srcdir)\/lib//g' \ |
| 144 | < $(top_builddir)/src/Makefile.android > $@ | 144 | < $(top_builddir)/src/Makefile.android > $@ |
| 145 | 145 | ||
| 146 | src/epaths.h: $(top_builddir)/src/epaths.h | 146 | src/epaths.h: $(top_builddir)/src/epaths.h |
diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in index ea1be5af6f1..9948e019e3b 100644 --- a/cross/ndk-build/ndk-build.mk.in +++ b/cross/ndk-build/ndk-build.mk.in | |||
| @@ -27,6 +27,7 @@ NDK_BUILD_CXX_LDFLAGS = @NDK_BUILD_CXX_LDFLAGS@ | |||
| 27 | NDK_BUILD_ANY_CXX_MODULE = @NDK_BUILD_ANY_CXX_MODULE@ | 27 | NDK_BUILD_ANY_CXX_MODULE = @NDK_BUILD_ANY_CXX_MODULE@ |
| 28 | NDK_BUILD_SHARED = | 28 | NDK_BUILD_SHARED = |
| 29 | NDK_BUILD_STATIC = | 29 | NDK_BUILD_STATIC = |
| 30 | NDK_BUILD_READELF = @NDK_BUILD_READELF@ | ||
| 30 | 31 | ||
| 31 | define uniqify | 32 | define uniqify |
| 32 | $(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1))) | 33 | $(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1))) |
diff --git a/java/Makefile.in b/java/Makefile.in index 7d732be8f91..bd1938689d5 100644 --- a/java/Makefile.in +++ b/java/Makefile.in | |||
| @@ -83,6 +83,10 @@ RESOURCE_FILES := $(foreach file,$(wildcard $(srcdir)/res/*), \ | |||
| 83 | # code. Instead, it is automatically included by the Java compiler. | 83 | # code. Instead, it is automatically included by the Java compiler. |
| 84 | RESOURCE_FILE := $(srcdir)/org/gnu/emacs/R.java | 84 | RESOURCE_FILE := $(srcdir)/org/gnu/emacs/R.java |
| 85 | 85 | ||
| 86 | # EmacsConfig.java is a file that holds information regarding the set of | ||
| 87 | # shared libraries this binary links to, and similar build variables. | ||
| 88 | CONFIG_FILE := $(builddir)/org/gnu/emacs/EmacsConfig.java | ||
| 89 | |||
| 86 | # CLASS_FILES is what should actually be built and included in the | 90 | # CLASS_FILES is what should actually be built and included in the |
| 87 | # resulting Emacs executable. The Java compiler might generate more | 91 | # resulting Emacs executable. The Java compiler might generate more |
| 88 | # than one class file for each source file, so this only serves as a | 92 | # than one class file for each source file, so this only serves as a |
| @@ -294,8 +298,72 @@ $(RESOURCE_FILE): $(RESOURCE_FILES) | |||
| 294 | -J $(dir $@) -M AndroidManifest.xml \ | 298 | -J $(dir $@) -M AndroidManifest.xml \ |
| 295 | -S $(top_srcdir)/java/res | 299 | -S $(top_srcdir)/java/res |
| 296 | 300 | ||
| 297 | # Make all class files depend on R.java being built. | 301 | # Generate a list of libemacs's dependencies with each item ordered |
| 298 | $(CLASS_FILES): $(RESOURCE_FILE) | 302 | # before its dependents for the startup process to load in advance, as |
| 303 | # older versions of the dynamic linker do not consider these libraries | ||
| 304 | # when resolving its imports. The several following statements are | ||
| 305 | # executed from a recursive `make' run after shared libraries are | ||
| 306 | # generated. | ||
| 307 | |||
| 308 | ALL_DEPENDENCIES := | ||
| 309 | |||
| 310 | ifneq (,$(filter cf-stamp-1,$(MAKECMDGOALS))) | ||
| 311 | # Don't be sidetracked by dependencies of shared libraries outside the | ||
| 312 | # ndk-build directory. | ||
| 313 | define get-dependencies | ||
| 314 | $(foreach x, \ | ||
| 315 | $(and $(wildcard $(top_builddir)/cross/ndk-build/$1.so), \ | ||
| 316 | $(shell $(NDK_BUILD_READELF) -d \ | ||
| 317 | $(wildcard $(top_builddir)/cross/ndk-build/$1.so) \ | ||
| 318 | | sed -n 's/.*(NEEDED).*\[\(.*\.so\)\].*/\1/p')), \ | ||
| 319 | $(basename $(notdir $(x)))) | ||
| 320 | endef #get-dependencies | ||
| 321 | define resolve-one-dependency | ||
| 322 | $(foreach dependency,$(call get-dependencies,$1),\ | ||
| 323 | $(if $(findstring "$(dependency)",$(ALL_DEPENDENCIES)),,\ | ||
| 324 | $(call resolve-one-dependency,$(basename $(notdir $(dependency)))) \ | ||
| 325 | $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(dependency)",))) | ||
| 326 | endef #resolve-one-dependency | ||
| 327 | DEPENDENCIES := $(foreach file,$(NDK_BUILD_SHARED),\ | ||
| 328 | $(basename $(notdir $(file)))) | ||
| 329 | $(foreach file,$(DEPENDENCIES),\ | ||
| 330 | $(if $(findstring "$(file)",$(ALL_DEPENDENCIES)),,\ | ||
| 331 | $(call resolve-one-dependency,$(file)) \ | ||
| 332 | $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(file)",))) | ||
| 333 | endif | ||
| 334 | |||
| 335 | # EmacsConfig.java: | ||
| 336 | ifeq (${V},1) | ||
| 337 | AM_V_EMACSCONFIG = | ||
| 338 | else | ||
| 339 | AM_V_EMACSCONFIG = @$(info $. GEN org/gnu/emacs/EmacsConfig.java) | ||
| 340 | endif | ||
| 341 | |||
| 342 | .PHONY: cf-stamp-1 | ||
| 343 | cf-stamp-1: | ||
| 344 | $(AM_V_at) echo 'package org.gnu.emacs;\ | ||
| 345 | public class EmacsConfig\ | ||
| 346 | {\ | ||
| 347 | /* This is a generated file. Do not edit! */\ | ||
| 348 | public static final String[] EMACS_SHARED_LIBRARIES\ | ||
| 349 | = {$(ALL_DEPENDENCIES)};\ | ||
| 350 | }' | sed 's/\\//g' > globals.tmp | ||
| 351 | $(AM_V_at) mkdir -p org/gnu/emacs | ||
| 352 | $(AM_V_at) $(top_srcdir)/build-aux/move-if-change \ | ||
| 353 | globals.tmp org/gnu/emacs/EmacsConfig.java | ||
| 354 | |||
| 355 | # cf-stamp-1 is a phony target invoked in a second `make' instance after | ||
| 356 | # all shared libraries are compiled, because the computation of | ||
| 357 | # ALL_DEPENDENCIES cannot be postponed until that stage in this instance | ||
| 358 | # of Make. | ||
| 359 | cf-stamp: $(NDK_BUILD_SHARED) $(CROSS_LIBS) | ||
| 360 | $(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1 | ||
| 361 | $(AM_V_at) touch $@ | ||
| 362 | $(CONFIG_FILE): cf-stamp; @true | ||
| 363 | |||
| 364 | # Make all class files depend on R.java and EmacsConfig.java being | ||
| 365 | # built. | ||
| 366 | $(CLASS_FILES): $(RESOURCE_FILE) $(CONFIG_FILE) | ||
| 299 | 367 | ||
| 300 | .SUFFIXES: .java .class | 368 | .SUFFIXES: .java .class |
| 301 | $(CLASS_FILES) &: $(JAVA_FILES) | 369 | $(CLASS_FILES) &: $(JAVA_FILES) |
| @@ -305,13 +373,23 @@ $(CLASS_FILES) &: $(JAVA_FILES) | |||
| 305 | # N.B. that find must be called all over again in case javac generated | 373 | # N.B. that find must be called all over again in case javac generated |
| 306 | # nested classes. | 374 | # nested classes. |
| 307 | 375 | ||
| 376 | ALL_CLASS_FILES = \ | ||
| 377 | $(subst $$,\$$,$(shell find $(srcdir) -type f -name *.class)) | ||
| 378 | |||
| 379 | ifneq ($(builddir),$(srcdir)) | ||
| 380 | # If the build directory is distinct from the source directory, also | ||
| 381 | # include generated class files located there. | ||
| 382 | ALL_CLASS_FILES = $(ALL_CLASS_FILES) \ | ||
| 383 | $(subst $$,\$$,$(shell find $(builddir) -type f -name *.class)) | ||
| 384 | endif | ||
| 385 | |||
| 308 | classes.dex: $(CLASS_FILES) $(if $(IS_D8_R8), $(srcdir)/proguard.conf) | 386 | classes.dex: $(CLASS_FILES) $(if $(IS_D8_R8), $(srcdir)/proguard.conf) |
| 309 | $(AM_V_D8) $(D8) --classpath $(ANDROID_JAR) \ | 387 | $(AM_V_D8) $(D8) --classpath $(ANDROID_JAR) \ |
| 310 | $(subst $$,\$$,$(shell find $(srcdir) -type f \ | 388 | $(ALL_CLASS_FILES) \ |
| 311 | -name *.class)) --output $(builddir) \ | 389 | --output $(builddir) \ |
| 312 | --min-api $(ANDROID_MIN_SDK) \ | 390 | --min-api $(ANDROID_MIN_SDK) \ |
| 313 | $(if $(filter false,$(ANDROID_DEBUGGABLE)),--release, \ | 391 | $(if $(filter false,$(ANDROID_DEBUGGABLE)),--release, \ |
| 314 | --debug) \ | 392 | --debug) \ |
| 315 | $(if $(IS_D8_R8),--pg-conf $(srcdir)/proguard.conf) | 393 | $(if $(IS_D8_R8),--pg-conf $(srcdir)/proguard.conf) |
| 316 | 394 | ||
| 317 | # When emacs.keystore expires, regenerate it with: | 395 | # When emacs.keystore expires, regenerate it with: |
| @@ -345,7 +423,8 @@ TAGS: $(ETAGS) $(tagsfiles) | |||
| 345 | $(AM_V_GEN) $(ETAGS) $(tagsfiles) | 423 | $(AM_V_GEN) $(ETAGS) $(tagsfiles) |
| 346 | 424 | ||
| 347 | clean: | 425 | clean: |
| 348 | rm -f *.apk emacs.apk-in *.dex *.unaligned *.class *.idsig | 426 | rm -f *.apk emacs.apk-in *.dex *.unaligned *.class *.idsig \ |
| 427 | cf-stamp $(CONFIG_FILE) | ||
| 349 | rm -rf install-temp $(RESOURCE_FILE) TAGS | 428 | rm -rf install-temp $(RESOURCE_FILE) TAGS |
| 350 | find . -name '*.class' $(FIND_DELETE) | 429 | find . -name '*.class' $(FIND_DELETE) |
| 351 | 430 | ||
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index 567242f2ec3..9b3e60e1a84 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java | |||
| @@ -321,39 +321,35 @@ public final class EmacsNative | |||
| 321 | 321 | ||
| 322 | static | 322 | static |
| 323 | { | 323 | { |
| 324 | /* Older versions of Android cannot link correctly with shared | 324 | /* A library search path misconfiguration prevents older versions of |
| 325 | libraries that link with other shared libraries built along | 325 | Android from successfully loading application shared libraries |
| 326 | Emacs unless all requisite shared libraries are explicitly | 326 | unless all requisite shared libraries provided by the application |
| 327 | loaded from Java. | 327 | are explicitly loaded from Java. The build process arranges that |
| 328 | 328 | EmacsConfig.EMACS_SHARED_LIBRARIES hold the names of each of | |
| 329 | Every time you add a new shared library dependency to Emacs, | 329 | these libraries in the correct order, so load them now. */ |
| 330 | please insert it here as well, before other shared libraries of | 330 | |
| 331 | which it might be a dependency. */ | 331 | libraryDeps = EmacsConfig.EMACS_SHARED_LIBRARIES; |
| 332 | |||
| 333 | libraryDeps = new String[] { "c++_shared", "gnustl_shared", | ||
| 334 | "stlport_shared", "gabi++_shared", | ||
| 335 | "png_emacs", "pcre_emacs", | ||
| 336 | "selinux_emacs", "crypto_emacs", | ||
| 337 | "packagelistparser_emacs", | ||
| 338 | "gmp_emacs", "nettle_emacs", | ||
| 339 | "p11-kit_emacs", "tasn1_emacs", | ||
| 340 | "hogweed_emacs", "gnutls_emacs", | ||
| 341 | "jpeg_emacs", "tiff_emacs", | ||
| 342 | "icuuc_emacs", "xml2_emacs", | ||
| 343 | "harfbuzz_emacs", "tree-sitter_emacs", }; | ||
| 344 | 332 | ||
| 345 | for (String dependency : libraryDeps) | 333 | for (String dependency : libraryDeps) |
| 346 | { | 334 | { |
| 347 | try | 335 | /* Remove the "lib" prefix, if any. */ |
| 348 | { | 336 | if (dependency.startsWith ("lib")) |
| 349 | System.loadLibrary (dependency); | 337 | dependency = dependency.substring (3); |
| 350 | } | 338 | |
| 351 | catch (UnsatisfiedLinkError exception) | 339 | /* If this library is provided by the operating system, don't |
| 352 | { | 340 | link to it. */ |
| 353 | /* Ignore this exception. */ | 341 | if (dependency.equals ("z") |
| 354 | } | 342 | || dependency.equals ("c") |
| 343 | || dependency.equals ("m") | ||
| 344 | || dependency.equals ("dl") | ||
| 345 | || dependency.equals ("log") | ||
| 346 | || dependency.equals ("android")) | ||
| 347 | continue; | ||
| 348 | |||
| 349 | System.loadLibrary (dependency); | ||
| 355 | } | 350 | } |
| 356 | 351 | ||
| 352 | /* At this point, it should be alright to load Emacs. */ | ||
| 357 | System.loadLibrary ("emacs"); | 353 | System.loadLibrary ("emacs"); |
| 358 | }; | 354 | }; |
| 359 | }; | 355 | }; |
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4 index abe06063ab0..2689ee34287 100644 --- a/m4/ndk-build.m4 +++ b/m4/ndk-build.m4 | |||
| @@ -339,6 +339,16 @@ NDK_BUILD_NASM= | |||
| 339 | AS_IF([test "$ndk_ARCH" = "x86" || test "$ndk_ARCH" = "x86_64"], | 339 | AS_IF([test "$ndk_ARCH" = "x86" || test "$ndk_ARCH" = "x86_64"], |
| 340 | [AC_CHECK_PROGS([NDK_BUILD_NASM], [nasm])]) | 340 | [AC_CHECK_PROGS([NDK_BUILD_NASM], [nasm])]) |
| 341 | 341 | ||
| 342 | # Search for a suitable readelf binary, which is required to generate | ||
| 343 | # the shared library list loaded on old Android systems. | ||
| 344 | AC_PATH_PROGS([READELF], [readelf llvm-readelf $host_alias-readelf], | ||
| 345 | [], [$ndk_ranlib_search_path:$PATH]) | ||
| 346 | AS_IF([test -z "$READELF"], | ||
| 347 | [AC_MSG_ERROR([A suitable `readelf' utility cannot be located. | ||
| 348 | Please verify that the Android NDK has been installed correctly, | ||
| 349 | or install a functioning `readelf' yourself.])]) | ||
| 350 | NDK_BUILD_READELF="$READELF" | ||
| 351 | |||
| 342 | # Search for a C++ compiler. Upon failure, pretend the C compiler is a | 352 | # Search for a C++ compiler. Upon failure, pretend the C compiler is a |
| 343 | # C++ compiler and use that instead. | 353 | # C++ compiler and use that instead. |
| 344 | 354 | ||
| @@ -644,6 +654,7 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES], | |||
| 644 | AC_SUBST([NDK_BUILD_CXX_LDFLAGS]) | 654 | AC_SUBST([NDK_BUILD_CXX_LDFLAGS]) |
| 645 | AC_SUBST([NDK_BUILD_ANY_CXX_MODULE]) | 655 | AC_SUBST([NDK_BUILD_ANY_CXX_MODULE]) |
| 646 | AC_SUBST([NDK_BUILD_CFLAGS]) | 656 | AC_SUBST([NDK_BUILD_CFLAGS]) |
| 657 | AC_SUBST([NDK_BUILD_READELF]) | ||
| 647 | 658 | ||
| 648 | AC_CONFIG_FILES([$ndk_DIR/Makefile]) | 659 | AC_CONFIG_FILES([$ndk_DIR/Makefile]) |
| 649 | AC_CONFIG_FILES([$ndk_DIR/ndk-build.mk]) | 660 | AC_CONFIG_FILES([$ndk_DIR/ndk-build.mk]) |