美文网首页Android NDK开发
NDK开发(六)--SO的生成

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

作者: 骑着蜗牛闯世界666 | 来源:发表于2019-11-24 23:09 被阅读0次

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

    相关文章

      网友评论

        本文标题:NDK开发(六)--SO的生成

        本文链接:https://www.haomeiwen.com/subject/sjirwctx.html