Android Lint Aosp App With SonarQube

date
slug
Android-Lint-Aosp-with-SonarQube
status
Published
tags
Android
Lint
AOSP
SonarQube
summary
背景第三方 App 在 Android Studio 中可以直接使用 Lint 展示结果. 源码编译时在 make 之后工程根目录执行 lint packages/apps/Calendar/ 也可以 Lint. 但在实际使用中 lint vendor/letv/apps/Camera/ 时提示 `No bytecode found: Has the project been bu...
type
Post

背景

第三方 App 在 Android Studio 中可以直接使用 Lint 展示结果. 源码编译时在 make 之后工程根目录执行 lint packages/apps/Calendar/ 也可以 Lint. 但在实际使用中 lint vendor/letv/apps/Camera/ 时提示 No bytecode found: Has the project been built? (Camera), 同时还有资源使用的误报。

原因

分析 lint 源码可知 lint/detector/api/Project.java#654
Lint 会尝试从 out 目录中寻找 ModuleName_intermediates/classes.jar, 找不到则会报 No bytecode found. 比如 /letv/workspace/DEMETER_FINAL/out/target/common/obj/APPS/StvCamera_intermediates 而找不到有两个原因:
  1. 从 Android M 开始 AOSP 使用 Jack 编译 (Android N 开始使用 JaCoCo?), Jack 编译时生成 classes.jack / classes.dex 而非 classes.jar
  1. getIntermediateDirs() 方法中 moduleName = mDir.getName() 而不是 vendor/letv/app/**/Android.mk 中指定的 LOCAL_PACKAGE_NAME

禁用 Jack / dex2jar

对于问题 1 要么禁用掉 Jack make 时生成 classed.jar, 要么把 classes.dex 转换成 classes.jar 禁用掉整个项目的 Jack 则会 make 不过, 尝试了几个 module 级别的禁用都无效 测试 dex2jar 可行

修改 lint-api.jar

对于问题 2 修改 lint-api.jar 比编译整个 lint 工具更简单, 方法与 2. CrossWalk.jar 修改 类似 修改过程见 https://github.com/likaci/android-lint-mod-jar/commits/master 另外源码环境中的 lint 使用的是 DEMETER_FINAL/prebuilts/devtools/tools/lint 版本太旧, 直接使用最新的 lint-api 修改, 但最新的 lint 需要 jre8 才能执行

使用

以 DEMETER_FINAL/vendor/letv/apps/Camera/ 为例 下载 https://github.com/likaci/android-lint-mod 修改 bin/lint 92行 JAVACMD="/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java" 成合适的 jre8 路径 make 整个 AOSP 工程 下载 dex2jar - https://github.com/pxb1988/dex2jar/releases 解压到合适的路径
之后运行 SonarScanner 指定 -Dsonar.android.lint.report=./lint-report.xml 即可

参考

使用 Lint 改进您的代码 - https://developer.android.com/studio/write/lint.html?hl=zh-cn Compiling with Jack - https://source.android.com/source/jackey Using SonarQube with Jenkins Continuous Integration and GitHub to Improve Code Review

© likaci 2013 - 2024