【问题标题】:Limit CPU cores for ndkBuild with Cmake and Ninja使用 Cmake 和 Ninja 限制 ndkBuild 的 CPU 内核
【发布时间】:2019-01-04 13:21:31
【问题描述】:

之前,当我使用 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()
    }
}

谢谢。

【问题讨论】:

    标签: android cmake ndk-build ninja


    【解决方案1】:

    控制 ninja 并行度

    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 和/或 link 作业的数量。

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

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

    现在,如果您的项目最终产生了其他正在使用 ninja 构建项目的子进程,那么您必须:

    • 使用包含 Job Server 支持的 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()
        }
    }
    

    【讨论】:

    • 您能在 Android gradle 构建文件的上下文中提出解决方案吗?如果我将参数放入 externalNativeBuild { cmake { arguments 部分,则会收到以下错误:Error while executing process D:\Android\sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build D:\...\.externalNativeBuild\cmake\fullDebug\arm64-v8a --target JniInterface} ninja: error: build.ninja:113: unknown pool name 'compile' 对于其他解决方案。我知道 ninja 可以接受 -j 参数,但我没有直接运行 ninja 并且添加 -Dj X 作为 cmake 的参数不会做任何事情......
    • 考虑到-jN 是特定于构建工具ninja 的选项,指定-Dj X(或-Dj=X)将不起作用。错误unknown pool name 'compile' 可能表明您仅通过选项'-DCMAKE_JOB_POOLS:STRING=compile=5;link=2' 配置项目而忘记传递-DCMAKE_JOB_POOL_COMPILE:STRING=compile-DCMAKE_JOB_POOL_LINK:STRING=link
    • 我更新了答案以建议使用externalNativeBuild的可能方法
    • 不,我之前已经把所有的论点都放在那里了。无论如何,按照您的建议进行操作也不起作用Build command failed. Error while executing process D:\...\cmake.exe with arguments {-HD:\...\sdk -BD:\...\arm64-v8a -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-21 -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=D:\...\arm64-v8a -DCMAKE_BUILD_TYPE=Debug ... -DCMAKE_MAKE_PROGRAM=D:\...\ninja.exe -GAndroid Gradle - Ninja -DANDROID_STL=c++_static -DCMAKE_JOB_POOL_COMPILE:STRING=compile -DCMAKE_JOB_POOL_LINK:STRING=link '-DCMAKE_JOB_POOLS:STRING=compile=5;link=2'}
    • 整个错误消息太长,所以我删除了路径和一些不重要的参数。但我认为这对你来说应该不是问题
    【解决方案2】:

    我可以通过添加以下内容来解决此问题:

    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) 版本

    【讨论】:

      【解决方案3】:

      好的,这似乎是 NDK 中的一个错误/缺失功能。我与一些“NDK Google 员工”交谈过,他们也无法帮助我。希望以后版本的 NDK/AS 能支持它。

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

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

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

      【讨论】:

        【解决方案4】:

        我创建了一个解决方法:将 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
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-09-18
          • 2017-08-30
          • 2017-01-25
          • 2017-11-20
          • 2016-12-01
          • 2016-08-19
          • 2022-08-15
          • 2020-05-21
          相关资源
          最近更新 更多