Android NDK开发

NDK开发(六)--SO的生成

2019-11-24  本文已影响0人  骑着蜗牛闯世界666

为啥能够生成一个带符号、一个不带符号的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相关的源码。

参考链接

http://www.relaxcms.com/shtml/52/content_368.html

上一篇下一篇

猜你喜欢

热点阅读