为啥能够生成一个带符号、一个不带符号的so?
在执行gradle assembleRelease
之后,我们的工程就会输出三个so 文件。
-w1353
其中有两个是带符号表信息的,另外一个是不带符号表信息的,看到这不禁有些疑惑,其他两个so 是怎样生成的?为啥能够输出不带符号表的so?生成的位置以及相关的设置是在哪里配置的?
一开始在研究的时候,以为是ndk-build
的时候生成的,一直在找CMakeList.txt
里面是不是有哪些变量是可以设置的。
无意间看到了gradle assembleRelease的控制台log输出,
image
看到这两个任务的名称功能生成的so的文件位置很相似,猜测可以是跟着两个有关。
> Task :app:transformNativeLibsWithMergeJniLibsForRelease UP-TO-DATE
> Task :app:transformNativeLibsWithStripDebugSymbolForRelease UP-TO-DATE
进一步看到gradle
这两个任务对应的源码,果然,猜测的没错,其他的两个so 文件,其实是gradle
的两个任务帮我们生成的。
对应的任务源码如下:
image.png
其中,去掉符号的操作,是在stripFile
实现的。
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);
}
}
主要就是执行strip
命令将动态库的符号进行去除。
SO是怎样生成的?
我们现在NDK的开发一般都是使用cmake的方式来开发,如果你在gradle中使用过cmake,你会发现在gradle执行sync操作后,app目录下就会生成一个叫.externalNativeBuild的文件夹,这个文件夹就是用来进行C/C++代码的编译的,
[图片上传失败...(image-4172d5-1574608178029)]
在文件夹下面都会有android_gradle_build.json
这个文件, 它就是用来被 Gradle Plugin中的Task :app:externalNativeBuildRelease
任务解析,将构建命令解析出来,然后编译C/C++代码,最后产生对应的so文件。具体的实现可以看CmakeExternalNativeJsonGenerator
相关的源码。
网友评论