Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Studio NDK built strips references required by other static libraries #553

Closed
cmeng-git opened this issue Oct 24, 2017 · 3 comments

Comments

@cmeng-git
Copy link

Description

I was building a ffmpeg.so shared libraries from multiple pre-built static libraries using standalone-toolchains on Ubuntu 16.04

The static libraries are built based on the scripts in the following site but with ffmpeg version 3.3.3
https://github.com/IljaKosynkin/FFmpeg-Development-Kit/tree/master

The Android.mk (shown below) is used to build the shared library.
I found that when I specify the LOCAL_STATIC_LIBRARIES contents in alphabetic order; the linker throws multiple undefined references e.g.

Error:error: undefined reference to 'av_bitstream_filter_init'
Error:error: undefined reference to 'av_bitstream_filter_close'
Error:error: undefined reference to 'av_bitstream_filter_filter'
Error:error: undefined reference to 'av_spherical_projection_name'
Error:error: undefined reference to 'av_spherical_tile_bounds'

After some trial, found that I need to specify as follow to avoid any undefined reference being throw by the linker.
LOCAL_STATIC_LIBRARIES := libavfilter libavformat libavcodec libavdevice libavutil libswresample libswscale

Shouldn't the linker has multiple passes to ensure all used references are not accidentally being stripped.

Android.mk

# The static libraries are built based on the scripts in the following site but with ffmpeg 3.3.3
# https://github.com/IljaKosynkin/FFmpeg-Development-Kit/tree/master
# see => https://medium.com/@ilja.kosynkin/building-ffmpeg-for-android-607222677a9e

LOCAL_PATH := $(call my-dir)
LOCAL_LIB_PATH = android/$(TARGET_ARCH_ABI)

# ========== libavcodec ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavcodec.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libavdevice ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavdevice.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libavfilter ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libavformat ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavformat.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libavutil ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavutil.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libswresample ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libswresample.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== libswscale ==================
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libswscale.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

# ========== jnffmpeg (.so library) ==================
include $(CLEAR_VARS)
LOCAL_MODULE := jnffmpeg
LOCAL_LDLIBS += -llog -lz
# Order of static libraries is important to avoid ndk strips of reference required by later libraries
LOCAL_STATIC_LIBRARIES := libavfilter libavformat libavcodec libavdevice libavutil libswresample libswscale
LOCAL_C_INCLUDES := $(LOCAL_LIB_PATH)/include
LOCAL_SRC_FILES := ./org_atalk_impl_neomedia_codec_FFmpeg.c
LOCAL_CFLAGS = -DFIXED_POINT -DUSE_KISS_FFT -DEXPORT="" -UHAVE_CONFIG_H -Wdeprecated-declarations
include $(BUILD_SHARED_LIBRARY)

Environment Details

  • NDK Version: version 15.2.4303891
  • Build sytem: ndk-build with static libraries generated using standalone toolchains on Ubuntu 16.04
    using build.gradle i.e.
    commandLine "$ndkDir/ndk-build",
    '-C' + projectDir + '/jni',
    '-j', Runtime.runtime.availableProcessors(),
    'all',
    'NDK_OUT=' + project.buildDir,
    'NDK_LIBS_OUT=' + projectDir + '/libs/$(TARGET_ARCH_ABI)',
    'NDK_TOOLCHAIN_VERSION=4.9'
  • Host OS: Windows 7 and Ubuntu 16.04 (both 64-bits)
  • Compiler: tools default to use gcc on stanalone-toolchain
  • ABI: armeabi armeabi-v7a
  • STL: system
  • NDK API level: API-15
  • Device API level: API-15 and API-21
@stephenhines
Copy link
Collaborator

#545 is a similar request, but order matters for most linkers today. While circular dependencies can arise, it is much better to just keep your list in order, especially considering that you are building a known project that already should have a properly "sorted" set of input libraries. I'm marking this closed, since it is really a duplicate of #545.

@DanAlbert
Copy link
Member

ndk-build topologically sorts your libraries so they link in the right order, but you have to tell ndk-build about the dependencies of your prebuilts. i.e.

include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= $(LOCAL_LIB_PATH)/lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := libavformat  # tell ndk-build about the dependency
include $(PREBUILT_STATIC_LIBRARY)

No idea if that dependency is correct, I'm just using it as an example.

@cmeng-git
Copy link
Author

Thank for the information. I struggled for two days thinking that there was a problem in the include path specified. Only then I realised it is the libraries interdependency that is the cause of problem and found the order of libraries helps to get rid of problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants