赞
踩
目录
目录
二、使用Linux自带的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
(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++去编译才可以
- #下载NDK
- wget https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip
-
- #解压 unzip后面跟着的是刚刚下载的文件
- unzip android-ndk-r17b-linux-x86_64.zip
- 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位的
有人认为,使用刚刚设置的临时变量的gcc去编译应该没问题了吧,其实不然。为什么,这个简单的c源文件中引入了stdio.h这个头文件,我们需要给编译器指定一个头文件及库文件的查找路径才行。
关于头文件及库文件的路径的指定有下面几条指令:
(1)--sysroot=目录1
在AAA这个路径下的 usr/include中查找头文件;在目录1这个路径下的 usr/lib中查找库文件
(2)-isysroot 目录2
在目录2这个路径下的usr/include中查找头文件,需要注意的是:这样设置之后,会覆盖--sysroot=目录1中的头文件的查找路径
(3)-isystem 目录3
直接在目录3这个路径的目录下去查找头文件,并不是usr/include中了,需要注意
(4)-I目录4
同(3)
而优先级是:先(4),后(3),再(2)
(5)-L目录 -l库名
-L目录:指定库文件查找目录
-l库名:指定需要链接的库名
比如我需要链接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
- 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,否则执行可执行文件时会报错
$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
- $ANDROID_64_ARM_GCC $C_H_PATH -o libTest.so test.c
-
- 注意:
- (1)ANDROID_64_ARM_GCC 与 C_H_PATH 是上面定义好的环境变量
- (2)libTest.so是生成的动态库文件
(1)将动态库放在下面的文件夹下,这个路径不可变(可在build.gradle中改变这个路径,默认的话就是这个路径)
(2)在相应的类中调用native-lib-test(动态库的调用在native-lib-test文件中)
(3)native-lib-test.cpp文件的内容
红色的地方一定要特别注意:
⒈动态库是由.c的源文件生成的,所以extern "C"不能少
⒉extern in test() 表示声明动态库的test()文件
- 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}")
有问题可以留言,欢迎指错!欢迎纠正!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。