首页 > 解决方案 > 来自外部镶木地板项目的静态库的“未定义引用”错误

问题描述

我想将 expernal 'parquet' 项目(https://github.com/apache/arrow/tree/master/cpp)链接为我当前在 Linux 上的项目的一部分。

为此,我使用这些参数运行了镶木地板的 cmake

cd build_parquet
cmake -DCMAKE_BUILD_TYPE=Release -DARROW_PARQUET=ON  \
 -DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_ROOT=${BOOST_BUILD_DIR}/include  -DBOOST_LIBRARYDIR=${BOOST_BUILD_DIR}/lib/boost -DARROW_BOOST_USE_SHARED=OFF -DBOOST_INCLUDEDIR=${BOOST_BUILD_DIR}/include/boost ..

cmake --build . --config Release

// 除了boost还有很多依赖,但是只有boost需要安装在系统上,其他的可以通过cmake脚本下载安装

项目编译成功。我得到了可以启动的可执行文件,生成了静态库 libarrow.a、libparquet.a、共享库 libarrow.so、libparquet.so

在我的主项目中,我想使用这样的库,我在 cmake 中使用这样的命令来找到它们

find_path(PARQUET_INCLUDE_DIR NAMES arrow/api.h PATHS ${PARQUET_DIR}/src)

find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.a
              PATHS build_parquet/release/Release/ )

find_library(ARROW_LIBRARY_RELEASE NAMES arrow.a
             PATHS build_parquet/release/Release/ )

set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Parquet DEFAULT_MSG PARQUET_INCLUDE_DIR
                                  ${PARQUET_LIBRARIES_RELEASE } )

没关系,找到了库和包含。

然后我将这个库链接到我的项目

target_link_libraries(${myExe} ${PARQUET_LIBRARIES_RELEASE} ${mySomeOtherLibraries} )

在此之后,我得到了大量的链接器错误,例如

libparquet.a(column_writer.cc.o): In function `apache::thrift::transport::TMemoryBuffer::~TMemoryBuffer()':
column_writer.cc:(.text._ZN6apache6thrift9transport13TMemoryBufferD0Ev[_ZN6apache6thrift9transport13TMemoryBufferD5Ev]+0x3): undefined reference to `vtable for apache::thrift::transport::TMemoryBuffer'
.....

所以这就是我不太了解的,为什么lib在parquet项目本身中编译得很好,但现在有很多未解决的问题,当我用它来链接我自己的项目时?此外,我为 windows 编译了项目,当我做同样的事情时,但使用 arrow.lib 和 parquet.lib (而不是 libparquet.a 和 libarrow.a ),一切正常!我只需要将 arrow.dll、parquet.dll 放入可执行文件即可运行项目。但是在Linux中我已经崩溃了

那么,为什么它不起作用,我应该怎么做才能最终将项目与库链接?

更新

我发现了问题,我必须像这样添加 .so 文件(不仅是 .a 文件)来链接库


find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.so parquet.a
             PATHS build_parquet/release/Release/ )

find_library(ARROW_LIBRARY_RELEASE NAMES arrow.so arrow.a
            PATHS build_parquet/release/Release/ )

set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )

项目已建成。所以现在的问题是,为什么我需要将 .so 文件添加到链接器(在 Windows 中只有静态 .lib 就足够了),在 Linux 中构建项目时总是这样吗?链接顺序重要吗(首先是 .so 文件,然后是 .a 文件?)

标签: linuxcmakelinkerparquet

解决方案


正如 Uwe 在评论中所写,https://github.com/apache/parquet-cpp存储库已被弃用,Parquet C++ 库正在开发为 Apache Arrow C++ 代码库https://github.com/apache /arrow/tree/master/cpp。你可以尝试在此基础上进行构建吗?如果遇到问题,你可以在 dev@arrow.apache.org 邮件列表上发帖吗?


推荐阅读