NDK在Linux下载配置以及C、C++编译配置(交叉编译)

article/2025/9/20 23:19:14

NDK在Linux下载配置以及C、C++编译配置(交叉编译)

前言:

我们搭建好Ubutu虚拟机之后,通过xShell远程登录Ubutu上SSH服务器,在xShell上可以进行相关的编译操作了。但是我们在xShell上gcc、g++编译的可执行文件只能在Linux上执行,但是我们需要编译出来的东西可以在Android端使用,这就需要进行交叉编译,在Ubutu上编译出Android可执行的文件以及动态库。在编译之前,需要将NDK下载安装完成,并且成功配置环境变量,才能进行下面编译。废话不多说了,开始介绍了(备注:以下命令均在xShell中输入完成的):

1、下载安装NDK以及配置环境变量

wget https://dl.google.com/android/repository/android-ndk-r17-beta2-linux-x86_64.zip

下载完成之后查看当前目录(主要是查看下载完之后安装包的名字:android-ndk-r17-beta2-linux-x86_64.zip):

ls -l

解压安装

unzip android-ndk-r17-beta2-linux-x86_64.zip

解压完成之后再次查看目录:

ls -l
你将会看到一个文件夹:android-ndk-r17-beta2(这个就是解压之后文件夹)根据个人习惯,将此文件夹放在存储的位置。

我是将此文件夹移动到/usr/local/目录下:

mv android-ndk-r17-beta2 /usr/local/

配置NDK的环境变量:

vi /etc/profile
进入之后输入一个i,进入编辑状态

export NDK=/usr/local/android-ndk-r17-beta2

export PATH= P A T H : PATH: PATH:NDK

按一下返回键,再按:,再输入wq! 保存并退出。

刷新一下/etc/profile

source /etc/profile
检查是否安装成功:
ndk-build -v

img

image.png

到这里只是将NDK安装成功了而已,编译之路漫长。

2、交叉编译Android可执行文件

创建一个C文件,并在里面编写相关的代码:

vi main.c

#include <stdio.h>
void main(){printf("成都");
}

保存并退出,ls -l查看当前目录是否存在main.c的文件,这里我们需要用NDK里面的gcc编译器进行编译,南无我们进行相关环境变量的配置(在/etc/profile配置保存并退出)。同时也引入相关的头文件,不然找不到头文件。

export NDK_GCC=/usr/local/android-ndk-r17-beta2/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
export HO="--sysroot=/usr/local/android-ndk-r17-beta2/platforms/android-21/arch-arm -isystem /usr/local/android-ndk-r17-beta2/sysroot/usr/include  -isystem /usr/local/android-ndk-r17-beta2/sysroot/usr/include/arm-linux-androideabi"

配置好之后,我们进行编译
$NDK_GCC $HO -pie main.c -o main

这时候再去查看目录多了一个main文件,将main文件到处到桌面

sz main

这时打开Windows命令行(进入到桌面的目录,需提前配置好adb命令):

cd Desktop

将main文件放进存储卡

adb push main /sdcard/

使用adb shell命令

adb shell

进入到手机存储卡目录

cd /sdcard/

执行文件(需要手机获取root权限才可以执行)

./main

此时可在Windows命令行上面看到输出乱码(由于编码问题),表示成功了。这样操作就顺利完成交叉编译。

注意如果出现了没有这个文件,或者权限被拒绝 这样操作

打开Android 模拟器
将文件拷贝到sd卡中
执行命令将文件拷贝到 /data/local/tmp 下

cp -r file(文件名字) /data/local/tmp

这个是时候这个文件是没有执行权限的,也没有权限给这个文件添加可执行权限需要执行 获取root权限

su root

执行给main 这个可执行的文件添加 可执行权限

chmod 777 main

然后执行这个文件

./main

2、编译Android可执行动态库

创建一个C文件

#include <stdio.h>
int test(int a){return 20+a;
}

把创建的C文件编译成动态库,同样将该动态库导出到桌面

$NDK_GCC $HO -shared -fPIC test.c -o libTest.so

创建一个Android NDK项目,按照下图目录将.so文件放置进去

img

image.png

好了接下来我们配置Android端动态库相关信息(native-lib.cpp文件)

#include <jni.h>
#include <string>
#include <android/log.h>
extern "C"{
extern int test(int a);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_administrator_lsn_19_MainActivity_stringFromJNI(JNIEnv *env, jobject instance) {std::string hello = "Hello from C++";__android_log_print(ANDROID_LOG_ERROR,"jni","libtest.so 里面的 test 方法:%d",test(5));return env->NewStringUTF(hello.c_str());
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.native-libSHAREDsrc/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.log-liblog )
#设置一个变量
#CMAKE_CXX_FLAGS c++参数 会传给编译器
#CMAKE_C_FLAGS   c参数   会传给编译器
#重新定义 CMAKE_CXX_FLAGS变量
#CMAKE_SOURCE_DIR指的是当前这个文件的地址
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a")target_link_libraries( # Specifies the target library.native-libTest# Links the target library to the log library# included in the NDK.${log-lib} )

最后在Maintivity使用

package com.example.administrator.lsn_9;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");System.loadLibrary("Test");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = (TextView) findViewById(R.id.sample_text);tv.setText(stringFromJNI());}public native String stringFromJNI();
}

可以看到输出的日志中结果是25,成功运行动态库里面的test(int a)方法。

一、Android NDK cmak 脚本编译
从Android官方下载NDK工具,然后在系统变量中记得添加NDK主目录,不然无法使用ndk-build命令编译应用。
使用NDK手动编译生成.so文件:
1)新建应用名称,如hello。
2)在hello文件夹下新建目录jni
3)在jni目录下新建hello.c,内容如下:

 #include<stdio.h>
int main(int argc, char* argv[])
{
printf("hello world");
return 0;
}

4)同样在jni目录下 新建 Android.mk 和 Application.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog    
#编译hello.c时需要依赖的共享库(android下的log,此处并没有使用)#LOCAL_ARM_MODE := arm
LOCAL_MODULE := hello                                 #编译完成后需要生成的.so名称
LOCAL_SRC_FILES := hello.c                            #编译的原文件名
include $(BUILD_SHARED_LIBRARY)           #编译结果可以生成共享库和可执行库,NDK都是共

以上是Android.mk中内容,Application.mk内容如下:

APP_ABI := x86 armeabi-v7a                                #希望编译生成的平台

保存好上面三个文件,然后进入到hello文件夹下,执行命令:ndk-build。
命令执行完会在hello文件夹下生成额外的两个文件夹:libs和obj,libs文件夹下的.so文件正是我们所需要的。

注意在使用如上的mk 是会报错如下

[x86] Executable     : hello
/usr/local/android-ndk-r16b/platforms/android-14/arch-x86
/usr/lib/crtbegin_dynamic.o:crtbegin.c:function _start: error: undefined reference to 'main'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

解决 mk 文件是这样的

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog    #编译hello.c时需要依赖的共享库(android下的log,此处并没有使用)#LOCAL_ARM_MODE := arm
LOCAL_MODULE := hello                                     #编译完成后需要生成的.so名称
LOCAL_SRC_FILES := hello.c
include $(BUILD_EXECUTABLE)                  #编译结果可以生成共享库和可执行库,NDK都是共享库-Shared

通过上面的mk 文件编译后的可执行文件在Android 手机上执行时会报错,错误如下

generic_x86_arm:/data/local/tmp # ./hello 
"./hello": error: Android 5.0 and later only support position-independent executables (-fPIE).

正确的mk文件的内容为

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog    #编译hello.c时需要依赖的共享库(android下的log,此处并没有使用)#LOCAL_ARM_MODE := arm
LOCAL_MODULE := hello                                     #编译完成后需要生成的.so名称
LOCAL_SRC_FILES := hello.cLOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIEinclude $(BUILD_EXECUTABLE)                  #编译结果可以生成共享库和可执行库,NDK都是共享库-Shared

到此ok


http://chatgpt.dhexx.cn/article/VyOfYTP3.shtml

相关文章

Android——NDK下载提示缺少toolchains问题解决

更新下载了最新的NDK&#xff0c;发现Android SDK报错。 No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android。 解决办法&#xff1a; 1.找到并进入下载安装的ndk目录 lydeMacBook-Pro:~ imac$ cd /Users/ly/Library/Android/sd…

android ndk 下载安装(ubuntu)

1. 下载并解压安装包 官网下载&#xff1a;https://developer.android.com/studio ndk各个版本下载地址&#xff1a;https://blog.csdn.net/u011077027/article/details/102706283 官网下载需要梯子&#xff0c;百度云盘下载&#xff1a;链接: https://pan.baidu.com/s/1Ge8fQu…

Window NDK下载以及环境变量配置

作者介绍&#xff1a;铸梦xy。IT公司技术合伙人&#xff0c;IT高级讲师&#xff0c;资深Unity架构师&#xff0c;铸梦之路系列课程创始人。 第一种 NDK下载安装步骤一 NDK环境变量配置步骤一 测试NDK配置 第二种 支持编译c ninja 前言 NDK是开发者必不可少的一部分&#xff0c…

3、NDK下载、安装

文章目录 一、下载NDK二、配置环境变量三、测试 一、下载NDK 官网下载地址:https://developer.android.google.cn/ndk/downloads/,选择自己相应的版本&#xff0c;下载解压。(我安装在D:\utils\android-ndk-r21d) 特别注意&#xff1a;安装路径不要有中文和空格 二、配置环境…

【Android NDK 开发】Android NDK 下载 ( 下载指定历史版本 NDK | Android NDK r10e - 2015 年 5 月 )

文章目录 一、下载指定历史版本 NDK 一、下载指定历史版本 NDK 进入到 ndk 下载的 " 修订历史记录 " 页面 https://developer.android.google.cn/ndk/downloads/revision_history ; 在该页面中 , 有 Android NDK r1&#xff08;2009 年 6 月&#xff09;~ Android N…

android ndk官网下载地址,android ndk下载

android ndk&#xff0c;在SDK前加上原生二字就是Native Development Kit&#xff0c;支持32位和64位使用&#xff0c;有需要的朋友可以来本站下载。 【使用方法】 1、打开Eclipse&#xff0c;点Window->Preferences->Android->NDK,设置NDK路径&#xff0c;例如Shamoo…

【NDK】Android NDK下载安装教程

目录 Android NDK下载安装教程 不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。要沉下心来&#xff0c;诗和远方的路费真的很贵&#xff01; Android NDK下载安装教程 打开Android Studio的 SDK Manager。 选中SDK Tools&#xff0c;选择要下载…

android studio 如何下载指定版本的NDK

安装及配置 NDK 和 CMake | Android 开发者 | Android Developers 如果官方文档看不懂的&#xff0c;就看我写的口水话版本吧&#xff1b; 1、AS打开SDK、NDK下载的那个对话框&#xff0c;如图&#xff1a; 2、非常关键的一步&#xff0c;默认情况下选项的子项未展开&…

fallback method wasn‘t found

两种情况会报这个异常&#xff1a; 1、指定的降级方法 确保配置和注解都是开启了的前提下 2、全局使用的降级方法

设置统一的hystrix fallback接口

设置统一的hystrix fallback接口 前言Order工程改进&#xff08;将fallback方法放到类中&#xff09;&#xff1a;即设置统一的hystrix fallback接口1.不在方法上使用HystrixCommand注解2、创建回调类3、在Feign客户端中添加fallback属性4、配置文件中开启hystrix5、重新启动应…

Sentinel服务熔断功能(sentinel整合ribbon+openFeign+fallback)

目录 1、Sentinel服务熔断功能 一、Ribbon系列 &#xff08;一&#xff09;提供者9003/9004 &#xff08;二&#xff09;消费者84 二、OpenFeign系列 三、熔断框架比较 2、规则持久化 1、Sentinel服务熔断功能 一、Ribbon系列 &#xff08;一&#xff09;提供者9003/9004 …

Sentinel的blockHandler与fallback的区别

一、两者区别 这里说明一下&#xff0c;笔者使用的是Alibaba的Sentinel限流降级框架&#xff0c;Sentinel提供了限流、服务降级功能&#xff0c;但是只是限制后&#xff0c;返回不可控的结果肯定是不行的&#xff0c;我们还要保证调用者在调用那些被限制的服务时候&#xff0c…

Fallback函数

Fallback函数的使用 特点&#xff1a; 1.无名字&#xff0c;无参数&#xff0c;无返回值 2.如果请求的方法在合约中不存在&#xff0c;则会调用fallback函数 3.对合约转账的时候&#xff0c;会自动执行fallback函数(可能会产生Reentrancy漏洞) 4.在高版本中已经将定义形式改为…

sentinel1.8.1中fallback兜底方法和@RestControllerAdvice全局异常处理

环境描述&#xff0c;同上一篇文章 sentinel设置blockHandlerClass和blockHandler不生效的坑 目录 1.sentinel的blockHandler和fallback 2.RestControllerAdvice是否也可以兜底&#xff1f;&#xff1f;&#xff1f; 总结&#xff1a;二者结果相似&#xff0c;按需自取即…

Spring Cloud Alibaba(四)简单接入Sentinel(fallback用法)

SentinelResource 注解 接着 Spring Cloud Alibaba&#xff08;三&#xff09;简单接入Sentinel&#xff08;Sentinel 控制台&#xff09;&#xff0c;来看一下 SentinelResource 一些常用的属性&#xff1a; value &#xff1a; 资源名称&#xff0c;必需项&#xff08;不能为…

【mysql】sql优化常用的几种方法,19种最有效的sql优化技巧(转载)

前言 转载 有哪些方法 转载自&#xff1a;https://www.changchenghao.cn/n/174426.html EXPLAIN 做MySQL优化&#xff0c;我们要善用EXPLAIN查看SQL执行计划。 下面来个简单的示例&#xff0c;标注&#xff08;1、2、3、4、5&#xff09;我们要重点关注的数据&#xff1a; typ…

SQL查询优化技巧

查询优化的本质是让数据库优化器为SQL语句选择最佳的执行计划。一般来说&#xff0c;对于在线交易处理&#xff08;OLTP&#xff09;系统的数据库&#xff0c;减少数据库磁盘I/O是SQL语句性能优化的首要方法&#xff0c;因为磁盘访问通常是数据库性能的瓶颈所在。 另外&#xf…

SQL语句优化有哪些方法

1.如何定位慢查询? mysql默认慢查询为10秒,如果超过10秒,没有数据返回则为慢查询. 当我们通过安全日志启动时,当超过超时时间时,会将超时的SQl存放在日志中,我们去分析这些sql然后进行调优. 2.数据库设计要合理 什么是数据库设计? 主要就是三范式 1p原子性:每列不可再分…

MySQL的SQL优化常用30种方法

1、对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。 &#xff08;1&#xff09;未建立索引前&#xff0c;执行计划是全表扫描&#xff1a; &#xff08;2&#xff09;建立索引后&#xff0c;走索引查询&…

常用SQL优化方法

个人博客请访问 http://www.x0100.top 1、应尽量避免在 where 子句中使用!或<>操作符&#xff0c;否则将引擎放弃使用索引而进行全表扫描。 2、对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。 3、应…