From 54836c47c76f655a7e3d6cf28f0cf27b8d9f3cdd Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 24 Jan 2023 19:10:58 +0800 Subject: [PATCH] Enable libjpeg on Android * INSTALL.android: Update documentation. * build-aux/ndk-build-helper-1.mk: When building shared libraries, do not link libemacs.so with dependent archive files. * build-aux/ndk-build-helper-2.mk: Add whole archive dependencies as well. * configure.ac (HAVE_JPEG): Enable on Android. * cross/ndk-build/ndk-build-shared-library.mk: Link the shared object with archive file dependencies. * cross/ndk-build/ndk-build-static-library.mk: Build all code position-independently. * cross/ndk-build/ndk-resolve.mk: Separately resolve a names of archive and whole archive dependencies. * src/Makefile.in (JPEG_CFLAGS): New variable. (EMACS_CFLAGS): Add it. --- INSTALL.android | 21 +++-- build-aux/ndk-build-helper-1.mk | 22 +---- build-aux/ndk-build-helper-2.mk | 2 +- configure.ac | 91 ++++++++++++--------- cross/ndk-build/ndk-build-shared-library.mk | 20 +++-- cross/ndk-build/ndk-build-static-library.mk | 2 +- cross/ndk-build/ndk-resolve.mk | 31 +++++-- src/Makefile.in | 3 +- 8 files changed, 113 insertions(+), 79 deletions(-) diff --git a/INSTALL.android b/INSTALL.android index 79366425125..975a6249bb2 100644 --- a/INSTALL.android +++ b/INSTALL.android @@ -140,13 +140,16 @@ automatically build and use those modules. Google, Inc. has adapted many common Emacs dependencies to use the `ndk-build' system. Here is a non-exhaustive list of what is known to -work: +work, along with what has to be patched to make them work: libpng - https://android.googlesource.com/platform/external/libpng libwebp - https://android.googlesource.com/platform/external/webp giflib - https://android.googlesource.com/platform/external/giflib (You must add LOCAL_EXPORT_CFLAGS := -I$(LOCAL_PATH) before its Android.mk includes $(BUILD_STATIC_LIBRARY)) + libjpeg-turbo - https://android.googlesource.com/platform/external/libjpeg-turbo + (You must add LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) before + its Android.mk includes $(BUILD_SHARED_LIBRARY)) In addition, some Emacs dependencies provide `ndk-build' support themselves: @@ -382,12 +385,16 @@ them. The name under which the module is linked is the same as the Make target found on the sixth line of output from build-aux/ndk-build-helper.mk. -While the rules defined by the Makefiles in cross/ndk-build do not -have their dependencies as prerequisites (with the assumption that the -ndk-build.m4 and the Makefiles in build-aux have already added all of -the necessary targets to ndk-build.mk), dependency resolution is still -performed, as the CFLAGS and includes from dependencies must be -appended to the module's CFLAGS. +In doing so, they both include the file ndk-resolve.mk. +ndk-resolve.mk is expected to recursively add all of the exported +CFLAGS and includes of any dependencies to the compiler and linker +command lines for the module being built. + +When building a shared library module, ndk-resolve.mk is also expected +to define the variables NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) and +NDK_WHOLE_A_NAMES_$(LOCAL_MODULE), containing all static library +dependencies' archive files. They are to be linked in to the +resulting shared object file. This is done by including cross/ndk-build/ndk-resolve.mk each time a shared or static library module is going to be built. How is this diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk index d20f7d4472f..86e3ebd6558 100644 --- a/build-aux/ndk-build-helper-1.mk +++ b/build-aux/ndk-build-helper-1.mk @@ -47,22 +47,6 @@ else NDK_SO_NAMES = $(LOCAL_MODULE_FILENAME).so endif -define add-a-name -ifeq ($(findstring lib,$(1)),lib) -NDK_A_NAME = $(1).a -else -NDK_A_NAME = lib$(1).a -endif - -ifeq ($$(NDK_A_NAMES:$$(NDK_A_NAME)=),$$(NDK_A_NAMES)) -NDK_A_NAMES := $$(NDK_A_NAMES) $$(NDK_A_NAME) - -# Now recurse over this module's dependencies. -$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module)))) -$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module)))) -endif -endef - define add-so-name ifeq ($(findstring lib,$(1)),lib) NDK_SO_NAME = $(1)_emacs.so @@ -74,17 +58,17 @@ ifeq ($$(NDK_SO_NAMES:$$(NDK_SO_NAME)=),$$(NDK_SO_NAMES)) NDK_SO_NAMES := $$(NDK_SO_NAMES) $$(NDK_SO_NAME) # Now recurse over this module's dependencies. -$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module)))) $$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module)))) endif endef # Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and -# LOCAL_SHARED_LIBRARIES. +# LOCAL_SHARED_LIBRARIES. Static library dependencies can be ignored +# while building a shared library, as they will be linked in to the +# resulting shared object file later. SYSTEM_LIBRARIES = z libz libc c -$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module)))) $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module)))) $(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname))) diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk index 82c1d53c7d0..bd50e8b3efa 100644 --- a/build-aux/ndk-build-helper-2.mk +++ b/build-aux/ndk-build-helper-2.mk @@ -79,7 +79,7 @@ endef SYSTEM_LIBRARIES = z libz -$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module)))) +$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module)))) $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module)))) $(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) $(and $(NDK_SO_NAMES), -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname)))) diff --git a/configure.ac b/configure.ac index f3a4b4301a4..6e8fc1f0835 100644 --- a/configure.ac +++ b/configure.ac @@ -1046,6 +1046,7 @@ package will likely install on older systems but crash on startup.]) passthrough="$passthrough --with-webp=$with_webp" passthrough="$passthrough --with-gif=$with_gif" passthrough="$passthrough --with-json=$with_json" + passthrough="$passthrough --with-jpeg=$with_jpeg" AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \ ANDROID_SDK="$android_sdk" android_abi=$android_abi \ @@ -1104,7 +1105,6 @@ if test "$ANDROID" = "yes"; then # disabled, both within the recursive invocation of configure and # outside. with_xpm=no - with_jpeg=no with_tiff=no # Some of these dependencies are now supported within Android, so @@ -1114,6 +1114,7 @@ if test "$ANDROID" = "yes"; then with_webp=no with_gif=no with_json=no + with_jpeg=no fi with_xml2=no @@ -4551,52 +4552,66 @@ AC_SUBST([LIBXPM]) ### Use -ljpeg if available, unless '--with-jpeg=no'. HAVE_JPEG=no LIBJPEG= +JPEG_CFLAGS= if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ || test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes" \ || test "$window_system" = "pgtk" \ || test "${REALLY_ANDROID}" = "yes"; then if test "${with_jpeg}" != "no"; then - AC_CACHE_CHECK([for jpeglib 6b or later], - [emacs_cv_jpeglib], - [OLD_LIBS=$LIBS - for emacs_cv_jpeglib in yes -ljpeg no; do - case $emacs_cv_jpeglib in - yes) ;; - no) break;; - *) LIBS="$LIBS $emacs_cv_jpeglib";; - esac - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[#undef HAVE_STDLIB_H /* Avoid config.h/jpeglib.h collision. */ - #include /* jpeglib.h needs FILE and size_t. */ - #include - #include - char verify[JPEG_LIB_VERSION < 62 ? -1 : 1]; - struct jpeg_decompress_struct cinfo; - ]], - [[ - jpeg_create_decompress (&cinfo); - WARNMS (&cinfo, JWRN_JPEG_EOF); - jpeg_destroy_decompress (&cinfo); - ]])], - [emacs_link_ok=yes], - [emacs_link_ok=no]) - LIBS=$OLD_LIBS - test $emacs_link_ok = yes && break - done]) - if test "$emacs_cv_jpeglib" != no; then - HAVE_JPEG=yes - AC_DEFINE([HAVE_JPEG], [1], - [Define to 1 if you have the jpeg library (typically -ljpeg).]) - ### mingw32 doesn't use -ljpeg, since it loads the library - ### dynamically when needed, and doesn't want a run-time - ### dependency on the jpeglib DLL. - test "$emacs_cv_jpeglib" != yes && test "${opsys}" != "mingw32" \ - && LIBJPEG=$emacs_cv_jpeglib + if test "${REALLY_ANDROID}" = "yes"; then + # Look for libjpeg using the NDK. + ndk_SEARCH_MODULE([libjpeg], [JPEG], [HAVE_JPEG=yes]) + + if test "$HAVE_JPEG" = "yes"; then + LIBJPEG="$JPEG_LIBS" + + AC_DEFINE([HAVE_JPEG], [1], + [Define to 1 if you have the jpeg library (typically -ljpeg).]) + fi + else + AC_CACHE_CHECK([for jpeglib 6b or later], + [emacs_cv_jpeglib], + [OLD_LIBS=$LIBS + for emacs_cv_jpeglib in yes -ljpeg no; do + case $emacs_cv_jpeglib in + yes) ;; + no) break;; + *) LIBS="$LIBS $emacs_cv_jpeglib";; + esac + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#undef HAVE_STDLIB_H /* Avoid config.h/jpeglib.h collision. */ + #include /* jpeglib.h needs FILE and size_t. */ + #include + #include + char verify[JPEG_LIB_VERSION < 62 ? -1 : 1]; + struct jpeg_decompress_struct cinfo; + ]], + [[ + jpeg_create_decompress (&cinfo); + WARNMS (&cinfo, JWRN_JPEG_EOF); + jpeg_destroy_decompress (&cinfo); + ]])], + [emacs_link_ok=yes], + [emacs_link_ok=no]) + LIBS=$OLD_LIBS + test $emacs_link_ok = yes && break + done]) + if test "$emacs_cv_jpeglib" != no; then + HAVE_JPEG=yes + AC_DEFINE([HAVE_JPEG], [1], + [Define to 1 if you have the jpeg library (typically -ljpeg).]) + ### mingw32 doesn't use -ljpeg, since it loads the library + ### dynamically when needed, and doesn't want a run-time + ### dependency on the jpeglib DLL. + test "$emacs_cv_jpeglib" != yes && test "${opsys}" != "mingw32" \ + && LIBJPEG=$emacs_cv_jpeglib + fi fi fi fi AC_SUBST([LIBJPEG]) +AC_SUBST([JPEG_CFLAGS]) HAVE_LCMS2=no LCMS2_CFLAGS= diff --git a/cross/ndk-build/ndk-build-shared-library.mk b/cross/ndk-build/ndk-build-shared-library.mk index c4fb523a0c1..6a607049a9c 100644 --- a/cross/ndk-build/ndk-build-shared-library.mk +++ b/cross/ndk-build/ndk-build-shared-library.mk @@ -60,15 +60,11 @@ NDK_CFLAGS ::= -mthumb endif endif -LOCAL_MODULE_FILENAME := $(strip $(LOCAL_MODULE_FILENAME)) - -ifndef LOCAL_MODULE_FILENAME ifeq ($(findstring lib,$(LOCAL_MODULE)),lib) LOCAL_MODULE_FILENAME := $(LOCAL_MODULE)_emacs else LOCAL_MODULE_FILENAME := lib$(LOCAL_MODULE)_emacs endif -endif # Since a shared library is being built, suffix the library with # _emacs. Otherwise, libraries already on the system will be found @@ -89,6 +85,16 @@ ALL_OBJECT_FILES$(LOCAL_MODULE) = $(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source)))) -# Now define the rule to build the shared library. -$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE)) - $(NDK_BUILD_CC) $^ -o $@ -shared $(NDK_LDFLAGS$(LOCAL_MODULE)) +# Now define the rule to build the shared library. Shared libraries +# link with all of the archive files from the static libraries on +# which they depend. + +define define-module-rule +$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE)) $(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)) $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE)) + $(NDK_BUILD_CC) $(1) $(2) -o $$@ -shared $(NDK_LDFLAGS$(LOCAL_MODULE)) +endef + +NDK_WHOLE_ARCHIVE_PREFIX = -Wl,--whole-archive +NDK_WHOLE_ARCHIVE_SUFFIX = -Wl,--no-whole-archive + +$(eval $(call define-module-rule,$(ALL_OBJECT_FILES$(LOCAL_MODULE)) $(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)),$(and $(strip $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE))),$(NDK_WHOLE_ARCHIVE_PREFIX) $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE)) $(NDK_WHOLE_ARCHIVE_SUFFIX)))) diff --git a/cross/ndk-build/ndk-build-static-library.mk b/cross/ndk-build/ndk-build-static-library.mk index 2eddb215429..2e4893a997b 100644 --- a/cross/ndk-build/ndk-build-static-library.mk +++ b/cross/ndk-build/ndk-build-static-library.mk @@ -44,7 +44,7 @@ ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1 endef NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(LOCAL_C_INCLUDES)) -NDK_CFLAGS_$(LOCAL_MODULE) += -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH)) +NDK_CFLAGS_$(LOCAL_MODULE) += -fPIC -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH)) NDK_ASFLAGS_$(LOCAL_MODULE) := $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH)) NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS) $(LOCAL_LDFLAGS) ALL_OBJECT_FILES$(LOCAL_MODULE) := diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk index 29dd5c9908d..7fe807e35cc 100644 --- a/cross/ndk-build/ndk-resolve.mk +++ b/cross/ndk-build/ndk-resolve.mk @@ -22,9 +22,12 @@ # Save information. NDK_LOCAL_PATH_$(LOCAL_MODULE) := $(LOCAL_PATH) NDK_LOCAL_STATIC_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES) +NDK_LOCAL_WHOLE_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_WHOLE_STATIC_LIBRARIES) NDK_LOCAL_SHARED_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_SHARED_LIBRARIES) NDK_LOCAL_EXPORT_CFLAGS_$(LOCAL_MODULE) := $(LOCAL_EXPORT_CFLAGS) NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE) := $(LOCAL_EXPORT_C_INCLUDES) +NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) := +NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) := # List of all dependencies resolved for this module thus far. # Used to avoid infinite recursion. @@ -33,15 +36,33 @@ NDK_RESOLVED_$(LOCAL_MODULE) := define ndk-resolve ifeq ($(patsubst $(1),,$(NDK_RESOLVED$(LOCAL_MODULE))),$(NDK_RESOLVED$(LOCAL_MODULE))) -NDK_RESOLVED$(LOCAL_MODULE) += $(1) +NDK_RESOLVED_$(LOCAL_MODULE) += $(1) NDK_CFLAGS_$(LOCAL_MODULE) += $(NDK_LOCAL_EXPORT_CFLAGS_$(1)) NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix -I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1))) -$$(foreach module,$$(NDK_LOCAL_STATIC_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module)))) -$$(foreach module,$$(NDK_LOCAL_SHARED_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module)))) +ifneq ($(2),) +ifneq ($(findstring lib,$(1)),) +NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += $(1).a +else +NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += lib$(1).a +endif +endif + +ifneq ($(3),) +ifneq ($(findstring lib,$(1)),) +NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) += $(1).a +else +NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) += lib$(1).a +endif +endif + +$$(foreach module,$$(NDK_LOCAL_STATIC_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),1,))) +$$(foreach module,$$(NDK_LOCAL_SHARED_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),,))) +$$(foreach module,$$(NDK_LOCAL_WHOLE_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),,1))) endif endef -$(foreach module,$(LOCAL_SHARED_LIBRARIES),$(eval $(call ndk-resolve,$(module)))) -$(foreach module,$(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES),$(eval $(call ndk-resolve,$(module)))) +$(foreach module,$(LOCAL_SHARED_LIBRARIES),$(eval $(call ndk-resolve,$(module),,))) +$(foreach module,$(LOCAL_STATIC_LIBRARIES),$(eval $(call ndk-resolve,$(module),1,))) +$(foreach module,$(LOCAL_WHOLE_STATIC_LIBRARIES), $(eval $(call ndk-resolve,$(module),,1))) diff --git a/src/Makefile.in b/src/Makefile.in index ddc0b89dda1..29beb519abb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -139,6 +139,7 @@ LIB_PTHREAD=@LIB_PTHREAD@ LIBIMAGE=@LIBTIFF@ @LIBJPEG@ @LIBPNG@ @LIBGIF@ @LIBXPM@ @WEBP_LIBS@ GIF_CFLAGS=@GIF_CFLAGS@ +JPEG_CFLAGS=@JPEG_CFLAGS@ XCB_LIBS=@XCB_LIBS@ XFT_LIBS=@XFT_LIBS@ @@ -431,7 +432,7 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ $(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) $(XSYNC_CFLAGS) $(TREE_SITTER_CFLAGS) \ $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ $(WERROR_CFLAGS) $(HAIKU_CFLAGS) $(XCOMPOSITE_CFLAGS) $(XSHAPE_CFLAGS) \ - $(ANDROID_CFLAGS) $(GIF_CFLAGS) + $(ANDROID_CFLAGS) $(GIF_CFLAGS) $(JPEG_CFLAGS) ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS) ALL_OBJC_CFLAGS = $(EMACS_CFLAGS) \ $(filter-out $(NON_OBJC_CFLAGS),$(WARN_CFLAGS)) $(CFLAGS) \ -- 2.39.5