在 Windows、Visual Studio 2013 年将 google protobuf 与 cmake 中的库一起使用

Using google protobuf with libraries in cmake on Windows, Visual Studio 2013

我有一个 CMake 项目,其中包含几个子目录和库模块,最终构建到客户端和服务器库中,这些库用于可执行文件以测试它们。我正在尝试在其中一个库中使用 Google 的 protobuf 库。我正在创建我的子库如下:

include_directories(
    .
    ../rendering_backend
    ../shared
    ${MY_THIRDPARTY_DIR}/protobuf/include
)

add_library(Client STATIC
    client.cpp
    client.hpp
    ../common.hpp
    ../shared/protobufs/my_bufs.pb.cc
    ../shared/protobufs/my_bufs.pb.h
)

target_link_libraries(Client
    RenderingBackend
    ${MY_THIRDPARTY_DIR}/protobuf/lib/libprotobufd.lib
)

可执行文件声明如下:

add_executable(TEST_Client
    client_tester.cpp
    ../src/rendering_backend/rendering_backend.hpp)

target_link_libraries(TEST_Client Client)

所有这些文件似乎都能正确生成,但是当我构建时,出现以下错误(很多都是类似的错误):

libprotobufd.lib(zero_copy_stream_impl.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in client_tester.obj

我已经回到 protobuf 解决方案并验证所有项目都设置为在其运行时库设置中使用 /MDd。它是按照 https://github.com/google/protobuf/tree/master/cmake.

处的指南生成的

我看过很多关于 protobufs 的问答,但是 none 似乎解决了这个问题。我不知道当 Visual Studio.

中的所有内容都设置为 /MDd 时,可能会尝试构建 /MTd

假设如果我做对了这个过程会起作用,我只能假设我做错了什么。做这样的事情的预期方法是什么?

[编辑] 我在这里尝试使用 protobuf 3.0.0。

为了 find_package 识别正确的路径,您必须编辑 CMAKE_PREFIX_PATH 变量来搜索库。假设您已正确设置 THIRDPARTY_DIR 并且下载了 protobuf 的发布版本(撰写本文时为 2.6.1),此代码允许它正确找到路径:

set(CMAKE_PREFIX_PATH
    ${CMAKE_PREFIX_PATH}
    ${THIRDPARTY_DIR}/protobuf-2.6.1
)

Protobuf3 也可以使用,但除了在 CMAKE_PREFIX_PATH 中设置安装路径外,您还必须向 find_package 提供 CONFIG 参数,如下所示:

find_package(Protobuf CONFIG REQUIRED)

...假设需要 Protobuf。

就我而言,我将 Protobuf 3.0.0 beta 2 配置为安装到其自己目录中的文件夹“install”:

set(CMAKE_PREFIX_PATH
    ${CMAKE_PREFIX_PATH}
    ${THIRDPARTY_DIR}/protobuf-3.0.0-beta-2/install
)

find_package(Protobuf CONFIG REQUIRED)

(感谢 tamas.kenez 纠正我的错误。)

请注意,我必须先构建发布库,然后 find_package(Protobuf) 才能 return 没有错误。我最初只构建调试库。

我还必须谨慎选择使用哪个 MSVC 运行时进行构建。动态似乎是大多数项目的默认设置,但 Protobuf3 使用静态运行时构建,除非您将其配置为其他方式(如果您使用的是 GUI,则有一个复选框)。将静态运行时库链接到动态运行时可执行文件会导致各种链接器问题和重新定义,所以要小心。

最后,CMake GUI 似乎保留了一些关于目录结构的信息,直到您重新加载项目(或者可能完全重新启动程序);所以我在尝试更改我使用的 protobuf 版本时遇到了障碍,因为 CMake 一直在寻找我已经删除的目录结构,即使在清除了整个构建目录之后也是如此。 (通过清除构建目录并重新启动 CMake GUI 并重新加载基础项目来解决。)

您可以使用 git-subtree or git-submodule to make google protobuf sources 部分解决方案并使用您的项目构建它。

添加到您的顶级CMakeLists.txt

add_subdiretory("third-party/protobuf/cmake")
include_directories("third-party/protobuf/src")

获取所有 protobuf 目标。 然后你可以使用

添加对 protobuf 的依赖
target_link_libraries(YourLibrary libprotobuf libprotobuf-lite libprotoc)

希望对您有所帮助。