用Clion开发Android AOSP native代码(完整操作步骤)

一、准备工作

先准备一个演示用的native工程,名为clion_demo。
工程所在目录:aosp/vendor/clion_demo

1. 文件目录结构

aosp/vendor/clion_demo$ tree
.
├── Android.bp
└── clion_demo.cpp

2. Android.bp文件

源码文件:clion_demo.cpp
目标可执行文件:clion_demo

cc_binary {
    name: "clion_demo",

    shared_libs: [
        "libbase",
        "libprocessgroup",
        "libcutils",
        "libutils",
        "libbinder",
        "liblog",
        "libziparchive",
    ],

    srcs: [
        "clion_demo.cpp",
    ],
}

3. native源文件:clion_demo.cpp

在代码里引用了Android native源码中的一些方法,目的是让生成的CMake项目中多包含一些include。
如果代码中没有引用到相关的类或方法,对应库的头文件就不会包含。下面有对比。
如果代码中,只调用一个printf,生成的CMake工程里面会包含

#pragma GCC diagnostic warning "-Wunused"
#define LOG_TAG "clion_demo"

#include <string>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <utils/Log.h>

int main(int /* argc */, char **/* argv */)
{
    std::string msg = android::base::StringPrintf("Hello AOSP~");
    ALOGD("The message is: %s.", msg.data());
    return 0;
}

以下编译和运行步骤不是准备CLion工程必须的,仅为验证代码编译正确
直接在工程目录中执行编译:

$ mm

编译完成后,可执行文件生成目录:

aosp/out/target/product/hqcos/system/bin/clion_demo

push到开发板上运行测试:

adb push clien_demo /system/bin/
$ adb shell
$ clion_demo                                                      
$ logcat *:S clion_demo
03-11 19:54:09.307 28971 28971 D clion_demo: The message is: Hello AOSP~.

4. 准备工作总结

准备一个用Android.bp编译的工程。
也可以用已有工程。
使用简单的demo程序,相当于生成一个空的模板工程,可以从头开发程序。

二、生成CMake工程

1. 打开编译开关

通过环境变量,打开生成CMakeLists.txt的编译开发

$ export SOONG_GEN_CMAKEFILES=1
$ export SOONG_GEN_CMAKEFILES_DEBUG=1

2. 编译工程

在demo工程目录下,执行mm命令进行编译。

$ mm

3. 在CLion中导入生成的CMakeLists.txt

编译完成后,找到生成的CMakeLists.txt文件,保存在以下目录:

aosp_dir/out/development/ide/clion/

目录下各个工程的相对路径和aosp根目录保持一致。
例如:
源码目录为:

aosp/system/core/liblog

对应的CMakeLists.txt文件保存在:

aosp_dir/out/development/ide/clion/system/core/liblog/

在此目录下会有多个目录,对应不同的硬件平台,比如arm64、x86等。取决于bp文件中的配置。

4. CLion中查看导入的工程

在左侧project视图中可以看到导入的CMakeLists.txt和clion_demo.cpp文件,以及下方有大量的include头文件。
展开了一些头文件,可以看到包括C语言库,C++库(上面几个include,内容太多收缩起来)和很多Android源码中的库。
此时在编辑窗口,可以点击跳转,也可以在输入时自动提示补全。
在这里插入图片描述
作为对比,如果源码中引用的库比较少,生成的工程中include也相对较少。
例如,一下源码:

// clion_empty.cpp
#pragma GCC diagnostic warning "-Wunused"
#include <stdio.h>
int main(int /* argc */, char **/* argv */)
{
    printf("hello LION!");
    return 0;
}

下图所示,左侧是上面的clion_demo.cpp生成的工程,右侧是clion_empty.cpp生成的工程。可以看到include数量差别明显。
即使clion_empty.cpp这么简单的文件,除了C/C++的库,大部分基础的Android native和源码中的基础库也都已经包含进来了。
在开发过程中,在此基础上,增加所需的依赖库,可直接修改CMakeLists.txt文件。
在这里插入图片描述

5. 修改工程的源码根目录

在这里插入图片描述

三、总结一下

1. 操作步骤

  1. 先已有一个可以用Android.bp正常编译的工程。
  2. 打开环境变量开关。
  3. 在aosp中编译工程,生成CMakeLists.txt文件。
  4. 导入CLion中使用。

2. 动机

CLion比vs code更好用,CLion仅支持CMake工程。
具体一些,vs code阅读代码没问题,需要添加所依赖的头文件即可实现代码跳转。
编写代码的补全不如clion更加智能,所以如果要编写代码,clion要更好用一些。

3. 原理

AOSP支持编译过程中自动生成CMakeLists.txt文件,导入CLion即可。默认开关是关闭的。

4. 限制

1)只有用Android.bp编译的项目才可以,Android.mk文件编译的项目不能用。
2)只能逐个项目导入,不支持导入整个AOSP工程。需要手动创建CMake工程,把需要的工程引入。

参考文档:aosp/build/soong/docs/clion.md

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
很抱歉,我是一个文本AI模型,无法为您提供完整代码。但我可以为您提供一些思路和代码片段来帮助您完成这个任务。 首先,您需要定义一些数据结构来存储学生和课程的信息。例如,学生的信息可以包括学号、姓名、选修的课程等等。课程的信息可以包括课程编号、课程名称、授课教师等等。 以下是一个示例的数据结构定义: ```c++ struct Student { int id; string name; vector<Course> courses; }; struct Course { int id; string name; string teacher; }; ``` 接下来,您需要编写函数来实现学生选修课程的功能,例如添加学生、添加课程、选修课程等等。以下是一个示例的函数定义: ```c++ void add_student(vector<Student>& students, int id, string name) { Student student; student.id = id; student.name = name; students.push_back(student); } void add_course(vector<Course>& courses, int id, string name, string teacher) { Course course; course.id = id; course.name = name; course.teacher = teacher; courses.push_back(course); } void enroll_course(vector<Student>& students, int student_id, int course_id) { for (auto& student : students) { if (student.id == student_id) { for (auto& course : courses) { if (course.id == course_id) { student.courses.push_back(course); break; } } break; } } } ``` 最后,您需要编写一个主函数来调用这些函数,读取用户输入并输出查询结果。以下是一个示例的主函数: ```c++ int main() { vector<Student> students; vector<Course> courses; add_student(students, 1, "Alice"); add_student(students, 2, "Bob"); add_student(students, 3, "Charlie"); add_course(courses, 1001, "Math", "Mr. Smith"); add_course(courses, 1002, "Physics", "Ms. Johnson"); add_course(courses, 1003, "Chemistry", "Dr. Lee"); enroll_course(students, 1, 1001); enroll_course(students, 1, 1002); enroll_course(students, 2, 1002); enroll_course(students, 3, 1003); // TODO: Read user input and output query results return 0; } ``` 您可以根据您的具体需求修改和扩展这些代码。希望这些代码片段能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抓饼先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值