在 Windows 上使用 CMake 强制静态链接

问题描述

我想将我的代码编译成一个独立的 EXE,在 Windows 上没有任何 DLLs

我的 CMakeLists.txt 如下所示:

cmake_minimum_required(VERSION 3.18)
set(TARGET_NAME "Windows_Static_Compilation_Test")
project(${TARGET_NAME})

set(CMAKE_CXX_STANDARD 20)

set(IS_LINUX_BUILD "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")

find_package(Catch2 CONfig required)

# We need Boost
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS filesystem required) # iostreams removed
include_directories(${Boost_INCLUDE_Dirs})

# Always compile loguru with streams
add_compile_deFinitions(LOGURU_WITH_STREAMS)

include_directories(${TARGET_NAME} include)

add_executable(${TARGET_NAME} main.cpp)

if(WIN32)
    add_deFinitions("-DCURL_STATICLIB")
endif()

# We need cURL for web requests
# find_package(CURL required)

# We need zlib for compression
find_package(ZLIB required)

if (${IS_LINUX_BUILD})
    # Link against the dependency of loguru
    target_link_libraries(${TARGET_NAME} pthread)
endif ()

# Link against zlib
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})

# Link against Catch2
target_link_libraries(${TARGET_NAME} Catch2::Catch2)

# Link against cURL
# target_link_libraries(${TARGET_NAME} CURL::libcurl)

# Link against Boost
target_link_libraries(${TARGET_NAME} ${Boost_LIBRARIES})

我的 main.cpp 如下所示:

#define CATCH_CONfig_RUNNER

#include "catch.hpp"

#include <loguru.cpp>
#include <zlib.h>
// #include <curl/curl.h>
#include <boost/filesystem.hpp>

using namespace boost::filesystem;

/* #include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>

namespace io = boost::iostreams;
*/

TEST_CASE("Test") {
    LOG_S(INFO) << "Hello from loguru";
    LOG_S(INFO) << "zlib version: " << ZLIB_VERSION;
    // curl_easy_init();
    /* io::stream_buffer<io::file_sink> buf("log.txt");
    std::ostream out(&buf); */
    REQUIRE(true);
}

int main(const int argument_count,char *arguments[]) {
    const auto program_file_size = file_size(arguments[0]);
    LOG_S(INFO) << "Program file size: " << program_file_size;
    const auto result = Catch::Session().run(argument_count,arguments);
    return result;
}

但是,如果我在 Release 模式下编译,尽管在 Boost 中指定了静态链接,我还是会得到 DLL CMakeLists.txt

如果我进一步依赖 cURL 我会得到例如尽管 libcurl.dlladd_deFinitions("-DCURL_STATICLIB")

我使用 vcpkg 通过 x64-windows-static元组安装库以获得库的静态版本。

如何确保所有库都静态链接到最终可执行文件中?我需要调整我的 CMakeSettings.json 吗?

VCPKG_TARGET_TRIPLET 设置为 x64-windows-static 的原因:

Error   LNK2038 mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in main.cpp.obj    D:\Cpp\Windows-Static-Compilation-Test\out\build\x64-Release\Windows-Static-Compilation-Test    D:\Cpp\Windows-Static-Compilation-Test\out\build\x64-Release\boost_filesystem-vc140-mt.lib(path_traits.obj) 1   

除了导致此错误Boost 之外,其他库都是静态链接的,这很好。

有关静态链接到 Boost here 的问题的更多详细信息。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)