"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,还有一些额外的问题:
你还需要编译link生成的代码gen-cpp/model_types.cpp
您需要在程序中添加Coordinate::operator的实现。 Thrift 会生成 Coordinate::operator< 的声明,但不会生成 Coordinate::operator< 的实现。这样做的原因是 Thrift 不理解结构的语义,因此无法猜测比较运算符的正确实现。这在 http://mail-archives.apache.org/mod_mbox/thrift-user/201007.mbox/%3C4C4E08BD.8030407@facebook.com%3E
中讨论
.
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;尽管他的回复没有完全给出答案,但他建议的测试程序让我走上了最终导致解决方案的道路。
我使用的是 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,还有一些额外的问题:
你还需要编译link生成的代码gen-cpp/model_types.cpp
您需要在程序中添加Coordinate::operator的实现。 Thrift 会生成 Coordinate::operator< 的声明,但不会生成 Coordinate::operator< 的实现。这样做的原因是 Thrift 不理解结构的语义,因此无法猜测比较运算符的正确实现。这在 http://mail-archives.apache.org/mod_mbox/thrift-user/201007.mbox/%3C4C4E08BD.8030407@facebook.com%3E
中讨论
.
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;尽管他的回复没有完全给出答案,但他建议的测试程序让我走上了最终导致解决方案的道路。