Android NDK Makefile、Android.mk 和 OCaml 的通用链接
General Linking for Android NDK Makefile, Android.mk and OCaml
我正在使用 Android NDK 套件并拥有此 Android.mk 文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := main.c
# This name had to be that created shared library
LOCAL_STATIC_LIBRARIES := ocaml
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
这编译成功并在 /home/gar/ocaml_on_android/libs/armeabi
simple_test 和 hello.so.
中创建
然而,当我 运行 我的 Nexus 7 上的代码时,我得到
CANNOT LINK EXECUTABLE: library "/home/gar/ocaml_on_android/obj/local/armeabi/hello.so" not found
这意味着它在编译时没有正确链接。我如何编写这个 Android.mk 文件,以便所有内容都在一个可执行文件中静态编译?
编辑:
评论后,使用这个:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := wrapper.c
# This name had to be that created shared library
LOCAL_SHARED_LIBRARIES := hello.so
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
并且在我的项目的 libs
文件夹中我仍然有两个对象,hello.so 和 simple_test 可执行文件,我希望只看到一个。对于 LOCAL_SHARED_LIBRARIES
,不确定我是否需要输入模块名称、ocaml 或实际的共享对象 hello.so。这两种情况仍然在 libs 目录中产生了两个对象。
EDIT2:我的 Android.mk
现在有了这个
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := wrapper.c
# This name had to be that created shared library
LOCAL_CFLAGS := -Wl,-Bstatic -static
LOCAL_SHARED_LIBRARIES := hello ocaml
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
当我检查创建的可执行文件时,我仍然看到它依赖于共享库
arm-linux-androideabi-readelf -d simple_test | grep NEEDED
0x00000001 (NEEDED) Shared library: [/home/gar/asm_on_android/obj/local/armeabi/hello.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
我还在设备上的 shell 上尝试了 LD_LIBRARY_PATH=. ./simple_test
命令,但出现此错误:
LD_LIBRARY_PATH= . ./simple_test
sh: ./simple_test[1]: syntax error: '\
4' unexpected
这就是共享库的使用方式。您可以将 hello.so
推送到 simple_test
可执行文件附近的设备。
Android.mk 的语法应该是
LOCAL_SHARED_LIBRARIES := ocaml
在 shell 命令行上,使用
LD_LIBRARY_PATH=. ./simple_test
感谢 Alex 的帮助。
我决定暂时跳过 Android-NDK,直接使用 Makefile 解决方案,它确实有效。
这是 Makefile
cc := arm-linux-androideabi-gcc
sys_root := /Users/Edgar/.opam/4.02.3+32bit/lib/android-ndk/platforms/android-21/arch-arm
includes := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/include
ml_includes := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/lib/ocaml/
libs := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/lib
# Be sure to do export LD_LIBRARY_PATH=. and then run the program.
# Not sure how to do static linking yet, this will only dynamically
# link the program
complete: lib
$(cc) --sysroot $(sys_root) -I$(includes) -L$(libs) \
-pie -I$(ml_includes) hello.so main.c -o Finished
lib:
ocamlfind -toolchain android ocamlopt -output-complete-obj \
-cclib '-lm -shared' hello.ml -o hello.so
# This is a pure OCaml exectuable
exec:
ocamlfind -toolchain android ocamlopt \
-verbose -ccopt '-fPIE' -cclib '-pie' hello.ml -o hello
.PHONY: clean
clean:
@rm -rf *.{cmi,cmt,o,cmx,so} Finished
...根据需要替换您的名称和路径。
也把回购放在这里,https://github.com/fxfactorial/ocaml_on_android
我正在使用 Android NDK 套件并拥有此 Android.mk 文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := main.c
# This name had to be that created shared library
LOCAL_STATIC_LIBRARIES := ocaml
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
这编译成功并在 /home/gar/ocaml_on_android/libs/armeabi
simple_test 和 hello.so.
然而,当我 运行 我的 Nexus 7 上的代码时,我得到
CANNOT LINK EXECUTABLE: library "/home/gar/ocaml_on_android/obj/local/armeabi/hello.so" not found
这意味着它在编译时没有正确链接。我如何编写这个 Android.mk 文件,以便所有内容都在一个可执行文件中静态编译?
编辑: 评论后,使用这个:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := wrapper.c
# This name had to be that created shared library
LOCAL_SHARED_LIBRARIES := hello.so
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
并且在我的项目的 libs
文件夹中我仍然有两个对象,hello.so 和 simple_test 可执行文件,我希望只看到一个。对于 LOCAL_SHARED_LIBRARIES
,不确定我是否需要输入模块名称、ocaml 或实际的共享对象 hello.so。这两种情况仍然在 libs 目录中产生了两个对象。
EDIT2:我的 Android.mk
现在有了这个LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ocaml
LOCAL_SRC_FILES := ocaml/hello.so
include $(PREBUILT_SHARED_LIBRARY)
# ocamlfind -toolchain android ocamlopt \
# -output-complete-obj -cclib -shared hello.ml -o hello.so
include $(CLEAR_VARS)
LOCAL_MODULE := simple_test
LOCAL_SRC_FILES := wrapper.c
# This name had to be that created shared library
LOCAL_CFLAGS := -Wl,-Bstatic -static
LOCAL_SHARED_LIBRARIES := hello ocaml
LOCAL_C_INCLUDES += /home/gar/.opam/android_coding/lib/ocaml
include $(BUILD_EXECUTABLE)
当我检查创建的可执行文件时,我仍然看到它依赖于共享库
arm-linux-androideabi-readelf -d simple_test | grep NEEDED
0x00000001 (NEEDED) Shared library: [/home/gar/asm_on_android/obj/local/armeabi/hello.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
我还在设备上的 shell 上尝试了 LD_LIBRARY_PATH=. ./simple_test
命令,但出现此错误:
LD_LIBRARY_PATH= . ./simple_test
sh: ./simple_test[1]: syntax error: '\
4' unexpected
这就是共享库的使用方式。您可以将 hello.so
推送到 simple_test
可执行文件附近的设备。
Android.mk 的语法应该是
LOCAL_SHARED_LIBRARIES := ocaml
在 shell 命令行上,使用
LD_LIBRARY_PATH=. ./simple_test
感谢 Alex 的帮助。
我决定暂时跳过 Android-NDK,直接使用 Makefile 解决方案,它确实有效。
这是 Makefile
cc := arm-linux-androideabi-gcc
sys_root := /Users/Edgar/.opam/4.02.3+32bit/lib/android-ndk/platforms/android-21/arch-arm
includes := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/include
ml_includes := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/lib/ocaml/
libs := /Users/Edgar/.opam/4.02.3+32bit/arm-linux-androideabi/lib
# Be sure to do export LD_LIBRARY_PATH=. and then run the program.
# Not sure how to do static linking yet, this will only dynamically
# link the program
complete: lib
$(cc) --sysroot $(sys_root) -I$(includes) -L$(libs) \
-pie -I$(ml_includes) hello.so main.c -o Finished
lib:
ocamlfind -toolchain android ocamlopt -output-complete-obj \
-cclib '-lm -shared' hello.ml -o hello.so
# This is a pure OCaml exectuable
exec:
ocamlfind -toolchain android ocamlopt \
-verbose -ccopt '-fPIE' -cclib '-pie' hello.ml -o hello
.PHONY: clean
clean:
@rm -rf *.{cmi,cmt,o,cmx,so} Finished
...根据需要替换您的名称和路径。 也把回购放在这里,https://github.com/fxfactorial/ocaml_on_android