我一直在尝试使用 Armadillo 库创建一个小型 C++ 项目,作为学习 C++ 和 CMake 的一部分 - 我对两者都是新手。我使用的是带有 MinGW 编译器的 Windows 计算机。经过比我愿意承认的更多的时间,在网上查看各种问题的答案,例如这里和这里,我终于得到了以下内容:
文件/文件夹结构
ProjectDIR
|
+-- CMakeLists.txt
+-- test.cxx
+-- testConfig.h.in
+-- thirdParty
|
+-- armadillo
|
+-- include
+-- lib_win64
测试.cxx
#include <iostream>
#include <armadillo>
#include "testConfig.h"
int main()
{
arma::mat A = {{1.0, 2.0, 3.0},{4.0, 5.0, 6.0},{7.0, 8.0, 9.0}};
std::cout << "A:\n" << A << std::endl;
std::cout << "A.t()\n" << A.t() << std::endl;
std::cout << "A*A.t()\n" << A*A.t() << std::endl;
return 0;
}
testConfig.h.in
#define MyLatestFrustration_VERSION_MAJOR @MyLatestFrustration_VERSION_MAJOR@
#define MyLatestFrustration_VERSION_MINOR @MyLatestFrustration_VERSION_MINOR@
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyLatestFrustration VERSION 0.1)
add_library(CompilerFlags INTERFACE)
target_compile_features(CompilerFlags INTERFACE cxx_std_11)
configure_file(testConfig.h.in testConfig.h)
add_executable(MyLatestFrustration test.cxx)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/thirdParty/armadillo/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/thirdParty/armadillo/lib_win64)
#add_subdirectory(custom)
target_link_libraries(MyLatestFrustration PUBLIC
CompilerFlags
${CMAKE_CURRENT_SOURCE_DIR}/thirdParty/armadillo/lib_win64/libopenblas.lib
)
target_include_directories(MyLatestFrustration PUBLIC "${PROJECT_BINARY_DIR}")
其中
armadillo/include
文件夹是直接从 armadillo-14.0.3 下载中复制的,而 armadillo/lib_win64
文件夹是从 armadillo-14.0.3 提供的示例中复制的。
虽然这个解决方案适用于这个基本实现,但我感觉这不是应该如何完成的。当我尝试创建并链接一个使用犰狳的自定义库时,我证实了我的怀疑,方法是将一个名为
custom
的文件夹添加到 ProjectDiR
,其中包含
矩阵.h
#pragma once
#include <armadillo>
arma::mat f1(arma::mat A);
矩阵.cxx
#include "matrices.h"
arma::mat f1(arma::mat A)
{
arma::mat B = A*A.t();
return B;
}
CMakeLists.txt
add_library(MatrixFunctions matrices.cxx)
target_include_directories(MatrixFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(MatrixFunctions PUBLIC CompilerFlags)
以及取消注释
add_subdirectory(custom)
并将 MatrixFunctions
添加到顶级 CMakeLists.txt 文件中的 target_link_libraries
中,然后修改 test.cxx 以包含 matrices.h 并调用 f1
。这构建得很好,但在尝试运行时会产生以下错误“代码执行无法继续,因为找不到 libopenblas.dll。重新安装程序可能会解决此问题。”
所以,我想了解如何使用 CMake 正确链接到犰狳,以及是否可以在使用提供的预编译 libopenblas.lib 时完成,或者是否必须安装 BLAS 和 LAPACK 或 OPENBLAS;我之前曾尝试遵循这条路线,但遇到了更多问题,显然做错了什么。
按照评论中的建议,我通过使用CMake复制所需文件解决了问题。特别是,我使用解决方案here将 libopenblas.dll 复制到构建目录。我的 CMakeLists.txt 文件现在是
cmake_minimum_required(VERSION 3.15)
project(MyLatestFrustration VERSION 0.1)
add_library(CompilerFlags INTERFACE)
target_compile_features(CompilerFlags INTERFACE cxx_std_11)
configure_file(testConfig.h.in testConfig.h)
add_executable(MyLatestFrustration test.cxx)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/thirdParty/armadillo/include)
add_custom_command(TARGET MyLatestFrustration POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/thirdParty/armadillo/lib_win64/libopenblas.dll"
$<TARGET_FILE_DIR:MyLatestFrustration>)
target_link_libraries(MyLatestFrustration PUBLIC
CompilerFlags
${CMAKE_CURRENT_SOURCE_DIR}/thirdParty/armadillo/lib_win64/libopenblas.lib
)
target_include_directories(MyLatestFrustration PUBLIC "${PROJECT_BINARY_DIR}")
其中自定义命令会在构建后复制 .dll 文件。
这个解决方案感觉并不理想,但希望它对面临类似问题的任何人都有用。