【问题标题】:C++ adding static library to CMake project results in undefined referencesC++ 将静态库添加到 CMake 项目会导致未定义的引用
【发布时间】:2017-03-08 04:33:37
【问题描述】:

我已经设置了一个简单的 C++ 项目,我正在尝试使用 CMake 进行编译,并且我正在尝试将 libcurl 静态链接到它。在我的main.cpp 中,我有标准的curl_easy_init 示例代码,我正在尝试发送一个简单的请求以确保库正常工作。但是,我在每次 cURL 函数调用时都会遇到未定义的引用错误。在我的 CMakeLists.txt 中,我正在检查当前平台,然后从该特定 if 语句链接正确的库。我的错误日志、main.cpp 和 CMakeLists.txt 如下。 我唯一的问题是如何让我的 libcurl 正确链接,因为我现在不认为是这样,因为我的二进制文件只有 72KB,而我实际上可以编译它,删除 cURL 特定代码但留下标题 除了显而易见的,我尝试使用的一件事是 --enable-stdcall-fixup 链接器标志,它根本不起作用。

错误日志:

C:\Users\bfsco\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\163.13906.4\bin\cmake\bin\cmake.exe --build D:\Programming\CPP\cppackage\cmake-build-debug --target all -- -j 4
[ 50%] Linking CXX executable cppackage.exe
CMakeFiles\cppackage.dir/objects.a(main.cpp.obj): In function `main':
D:/Programming/CPP/cppackage/main.cpp:6: undefined reference to `curl_easy_init'
D:/Programming/CPP/cppackage/main.cpp:10: undefined reference to `curl_easy_setopt'
D:/Programming/CPP/cppackage/main.cpp:11: undefined reference to `curl_easy_perform'
D:/Programming/CPP/cppackage/main.cpp:13: undefined reference to `curl_easy_cleanup'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[2]: *** [cppackage.exe] Error 1
CMakeFiles\cppackage.dir\build.make:98: recipe for target 'cppackage.exe' failed
mingw32-make.exe[1]: *** [CMakeFiles/cppackage.dir/all] Error 2
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/cppackage.dir/all' failed
mingw32-make.exe: *** [all] Error 2
Makefile:82: recipe for target 'all' failed

main.cpp:

#include <iostream>

#include "include/curl/curl.h"

int main() {
    CURL *curl = curl_easy_init();

    if(curl) {
        CURLcode res;
        curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
        res = curl_easy_perform(curl);
        std::cout << res << std::endl;
        curl_easy_cleanup(curl);
    }

    std::cout << "Hello, World!" << std::endl;
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.6)
project(cppackage)

set(CMAKE_CXX_STANDARD 14)
set(SOURCE_FILES main.cpp)

include_directories(${CMAKE_SOURCE_DIR}/include/curl)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

if(WIN32)
    add_definitions(-DCURL_STATICLIB)
    target_link_libraries(cppackage ${CMAKE_SOURCE_DIR}/thirdparty/openssl/openssl.lib ${CMAKE_SOURCE_DIR}/thirdparty/curl/libcurl.lib)
else()
    target_link_libraries(cppackage ${CMAKE_SOURCE_DIR}/thirdparty/curl/libcurl.a)
endif()

【问题讨论】:

  • VERBOSE=1添加到您的命令行以查看生成的链接命令

标签: c++ curl cmake libcurl


【解决方案1】:

您似乎正在尝试将从 Visual Studio 构建的库链接到使用 MinGW 构建的应用程序。 This is normally not possible。您应该尝试使用 MinGW 从源代码构建 libcurl。


原答案:

尝试将 2 个库版本分别放在 2 个不同的目录 /thirdparty/curl_win32 和 /thirdparty/curl_2 中,然后将代码更改为:

if(WIN32)
    add_definitions(-DCURL_STATICLIB)
    link_directories("${CMAKE_SOURCE_DIR}/thirdparty/openssl/" "${CMAKE_SOURCE_DIR}/thirdparty/"curl_win32)
else()
    link_directories("${CMAKE_SOURCE_DIR}/thirdparty/curl2")
endif()

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

if(WIN32)
    target_link_libraries(${PROJECT_NAME} openssl curl)
else()
    target_link_libraries(${PROJECT_NAME} curl)
endif()

请注意,link_directories 命令显然必须在 add_executable 命令之前。见here

【讨论】:

  • 使用它会导致此错误:C:\Users\bfsco\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\163.13906.4\bin\cmake\bin\cmake。 exe --build D:\Programming\CPP\cppackage\cmake-build-debug --target all -- -j 4 [ 50%] 链接 CXX 可执行文件 cppackage.exe c:/binaries/mingw/bin/../lib /gcc/mingw32/5.3.0/../../../../mingw32/bin/ld.exe:找不到-lopenssl c:/binaries/mingw/bin/../lib/gcc/mingw32 /5.3.0/../../../../mingw32/bin/ld.exe:找不到-lcurl collect2.exe:错误:ld返回1退出状态
  • @Wargog 你在这个位置真的有图书馆吗? ${CMAKE_SOURCE_DIR}/thirdparty/curl_win32 ...并且,通过将 VERBOSE=1 添加到命令行来检查输出
  • 好的,我实际上已经让它过去了找不到要链接的包,我仍然收到未找到参考错误。这是我当前的 CMakeLists.txt:pastebin.com/CEi8q6JF
  • 检查您的第三方库中是否确实有符号stackoverflow.com/questions/305287/…
  • 从这里:github.com/peters/curl-for-windows。我从 Sourceforge 链接下载了 x64 二进制包。 DUMPBIN /SYMBOLS 也返回这个:pastebin.com/qmdjgxrF
【解决方案2】:

就个人而言,我总是对传递相对路径的库使用命令“set”,然后将该变量放入 target_link_libraries。

【讨论】:

  • 我的理解是,如果它是一个已编译的库,我的库是,它必须是库的显式路径(在我的情况下是 .lib 文件或 .a或 .o 文件),而不是路径。我很确定使用路径意味着您正在尝试在该位置编译库,而我不是。
  • Mh... 对不起,我给你举了一个例子: set(CURL_LIB ${CMAKE_SOURCE_DIR}/thirdparty/curl/libcurl.lib) 并在 target_link_libraries 命令中使用变量 &{CURL_LIB}。我对一个项目有相同的需求(只是不同的库),我在 3 个平台上这样做(当然传递了正确的库)
猜你喜欢
  • 2018-11-19
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2018-10-31
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
相关资源
最近更新 更多