"thrift -gen cpp" 生成的代码无法在 macOS 上编译:'boost/tr1/functional.hpp' 找不到文件

Code generated by "thrift -gen cpp" does not compile on macOS: 'boost/tr1/functional.hpp' file not found

我使用的是 macOS High Sierra 10.13.6

我安装的thrift如下:

$ brew install thrift

是以下版本:

$ thrift --version
Thrift version 0.11.0

我安装的boost如下:

$ brew install boost

我有以下 model.thrift 文件:

struct Person {
    1: required i32 age;
}

我运行Thrift编译器生成的cpp代码如下:

$ thrift -gen cpp model.thrift

我必须遵循包含生成代码的 cpp_encode.cpp 文件:

#include "gen-cpp/model_types.h"

int main(int argc, char const *argv[])
{
    return 0;
}

我尝试编译文件如下:

$ g++ -Wall -I /usr/local/include -L /usr/local/lib -o cpp_encode cpp_encode.cpp

编译版本如下:

 $ g++ --version
 Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
 Apple LLVM version 9.1.0 (clang-902.0.39.2)
 Target: x86_64-apple-darwin17.7.0
 Thread model: posix
 InstalledDir: /Library/Developer/CommandLineTools/usr/bin

我得到以下编译错误:

 $ g++ -Wall -I /usr/local/include -L /usr/local/lib -o cpp_encode cpp_encode.cpp
 In file included from cpp_encode.cpp:1:
 In file included from ./gen-cpp/model_types.h:14:
 In file included from /usr/local/include/thrift/TBase.h:24:
 In file included from /usr/local/include/thrift/protocol/TProtocol.h:28:
 In file included from /usr/local/include/thrift/transport/TTransport.h:24:
 /usr/local/include/thrift/stdcxx.h:32:10: fatal error: 'boost/tr1/functional.hpp' file not found
 #include <boost/tr1/functional.hpp>

目录/usr/local/boost目录存在:

$ ls -1 /usr/local/include/boost
accumulators
algorithm
align
align.hpp
aligned_storage.hpp
any.hpp
archive
[...]

但是目录/usr/local/include/boost/tr1不存在:

$ ls -1 /usr/local/include/boost/tr1
ls: /usr/local/include/boost/tr1: No such file or directory

我应该安装 /usr/local/include/boost/tr1 吗?如果是,怎么做?

我应该以不同的方式使用 Thrift 吗?

thrift 似乎正在生成不推荐使用的代码。

也许您可以升级到更新的版本(如果存在)。

否则,您可以尝试降级 boost 版本(注意支持限制)。

TR1 bits 很早就被采纳到标准中了。

所以通常存在相同的东西,但不再使用 tr1 命名空间。例如

#include <boost/function.hpp>

可以工作,或者

#include <functional>

对于标准库版本。

你可以看看导致在thrift/stdcxx.h

中包含boost/tr1/functional的代码
#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || (defined(_MSC_VER) \
    && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL)
#include <boost/tr1/functional.hpp>
#define _THRIFT_FUNCTIONAL_TR1_ 1
#endif

因为我们可以安全地假设您的 MacOS g++ 没有定义 _MSC_VER,所以只剩下两个选项之一:您自己定义了 FORCE_BOOST_FUNCTIONAL 宏(不太可能),或者 BOOST_NO_CXX11_HDR_FUNCTIONAL 未定义。

通过查看 boost config documentation 我们发现 BOOST_NO_CXX11_HDR_FUNCTIONAL 是在

时定义的

The standard library does not provide a C++11 compatible version of < functional >.

因为我不知道 Apple 的 LLVM 版本如何映射到真正的 LLVM 版本,所以我无法判断你的 clang 版本是否默认启用了 C++11,但我最好的猜测是你需要启用它手动。唯一的另一种选择是存在一个 boost 配置错误,它导致 clang 被识别为没有 C++11 <functional>.

要测试你的clang版本是否默认启用了C++11你可以尝试编译一个包含以下内容的文件

int main() 
{
  return []() -> int { return 0; }
}

没有设置任何编译器标志。

总结一下:

  • 检查您(或除 thrift 之外您使用的第三方库)是否定义了 FORCE_BOOST_FUNCTIONAL
  • 检查您的编译器是否默认支持 C++11,如果不支持,请将 -std=c++11 添加到编译器标志列表中
  • 如果两者都不是,请尝试升级您的 Boost 版本,也许较新的版本会正确识别您的编译器支持 C++11 功能
  • 否则,请使用 boost.config 提交错误。

这里有几个问题:

  • 在 macOS 上,您必须使用 clang++ 而不是 g++。此外,您必须使用 libc++ 库而不是默认的 libstdc++;包含的 libstdc++ 版本很旧,因此不包含 C++11 库功能。参见 How to compile C++ with C++11 support in Mac Terminal

  • 您不需要 -I /usr/local/include 或 -L /usr/local/lib(但添加它们不会造成伤害)

如果您希望程序不仅可以编译还可以link,还有一些额外的问题:

.

bool Coordinate::operator<(const Coordinate& other) const
{
    if (x < other.x) {
        return true;
    } else if (x > other.x) {
        return false;
    } else if (y < other.y) {
        return true;
    } else {
        return false;
    }
}

鉴于以上所有,以下工作:

clang++ -std=c++11 -stdlib=libc++ -Wall -o cpp_encode cpp_encode.cpp gen-cpp/model_types.cpp

注意 1:这个简单的程序不需要它,但是一旦您编写了更完整的 Thrift 代码,您将需要 link 使用 thrift 库 (-lthrift) 和 boost 库 (-lboost ).

注意 2:我将赏金授予 Corristo;尽管他的回复没有完全给出答案,但他建议的测试程序让我走上了最终导致解决方案的道路。