為啥能夠生成一個(gè)帶符號(hào)拙吉、一個(gè)不帶符號(hào)的so?
在執(zhí)行gradle assembleRelease
之后军拟,我們的工程就會(huì)輸出三個(gè)so 文件。
其中有兩個(gè)是帶符號(hào)表信息的,另外一個(gè)是不帶符號(hào)表信息的碱妆,看到這不禁有些疑惑,其他兩個(gè)so 是怎樣生成的昔驱?為啥能夠輸出不帶符號(hào)表的so?生成的位置以及相關(guān)的設(shè)置是在哪里配置的疹尾?
一開始在研究的時(shí)候,以為是ndk-build
的時(shí)候生成的舍悯,一直在找CMakeList.txt
里面是不是有哪些變量是可以設(shè)置的航棱。
無意間看到了gradle assembleRelease的控制臺(tái)log輸出,
看到這兩個(gè)任務(wù)的名稱功能生成的so的文件位置很相似萌衬,猜測(cè)可以是跟著兩個(gè)有關(guān)饮醇。
> Task :app:transformNativeLibsWithMergeJniLibsForRelease UP-TO-DATE
> Task :app:transformNativeLibsWithStripDebugSymbolForRelease UP-TO-DATE
進(jìn)一步看到gradle
這兩個(gè)任務(wù)對(duì)應(yīng)的源碼,果然秕豫,猜測(cè)的沒錯(cuò)朴艰,其他的兩個(gè)so 文件,其實(shí)是gradle
的兩個(gè)任務(wù)幫我們生成的混移。
對(duì)應(yīng)的任務(wù)源碼如下:
其中祠墅,去掉符號(hào)的操作,是在stripFile
實(shí)現(xiàn)的歌径。
private void stripFile(@NonNull File input, @NonNull File output, @Nullable Abi abi)
throws IOException {
FileUtils.mkdirs(output.getParentFile());
ILogger logger = new LoggerWrapper(project.getLogger());
File exe = stripToolFinder.stripToolExecutableFile(
input,
abi,
msg -> {
logger.warning(msg + " Packaging it as is.");
return null;
});
if (exe == null) {
// The strip executable couldn't be found and a message about the failure was reported
// in getPathToStripExecutable.
// Fall back to copying the file to the output location
FileUtils.copyFile(input, output);
return;
}
ProcessInfoBuilder builder = new ProcessInfoBuilder();
builder.setExecutable(exe);
builder.addArgs("--strip-unneeded");
builder.addArgs("-o");
builder.addArgs(output.toString());
builder.addArgs(input.toString());
ProcessResult result = new GradleProcessExecutor(project).execute(
builder.createProcess(),
new LoggedProcessOutputHandler(logger));
if (result.getExitValue() != 0) {
logger.warning(
"Unable to strip library '%s' due to error %s returned "
+ "from '%s', packaging it as is.",
result.getExitValue(), exe, input.getAbsolutePath());
FileUtils.copyFile(input, output);
}
}
主要就是執(zhí)行strip
命令將動(dòng)態(tài)庫的符號(hào)進(jìn)行去除毁嗦。
SO是怎樣生成的?
我們現(xiàn)在NDK的開發(fā)一般都是使用cmake的方式來開發(fā)回铛,如果你在gradle中使用過cmake狗准,你會(huì)發(fā)現(xiàn)在gradle執(zhí)行sync操作后克锣,app目錄下就會(huì)生成一個(gè)叫.externalNativeBuild的文件夾,這個(gè)文件夾就是用來進(jìn)行C/C++代碼的編譯的腔长,
[圖片上傳失敗...(image-4172d5-1574608178029)]
在文件夾下面都會(huì)有android_gradle_build.json
這個(gè)文件袭祟, 它就是用來被 Gradle Plugin中的Task :app:externalNativeBuildRelease
任務(wù)解析,將構(gòu)建命令解析出來捞附,然后編譯C/C++代碼巾乳,最后產(chǎn)生對(duì)應(yīng)的so文件。具體的實(shí)現(xiàn)可以看CmakeExternalNativeJsonGenerator
相關(guān)的源碼鸟召。