使用 CMake 编译项目

Posted

技术标签:

【中文标题】使用 CMake 编译项目【英文标题】:Using CMake to compile the project 【发布时间】:2021-06-24 12:03:49 【问题描述】:

我的项目结构是这样的。

build
  - folder where cmake outputs the solution file

client
  - client.c
  - CMakeLists.txt

server
  - server.c
  - CMakeLists.txt

open62541
  - open62541.c
  - open62541.h
  - CMakeLists.txt

CMakeLists.txt

主CMakeLists.txt有如下代码

cmake_minimum_required(VERSION 3.0)
project(openstack)
add_subdirectory(open62541)
add_subdirectory(server)

open62541/CMakeLists.txt 有如下代码

project(Lib1)
add_library(lib1 open62541.c open62541.h)

server/CMakeLists.txt 看起来像这样

   project(App)

   add_executable(app server.c)

   include_directories($Lib1_SOURCE_DIR)

   target_link_libraries(app PRIVATE lib1 ws2_32 wsock32)

server.c 有以下代码。

#include "open62541.h"
#include "signal.h"
#include <stdlib.h>
#include "stdio.h"

static volatile UA_Boolean running = true;
static void stopHandler(int sig) 
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
    running = false;


int main(void) 
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);

    UA_Server *server = UA_Server_new();
    UA_ServerConfig_setDefault(UA_Server_getConfig(server));

    UA_StatusCode retval = UA_Server_run(server, &running);

    UA_Server_delete(server);
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;

server.c 需要在 open62541.c 和 open62541.h 中定义和声明的函数。(我现在没有构建客户端项目)所以,我在 server.c 文件和服务器中包含了 open62541.h /CMakeLists.txt,如您所见,我已经给出了 open62541 文件夹的链接。我在 Visual Studio 中收到以下链接器错误。这条消息是德语的,对此感到抱歉。

    Erstellen gestartet...
1>------ Erstellen gestartet: Projekt: app, Konfiguration: Debug x64 ------
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_Server_delete" in Funktion "main".
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_Server_getConfig" in Funktion "main".
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_Server_run" in Funktion "main".
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_Server_new" in Funktion "main".
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_ServerConfig_setMinimalCustomBuffer" in Funktion "UA_ServerConfig_setMinimal".
1>server.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp_UA_Log_Stdout" in Funktion "stopHandler".
1>C:\Users\acer\CMake_Project\build\server\Debug\app.exe : fatal error LNK1120: 6 nicht aufgelöste Externe
1>Die Erstellung des Projekts "app.vcxproj" ist abgeschlossen -- FEHLER.
2>------ Erstellen übersprungen: Projekt: ALL_BUILD, Konfiguration: Debug x64 ------
2>Für diese Projektmappenkonfiguration wurde kein zu erstellendes Projekt ausgewählt. 
========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 2 aktuell, 1 übersprungen ==========

当我包含服务器时,项目构建良好。 c,open62541.c,open62541.h 文件放在一个文件夹中,并像这样使用单个 CMakeLists.txt 文件。

cmake_minimum_required(VERSION 3.0)

project(openstack)

set(SOURCES server.c open62541.c open62541.h)

add_executable(openstack $SOURCES)

target_link_libraries(openstack PRIVATE ws2_32 wsock32)

但是,当我尝试在不同文件夹中构建我的项目时出现错误。我该如何解决这些错误?

【问题讨论】:

前缀__imp_ 表示您的可执行文件需要在shared 库中定义符号。但是 Windows 上的 add_library() 默认会创建一个 static 库。最有可能的是,标题open62541.h 是“多用途”:它可以在 build 库作为共享时使用,它可以在 link 库作为 static,当link与库作为shared时可以使用。后一个用例——与共享库链接——是默认的。其他用例需要特定的宏定义。 所以我应该将库添加为共享库吗?我该怎么做? 【参考方案1】:

我对您的项目进行了一些重组,使其更加现代。看看这是否有效,然后告诉我你得到了什么。

cmake_minimum_required(VERSION 3.15)
project(openstack LANGUAGES C)

add_subdirectory(open62541)
add_subdirectory(server)

# You didn't add_subdirectory client.
add_subdirectory(client)

open62541/CMakeLists.txt 有如下代码

add_library(lib1 STATIC)
target_sources(lib1 PRIVATE open62541.c open62541.h)
# Prefer to use public. To ease use of your library.
target_include_directores(lib1 PUBLIC $CMAKE_CURRENT_LIST_DIR)

server/CMakeLists.txt 看起来像这样

add_executable(app)
target_sources(app PRIVATE server.c)
target_link_libraries(app PRIVATE lib1 ws2_32 wsock32)

【讨论】:

感谢您的回答。我得到了同样的错误:(。同样在主 CMakeLists.txt 中,这一行 'project(openstack LANGUAGES CXX)' 给出了错误 'CMake cannot determine linker language for Target ',为了使它工作 CXX 应该被 C 替换。 我修复了使用 C 语言的问题。你能发布你原来的 CMakeLists.txt 吗?否则很难找出你的问题。 我已经在问题中发布了原始主 CMakeLists.txt。 ?您说“当我在单个文件夹中包含 server.c、open62541.c、open62541.h 文件并使用单个 CMakeLists.txt 文件时,项目构建良好”该文件是什么样的。 让你的库静态看看是否能解决问题。

以上是关于使用 CMake 编译项目的主要内容,如果未能解决你的问题,请参考以下文章

cmake编译后能给vs使用吗

重新编译使用CMake的旧项目的问题处理

使用 cmake 进行交叉编译

为啥 cl.exe(Visual Studio 编译器)无法使用 CMake(错误报告)编译项目?

CMake 在编译使用 OpenCV 的项目时遇到问题

在 CMake 项目中动态更改编译器标志