[Solved] How to link shared library (MuPDF) with cocos-x for android studio project

I need to resize PDF graphics on Android (which in iOS could be done by Core Graphics library easily) and therefore I’ve decided to use MuPDF library.

  1. I’ve created a HelloWorld cocs2d-x project

  2. I’ve added a very simple MuPDF code into HelloWorldScene.cpp:

     #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
     #include <mupdf/fitz.h>
     #endif
       ...
       #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
         fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
         fz_drop_context(ctx);
      #endif
      ...
    
  3. I’ve compiled MuPDF library as described in How to build MuPDF for Android and got a shared library “mupdf/platform/android/libs/armeabi-v7a/libmupdf.so”

  4. I’ve added the library into Android project as a library module as described in Integration of MuPDF Project as a Library into an Android Studio Project

  5. I had issues with compiling of cocos2d-x and MuPDF by calling

    cd HelloWorld
    cocos compile -p android --android-studio

and therefore I’ve copied MuPDF header files into HelloWorld/cocos2d/external/mupdf

Now I have a linking problem:

cocos compile -p android --android-studio

brings:

 jni/../../../Classes/HelloWorldScene.cpp:80: error: undefined reference to 'fz_new_context_imp(fz_alloc_context_s const*, fz_locks_context_s const*, unsigned int, char const*)'
jni/../../../Classes/HelloWorldScene.cpp:81: error: undefined reference to 'fz_drop_context(fz_context_s*)'
collect2: error: ld returned 1 exit status
make: *** [obj/local/armeabi/libcocos2dcpp.so] Error 1
 make: Leaving directory `/Users/bsi/Development/HelloWorld/proj.android-studio/app'

Could someone point me to an example how can I add already compiled external C/C++ library into cocos2d-x proj.android-studio, so that it will work if I call cocos compile -p android --android-studio
brings?

I found some “elder references” to LOCAL_SHARED_LIBRARIES and Android.mk but both do not exist in proj.android-studio.

Thanks for your help
siarsky

After reading Mastering Cmake by Ken Martin, understanding Android.mk file and compiling+linking make process, I finally found the solution:

1. Compile mupdf
- follow the process described on the mupdf page, which builds a shared library for armeabi
- change the architecture:

  vi ./platform/android/jni/Application.mk
  • and compile shared library for armeabi-v7a, mips and x86. Be sure to use the same android-?? (for example android-19) version as you use for cocos2d-x compilation. If needed change minSdkVersion in mupdf AndroidManifest.xml:

     vi ./platform/android/AndroidManifest.xml
    

2. Copy include files and compiled shared libraries into cocos2d-x proj.android-studio

cd proj.android-studio
mkdir mupdf
mkdir mupdf/include
#copy mupdf header files into android studio directory
cp -pR mupdf/include/* proj.android-studio/mupdf/include  


mkdir mupdf/libs
mkdir mupdf/libs/armeabi
mkdir mupdf/libs/armeabi-v7a
mkdir mupdf/libs/mips
mkdir mupdf/libs/x86
<copy all builded shared mupdf libraries into architecture directory>

The result should look like:
./libs/armeabi/libmupdf.so
./libs/armeabi-v7a/libmupdf.so
./libs/mips/libmupdf.so
./libs/x86/libmupdf.so

3. Add mupdf shared library as a new module into Android.mk file

vi proj.android-studio/app/jni/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := mupdf
LOCAL_SRC_FILES := ../../mupdf/libs/$(TARGET_ARCH_ABI)/libmupdf.so
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/../../mupdf/include
include $(PREBUILT_SHARED_LIBRARY)

and add dependency to mupdf module from cocos2dcpp_shared module in the same file:

LOCAL_SHARED_LIBRARIES := mupdf
LOCAL_STATIC_LIBRARIES := cocos2dx_static

4. Use mupdf in cocos2d
This step costs me a lot lot lot lot lot time to find out how to do it.

I’ve added mupdf header file into HelloWorldScene.cpp

#include <mupdf/fitz.h>

and called a mupdf function

fz_document *doc = fz_open_document(NULL, NULL);

to just make sure compiling and linking work fine by calling

cocos compile -p android --android-studio

but I’ve got:

jni/../../../Classes/HelloWorldScene.cpp:82: error: undefined reference to 'fz_open_document(fz_context_s*, char const*)'
collect2: error: ld returned 1 exit status
make: *** [obj/local/armeabi/libcocos2dcpp.so] Error 1
make: Leaving directory `HelloWorld/proj.android-studio/app'

Problem: Name mangling, which I never heard about before (I am not a C/C++ guy). Solution is easy, if you understand, what’s the problem. Add extern “C” for all mupdf includes:

extern "C" {
    #include <mupdf/fitz.h>
}

I hope it helps others.

siarsky