【发布时间】:2017-10-30 00:08:29
【问题描述】:
我在一个相当小的爱好项目中,我们正在创建一个游戏,或者至少正在尝试这样做......我们面临的主要问题是我们能够在 MacOS 和 Linux 上编译该项目,但不是在 Windows 上。
我们使用 GLFW 作为 OpenGL 的接口,因此我们需要在屏幕上显示任何内容。问题是当我们告诉 Make 做它的事情时,它会编译每个单独的模块,但由于未定义的引用而无法链接它们。虽然这可能是有道理的,但奇怪的是这些未知的引用都有前缀__imp_,它在源代码中不存在。示例:我们使用了方法glfwInit,但是在尝试制作项目时,我们得到:graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0xa): undefined reference to `_imp__glfwInit'
做了一些研究,我找到了This SO Question,我尝试了其中的答案。它失败了,因为编译后唯一的lib是libglfw3.a,没有任何dll或dll提示。相应地重命名这个文件没有帮助,放置预编译的二进制文件也没有帮助。删除这个文件会导致它重新编译并重新出现,所以清楚地知道它在哪里。
我们还尝试切换到 clang,因为它可能有一个更智能的链接器,但它一开始就不想编译任何东西。
我对此进行了大量研究,发现了无数 SO 答案和论坛帖子中存在类似甚至相同问题的人,每个人都有不同的解决方案,但没有一个对我们有用。
为了生成 Makefile,我们在主子目录中使用 CMake 和以下脚本(别担心,它是从上面调用的,到目前为止我们已经完成了):
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
add_subdirectory(graphicsengine)
add_subdirectory(fileSys)
add_subdirectory(networking)
add_subdirectory(game)
add_subdirectory(glfw-3.2.1)
include_directories(glfw-3.2.1/include)
if (UNIX AND NOT APPLE)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
endif()
add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
target_link_libraries(${PROJECT_NAME} graphicsengine fileSys networking game)
if (APPLE)
target_link_libraries(${PROJECT_NAME} "-framework OpenGL")
endif()
if (WIN32)
target_link_libraries(${PROJECT_NAME} opengl32 gdi32)
endif()
if (UNIX AND NOT APPLE)
target_link_libraries(${PROJECT_NAME} ${OPENGL_gl_LIBRARY})
endif()
target_link_libraries(${PROJECT_NAME} glfw)
install(TARGETS ${PROJECT_NAME} DESTINATION ${INSTALL_DIR})
其余重要的 cmake 调用都在父目录中
这是自定义构建脚本调用的 cmake/make 的完整日志:
debug
release
-- The CXX compiler identification is GNU 5.3.0
-- Check for working CXX compiler: D:/MinGW/bin/g++.exe
-- Check for working CXX compiler: D:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is GNU 5.3.0
-- Check for working C compiler: D:/MinGW/bin/gcc.exe
-- Check for working C compiler: D:/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Could NOT find Vulkan (missing: VULKAN_INCLUDE_DIR)
-- Looking for dinput.h
-- Looking for dinput.h - not found
-- Looking for xinput.h
-- Looking for xinput.h - not found
-- Performing Test _GLFW_HAS_DEP
-- Performing Test _GLFW_HAS_DEP - Success
-- Performing Test _GLFW_HAS_ASLR
-- Performing Test _GLFW_HAS_ASLR - Success
-- Performing Test _GLFW_HAS_64ASLR
-- Performing Test _GLFW_HAS_64ASLR - Failed
-- Using Win32 for window creation
-- Configuring done
-- Generating done
-- Build files have been written to: D:/cpp-neon/Workspace/Supermerged
--------------MAKE STARTS HERE--------------
[ 60%] Built target glfw
[ 68%] Built target graphicsengine
[ 76%] Built target fileSys
[ 84%] Built target networking
[ 92%] Built target game
[ 96%] Linking CXX executable Submerged_PR0.exe
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0xa): undefined reference to `_imp__glfwInit'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x45): undefined reference to `_imp__glfwCreateWindow'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x55): undefined reference to `_imp__glfwTerminate'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x64): undefined reference to `_imp__glfwMakeContextCurrent'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x71): undefined reference to `_imp__glfwWindowShouldClose'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x98): undefined reference to `_imp__glfwSwapBuffers'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0x9f): undefined reference to `_imp__glfwPollEvents'
graphicsengine/libgraphicsengine.a(graphics.cpp.obj):graphics.cpp:(.text+0xa8): undefined reference to `_imp__glfwTerminate'
collect2.exe: error: ld returned 1 exit status
source\CMakeFiles\Submerged_PR0.dir\build.make:101: recipe for target 'source/Submerged_PR0.exe' failed
mingw32-make[2]: *** [source/Submerged_PR0.exe] Error 1
CMakeFiles\Makefile2:102: recipe for target 'source/CMakeFiles/Submerged_PR0.dir/all' failed
mingw32-make[1]: *** [source/CMakeFiles/Submerged_PR0.dir/all] Error 2
Makefile:128: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
Make Failed, Aborting Install
PS D:\cpp-neon\Workspace\Supermerged>
如果你想知道,这是我们的项目结构:
上面的 CMakeLists.txt 就是你在 /source 中看到的那个
其余模块的构建方式相同,除了 glfw,您可以在他们的网站上找到它
在这个时间点上,我们或多或少地无助和厌倦了寻找解决方案,我们只是尝试一些东西直到它有点工作,但最终导致一切本不应该存在的巨大混乱,我们都知道结果如何... (咳)这些分支中的哪一个是我做的事情让它做另一件事的地方?(咳嗽)我们希望你们中的一些人(所以) 可能比我们任何人都有更好的方法来找到解决方案。随意提出任何其他可能有助于您找到有效方法的问题!
提前致谢!
以:sDev的名义
【问题讨论】:
-
在你
CMakeLists.txt中你有add_subdirectory(graphicsengine),然后是add_subdirectory(glfw-3.2.1)。但是构建顺序是颠倒的:Built target glfw,然后是Built target graphicsengine。这怎么可能?以及如何将graphicsengine与glfw链接起来,因为在处理graphicsengine文件夹时glfw目标无法访问? -
@Tsyvarev 确实很奇怪,但我认为构建顺序确实取决于
target_link_libraries(${PROJECT_NAME} graphicsengine fileSys networking game)行,然后才在target_link_libraries(${PROJECT_NAME} glfw)行之后 -
其实我的第二个问题更重要:在
graphicsengine下你构建了库,它使用glfw。但是glfw库会在稍后 注明,这意味着您甚至没有为graphicsengine提供glfw标头。看起来graphicsengine使用 它自己的 glfw 进行标题和链接。并且“它自己的 glfw”与您的不兼容。 -
@Tsyvarev 我尝试在链接其他所有内容的调用之前将调用移至
target_link_libraries(...glfw),唯一改变的是构建顺序。从Linking CXX executable Submerged_PR0.exe开始,其余错误仍然存在。 -
简单地交换
add_subdirectorys 的顺序没有任何改变:如果graphicsengine没有链接到glfw目标,交换顺序后它不会链接到它。CMakeList.txt的graphicsengine有问题,但你没有显示出来。