使用 Cmake 和 Ninja 限制 ndkBuild 的 CPU 个内核

Limit CPU cores for ndkBuild with Cmake and Ninja

之前,当我使用 ndkBuld 在 Android 上构建本机代码时,我能够将参数传递给 make 以定义多个 CPU 要使用的核心。如果我想使用 4 个内核,我可以添加类似这样的内容

externalNativeBuild {
    ndkBuild {
        arguments "-j4", "APP_SHORT_COMMANDS=true"
        abiFilters "armeabi-v7a"
    }
}

有人可以建议我如何使用 Cmake 和 Ninja 做类似的事情吗? cmake 配置是否有一些等效参数?

externalNativeBuild {
    cmake {
        arguments "-DANDROID_STL=c++_static"
        abiFilters getAbis()
    }
}

谢谢。

控制忍者并行度

Ninja 也支持同样的参数:

$ ninja --help
usage: ninja [options] [targets...]

[...]

options:
  [...]

  -j N     run N jobs in parallel [default=10, derived from CPUs available]

  [...]

控制 ninja 并行性区分 compilelink 作业

现在,如果您想要更详细的信息。例如,如果您想同时限制 link jobscompile jobs 或两者的数量。

从 CMake 3.11 开始,现在可以限制 compile and/or link 个作业的数量。

然后您可以使用这些选项配置您的项目:

-DCMAKE_JOB_POOL_COMPILE:STRING=compile
-DCMAKE_JOB_POOL_LINK:STRING=link
'-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'

现在,如果您的项目最终产生了其他正在使用忍者构建项目的子进程,您将不得不:

  • 使用包含作业服务器支持的 ninja 分支,就像在 make 中所做的那样。相关的 GitHub 版本中也提供了二进制文件。参见 https://github.com/kitware/ninja#readme

  • 确保子项目也配置了相同的 -DCMAKE_JOB_ 选项

在 externalNativeBuild 的上下文中

这意味着您可以尝试这样的操作:

externalNativeBuild {
    cmake {
        arguments "-DANDROID_STL=c++_static -DCMAKE_JOB_POOL_COMPILE:STRING=compile -DCMAKE_JOB_POOL_LINK:STRING=link '-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'"
        abiFilters getAbis()
    }
}

好的,这似乎是 NDK 中的错误/缺失功能。我已经和一些 "NDK Googlers" 交谈过,他们也无法帮助我。希望以后的NDK/AS版本能支持。

以下是您可以跟踪进度的问题:

https://github.com/android-ndk/ndk/issues/983

https://issuetracker.google.com/issues/137878831

我创建了一个解决方法:用一个脚本包装 Android Studio 使用的 ninja 可执行文件,该脚本调用 ninja,所有给定参数在末尾加上“-j1”。

  1. 找到 Android Studio 使用的 ninja 可执行文件。例如,somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
  2. 将其重命名为其他名称,例如 ninja_orig
  3. 创建一个 shell 脚本(并为其添加执行权限)以将 somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja 中的原始 ninja 可执行文件替换为以下内容:
    #!/bin/sh
    somefolder/Android/Sdk/cmake/3.10.2.4988404/bin/ninja_orig $@ -j1
    

我能够通过添加来解决这个问题:

if (PARALLEL_COMPILE_JOBS)
  set(CMAKE_JOB_POOL_COMPILE compile_job_pool${CMAKE_CURRENT_SOURCE_DIR})
  string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" CMAKE_JOB_POOL_COMPILE ${CMAKE_JOB_POOL_COMPILE})
  set_property(GLOBAL APPEND PROPERTY JOB_POOLS ${CMAKE_JOB_POOL_COMPILE}=${PARALLEL_COMPILE_JOBS})
endif ()
  if (PARALLEL_COMPILE_JOBS)
    message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}: Limiting compiler jobs to ${PARALLEL_COMPILE_JOBS}")
endif ()

到我的基础 CMakeLists.txt,然后在我的 build.gradle 中,我添加到 cmake 参数:“-DPARALLEL_COMPILE_JOBS=8”以指定最多 8 个并行 clang++ 编译进程。这适用于当前 Android Studio cmake (3.10) 和 ninja (1.8.2) 版本