静态构建和链接CMake



我正在尝试用CMake静态链接c++应用程序。

我已经静态地构建了libcurl:

./buildconf
./configure --disable-shared --with-openssl
make -j$(nproc)
make install

生成静态/usr/local/lib/libcurl.a:

$ ldd /usr/local/lib/libcurl.a
not a dynamic executable

我的CMake配置为静态构建和链接:

include(CMakePrintHelpers)
cmake_minimum_required(VERSION 3.17)
project(static-build-test)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
find_package(CURL REQUIRED)
cmake_print_variables(CURL_LIBRARIES)
add_executable(static-test main.cpp)
target_link_libraries(static-test PRIVATE ${CURL_LIBRARIES})

但是我的构建无法链接到许多未定义的引用。错误:

$ make
Scanning dependencies of target static-test
[ 50%] Building CXX object CMakeFiles/static-test.dir/main.cpp.o
[100%] Linking CXX executable static-test
...
url.c:(.text+0xf6): undefined reference to `idn2_free'
md5.c:(.text+0x6a): undefined reference to `MD5_Init'
openssl.c:(.text+0x29a): undefined reference to `SSL_set_ex_data'
...

我的libcurl.a的静态构建完成没有错误,但仍然未能与我的应用程序链接由于这些未定义的引用。为什么libcurl的静态库不包括它所依赖的静态库(openssl等)?

我想我需要找到所有这些缺失的引用,并跟踪它们的静态库。我是否需要将所有这些库直接链接到我的最终可执行文件?

对于像CURL这样拥有一流CMake包支持的库,您应该使用它。这是我如何静态链接到CURL的。

首先,我们下载并构建CURL:
$ git clone git@github.com:curl/curl.git
$ cmake -G Ninja -S curl/ -B _build/curl -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=NO
$ cmake --build _build/curl
$ cmake --install _build/curl --prefix _local
在此之后,我们可以编写正确的CMakeLists.txt,它只链接到导入的目标。注意,这个构建使用无变量
cmake_minimum_required(VERSION 3.23)
project(test)
find_package(CURL REQUIRED)
add_executable(static-test main.cpp)
target_link_libraries(static-test PRIVATE CURL::libcurl)

现在我们可以构建这个,通过CMAKE_PREFIX_PATH:

将CMake指向我们刚刚构建的CURL包
$ cmake -G Ninja -S . -B _build/test -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PWD/_local
...
-- Found CURL: /path/to/_local/lib/cmake/CURL/CURLConfig.cmake (found version "7.85.0-DEV")  
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/_build/test

,现在我们可以运行构建,看到所有需要的库都在那里:

$ cmake --build _build/test --verbose
[1/2] /usr/bin/c++ -DCURL_STATICLIB -isystem /path/to/_local/include -O3 -DNDEBUG -MD -MT CMakeFiles/static-test.dir/main.cpp.o -MF CMakeFiles/static-test.dir/main.cpp.o.d -o CMakeFiles/static-test.dir/main.cpp.o -c /usr/local/google/home/reinking/test/main.cpp
[2/3] : && /usr/bin/c++ -O3 -DNDEBUG  CMakeFiles/static-test.dir/main.cpp.o -o static-test  ../../_local/lib/libcurl.a  -ldl  -lpthread  /usr/lib/x86_64-linux-gnu/libssl.so  /usr/lib/x86_64-linux-gnu/libcrypto.so  /usr/lib/x86_64-linux-gnu/libz.so && :

正如你所看到的,旋度及其传递依赖,dl, pthreads, openssl, libcrypto,和libz出现正确的链接线。

最新更新