百度 Apollo 使用 bazel 编译 C++ Boost 依赖出现 undefined reference to `boost::python::api::object::object(boost::pyth_undefined reference to `boost::python::import(boos

因为一些原因,楼主想在 Apollo 自动驾驶框架里使用 Boost.python 工具来用 C++ 调用 Python,从网上找了个例子想编译下试试。

C++ 代码如下(boost.python/EmbeddingPython - Python Wiki):

#include <boost/python.hpp>
 
 
using namespace boost::python;
 
int main( int argc, char ** argv ) {
  try {
    Py_Initialize();
 
    object main_module((
      handle<>(borrowed(PyImport_AddModule("__main__")))));
 
    object main_namespace = main_module.attr("__dict__");
 
    handle<> ignored(( PyRun_String( "print (\"Hello, World\")",
                                     Py_file_input,
                                     main_namespace.ptr(),
                                     main_namespace.ptr() ) ));
  } catch( error_already_set ) {
    PyErr_Print();
  }
}

BUILD 文件如下:

cc_binary(
    name = "hello",
    srcs = [
        "hello.cc",
    ],
    deps = [
        #"@local_config_python//:python_headers",
        #"@local_config_python//:python_lib",
        "@boost",
    ],
)

一开始没有引入 local_config_python 的两个依赖,导致出现

(01:50:17) ERROR: /apollo/modules/zj_prediction/BUILD:52:10: Linking of rule '//modules/zj_prediction:hello' failed (Exit 1): crosstool_wrapper_driver_is_not_gcc failed: error executing command external/local_config_cuda/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc @bazel-out/k8-opt/bin/modules/zj_prediction/hello-2.params
bazel-out/k8-opt/bin/modules/zj_prediction/_objs/hello/hello.o: In function `main':
hello.cc:(.text.startup.main+0x3c): undefined reference to `boost::python::api::object::object(boost::python::handle<_object> const&)'
hello.cc:(.text.startup.main+0x75): undefined reference to `boost::python::api::getattr(boost::python::api::object const&, char const*)'
hello.cc:(.text.startup.main+0xe8): undefined reference to `boost::python::throw_error_already_set()'
hello.cc:(.text.startup.main+0xf2): undefined reference to `boost::python::throw_error_already_set()'
hello.cc:(.text.startup.main+0x126): undefined reference to `vtable for boost::python::error_already_set'
hello.cc:(.text.startup.main+0x141): undefined reference to `boost::python::error_already_set::~error_already_set()'
hello.cc:(.text.startup.main+0x15f): undefined reference to `boost::python::error_already_set::~error_already_set()'
bazel-out/k8-opt/bin/modules/zj_prediction/_objs/hello/hello.o:(.data.rel.local.DW.ref._ZTIN5boost6python17error_already_setE[DW.ref._ZTIN5boost6python17error_already_setE]+0x0): undefined reference to `typeinfo for boost::python::error_already_set'
collect2: error: ld returned 1 exit status

去掉注释后就好了。

然后使用 bazel 编译这个模块时出现了报错信息

load("@rules_cc//cc:defs.bzl", "cc_library")
 
licenses(["notice"])
 
package(default_visibility = ["//visibility:public"])
 
# TODO(all): May use rules_boost.
cc_library(
    name = "boost",
    includes = ["."],
    linkopts = [
        "-L/opt/apollo/sysroot/lib",
        "-lboost_filesystem",
        "-lboost_program_options",
        "-lboost_regex",
        "-lboost_system",
        "-lboost_thread",
        # "-lboost_python36",        一开始没有
    ],
)

看报错信息大概意思是 boost 找不到包里的 Python 库,为此上网找了一下午都没解决,后来突然发现是因为楼主的环境配置跟别人不一样,lib 的名字不同当然不能直接复制解决了,下面说一下解决思路。

主要参考的是 Add boost library as Bazel dependency c++ - Stack Overflow

Since you're linking your executable to Boost Python/Numpy, you also need to provide Python symbols.

If you don't need Python, the easiest solution is add libboost_numpy.so to exclude in your glob. If you actually need Python, a quick fix would be to add -lpython to linkopts in BOOST.build (this is not a solution that I would recommend for production, since you have no control over Python versions, etc..)

里面提到要在 BOOST.build里面加入-lpython,

还有對 boost::python::detail::init_module 和 friend 的 undefined reference - C++ _程式人

我添加了兩個額外的標誌來增強效果,然後就可以了!

-lboost_python -lboost_system

里面提到加入的是 - lboost_python,我两种都试了一下发现不行,于是开始思考人生。

先看下我的 boost.BUILD 文件是什么样的:

load("@rules_cc//cc:defs.bzl", "cc_library")
 
licenses(["notice"])
 
package(default_visibility = ["//visibility:public"])
 
# TODO(all): May use rules_boost.
cc_library(
    name = "boost",
    includes = ["."],
    linkopts = [
        "-L/opt/apollo/sysroot/lib",
        "-lboost_filesystem",
        "-lboost_program_options",
        "-lboost_regex",
        "-lboost_system",
        "-lboost_thread",
        # "-lboost_python36",        一开始没有
    ],
)

直接在 linkopts 里面加上这两种 - l 都没用,于是急需谷歌搜 bazel cannot find -lboost_python,然后出现这一条:

https://stackoverflow.com/questions/65675412/bazel-build-cannot-find-shared-library​​​​​​,里面提到了-L/usr/local/lib

Bazel likes to use the gold linker instead of GNU ld by default. gold, unlike GNU ld, doesn't put /usr/local/lib on the default library search path. This can be remediated by passing --linkopt=-L/usr/local/lib to Bazel.

然后猛然发现自己的 boost.BUILD 文件里面有一行 "-L/opt/apollo/sysroot/lib", 这明显是跟上面提到的-L/usr/local/lib 起相同的作用,于是

ll /opt/apollo/sysroot/lib/

发现下面有很多 libboost***,然后果然找到了一个

/opt/apollo/sysroot/lib/libboost_python36.so -> libboost_python36.so.1.74.0*

所以合理猜测在我的环境里,并不是 -lboost_python,而应该是 -lboost_python36!!!

在 boost.BUILD 文件里加入这行后,顺利编译成功,实现了 C++ 调用 Python 输出

Hello, World
posted @ 2024-05-21 19:53  钢之炼丹术师  阅读(108)  评论(0)    收藏  举报