使用CMake编译C/C++程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用CMake编译C/C++程序相关的知识,希望对你有一定的参考价值。

参考技术A CMake Tutorial
CMake Reference

定义程序编译规则

生成可执行文件的最简单版本的 CMakeLists.txt

以上CMakeLists.txt定义的编译规则是将源文件tutorial.c编译成名为 Tutorial 的可执行文件。

一般用法是,新建一个文件夹,一般命名为 build ,在终端进入该文件夹,然后调用 cmake ../ , cmake 会在找到上级目录找到 CMakeLists.txt ,生成 makefile 和一些其它文件。

在 makefile 所在目录,调用 make 命令,会根据 makefile 对程序进行编译生成。

C - 使用 libcurl 编译 Cmake 程序

【中文标题】C - 使用 libcurl 编译 Cmake 程序【英文标题】:C - Cmake compiling program with libcurl 【发布时间】:2018-04-11 15:06:58 【问题描述】:

我正在尝试使用一些 curl 代码来测试 lib,但我无法编译它:(

我正在使用 Clion (Cmake + gcc),我有一个 libcurl.a、一个 libcurl.dll 和一个 libcurl.dlla 我应该如何处理这 3 个文件?

这是我的 CmakeLists.txt :

cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)

set(CMAKE_C_STANDARD 99)

ADD_DEFINITIONS( -DCURL_STATICLIB )
include_directories( "include" )

set(SRCS"
srcs/main.c")
set(HEADERS
    "include/curl/curl.h"
     "include/curl/easy.h")

link_directories("lib")

add_executable(curl_test2 $SRCS $HEADERS)

target_link_libraries(curl_test2 "curl")

这是我的项目:

include
    --curl
        --curl.h
srcs
    --main.c
lib
    --libcurl.a
    (--dlls
        --libcurl.dll
        --libcurl.dlla) <- i'm not using them for now

这是我的 main.c(只是一个 libcurl 示例,并不是很重要 - 我只是想编译):

#include <stdio.h>
#include "curl/curl.h"

int main(void)

    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_ALL);

    curl = curl_easy_init();
    if(curl) 
        curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");

        res = curl_easy_perform(curl);
        if(res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));

        curl_easy_cleanup(curl);
    
    curl_global_cleanup();
    return 0;

当我尝试构建编译器时,请删除此错误:“未定义对 `_imp__curl_global_init' 的引用”(以及所有其他 curl 函数调用)

你能帮帮我吗?我有点迷茫 - 我之前并没有真正使用过 Cmake..

谢谢!

【问题讨论】:

【参考方案1】:

您链接到需要 CURL_STATICLIB 定义的静态 curl 库 (libcurl.a)。在“project”和“add_executable”命令之间的 CMakeLists.txt 中添加:

add_definitions( -DCURL_STATICLIB )

此外,您的文件 .dlla 不是 .dll.a 吗?在这种情况下, .dll.a 文件(我认为)是由 MinGW 工具链生成的,只有当您与 curl 库(作为 .dll 文件)动态链接时才需要。

我下载了 cURL 库 here 的源代码并对其进行了编译(使用 Visual Compiler 2015)。它生成共享库(libcurl.dlllibcurl_imp.lib),我将它们移到 lib 目录中(我应该将 libcurl_imp.lib 重命名为 curl.lib)。我也移动了包含目录。

然后,我使用了这个CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)

set(CMAKE_C_STANDARD 99)

set(SRCS "srcs/main.c")

set( CURL_LIBRARY $CMAKE_SOURCE_DIR/lib )
set( CURL_INCLUDE_DIR $CMAKE_SOURCE_DIR/include )
find_package( CURL )

include_directories( $CURL_INCLUDE_DIRS )
link_directories( $CURL_LIBRARIES )

add_executable(curl_test2 $SRCS)
target_link_libraries(curl_test2 curl)

有了它,您的项目就可以编译并执行了。

我也尝试过使用 cURL 静态库(为此,如果您使用 CMake 编译 cURL,请在 cmake 命令行中添加 -DCURL_STATICLIB=ON)。我将生成的库libcurl.lib 移动到lib\curl.lib

我用过这个CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(curl_test2 C)

set(CMAKE_C_STANDARD 99)

set(SRCS "srcs/main.c")
add_definitions( -DCURL_STATICLIB )

set( CURL_LIBRARY $CMAKE_SOURCE_DIR/lib )
set( CURL_INCLUDE_DIR $CMAKE_SOURCE_DIR/include )
find_package( CURL )

include_directories( $CURL_INCLUDE_DIRS )
link_directories( $CURL_LIBRARIES )

add_executable(curl_test2 $SRCS)
target_link_libraries(curl_test2 curl wldap32 ws2_32)

而且它也有效。

【讨论】:

您好,谢谢您的回答! Cmake 给我这个:未知的 CMake 命令“add_denifition”。我的文件是 .dll.a,我的错误另外,我真的不明白为什么,但我添加了 include_directories 命令,我的 .c 不会使用新的相对路径编译.. 对不起,我忘记了命令“add_definitions”中的结尾“s”我更正了。对于包含目录,您是否删除了之前的 CMake 缓存? 我不知道如何删除 Cmake 缓存。删除 cmakecache.txt 文件?我仍然有“对 `curl_global_init' 的未定义引用”.. :( 如果您在源目录以外的其他地方执行 CMake(我希望您这样做),例如“构建”目录,请删除缓存:* 使用 CMake GUI:文件 > 删除缓存 * 使用命令行:rm -rf build/* 好的,包含工作,谢谢。但我仍然有“对 `curl_global_init' 的未定义引用”.. :(

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

使用 cmake 来搭建跨平台的应用程序框架:C++版本

cmake编译单/多文件

C++ Cmake OpenCV

gcc,g++,make,cmake的区别

C - 使用 libcurl 编译 Cmake 程序

Windows下使用mingw+cmake编译C/C++程序