3

I’m trying to compile my Cocos2d-x project with OpenSSL to Android. I can run the project properly on Visual Studio Community 2013, but can’t compile it on the command line with cocos compile -p android --android-studio.

I installed OpenSSL to path project\cocos2d\external\OpenSSL-Win32 and added the OpenSSL include path to the Android.mk file:

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../proj.win32 \
                    $(LOCAL_PATH)/../../../cocos2d/external/OpenSSL-Win32/include

I followed Undefined reference to libssl function with Android NDK, but it didn't really help. I don't have shared libraries in my OpenSSL folder, only static ones. The best I can come up with for now is this definition:

include $(CLEAR_VARS)
LOCAL_MODULE    := crypto
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../cocos2d/external/OpenSSL-Win32/lib/MinGW/libcrypto-1_1.a
include $(PREBUILT_STATIC_LIBRARY)

This gave me the following error:

Android NDK: ERROR:jni/Android.mk:crypto: LOCAL_SRC_FILES points to a missing file
Android NDK: Check that jni/jni/../../../cocos2d/external/OpenSSL-Win32/lib/MinGW/libcrypto-1_1.a exists or that its path is correct

The file libcrypto-1_1.a is in that folder.

Edit

I downloaded prebuilt OpenSSL libraries (shared libs included) for Android from here: https://github.com/r4sas/OpenSSL-1.1-Android-Prebuilt.

This package contains an Android.mk file that has definitions for shared libraries:

include $(CLEAR_VARS)
LOCAL_MODULE    := opencrypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := openssl
LOCAL_SRC_FILES := libssl.so
include $(PREBUILT_SHARED_LIBRARY)

I added these definitions to the Android.mk file in folder cocos2dx-project\proj.android-studio\app\jni.

It also contains libcrypto.so and libssl.so files. I copied these files to cocos2dx-project\proj.android-studio\app\jni and tried to compile the project, but got the following errors:

Android NDK: Trying to define local module 'openssl' in jni/Android.mk.
Android NDK: But this module was already defined by jni/Android.mk.

Edit 2

I think I have made some progress.

My Android.mk looks like this now:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := crypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := openssl
LOCAL_SRC_FILES := libssl.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/external)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos)
$(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos/audio/include)

LOCAL_MODULE := MyLib_shared

LOCAL_MODULE_FILENAME := libMyLib

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ...

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../proj.win32 \
                    $(LOCAL_PATH)/../../../cocos2d/external/openssl/include

# _COCOS_HEADER_ANDROID_BEGIN
# _COCOS_HEADER_ANDROID_END

LOCAL_STATIC_LIBRARIES := cocos2dx_static

# _COCOS_LIB_ANDROID_BEGIN
# _COCOS_LIB_ANDROID_END

# _COCOS_LIB_IMPORT_ANDROID_BEGIN
# _COCOS_LIB_IMPORT_ANDROID_END

include $(BUILD_SHARED_LIBRARY)
$(call import-module,.)

Those shared libraries are now build properly, but I get the undefined reference error:

[armeabi] Install        : libcrypto.so => libs/armeabi/libcrypto.so
[armeabi] Install        : libssl.so => libs/armeabi/libssl.so
[armeabi] SharedLibrary  : libMyLib.so
jni/../../../proj.win32/EncryptionHelper.cpp:61: error: undefined reference to 'EVP_CIPHER_CTX_new'
Deeds
  • 45
  • 8
  • In the cited dup pay particular attention to `LOCAL_LDLIBS`. – jww Aug 14 '17 at 11:45
  • @jww See the edited section. – Deeds Aug 14 '17 at 19:40
  • If you were using a shared object, then you would use `include $(PREBUILT_SHARED_LIBRARY)` and `LOCAL_SHARED_LIBRARIES := ssl crypto`. I'm not sure what you need for a static archive instead of a shared object. `LOCAL_SRC_FILES` seems wrong, but Google really f**k'd up that build system. Its poorly dcumented and an absolute mess to use. – jww Aug 15 '17 at 00:49
  • @jww What's wrong with using a static archive? – Deeds Aug 15 '17 at 10:32
  • There's nothing wrong with a static archive. When you need the wrapper shared object because of Android and Zygote, then you must use a static archive. Also see [Android](https://wiki.openssl.org/index.php/Android#Wrapper_Shared_Objects) on the OpenSSL wiki. However, if you use C++, then your options get slimmer. You must be very careful when *not* using a shared object. Android NDK used to have a C++ Readme covering the topic. – jww Aug 15 '17 at 17:47
  • @jww Ok, thanks for the info. Could you take a look at that "Edit 2" section? I think I'm pretty close to a solution. – Deeds Aug 16 '17 at 10:06
  • The `libcrypto.so` you specified as a local module will probably never be loaded because of Zygote. Also see [Understanding Android: Zygote and DalvikVM](https://stackoverflow.com/q/9153166/608639), [Changing OpenSSL library in Android app for HttpClient](https://stackoverflow.com/q/28341215/608639) and [Compile OpenSSL to different name due to Android Zygote](https://stackoverflow.com/q/39830507/608639). You should use the static archive and a wrapper shared object. It told you Google had this build system f**k'd up. I'm speaking from experience :) – jww Aug 16 '17 at 10:52
  • This is only moderately related, but see [Noloader GihUb | Android-PRNG](https://github.com/noloader/Android-PRNG/tree/master/jni). It is for Crypto++, and it uses shared objects because of Android's C++ requirements (you probably don't have this requirement). However, it shows you how to "chain" three modules in one `Android.mk`. For the Crypto++ sample, `libstlport_shared` and `libcryptopp` were specified to build the library `libprng`. `libprng` is what clients use. In your case, my guess is, you need to include OpenSSL with something like `LOCAL_LDLIBS := libcrypto.a libssl.a`. – jww Aug 16 '17 at 10:57

1 Answers1

0

Instead of trying to make this work using a shared library, I used a static one.

Added this to Android.mk:

include $(CLEAR_VARS)
LOCAL_MODULE    := crypto_static
LOCAL_SRC_FILES := libcrypto.a
include $(PREBUILT_STATIC_LIBRARY)
...
LOCAL_STATIC_LIBRARIES := cocos2dx_static \ crypto_static

It compiles properly now.

Thank you jww for all the helpful comments and for pointing me in the right direction!

Deeds
  • 45
  • 8