外部实木复合地板项目的静态库出现“未定义参考”错误

时间:2019-01-14 20:02:43

标签: linux cmake linker parquet

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

为此,我用这样的参数运行镶木地板

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链接到我自己的项目中时,为什么lib在镶木地板项目本身中编译良好,但是现在还有很多未解决的问题?此外,我为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文件?)

2 个答案:

答案 0 :(得分:0)

如Uwe在评论中所写,https://github.com/apache/parquet-cpp存储库已过时,并且Parquet C ++库正在作为Apache Arrow C ++代码库https://github.com/apache/arrow/tree/master/cpp的一部分进行开发。您可以尝试以此为基础进行构建吗?如果遇到问题,可以将其发布在dev@arrow.apache.org邮件列表中吗?

答案 1 :(得分:0)

shared .so)库而不是 static .a)库链接时,您已经成功构建了项目。

(命令find_library实际上会查找一个库,该名称在NAMES选项中列出。在您的情况下,它找到了.so库,因为它的名称位于{ {1}}一个。

实际上,共享静态 .a库都包含相同一组符号,并且这两个集合均不足用于链接。区别在于共享包含信息,可以在其中找到剩余符号(在您的案例中,parquet库中),而静态库则不

要与 static 库正确链接,您需要手动列出相关的库。


在Windows thrift文件中,静态库或共享({{1 }})一。看来您与动态链接(它没有.lib )连接了,就像在Linux上一样。