android studio编译JNI问题ninja: fatal: couldn‘t open nul的解决

  这几天编译同文trime输入法时遇到一个没法解决的问题,到网上搜也没有答案难道没人遇到类似的问题。问题描述如下:

D:\project\andriod\trime-develop\app\src\main\jni\CMakeLists.txt : C/C++ debug|x86 : CMake Error at C:/Users/Administrator/AppData/Local/Android/Sdk/cmake/3.18.1/share/cmake-3.19/Modules/CMakeTestCCompiler.cmake:68 (message):
  The C compiler

    "C:/Users/Administrator/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: D:/project/andriod/trime-develop/app/.cxx/cmake/debug/x86/CMakeFiles/CMakeTmp
    
    Run Build Command(s):C:\Users\Administrator\AppData\Local\Android\Sdk\cmake\3.18.1\bin\ninja.exe 
    cmTC_3c0a9 && ninja: fatal: couldn't open nul

于是找到CMakeTestCCompiler.cmake文件发现是以下代码报错:

  file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c
    "#ifdef __cplusplus\n"
    "# error \"The CMAKE_C_COMPILER is set to a C++ compiler\"\n"
    "#endif\n"
    "#if defined(__CLASSIC_C__)\n"
    "int main(argc, argv)\n"
    "  int argc;\n"
    "  char* argv[];\n"
    "#else\n"
    "int main(int argc, char* argv[])\n"
    "#endif\n"
    "{ (void)argv; return argc-1;}\n")
  #message(FATAL_ERROR "hello world")
  try_compile(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR}
    ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c
    OUTPUT_VARIABLE __CMAKE_C_COMPILER_OUTPUT)
  # Move result from cache to normal variable.
  set(CMAKE_C_COMPILER_WORKS ${CMAKE_C_COMPILER_WORKS})
  unset(CMAKE_C_COMPILER_WORKS CACHE)
  __TestCompiler_restoreTryCompileTargetType()
  if(NOT CMAKE_C_COMPILER_WORKS)
    PrintTestCompilerResult(CHECK_FAIL "broken")
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
      "Determining if the C compiler works failed with "
      "the following output:\n${__CMAKE_C_COMPILER_OUTPUT}\n\n")
    string(REPLACE "\n" "\n  " _output "${__CMAKE_C_COMPILER_OUTPUT}")
    message(FATAL_ERROR "hello world, The C compiler\n  \"${CMAKE_C_COMPILER}\"\n"
      "is not able to compile a simple test program.\nIt fails "
      "with the following output:\n  ${_output}\n\n"
      "CMake will not be able to correctly generate this project.")

  其中message命令中的hello world是我为了定位问题加的。file命令将测试代码写入testCCompiler.c,try_compile命令进行编译,成功则CMAKE_C_COMPILER_WORKS的值为true。就是这么简单的测试代码居然报错!!
  于是又从github上把ninja代码下载下来,找到subprocess-win32.cc文件找到报错的地方如下:

bool Subprocess::Start(SubprocessSet *set, const string &command)
{
        HANDLE child_pipe = SetupPipe(set->ioport_);

        SECURITY_ATTRIBUTES security_attributes;
        memset(&security_attributes, 0, sizeof(SECURITY_ATTRIBUTES));
        security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
        security_attributes.bInheritHandle = TRUE;
        // Must be inheritable so subprocesses can dup to children.必须是可继承的,以便子进程可以复制到子进程
        // HANDLE nul = CreateFileA("D:\testCCompiler.c", GENERIC_READ,
        HANDLE nul = CreateFileA("NUL", GENERIC_READ,
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                        &security_attributes, OPEN_EXISTING, 0, NULL);
        if (nul == INVALID_HANDLE_VALUE)
                Fatal("hello world, couldn't open nul");

  发现CreateFileA函数的第一个参数居然NUL,心想google这个坑货害人啊。于是改成D:\testCCompiler.c结果发现也不对。这时就无计可施了 哭!!
  编译ninja的时候明明好好的,用gcc编译也成功msvc编译也没问题,为什么在android studio上编译就失败呢。心想是不是ndk的cmake版本太低于是升级到3.18.1也没用。于是将本地cmake 3.9中的文件替换掉ndk中的文件重新编译结果还是一样。
  推测因为用本地cmake编译ninja时用的是make没用ninja,而android studio用的是ninja所以才会出错。到此时已经无计可施了。现在只有两个办法一个是修复ninja问题,一个是用make替换ninja看看。刚接触安卓开发很多东西还不熟。
  把ndk下cmake中的ninja.exe复制到独立安装的cmake的bin文件夹中,用ninja替换make果然还是不行,输出如下:

PS D:\projectcode\ninja-master\build_ninja> cmake -G Ninja ..
-- The C compiler identification is GNU 8.1.0
-- The CXX compiler identification is GNU 8.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: C:/mingw64/bin/gcc.exe
-- Check for working C compiler: C:/mingw64/bin/gcc.exe - broken
CMake Error at E:/Program Files/CMake/share/cmake-3.19/Modules/CMakeTestCCompiler.cmake:68 (message):
  The C compiler

    "C:/mingw64/bin/gcc.exe"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: D:/projectcode/ninja-master/build_ninja/CMakeFiles/CMakeTmp

    Run Build Command(s):E:/PROGRA~2/CMake/bin/ninja.exe cmTC_753f8 && ninja: fatal: couldn't open nul

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:6 (project)

-- Configuring incomplete, errors occurred!
See also "D:/projectcode/ninja-master/build_ninja/CMakeFiles/CMakeOutput.log".
See also "D:/projectcode/ninja-master/build_ninja/CMakeFiles/CMakeError.log".
PS D:\projectcode\ninja-master\build_ninja>

不行就只能换平台了拿到ubuntu上再看了。


####################################################################
  过了好多天一直在这个问题上纠结,ninja: fatal: couldn’t open nul这个问题不解决没法进行后面的问题。不是google的ninja有问题是win10有问题。换到win7上是没问题的,按照网上的答案应该是C:\Windows\System32\drivers\null.sys损坏了于是替换了null.sys,其实也没解决。执行下列命令说是指定的服务未安装。

C:\Windows\System32\drivers>sc query Null
[SC] EnumQueryServicesStatus:OpenService 失败 1060:

指定的服务未安装。

换到win7上是没问题的

Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\Windows\system32>sc query null

SERVICE_NAME: null
        TYPE               : 1  KERNEL_DRIVER
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

C:\Windows\system32>

NUL应该是个设备或者服务,以下是网上查到的:
Windows设备名称 "aux","com1","com2","prn","con","nul"等,因为这些名字都属于设备名称,等价于一个 DOS 设备,如果我们把文件命名为这些名字,Windows 就会误以为发生重名,所以会提示“不能创建同名的文件”等等。

  于是把ninja代码中subprocess-win32.cc文件中报错的地方HANDLE nul = CreateFileA(“NUL”, GENERIC_READ改成
HANDLE nul = CreateFileA(“con”, GENERIC_READ 没想到居然成功了。

bool Subprocess::Start(SubprocessSet *set, const string &command)
{
        HANDLE child_pipe = SetupPipe(set->ioport_);

        SECURITY_ATTRIBUTES security_attributes;
        memset(&security_attributes, 0, sizeof(SECURITY_ATTRIBUTES));
        security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
        security_attributes.bInheritHandle = TRUE;
        // Must be inheritable so subprocesses can dup to children.必须是可继承的,以便子进程可以复制到子进程
        // HANDLE nul = CreateFileA("D:\testCCompiler.c", GENERIC_READ,
        HANDLE nul = CreateFileA("con", GENERIC_READ,
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                        &security_attributes, OPEN_EXISTING, 0, NULL);
        if (nul == INVALID_HANDLE_VALUE)
                Fatal("hello world, couldn't open nul");

虽然问题解决了但没彻底解决说不定以后因为这个问题还会导致其他bug。


###########################################################

今天终于彻底解决了问题。

  在网上下载了几个null.sys替换原先的C:\Windows\System32\drivers\null.sys结果都不成功。一定要执行下面两句命令否则无法删除null.sys文件,需要权限。

PS D:\projectcode\ninja-master\build_ninja> takeown /f C:\Windows\System32\drivers\null.sys

成功: 此文件(或文件夹): "C:\Windows\System32\drivers\null.sys" 现在由用户 "YANGSAIL\Administrator" 所有。
PS D:\projectcode\ninja-master\build_ninja> icacls C:\Windows\System32\drivers\null.sys /grant administrators:F

将null.sys手动删除,下载win10操作系统到虚拟机中装好,到新系统中复制null.sys到本机系统C:\Windows\System32\drivers中再次执行sc命令如下:

D:\projectcode\ninja_test>sc query null

SERVICE_NAME: null
        TYPE               : 1  KERNEL_DRIVER
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

D:\projectcode\ninja_test>

成功了!
保留ninja代码中subprocess-win32.cc文件中报错的地方HANDLE nul = CreateFileA(“NUL”, 重新编译生成ninja.exe替换掉E:\CMake\bin\ninja.exe ,用ninja.exe编译ninja项目如下:

PS D:\projectcode\ninja-master\build_ninja\ninja-master\build_ninja> ninja -f build.ninja
[8/8] Linking CXX executable ninja_test.exe
PS D:\projectcode\ninja-master\build_ninja\ninja-master\build_ninja>

成功!!

重新编译trime输入法也成功。
说明ninja: fatal: couldn’t open nul彻底解决了,开心!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值