【问题标题】:CMake FindThreads.cmake won't find my pthreads.h headerCMake FindThreads.cmake 找不到我的 pthreads.h 标头
【发布时间】:2012-01-13 06:53:03
【问题描述】:

我正在使用android-cmake 为Android 编译一个应用程序。这实际上创建了一个 CMake 工具链文件,用于使用 Android 的 NDK 提供的工具链。

this related question 一样,我的 CMakeLists.txt 文件中的以下行存在问题:

find_package(Threads REQUIRED)

头文件位于

~/Android/android-ndk-r7/platforms/android-8/arch-arm/usr/include/pthread.h

库文件位于

~/Android/android-ndk-r7/platforms/android-8/arch-arm/usr/lib/libthread_db.so

问题是 FindThreads.cmake 调用了CHECK_INCLUDE_FILES("pthread.h", CMAKE_HAVE_PTHREAD_H),这似乎不需要检查那个目录。

根据CMake's Useful Variables wiki pageCMAKE_INCLUDE_PATH允许设置头搜索路径,CMAKE_LIBRARY_PATH允许设置库搜索路径,CMAKE_PREFIX_PATH似乎都提供了find_package。

但是,尽管我在运行 cmake 之前是否设置了环境变量...

export CMAKE_INCLUDE_PATH=~/Android/android-ndk-r7/platforms/android-8/arch-arm/usr:~/Android/android-ndk-r7/platforms/android-8/arch-arm/usr/include

...或者我是否直接在 CMakeLists.txt 中设置它们...

if(ANDROID)
    set(CMAKE_INCLUDE_PATH
        ${ANDROID_NDK_SYSROOT}/usr
        ${ANDROID_NDK_SYSROOT}/usr/include
        ${CMAKE_INCLUDE_PATH}
    )

    set(CMAKE_LIBRARY_PATH
        ${ANDROID_NDK_SYSROOT}/usr
        ${ANDROID_NDK_SYSROOT}/usr/lib
        ${CMAKE_LIBRARY_PATH})

    set(CMAKE_PREFIX_PATH
        ${ANDROID_NDK_SYSROOT}
        ${CMAKE_PREFIX_PATH})

    message(${ANDROID_NDK_SYSROOT})
    message(${CMAKE_INCLUDE_PATH})

endif()

find_package(Threads REQUIRED)

...(这确实被执行,消息被打印),并且${ANDROID_NDK_SYSROOT} 包含

/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm

我仍然收到消息

找不到线程(缺少:Threads_FOUND)

有人对我做错了什么有任何建议吗?

【问题讨论】:

    标签: android cmake


    【解决方案1】:

    经过大量调试,我找到了解决此问题的方法,这很奇怪。从本质上讲,FindThreads.cmake 调用了一个名为 CHECK_INCLUDE_FILES 的宏,它试图 TRY_COMPILE 一个源文件,该源文件仅包含 CHECK_INCLUDE_FILES 宏所提供的头文件。

    请注意,它确实使用@sakra 建议的CMAKE_REQUIRED_INCLUDES,所以这很有用。

    使用 android-cmake,TRY_COMPILE 宏尝试使用 NDK 中的 arm-linux-androideabi-gcc 编译器进行编译,并带有所有指定的编译标志。 android.toolchain.cmake 文件包含以下行,这些行设置了其中一些编译标志:

    if( BUILD_WITH_ANDROID_NDK )
     set( CMAKE_CXX_FLAGS "--sysroot=\"${ANDROID_NDK_SYSROOT}\" ${CMAKE_CXX_FLAGS}" )
     set( CMAKE_C_FLAGS "--sysroot=\"${ANDROID_NDK_SYSROOT}\" ${CMAKE_C_FLAGS}" )
    

    TRY_COMPILE 宏失败,根据 CMakeError.log 文件包含以下内容:

    Run Build Command:/opt/local/bin/gmake "cmTryCompileExec/fast"
    /opt/local/bin/gmake -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
    gmake[1]: Entering directory '/Users/martin/Repositories/Delta/build/android/CMakeFiles/CMakeTmp'
    "/Applications/CMake 2.8-4.app/Contents/bin/cmake" -E cmake_progress_report /Users/martin/Repositories/Delta/build/android/CMakeFiles/CMakeTmp/CMakeFiles 1
    Building C object CMakeFiles/cmTryCompileExec.dir/CheckIncludeFiles.c.o
    /Users/martin/Android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gcc   --sysroot=;/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm" -fPIC -DANDROID -Wno-psabi -fsigned-char -mthumb -march=armv7-a -mfloat-abi=softfp  " -I/Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -I/Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include -I/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm/usr -I/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm/usr/include   -o CMakeFiles/cmTryCompileExec.dir/CheckIncludeFiles.c.o   -c /Users/martin/Repositories/Delta/build/android/CMakeFiles/CMakeTmp/CheckIncludeFiles.c
    arm-linux-androideabi-gcc: no input files
    

    如果您在实际编译器行向右滚动(倒数第二个),您可以看到--sysroot=;/... 部分。尽管上面的 CMake 行使用转义字符串,但 CMake 已将第一个转义引号转换为分号,并将第二个引号保留为普通引号,从而在 sysroot 行中产生一个分号,然后是一个包含所有 CMAKE_CXX_FLAGS 的字符串文字(易于参见 SO 的语法高亮)。

    解决方案是修改 android.toolchain.cmake 以删除转义的引号,因为它们是不必要的。

    if( BUILD_WITH_ANDROID_NDK )
     set( CMAKE_CXX_FLAGS "--sysroot=${ANDROID_NDK_SYSROOT} ${CMAKE_CXX_FLAGS}" )
     set( CMAKE_C_FLAGS "--sysroot=${ANDROID_NDK_SYSROOT} ${CMAKE_C_FLAGS}" )
    

    【讨论】:

      【解决方案2】:

      设置CMAKE_INCLUDE_PATH 只会影响CMake find_filefind_path 命令。 FindThreads.cmake 调用的CHECK_INCLUDE_FILES 函数不支持该变量。对于CHECK_INCLUDE_FILES,您可以设置变量CMAKE_REQUIRED_INCLUDES

      set(CMAKE_REQUIRED_INCLUDES 
        ${ANDROID_NDK_SYSROOT}/usr 
        ${ANDROID_NDK_SYSROOT}/usr/include)
      

      【讨论】:

      • 进一步阅读 FindThreads.cmake 这个答案是合乎逻辑的,但由于某种原因它仍然不能解决我的问题。 Threads_FOUND 仍未设置。当我发现问题时,将尝试进行更多调试并更新我的问题。谢谢。
      【解决方案3】:

      好的,我正在使用 CMake 3.18.1-g262b901、NDK 21.4.7075529、Android Studio 2020.3.1

      这个问题出现了,你可能知道,因为 android 在 libc++ 中包含pthread.h,所以没有 pthread 包。 find_package(Threads REQUIRED) 使用的 FindThreads.cmake 文件确实试图通过尝试使用 #include "pthread.h" 编译程序来解释此类事情 here,并且成功时会假装它找到了一个包。

      那么为什么会失败?在我的环境中,在调查了 CHECK_INCLUDE_FILE 宏后,我发现它失败并出现以下错误

      error: invalid argument '-std=c++11' not allowed with 'C'
      

      似乎 android studio 环境正在为编译器设置此标志,即使对于 C 代码也是如此。

      什么可以解决它?

      find_package(Threads REQUIRED) 正在评估时,在失败的调用周围添加以下代码以将 CMAKE_C_COMPILER_LOADED 设置为 false 应该使 FindThreads.cmake 使用 CHECK_INCLUDE_FILE_CXX 而不是 C 版本。

      set(CMAKE_C_COMPILER_LOADED 0)
      
      #Your failing instruction
      
      set(CMAKE_C_COMPILER_LOADED 1)
      

      注意:如果您有权访问导致错误的 CMake 文件,则始终不能首先调用 find_package(Threads REQUIRED)#include "pthread.h" 调用应该可以在 android 环境中正常工作,无需任何额外的断言。

      奇怪...以下在我的顶级CMakeLists.txt 上评估为真。比我聪明的人可能想要这些信息。

      include(CheckIncludeFile)
      CHECK_INCLUDE_FILE("pthread.h" TEST)
      message("TEST: ${TEST}")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-10
        • 1970-01-01
        • 2017-05-01
        • 2015-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多