我正在使用gcc(cygwin),gnu make,windows 7和cmake。
我的cmake testprojekt有以下结构
rootdir |-- App | |-- app.cpp | +-- CMakeLists.txt |-- Lib | |-- lib.cpp | |-- CMakeLists.txt |-- MakeFileProject + CMakeLists.txt
ROOTDIR /应用/ app.cpp:
#include<string> void printThemMessageToScreen(std::string input);//prototype int main(int argc,char **argv){ printThemMessageToScreen("this will be displayed by our lib"); return 0; }
ROOTDIR /库/ lib.cpp:
#include<iostream> #include<string> void printThemMessageToScreen(std::string input){ std::cout<<input; }
ROOTDIR /的CMakeLists.txt:
cmake_minimum_required(VERSION 2.6) project(TestProject) add_subdirectory(App) add_subdirectory(Lib)
ROOTDIR / lib中/的CMakeLists.txt:
add_library(Lib SHARED lib.cpp)
ROOTDIR /应用/的CMakeLists.txt:
# Make sure the compiler can find include files from our Lib library. include_directories (${LIB_SOURCE_DIR}/Lib) # Make sure the linker can find the Lib library once it is built. link_directories (${LIB_BINARY_DIR}/Lib) # Add executable called "TestProjectExecutable" that is built from the source files add_executable (TestProjectExecutable app.cpp) # Link the executable to the lib library. target_link_libraries (TestProjectExecutable Lib)
现在,当我运行cmake并make,一切都会得到生成和没有错误,但是当我尝试执行二进制文件,它将失败,因为生成的库无法find。
但是:当我复制lib DLL到像应用程序的exe文件相同的目录,它会得到执行!
另外:如果我configuration库是静态的,它也会执行。
如何告诉运行时链接程序在哪里寻找我的DLL?
根据用户Vorren提出的方法解决scheme:
我打开了registry编辑器,然后导航到以下registry项:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
,在这里我创build了一个新的密钥,名称为我的Applikation:
在这种情况下:TestProjectExecutable.exe
之后,将(默认)值设置为TestProjectExecutable.exe的完整path,包括文件名和扩展名。 然后,我创build了另一个名为“path”的string值,并将该值设置为该dll所在的文件夹:
你的问题不在于链接器或编译器,而在于Windows搜索DLL的方式。
操作系统将使用以下算法来定位所需的DLL:
在看:
因此,如果您不想使用特定于应用程序的dll混淆OS目录,那么您有两个合理的选项:
我更喜欢的解决方案是没有提到的,就是将你的shared-libs和你的可执行文件放在同一个目录下。 这往往是一个更简单的解决方案。
用cmake做到这一点的一个方法是
设置(CMAKE_RUNTIME_OUTPUT_DIRECTORY $ {CMAKE_BINARY_DIR} / bin)
或者你也可以根据构建风格设置输出目录。
看看我如何使cmake输出到“bin”目录?
我从接受的答案(通过pdeschain)尝试了选项1。 我甚至创建了一个cmake挂钩来自动注册链接库的路径
function (xtarget_link_libraries target libs) # same as target_link_libraries but with additional improvements to allow windows find the library at runtime LIST(REMOVE_AT ARGV 0) SET(LIBS ${ARGV}) # this is to pass list into this function target_link_libraries(${target} ${LIBS}) # call standard routine if(WIN32) set(TFILE ".") get_property(slibs TARGET ${target} PROPERTY all_libs) # recall libs linked before set(LIBS ${slibs};${LIBS}) set_property(TARGET ${target} PROPERTY all_libs ${LIBS}) # save all libs FOREACH(lib ${LIBS}) # compose a list of paths set(TFILE "${TFILE};$<TARGET_LINKER_FILE_DIR:${lib}>") ENDFOREACH() #add reg key add_custom_command(TARGET ${target} POST_BUILD COMMAND reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\${target}.exe" /v "Path" /d "${TFILE}" /f ) endif() endfunction()
可以用作xtarget_link_libraries(test lib1 lib2)
。 应用程序将能够找到绝对路径上的动态库。
但是,这是一个很大的问题, App Paths
机制https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx#appPaths
不允许为“Debug / test.exe”和“Release / test.exe”设置不同的条目。 所以对我来说这是一个糟糕的选择。
您可以添加以下行来填充Default
键作为该文章中建议的程序的路径。
add_custom_command(TARGET ${target} POST_BUILD COMMAND reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\${target}.exe" /ve /d "$<TARGET_FILE:${target}>" /f )
现在你可以享受从系统中的任何地方运行test.exe …我想我的下一个尝试将是选择