使用CMake链接Armadillo库

6

我正在尝试在Windows 8上安装MLPack。 我使用以下命令配置CMakeLists.txt文件:

set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")

然后当我运行CMake时,出现了一系列类似这样的警告:

WARNING: Target "mlpack" requests linking to directory "C:\Program Files (x86)\armadillo\lib".  Targets may link only to libraries.  CMake is dropping the item.

在 \mlpack-1.0.4\src\mlpack 目录中,我找到了另一个带有以下内容的 CMakeLists 文件:
target_link_libraries(mlpack
  ${ARMADILLO_LIBRARIES}
  ${Boost_LIBRARIES}
  ${LIBXML2_LIBRARIES}
)

我改变了它(不确定这是否是个好主意):

target_link_libraries(mlpack
  ${Boost_LIBRARIES}
)
link_directories(mlpack
  ${ARMADILLO_LIBRARIES}
  ${LIBXML2_LIBRARIES}
)

然后CMake似乎顺利运行:

-- Found Armadillo: C:\Program Files (x86)\armadillo\lib (found suitable version "3.800.2", minimum required is "2.4.2")
-- Found LibXml2: C:\cpp\libraries\libxml2-2.7.8.win32\lib (found suitable version "2.7.8", minimum required is "2.6.0")
-- Boost version: 1.53.0
-- Found the following Boost libraries:
--   program_options
--   unit_test_framework
-- Boost version: 1.53.0
-- Found the following Boost libraries:
--   random
-- Could NOT find Doxygen (missing:  DOXYGEN_EXECUTABLE)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/cpp/libraries/mlpack-1.0.4

但是现在运行make命令时,我遇到了大量这样的错误:

Linking CXX executable ..\..\..\..\gmm.exe
CMakeFiles\gmm.dir/objects.a(gmm_main.cpp.obj):gmm_main.cpp:(.text+0xb9): undefined reference to `wrapper_dgemv_'
CMakeFiles\gmm.dir/objects.a(gmm_main.cpp.obj):gmm_main.cpp:(.text$_ZN4arma6auxlib10det_lapackIdEET_RKNS_3MatIS2_EEb[__ZN4arma6auxlib10det_lapackIdEET_RKNS_3MatIS2_EEb]+0x115): undefined reference to `wrapper_dgetrf_'

经过调查,似乎与Armadillo有关。

你有什么想法吗?我猜我应该使用target_link_libraries来使用Armadillo,但我不确定如何操作。


是的,您绝对需要在自己的CMakeLists.txt中使用target_link_libraries()来链接Armadillo库。您能否发布您的CMakeLists.txt的完整/相关部分? - Vaibhav Desai
非常感谢。我想知道是否可以真的发布整个文件,因为它相当长。对于相关部分,我只找到了一行代码 "find_package(Armadillo 2.4.2 REQUIRED)" 和稍后的一行代码 "include_directories(${ARMADILLO_INCLUDE_DIRS})"。但我是一个真正的初学者,我可能确实错过了什么。完整的文件在这里:http://www.mlpack.org/files/mlpack-1.0.4.tar.gz 我只是按照帖子中描述的进行了更改... - Vince
尝试添加类似这样的内容:target_link_libraries(gmm.exe ${ARMADILLO_LIBRARIES}),看看是否有效。或者只使用“gmm”而不是“gmm.exe”,然后再试一次。 - Vaibhav Desai
尝试使用 .exe 文件,但 cmake 报错说 gmm.exe 没有在该项目中构建。如果没有 .exe 文件,cmake 会报错说 gmm 没有在该目录中构建... - Vince
3个回答

6
问题应该很容易解决。 当你这样做时...
set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")

你实际上是绕过了find_package(Armadillo 2.4.2 REQUIRED)的调用,因为它预计要查找这些路径。然而,当find_package执行时,变量ARMADILLO_LIBRARY被设置为库本身的路径,而不是库的目录路径。
因此,问题归结为将ARMADILLO_LIBRARY设置为库的目录路径而不是库本身的路径。这最终会导致链接器错误,因为目标gmm(在src\mlpack\methods\gmm\CMakeLists.txt中添加)链接到mlpack,而mlpack已经被设置为链接到${ARMADILLO_LIBRARIES},由于其未正确设置,这最终会导致连接器错误。
事实证明,find_package(Armadillo ...)已经检查了"$ENV{ProgramFiles}/Armadillo/lib""$ENV{ProgramFiles}/Armadillo/include",我预期这些将解析为您的机器上的"C:\\Program Files (x86)\\armadillo\\lib""C:\\Program Files (x86)\\armadillo\\include"
因此,要解决此问题,您应该删除设置ARMADILLO_LIBRARYARMADILLO_INCLUDE_DIR的行,并恢复src\mlpack\CMakeLists.txt中的更改(使用link_directories通常也是一个不好的想法)。
在进行这些更改后,您应该删除至少您的CMakeCache.txt(位于构建树的根目录中),或者在重新运行CMake之前删除整个构建树,以避免使用先前失败尝试的错误缓存值。

尝试了这个,但是我收到了这个错误:CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:97 (message): Could NOT find Armadillo: Found unsuitable version "0.0.0", but required is at least "2.4.2" (found C:/Program Files (x86)/armadillo/lib/libarmadillo.dll) ... 是否可能是我的armadillo安装出了问题?谢谢! - Vince
是的 - 很可能。您是否使用与编译Armadillo相同的生成器来生成MLPack?(MinGW?)看起来Armadillo库已被正确找到,但无法正确读取以找出其版本。 - Fraser
我使用cmake编译了armadillo,然后使用mingw32-make install进行安装。现在,我没有更改cmake文件(除了删除缓存和树),再次执行它,一切都很顺利(与几天前执行时相同)。现在我不确定上次出了什么问题,因为在那之后,使用cmake为mlpack似乎对armadillo感到满意(检测版本3.800.2)。但是现在我收到有关libxml2的警告(“目标只能链接到库”)。没有编译libxml2,只是下载了二进制文件...可能是从那里来的?(顺便说一句,非常感谢您的帮助) - Vince
我们正在努力解决这个问题 :-) 你没有明确设置LIBXML2_LIBRARIES,对吗?如果是的话,它可能还应该引用库而不是库所在的文件夹。我自己没有使用MinGW,但看起来libxml2的Windows二进制文件只适用于MSVC,而不适用于MinGW。你需要使用mingw32-make构建libxml2,或者使用mingw-get获取它。尝试在谷歌上搜索"libxml2 mingw"。 - Fraser
现在正在与libxml2(http://stackoverflow.com/questions/16007716/gnuwin32-libxml2-installation-setting-several-lib-and-include-directories)苦苦挣扎...一旦解决了这个问题,我会尽快回来的(啊啊啊)。 - Vince
现在看起来cmake的工作表现很好,它可以找到所有需要的东西而且没有抱怨。但是现在当我使用mingw32-make编译mlpack时,在完成了32%后,它显示“扫描目标det的依赖项”,然后电脑开始忙于计算,但似乎什么也没有发生。现在已经一个小时了,我猜测出了些问题... - Vince

5

我知道这个答案有点晚了,希望你现在已经解决了。即便如此,我认为你的问题在于ARMADILLO_LIBRARY变量应该保存库的确切位置,而不是库所在的目录。因此,也许这样可以解决问题:

set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib\\armadillo.lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")

变量LIBXML2_LIBRARIES还应包含libxml2.lib(或实际库的名称)的实际路径。
你看过我之前为在Windows上编译mlpack编写的说明页面吗?

http://www.mlpack.org/trac/wiki/MLPACKOnWindows

如果您将来遇到更多问题,请随时在Trac上提交bug报告。我只是偶然发现这个问题,所以不会在Stack Overflow上监控问题。


3
我遇到了同样的问题。有两个小点需要您取消注释aramadillo库常见问题解答,即可解决问题。
#define ARMA_USE_LAPACK 
#define ARMA_USE_WRAPPER

文件中
include/armadillo_bits/config.hpp

这段代码位于犰狳源码树中。

当你取消注释后重新编译,你可以在犰狳共享库/动态链接库中看到这些符号。希望这能帮到你!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接