解决JNI在Windows环境下因长路径导致编译失败问题

96
杰嗒嗒的阿杰
2018.05.04 11:03 字数 1159

之前听一个朋友反馈LuaScriptoCore在Windows下编译会报错,今天特意跑到Windows环境下测试了一番,果然是存在问题。得到了下面的编译报错信息:

Build command failed.
Error while executing process C:\Users\vimfung\AppData\Local\Android\Sdk\ndk-bundle\ndk-build.cmd with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Users\vimfung\Documents\LuaScriptCore\Source\Unity3D\Android\luascriptcore-unity-android\src\main\jni\Android.mk APP_ABI=arm64-v8a NDK_ALL_ABIS=arm64-v8a NDK_DEBUG=1 APP_PLATFORM=android-21 NDK_OUT=C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=C:\Users\vimfung\Documents\LuaScriptCore\Source\Unity3D\Android\luascriptcore-unity-android\build\intermediates\ndkBuild\debug\lib APP_CPPFLAGS+=-frtti APP_CPPFLAGS+=-fexceptions APP_CPPFLAGS+=-std=gnu++11 APP_CPPFLAGS+=-Wno-format-contains-nul APP_CPPFLAGS+=-g APP_CPPFLAGS+=-Wno-deprecated-declarations APP_CPPFLAGS+=-fpermissive APP_STL=gnustl_static NDK_DEBUG=1 APP_PLATFORM=android-14 NDK_TOOLCHAIN_VERSION=4.9 C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libLuaScriptCore-Unity-Android.so}
Android NDK: WARNING: Unsupported source file extensions in C:\Users\vimfung\Documents\LuaScriptCore\Source\Unity3D\Android\luascriptcore-unity-android\src\main\jni\Android.mk for module LuaScriptCore-Unity-Android
Android NDK: ../../../../../../lua-core/src/lua.hpp
[arm64-v8a] Compile++ : LuaScriptCore-Unity-Android <= LuaScriptCoreForUnity.cpp
C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/src/main/jni/../../../../../UnityCommon/LuaScriptCoreForUnity.cpp:616:1: fatal error: opening dependency file C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/LuaScriptCore-Unity-Android/C_/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/src/main/jni//////UnityCommon/LuaScriptCoreForUnity.o.d: No such file or directory
}
^
compilation terminated.
make: *** [C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/LuaScriptCore-Unity-Android/C
/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/src/main/jni/
////_/UnityCommon/LuaScriptCoreForUnity.o] Error 1

其中最重要的信息就是这段描述:

fatal error: opening dependency file C:/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/LuaScriptCore-Unity-Android/C_/Users/vimfung/Documents/LuaScriptCore/Source/Unity3D/Android/luascriptcore-unity-android/src/main/jni/////__/UnityCommon/LuaScriptCoreForUnity.o.d: No such file or directory

意思是说没有找到对应的LuaScriptCoreForUnity.o.d文件。后来经过查找资料发现是因为Windows下如果你的路径超长,其实会导致编译失败,无法生成.o文件,因此就会出现无法找到的提示。

对于出现这种情况,可以尝试下面三种方案:

方案一:修改长路径文件

手动调整项目中的文件路径和文件名称来缩短编译的文件路径,让它在限制的长度以内。

不过这种方式不太适用于我的项目,主要因为我的项目是一款SDK,不能太随意地调整文件名称和目录结构。

方案二:Gradle编译设置

打开项目的build.gradle文件,在allprojects项下添加下面设置:

allprojects {

    if(org.gradle.internal.os.OperatingSystem.current().isWindows())
    {
        //Windows下由于路径问题会导致编译报错,这里重新设置build路径
        buildDir = "C:/tmp/${rootProject.name}/${project.name}"
    }

    repositories {
        jcenter()
        google()
    }
}

该设置主要是判断当前环境是否为Windows,如果是则将编译目录设置到C:/tmp目录下。

这种方式跟方案一类似,但是不会调整编译文件的名字,但是能够改变编译输出的路径。经过尝试能够解决部分项目编译问题,但是对于一些项目路径较深的项目依然不适用。

方案三:调整Android.mk文件

该方式主要针对使用mk文件进行编译的项目,如果你的mk文件中设置的LOCAL_SRC_FILES项中每个编译文件都带有$(LOCAL_PATH)环境变量,那么可以将这个变量给移除调,再进行编译。

估计是因为JNI编译问题,编译产生的文件会根据你在mk文件中指定的路径来创建,如果你在mk文件中配置了$(LOCAL_PATH)/cpp/Test.cpp,那么,它会先对这个编译路径进行解析,假设文件就放在C:/project/sample/下,那么转换出来的路径就是C:/project/sample/cpp/Test.cpp,最终输出文件路径就会是C:/tmp/buildDir/C/project/sample/cpp/Test.o。这样无形中增加了三级目录,而这目录正是$(LOCAL_PATH)带来的。

所以移除后这个环境变量后项目就会以相对路径来查找编译文件,不会影响编译,同时也能够去除掉由于$(LOCAL_PATH)产生的多余目录路径。我的项目正好是使用Android.mk进行编译的,调整后编译正常,问题解决!

其他技术文章
Web note ad 1