GNU/Linux >> Tutoriels Linux >  >> Linux

Comment créer un exécutable natif (ligne de commande) à exécuter sur Android ?

À partir de NDK r8d, cela peut être résolu de manière beaucoup plus simple.

  1. Créez un projet avec la hiérarchie de répertoires suivante :

    project/
        jni/
            Android.mk
            Application.mk
            *.c, *.cpp, *.h, etc.
    
  2. Remplissez Android.mk avec le contenu suivant. La chose la plus importante est la dernière ligne. Consultez la documentation NDK pour connaître la signification des autres variables.

    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.
    
  3. Aller au project/ répertoire, et tapez simplement

    ndk-build
    

    Le résultat sera placé en project/libs/<arch>/name-of-your-executable .


http://www.bekatul.info/content/native-c-application-android [cassé (9 novembre 2015)]
Lien Wayback Machine

Pour résumer l'article...

Le code de test est :

#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);
}

Le Makefile est :

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'auteur a stocké ces fichiers sur son ordinateur Linux local à :

/home/dd/android/dev/native/test.c
/home/dd/android/dev/native/Makefile

L'auteur l'a ensuite compilé et testé avec :

[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)!

SDK et NDK utilisés étaient :

source code: /home/dd/android/dev/native
android ndk: /home/dd/android/android-ndk-r5
android sdk: /home/dd/android/android-sdk-linux_86

Cependant, le guide de débogage était la très bonne partie ! Copier et coller ...

Définissez la compilation pour activer le débogage :

DEBUG = -g
CFLAGS := $(DEBUG) -fno-short-enums -I$(ANDROID_NDK_ROOT)/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include

copiez le fichier gdbserver ($(PREBUILD)/../gdbserver) dans l'émulateur, ajoutez la cible dans Makefile que pour simplifier :

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

Nous allons maintenant le déboguer sur le port 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)

Puis exécutez-le :

[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

Ouvrez maintenant une autre console et exécutez le débogueur :

[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

Eh bien, ça va. Et l'autre console donnera une sortie supplémentaire comme ceci :

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

Voici un exemple de projet qui suit la réponse de KennyTM. Vous pouvez le créer à partir de zéro ou modifier un autre projet, par exemple, hello-jni dans les exemples 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.

Je dois noter que vous ne verrez aucune journalisation dans la sortie stdout, vous devrez utiliser adb logcat pour le voir.

Donc, si vous voulez vous connecter :

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;
}

et la section correspondante dans jni/Android.mk devient :

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.

Linux
  1. Comment redémarrer Linux en utilisant la ligne de commande

  2. Comment puis-je exécuter correctement des scripts de ligne de commande Perl one liner?

  3. Comment installer un script pour qu'il s'exécute n'importe où à partir de la ligne de commande ?

  4. arguments de ligne de commande pour l'exécution de docker

  5. Comment ouvrir le gestionnaire AVD sur Ubuntu Linux depuis la ligne de commande ?

Comment créer une instance dans OpenStack via la ligne de commande

Comment exécuter une commande / un script Linux Shell en arrière-plan

Comment exécuter des commandes Linux en arrière-plan

Comment utiliser le proxy sur la ligne de commande Linux ?

Comment démarrer en ligne de commande Linux

Comment trouver une adresse IP dans la ligne de commande Linux