1. 为什么选择CLion来开发AOSP原生代码?
如果你正在或者即将参与Android底层开发,比如修改系统服务、开发新的HAL层驱动、或者为系统添加一个原生的命令行工具,那你肯定离不开对AOSP(Android Open Source Project)中C/C++代码的编写和调试。传统的开发方式是什么?要么是纯文本编辑器加命令行编译,要么是用一些通用IDE(比如VS Code)进行简单的代码阅读。我试过很多方法,踩过不少坑,最终发现,对于需要深度编写和调试Native代码的场景,JetBrains CLion 是一个被严重低估的效率神器。
很多朋友可能会问,VS Code不是也能看AOSP代码吗?确实,VS Code配合C/C++插件,阅读代码、简单的跳转基本够用。但一旦进入实际的编码和调试阶段,差距就出来了。CLion的核心优势在于它的“智能”是深入骨髓的。它的代码补全不仅仅是基于当前文件的关键词,而是真正理解了整个CMake工程的结构、依赖关系和符号定义。当你输入 android::base:: 时,它能准确地列出 StringPrintf、ReadFileToString 等所有可用的方法,并且能直接跳转到它们在AOSP源码中的定义。这对于探索庞大的、不熟悉的AOSP代码库来说,效率提升不是一点半点。
更重要的是调试体验。CLion集成了强大的GDB/LLDB调试器前端,你可以直接在IDE里设置断点、查看内存、监控变量、甚至进行多线程调试,界面直观,操作流畅。相比在命令行里手打GDB命令,或者用其他工具那简陋的调试界面,CLion能让你把精力完全集中在问题本身,而不是和调试工具搏斗。简单来说,如果你满足于“看”代码,VS Code或许可以;但如果你想高效地“写”和“调”AOSP原生代码,CLion几乎是目前最专业、最顺手的选择。接下来,我就手把手带你从零开始,配置好CLion,让它成为你开发AOSP原生模块的得力助手。
2. 搭建基础:准备你的AOSP编译与演示工程
在请出CLion这位“大神”之前,我们得先把它的“舞台”——AOSP源码和我们的演示工程——搭建好。这个过程是后续一切的基础,我会尽量把每一步都讲清楚,避免你在这里踩坑。
2.1 获取与编译AOSP源码
首先,你需要一个可以正常编译的AOSP源码树。这里假设你已经按照官方文档完成了源码下载和初始编译。有几个关键点需要注意:
- 编译环境:确保你的Ubuntu(或其他Linux发行版)开发环境满足AOSP的要求,比如足够的内存、磁盘空间,以及正确的JDK、Python等版本。我个人的经验是,磁盘空间至少预留300GB,内存16GB以上会比较舒适。
- 成功编译:在AOSP根目录下,执行
lunch选择你的目标设备(例如aosp_arm64-eng),然后运行make -jN(N为你的CPU核心数)进行完整编译。这一步必须成功,它意味着你的源码和编译工具链是正常的。如果编译失败,需要先解决基础环境问题。
2.2 创建我们的演示Native工程
为了演示,我们在AOSP的 vendor 目录下创建一个简单的原生可执行程序工程。这个工程将使用Android的构建系统Soong(也就是 Android.bp 文件)来管理。为什么不用老的 Android.mk?因为CLion的CMake工程生成功能目前只支持Soong(Android.bp),这是我们需要适应的一个点。
首先,创建工程目录和文件:
cd /path/to/your/aosp
mkdir -p vendor/clion_demo
cd vendor/clion_demo
接着,创建 Android.bp 文件。这个文件定义了我们的模块。为了让生成的CLion工程包含更多有用的头文件以便代码补全,我们故意多依赖一些Android基础库:
cc_binary {
name: "clion_demo",
srcs: ["clion_demo.cpp"],
shared_libs: [
"liblog",
"libbase",
"libutils",
"libcutils",
"libbinder",
],
cflags: ["-Wno-unused-parameter"],
}
这个 Android.bp 文件告诉构建系统:我们要编译一个名叫 clion_demo 的可执行文件(cc_binary),源代码是 clion_demo.cpp,并且它动态链接了 liblog(用于ALOGD打印)、libbase、libutils 等一些常用的Android原生库。
然后,创建我们的C++源文件 clion_demo.cpp:
#define LOG_TAG "ClionDemo"
#include <android-base/stringprintf.h>
#include <utils/Log.h>
#include <cutils/properties.h>
#include <iostream>
int main() {
// 使用android::base库中的工具函数
std::string greeting = android::base::StringPrintf("Hello from CLion & AOSP!");
// 使用Android特有的日志输出
ALOGD("Message: %s", greeting.c_str());
// 演示调用系统API
char sdk_version[PROPERTY_VALUE_MAX] = {};
property_get("ro.build.version.sdk", sdk_version, "unknown");
ALOGI("Current SDK version: %s", sdk_version);
// 也混合一点标准C++输出,方便在终端直接运行查看
std::cout << "Demo finished successfully." <


3276

被折叠的 条评论
为什么被折叠?



