使用 CMake 编译带有链接 dll 的应用程序。需要查看工作示例

Compile app with linked dll with CMake. Need to see a working sample

已找到答案。为了节省您大量阅读的时间:

这里有有用的文档:
https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets

工作CMakeLists.txt是这样的:

cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
add_library(Lib SHARED IMPORTED)
set_property(TARGET Lib PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/lib.dll")
set_property(TARGET Lib PROPERTY IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/lib.dll.a") //Notice: lib.lib here if you are using VS building system.
add_executable(App app.cxx)
target_link_libraries(App Lib)

大多数在线教程都假定您使用的是 MS VS 构建系统。因此,他们将继续谈论导入“*.lib”文件。
如果你像我一样使用 GCC(MinGW),那么你要查找的实际文件是 "*.dll.a"


9 月 17 日编辑
不,这是不对的。我们正在使用 DLL。而且一个DLL应该不会影响编译。
DLL 应该在您想要将它们放入 .exe 所需的文件夹中而不是编译检查 header.
但是我们正在尝试从 dll 中解压 header。
这个工作流程一定有问题。

CMake 和 GCC
由于我公司没有许可证,我无法使用任何 IDE 和 VS 构建工具。
因此,我必须了解 open-sourced 编译环境的 CMake + GCC。
我现在可以正确编译应用程序和静态库。但是卡在了dll链接中。
这应该很简单,但由于我在 Google 上找不到任何示例,因此我需要您的帮助来更正此 DLL 链接作业中的 CMake 工作流程。谢谢。

或者任何可以找到正确方向的超链接。
据我所知,我可以像 VisualStudio 一样简单地在 IDE 中添加 dll 库,它会发挥所有魔力将其交换为包含 header 文件的内容。 我必须在 CMake 中错过这部分。

我的步骤:

  1. 编译一个dll
  2. 编译不带 dll 的遗留应用程序
  3. 使用从 dll 链接的功能重新创建应用程序(BOOM!)

详细代码如下:


第一步:编译dll

Test.h中的代码:

#pragma once
#ifdef TEST_EXPORTS
    #define TEST_API __declspec(dllexport)
#else
    #define TEST_API __declspec(dllimport)
#endif
extern "C" TEST_API int helloworld();

Test.cxx中的代码:

#include <iostream>
#include "Test.h"
int helloworld() {
    std::cout << "I hate HelloWorld\n";
    return 0;
}

CMakeLists.txt中的代码:

cmake_minimum_required(VERSION 3.10)
project(Test)
include(GenerateExportHeader)
add_library(Test SHARED Test.cxx)
generate_export_header(Test)

编译它。得到一个“libTest.dll”。好

第 2 步:编译没有 dll 的遗留应用程序

让我们跳过它。只是一个你好世界控制台应用程序。没什么特别的。
编译完成。很高兴。

第 3 步:使用链接的 dll 重新创建应用程序

我已经尝试了很多来自 google 的样本,但直到现在都没有成功。
我试过库的名称“Test”和“libTest”。
我尝试将 dll 直接放在 ${PROJECT_BINARY_DIR}、${PROJECT_SOURCE_DIR} 中,并制作一个 add_subdirectory(libStore).
我试过使用 find_package(Test/libTest).
因此我认为我的 cmake 和源代码中应该有一些不正确的地方。

App.cxx中的代码:

#include <iostream>
#include "Test.h" //Also tried "libTest.h"
int main() {
    std::cout << helloworld();
    getchar();
    return 0;
}

尝试 1:

将libTest.dll放在子目录“/Lib”下
根目录中的代码 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}/Lib")
add_subdirecotry(Lib)
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest

/Lib 中的代码 CMakeLists.txt:

add_library(libTest libTest.dll)
set_target_properties(libTest PROPERTIES LINKER_LANGUAGE C)

构建结果:

Fatal Error: Test.h(libTest.h): No such file or directory.

尝试 2:

直接把libTest.dll放在源码目录下(${PROJECT_SOURCE_DIR})
CMakeLists.txt 中的代码:

cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}")
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest

构建结果:

Fatal Error: Test.h(libTest.h): No such file or directory.

尝试 3:

与尝试 2 相同,但添加了一个 find_package(libTest) 函数。

cmake_minimum_required(VERSION 3.10)
project(App VERSION 1.0)
include_directories("${PROJECT_SOURCE_DIR}")
find_package(libTest)
add_executable(App App.cxx)
target_link_libraries(App libTest) //Tried both Test and libTest

CMake 警告:

Could not find a package configuration file provided by "libTest" with any of the following names:
libTestConfig.cmake
libTest-config.cmake

在源目录中创建了一个空文件名 libTestConfig.cmake。 构建结果:

Fatal Error: Test.h(libTest.h): No such file or directory.

砰!

我觉得问题可能出在这里:

include_directories("${PROJECT_SOURCE_DIR}")

而不是查找 DLL 本身有问题,似乎 cmake 只是在查找 Test.h(或 libTest.h)头文件时遇到问题。尝试将 DLL 的头文件放在通过 cmake 的“include_directories”指定的路径中。

最后,我在这里找到了答案:

https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets

第一个:

我之前尝试的所有代码都假设您的源代码在您的项目文件夹中。
如果要导入从外部获取的 DLL,实际 CMakeLists.txt 应该如下所示:

cmake_minimum_required(VERSION 3.10)
project(Test VERSION 1.0)
add_library(Lib SHARED IMPORTED)
set_property(TARGET Lib PROPERTY IMPORTED_LOCATION "${PROJECT_SOURCE_DIR}/lib.dll")
set_property(TARGET Lib PROPERTY IMPORTED_IMPLIB "${PROJECT_SOURCE_DIR}/lib.dll.a") //Notice: lib.lib here if you are using VS building system.
add_executable(App app.cxx)
target_link_libraries(App Lib)

第二个:

几乎所有在线教程都假定您使用的是 MS VS 构建系统。因此,他们将继续谈论导入“*.lib”文件。
这将是一个很大的误导,让你毫无意义地追踪 non-exist lib 文件并将其与 dll 文件本身混淆。
如果你像我一样使用 GCC(MinGW),那么你要查找的实际文件是“lib.dll.a