AndiDog
AndiDog

Reputation: 70148

Native libraries .so.XY failing to link at runtime

I have built FFmpeg for Android and want to use it in an application like so:

System.loadLibrary("avutil");
System.loadLibrary("swscale");
System.loadLibrary("avcodec");
System.loadLibrary("avformat");

The build output are lib*.so, lib*.so.MAJOR and lib*.so.MAJOR.MINOR.OTHER files. Inside the shared objects are references like lib*.so.MAJOR, for example libswscale.so.2 requires libavutil.so.52.

Now if I put the *.so files in the project's libs folder (more exactly libs/armeabi-v7a), I of course get

01-25 12:06:40.270: E/AndroidRuntime(2905): java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 107 could not load needed library 'libavutil.so.52' for 'libswscale.so' (load_library[1091]: Library 'libavutil.so.52' not found)

However if instead I put the *.so.MAJOR files in the libs folder to solve the linking exception, I get the same error when running the app from Eclipse. And I noticed the files do not even get exported if I create an APK! So how do I tell Eclipse to package the *.so.MAJOR files as libraries? Or alternatively, how do I compile the shared objects in a way that they reference each other by *.so instead of *.so.MAJOR?

EDIT: It seems there's no way to package *.so.XYZ files automatically.

Upvotes: 2

Views: 935

Answers (2)

Sunderr
Sunderr

Reputation: 109

Actually, you don't need to do that. What you need to do is edit the configure file. And find out this:

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

Modified them to be:

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

Upvotes: 1

AndiDog
AndiDog

Reputation: 70148

Didn't find a solution to take the .so.MAJOR files as I wished. It seems to me that the Android build system only copies *.so files automatically and doesn't allow other file extensions.
So I rewrote the FFmpeg makefiles to have the shared objects reference each other by libXXX.so.

In library.mak, I replaced $(SHFLAGS) in the following recipe

$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver
    $(SLIB_CREATE_DEF_CMD)
    $$(LD) $(SHFLAGS) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
    $(SLIB_EXTRA_CMD)

so that the third line looks like

$(subst $$(@F),$(SLIBNAME),$(SHFLAGS))

For those who don't understand the substitution (like me before), check this directly related answer.

Upvotes: 1

Related Questions