C与C++编译器Android交叉编译配置

目录

目录

一、gcc与g++编译器

二、使用Linux自带的gcc或g++编译源文件生成的可执行文件

三、编译Android手机可用的可执行文件

四、编译动态库

五、编译静态库



一、gcc与g++编译器

了解C/C++编译器的基本使用,能够在后续移植第三方库进行交叉编译时,清楚了解应该传递什么参数

gcc与g++是我比较常用的编译器,关于这两个编译器有几点需要注意:

(1)gcc和g++都能够编译c/c++,但是编译时候行为不同

(2)后缀为.c的源文件,gcc把它当作是C程序,而g++当作是C++程序;后缀为.cpp的,两者都会认为是c++程序

(3)g++会自动链接c++标准库stl,gcc不会

(4)gcc不会定义__cplusplus宏,而g++会

Linux系统都是自带这两种编译器的,我们可以检验一下。

在终端输入 gcc或g++,出现如下字样,表明已安装

如果没有安装 使用下面指令安装

apt install build-essential

二、使用Linux自带的gcc或g++编译源文件生成的可执行文件

(1)编写一个简单的.c的文件

#include<stdio.h>
int main(){
        printf("hello linux!\n");
        return 0;
}

(2)使用gcc进行编译

#-o main.o  表示输出的文件名是main.o,也可以不带后缀
gcc -o main.o main.c

这时候有的人就会认为这个生成main.o这个可执行文件应该可以在android手机中执行,毕竟android手机也是Linux系统的。其实并不是这样,因为Ubuntu(我的服务器系统)与android手机的cpu指令集不一样,必须使用android NDK中的gcc或g++去编译才可以

三、编译Android手机可用的可执行文件

1.下载NDK,并进行解压

#下载NDK
wget https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip

#解压  unzip后面跟着的是刚刚下载的文件
unzip android-ndk-r17b-linux-x86_64.zip

2.设置NDK中gcc的临时环境变量

export ANDROID_64_ARM_GCC=/linux/android-ndk-r17b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc

#注意:
(1)这里填写的应该是绝对路径,我们进入到bin这个目录后输入 pwd这个指令,就可以输出绝对路径了
(2)这里我们用的64位的

3.头文件及库文件的设置

有人认为,使用刚刚设置的临时变量的gcc去编译应该没问题了吧,其实不然。为什么,这个简单的c源文件中引入了stdio.h这个头文件,我们需要给编译器指定一个头文件及库文件的查找路径才行。

关于头文件及库文件的路径的指定有下面几条指令:

(1)--sysroot=AAA

在AAA这个路径下的 usr/include中查找头文件;在AAA这个路径下的 usr/lib中查找库文件

(2)-isysroot BBB

在BBB这个路径下的usr/include中查找头文件,需要注意的是:这样设置之后,会覆盖--sysroot=AAA中的头文件的查找路径

(3)-isystem CCC

直接在CCC这个路径的目录下去查找头文件,并不是usr/include中了,需要注意

(4)-IDDD

同(3)

而优先级是:先(4),后(3),再(2)

(5)-LEEE -lfff

-LEEE:指定库文件查找目录 

-lfff:指定需要链接的库名

比如我需要链接C:\Users\codef\AppData\Local\Android\Sdk\ndk-bundle\platforms\android-21\arch-x86\usr\lib路径下的liblog.so文件,我就可以这样写

-LC:\Users\codef\AppData\Local\Android\Sdk\ndk-bundle\platforms\android-21\arch-x86\usr\lib -llog

4.给NDK中的头文件及库文件这只一个临时变量

export C_H_PATH="--sysroot=/linux/android-ndk-r17b/platforms/android-21/arch-arm -isysroot /linux/android-ndk-r17b/sysroot -isystem /linux/android-ndk-r17b/sysroot/usr/include/arm-linux-androideabi -pie"

#注意:结尾处一定要加 -pie,否则执行可执行文件时会报错

5.编译

$ANDROID_64_ARM_GCC $C_H_PATH -o main.o main.c

此时生成的main.o文件就可以在在Android手机中运行了

如何测试main.o文件能否在Android手机中运行呢

(1)将main.o文件copy到桌面,我使用的是XShell,所以指令如下

sz main.o

(2)将windows的cmd切换到桌面路径,之后执行如下指令

#将文件传到手机或虚拟中上(前提是有手机连接或虚拟机开启)
adb push main.o /sdcard/

#切换至手机或虚拟机
adb shell

#进入到sdcard目录
cd /sdcard

#执行,如果没有问题的话,就会执行c代码
./main.o

注意:手机需要root

四、编译动态库

1.生成动态库

$ANDROID_64_ARM_GCC $C_H_PATH -o libTest.so test.c

注意:
(1)ANDROID_64_ARM_GCC 与 C_H_PATH 是上面定义好的环境变量
(2)libTest.so是生成的动态库文件

2.在android手机中编译

(1)将动态库放在下面的文件夹下,这个路径不可变(可在build.gradle中改变这个路径,默认的话就是这个路径)

(2)在相应的类中调用native-lib-test(动态库的调用在native-lib-test文件中)

(3)native-lib-test.cpp文件的内容

红色的地方一定要特别注意:

⒈动态库是由.c的源文件生成的,所以extern "C"不能少

⒉extern in test() 表示声明动态库的test()文件

(4)CMakeLists.txt中文件的配置

cmake_minimum_required(VERSION 3.4.1)

add_library(
             native-lib-test

             SHARED

             src/main/cpp/native-lib-test.cpp)

#CMAKE_SOURCE_DIR:当前目录的地址
#ANDROID_ABI:jniLibs目录下的cpu架构
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}")

find_library(
              log-lib
              log )


target_link_libraries(
                       native-lib-test
                       Test
                       ${log-lib} )

这样动态库就能够在Android手机端运行了

五、编译静态库

和动态编译有两个不一样的地方

(1)指令不同

第一步:$ANDROID_64_ARM_GCC $CFLAGS -o staticTest.o -c staticTest.c

第二步:a r libstaticTest.a staticTest.o

(2)路径可随意指定,在CMakeLists.txt中进行引用就好了

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}")

有问题可以留言,欢迎指错!欢迎纠正!

资源地址

猜你喜欢

转载自blog.csdn.net/qq_32019367/article/details/83051951