A partire da NDK r8d, questo può essere risolto in un modo molto più semplice.
-
Crea un progetto con la seguente gerarchia di directory:
project/ jni/ Android.mk Application.mk *.c, *.cpp, *.h, etc.
-
Compila Android.mk con il seguente contenuto. La cosa più importante è l'ultima riga. Controlla il documento NDK per il significato delle altre variabili.
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := name-of-your-executable LOCAL_SRC_FILES := a.cpp b.cpp c.cpp etc.cpp LOCAL_CPPFLAGS := -std=gnu++0x -Wall -fPIE # whatever g++ flags you like LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -fPIE -pie # whatever ld flags you like include $(BUILD_EXECUTABLE) # <-- Use this to build an executable.
-
Vai allo
project/
directory e digitare semplicementendk-build
Il risultato verrà inserito in
project/libs/<arch>/name-of-your-executable
.
http://www.bekatul.info/content/native-c-application-android [rotto (9 novembre 2015)]
Collegamento Wayback Machine
Per riassumere l'articolo...
Il codice di prova è :
#include <stdio.h>//for printf
#include <stdlib.h>//for exit
int main(int argc, char **argv)
{
int i = 1;
i+=2;
printf("Hello, world (i=%d)!\n", i);
return 0;
exit(0);
}
Il Makefile è :
APP := test
ROOT := /home/dd/android
INSTALL_DIR := /data/tmp
NDK_PLATFORM_VER := 8
ANDROID_NDK_ROOT := $(ROOT)/android-ndk-r5
ANDROID_NDK_HOST := linux-x86
ANDROID_SDK_ROOT := $(ROOT)/android-sdk-linux_86
PREBUILD := $(ANDROID_NDK_ROOT)/toolchains/arm-eabi-4.4.0/prebuilt/$(ANDROID_NDK_HOST)
BIN := $(PREBUILD)/bin/
LIB := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
INCLUDE := $(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
CC := $(BIN)/arm-eabi-gcc
GDB_CLIENT := $(BIN)/arm-eabi-gdb
LIBCRT := $(LIB)/crtbegin_dynamic.o
LINKER := /system/bin/linker
DEBUG := -g
CFLAGS := $(DEBUG) -fno-short-enums -I$(INCLUDE)
CFLAGS += -Wl,-rpath-link=$(LIB),-dynamic-linker=$(LINKER) -L$(LIB)
CFLAGS += -nostdlib -lc
all: $(APP)
$(APP): $(APP).c
$(CC) -o [email protected] $< $(CFLAGS) $(LIBCRT)
install: $(APP)
$(ANDROID_SDK_ROOT)/platform-tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
$(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
shell:
$(ANDROID_SDK_ROOT)/platform-tools/adb shell
run:
$(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/$(APP)
debug-install:
$(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
$(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver
debug-go:
$(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234
$(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP)
debug:
$(GDB_CLIENT) $(APP)
clean:
@rm -f $(APP).o $(APP)
L'autore ha archiviato quei file sul suo computer Linux locale all'indirizzo:
/home/dd/android/dev/native/test.c
/home/dd/android/dev/native/Makefile
L'autore lo ha quindi compilato e testato con:
[email protected]:~/android/dev/native$ make clean; make; make install; make run
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test
45 KB/s (2545 bytes in 0.054s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/test
Hello, world (i=3)!
L'SDK e l'NDK utilizzati erano:
source code: /home/dd/android/dev/native
android ndk: /home/dd/android/android-ndk-r5
android sdk: /home/dd/android/android-sdk-linux_86
Tuttavia, la guida al debug è stata la parte davvero interessante! Copia e incolla...
Imposta la compilazione per abilitare il debug:
DEBUG = -g
CFLAGS := $(DEBUG) -fno-short-enums -I$(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
copia il file gdbserver ($(PREBUILD)/../gdbserver) nell'emulatore, aggiungi il target in Makefile piuttosto che semplificare:
debug-install:
$(ANDROID_SDK_ROOT)/platform-tools/adb push $(PREBUILD)/../gdbserver $(INSTALL_DIR)/gdbserver
$(ANDROID_SDK_ROOT)/platform-tools/adb shell chmod 777 $(INSTALL_DIR)/gdbserver
Ora eseguiremo il debug alla porta 1234:
debug-go:
$(ANDROID_SDK_ROOT)/platform-tools/adb forward tcp:1234: tcp:1234
$(ANDROID_SDK_ROOT)/platform-tools/adb shell $(INSTALL_DIR)/gdbserver :1234 $(INSTALL_DIR)/$(APP)
Quindi eseguilo:
[email protected]:~/android/dev/native$ make clean; make; make install; make debug-install; make debug-go
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gcc -c -g -fno-short-enums -I/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/include test.c -o test.o
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-g++ -Wl,--entry=main,-dynamic-linker=/system/bin/linker,-rpath-link=/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -L/home/dd/android/android-ndk-r5/platforms/android-9/arch-arm/usr/lib -nostdlib -lc -o test test.o
/home/dd/android/android-sdk-linux_86/platform-tools/adb push test /data/tmp/test
71 KB/s (3761 bytes in 0.051s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/test
/home/dd/android/android-sdk-linux_86/platform-tools/adb push /home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/../gdbserver /data/tmp/gdbserver
895 KB/s (118600 bytes in 0.129s)
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell chmod 777 /data/tmp/gdbserver
/home/dd/android/android-sdk-linux_86/platform-tools/adb forward tcp:1234: tcp:1234
/home/dd/android/android-sdk-linux_86/platform-tools/adb shell /data/tmp/gdbserver :1234 /data/tmp/test
Process /data/tmp/test created; pid = 472
Listening on port 1234
Ora apri un'altra console ed esegui il debugger:
[email protected]:~/android/dev/native$ make debug
/home/dd/android/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin//arm-eabi-gdb test
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-elf-linux"...
(gdb) target remote :1234
Remote debugging using :1234
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0xb0001000 in ?? ()
(gdb) b main
Breakpoint 1 at 0x82fc: file test.c, line 6.
(gdb) c
Continuing.
Error while mapping shared library sections:
/system/bin/linker: No such file or directory.
Error while mapping shared library sections:
libc.so: Success.
Breakpoint 1, main (argc=33512, argv=0x0) at test.c:6
6 int i = 1;
(gdb) n
7 i+=2;
(gdb) p i
$1 = 1
(gdb) n
9 printf("Hello, world (i=%d)!\n", i);
(gdb) p i
$2 = 3
(gdb) c
Continuing.
Program exited normally.
(gdb) quit
Bene, va bene. E l'altra console fornirà un output aggiuntivo in questo modo:
Remote debugging from host 127.0.0.1
gdb: Unable to get location for thread creation breakpoint: requested event is not supported
Hello, world (i=3)!
Child exited with retcode = 0
Child exited with status 0
GDBserver exiting
Ecco un esempio di progetto che segue la risposta di KennyTM. Puoi crearlo da zero o modificare un altro progetto, ad esempio hello-jni
negli esempi NDK.
jni/main.c:
#include <stdio.h>
int main() {
printf("hello\n");
return 0;
}
jni/Application.mk:
#APP_ABI := all
APP_ABI := armeabi-v7a
jni/Android.mk:
LOCAL_PATH := $(call my-dir)
# first target: the hello-jni example
# it shows how to build multiple targets
# {{ you may comment it out
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDLIBS := -llog -L$(LOCAL_PATH)/lib -lmystuff # link to libmystuff.so
include $(BUILD_SHARED_LIBRARY)
#}} you may comment it out
# second target
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE) # <-- Use this to build an executable.
Devo notare che non vedrai alcun accesso nell'output di stdout, dovrai usare adb logcat
per vederlo.
Quindi, se vuoi accedere:
jni/main.c:
#include <stdio.h>
#include <android/log.h>
int main() {
printf("hello\n");
__android_log_print(ANDROID_LOG_DEBUG , "~~~~~~", "log %i", 0); // the 3rd arg is a printf-style format string
return 0;
}
e la sezione corrispondente in jni/Android.mk diventa:
LOCAL_PATH := $(call my-dir)
#...
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS := -llog # no need to specify path for liblog.so
include $(BUILD_EXECUTABLE) # <-- Use this to build an executable.