当我链接动态库而不是静态库时,CMake 有效

Posted

技术标签:

【中文标题】当我链接动态库而不是静态库时,CMake 有效【英文标题】:CMake works when I link a dynamic library but not a static library 【发布时间】:2018-06-23 01:38:00 【问题描述】:

当我将动态库与 CMake 链接时,创建 make 文件然后使用 make,它可以正确编译和构建。

当我链接静态库时,CMake 不会抱怨,但是当我运行 make 时,它​​会向我抛出链接器错误,即使我所做的只是将 .dylib 替换为同名的 .a

这是我链接到静态库的 CMake 文件:

cmake_minimum_required (VERSION 3.0)
add_executable (TEST main.cpp)

include_directories ("$CMAKE_SOURCE_DIR/Dependencies/libpqxx/include")
target_link_libraries (TEST "$CMAKE_SOURCE_DIR/Dependencies/libpqxx/lib/libpqxx.a")

有什么想法吗?

cmake 的输出:

>> cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/john/Documents/Test/src

make 的输出:

>> make
[ 33%] Linking CXX executable TEST
Undefined symbols for architecture x86_64:
  "_PQbackendPID", referenced from:
      pqxx::connection_base::backendpid() const in libpqxx.a(connection_base.o)
  "_PQcancel", referenced from:
      pqxx::connection_base::cancel_query() in libpqxx.a(connection_base.o)
  "_PQclear", referenced from:
      pqxx::internal::clear_result(pg_result const*) in libpqxx.a(result.o)
  "_PQclientEncoding", referenced from:
      pqxx::connection_base::encoding_code() in libpqxx.a(connection_base.o)
  "_PQcmdStatus", referenced from:
      pqxx::result::cmd_status() const in libpqxx.a(result.o)
  "_PQcmdTuples", referenced from:
      pqxx::result::affected_rows() const in libpqxx.a(result.o)
  "_PQconnectPoll", referenced from:
      pqxx::connect_async::do_completeconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQconnectStart", referenced from:
      pqxx::connect_async::do_startconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQconnectdb", referenced from:
      pqxx::connectionpolicy::normalconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQconsumeInput", referenced from:
      pqxx::connection_base::consume_input() in libpqxx.a(connection_base.o)
  "_PQdb", referenced from:
      pqxx::connection_base::dbname() in libpqxx.a(connection_base.o)
  "_PQencryptPassword", referenced from:
      pqxx::encrypt_password(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQendcopy", referenced from:
      pqxx::connection_base::write_copy_line(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQerrorMessage", referenced from:
      pqxx::connection_base::err_msg() const in libpqxx.a(connection_base.o)
      pqxx::connectionpolicy::normalconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connect_direct::do_startconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connect_async::do_startconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connect_async::do_completeconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQescapeByteaConn", referenced from:
      pqxx::connection_base::esc_raw(unsigned char const*, unsigned long) in libpqxx.a(connection_base.o)
  "_PQescapeIdentifier", referenced from:
      pqxx::connection_base::quote_name(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQescapeStringConn", referenced from:
      pqxx::connection_base::esc(char const*, unsigned long) in libpqxx.a(connection_base.o)
  "_PQexec", referenced from:
      pqxx::connection_base::exec(char const*, int) in libpqxx.a(connection_base.o)
      pqxx::connection_base::add_receiver(pqxx::notification_receiver*) in libpqxx.a(connection_base.o)
  "_PQexecParams", referenced from:
      pqxx::connection_base::parameterized_exec(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const* const*, int const*, int const*, int) in libpqxx.a(connection_base.o)
      pqxx::connection_base::exec_params(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, pqxx::internal::params const&) in libpqxx.a(connection_base.o)
  "_PQexecPrepared", referenced from:
      pqxx::connection_base::prepared_exec(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const* const*, int const*, int const*, int) in libpqxx.a(connection_base.o)
      pqxx::connection_base::exec_prepared(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, pqxx::internal::params const&) in libpqxx.a(connection_base.o)
  "_PQfinish", referenced from:
      pqxx::connectionpolicy::normalconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connectionpolicy::do_disconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQfname", referenced from:
      pqxx::result::column_name(unsigned int) const in libpqxx.a(result.o)
  "_PQfnumber", referenced from:
      pqxx::result::column_number(char const*) const in libpqxx.a(row.o)
  "_PQfreeCancel", referenced from:
      (anonymous namespace)::cancel_wrapper::~cancel_wrapper() in libpqxx.a(connection_base.o)
  "_PQfreemem", referenced from:
      pqxx::internal::freepqmem(void const*) in libpqxx.a(util.o)
  "_PQftable", referenced from:
      pqxx::result::column_table(unsigned int) const in libpqxx.a(result.o)
  "_PQftablecol", referenced from:
      pqxx::result::table_column(unsigned int) const in libpqxx.a(result.o)
  "_PQftype", referenced from:
      pqxx::result::column_type(unsigned int) const in libpqxx.a(result.o)
  "_PQgetCancel", referenced from:
      pqxx::connection_base::cancel_query() in libpqxx.a(connection_base.o)
  "_PQgetCopyData", referenced from:
      pqxx::connection_base::read_copy_line(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) in libpqxx.a(connection_base.o)
  "_PQgetResult", referenced from:
      pqxx::connection_base::set_up_state() in libpqxx.a(connection_base.o)
      pqxx::connection_base::read_copy_line(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) in libpqxx.a(connection_base.o)
      pqxx::connection_base::end_copy_write() in libpqxx.a(connection_base.o)
      pqxx::connection_base::get_result() in libpqxx.a(connection_base.o)
  "_PQgetisnull", referenced from:
      pqxx::result::get_is_null(unsigned long, unsigned int) const in libpqxx.a(result.o)
  "_PQgetlength", referenced from:
      pqxx::result::get_length(unsigned long, unsigned int) const in libpqxx.a(result.o)
  "_PQgetvalue", referenced from:
      pqxx::result::GetValue(unsigned long, unsigned int) const in libpqxx.a(result.o)
  "_PQhost", referenced from:
      pqxx::connection_base::hostname() in libpqxx.a(connection_base.o)
  "_PQisBusy", referenced from:
      pqxx::connection_base::is_busy() const in libpqxx.a(connection_base.o)
  "_PQisthreadsafe", referenced from:
      pqxx::describe_thread_safety() in libpqxx.a(util.o)
  "_PQnfields", referenced from:
      pqxx::result::columns() const in libpqxx.a(result.o)
  "_PQnotifies", referenced from:
      pqxx::connection_base::get_notifs() in libpqxx.a(connection_base.o)
  "_PQntuples", referenced from:
      pqxx::result::size() const in libpqxx.a(result.o)
      pqxx::result::empty() const in libpqxx.a(result.o)
  "_PQoidValue", referenced from:
      pqxx::result::inserted_oid() const in libpqxx.a(result.o)
  "_PQport", referenced from:
      pqxx::connection_base::port() in libpqxx.a(connection_base.o)
  "_PQprepare", referenced from:
      pqxx::connection_base::register_prepared(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQprotocolVersion", referenced from:
      pqxx::connection_base::protocol_version() const in libpqxx.a(connection_base.o)
  "_PQputCopyData", referenced from:
      pqxx::connection_base::write_copy_line(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQputCopyEnd", referenced from:
      pqxx::connection_base::end_copy_write() in libpqxx.a(connection_base.o)
  "_PQreset", referenced from:
      pqxx::connection_base::reset() in libpqxx.a(connection_base.o)
  "_PQresultErrorField", referenced from:
      pqxx::result::ThrowSQLError(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const in libpqxx.a(result.o)
      pqxx::result::errorposition() const in libpqxx.a(result.o)
  "_PQresultErrorMessage", referenced from:
      pqxx::result::StatusError() const in libpqxx.a(result.o)
  "_PQresultStatus", referenced from:
      pqxx::result::StatusError() const in libpqxx.a(result.o)
  "_PQsendQuery", referenced from:
      pqxx::connection_base::set_up_state() in libpqxx.a(connection_base.o)
      pqxx::connection_base::start_exec(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in libpqxx.a(connection_base.o)
  "_PQserverVersion", referenced from:
      pqxx::connection_base::read_capabilities() in libpqxx.a(connection_base.o)
  "_PQsetErrorVerbosity", referenced from:
      pqxx::connection_base::set_verbosity(pqxx::connection_base::error_verbosity) in libpqxx.a(connection_base.o)
  "_PQsetNoticeProcessor", referenced from:
      pqxx::connection_base::set_up_state() in libpqxx.a(connection_base.o)
      pqxx::connection_base::close() in libpqxx.a(connection_base.o)
  "_PQsocket", referenced from:
      (anonymous namespace)::socket_of(pg_conn const*) in libpqxx.a(connection_base.o)
  "_PQstatus", referenced from:
      pqxx::connection_base::status() const in libpqxx.a(connection_base.o)
      pqxx::connectionpolicy::normalconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connect_direct::do_startconnect(pg_conn*) in libpqxx.a(connection.o)
      pqxx::connect_async::do_startconnect(pg_conn*) in libpqxx.a(connection.o)
  "_PQtrace", referenced from:
      pqxx::connection_base::internal_set_trace() in libpqxx.a(connection_base.o)
  "_PQunescapeBytea", referenced from:
      pqxx::connection_base::unesc_raw(char const*) in libpqxx.a(connection_base.o)
  "_PQuntrace", referenced from:
      pqxx::connection_base::internal_set_trace() in libpqxx.a(connection_base.o)
  "_PQuser", referenced from:
      pqxx::connection_base::username() in libpqxx.a(connection_base.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [TEST] Error 1
make[1]: *** [CMakeFiles/TEST.dir/all] Error 2
make: *** [all] Error 2

【问题讨论】:

欢迎来到 Stack Overflow。您能否将收到的错误消息添加到您的问题中?您的示例是否在没有 CMake 支持的情况下工作?意思是你确定动态库包含相同的符号并且是为同一个平台构建的,然后是你的静态库? @Florian 我已经添加了错误消息。关于您的“静态库是否与动态库具有相同的符号”问题,我不确定如何检查,但我会假设是这样。动态库和静态库都是作为一个包下载的,没有任何迹象表明它们不同。 【参考方案1】:

如果你发送错误消息会更好,但试试这个:

link_directories($CMAKE_SOURCE_DIR/Dependencies/libpqxx/lib)
target_link_libraries (TEST pqxx)

【讨论】:

我已更新原始帖子以包含错误消息。我也试过你的解决方案,但无济于事。这是我收到的错误消息:&gt;&gt; make[ 33%] Linking CXX executable TESTld: library not found for -lpqxxclang: error: linker command failed with exit code 1 (use -v to see invocation)make[2]: *** [TEST] Error 1make[1]: *** [CMakeFiles/TEST.dir/all] Error 2make: *** [all] Error 2 Dependencies/libpqxx/lib 持有 libpqxx-6.2.dylib libpqxx.a libpqxx.dylib pkgconfig/ 如果有任何帮助的话【参考方案2】:

我想通了。我只是缺少 pqxx 库的一些依赖项。我添加了对libpq.alibssl.alibcrypto.a 以及它们的include/ 目录的引用,它最终工作了。我猜.dylib 文件自己链接到依赖项,但您必须手动将它们包含在静态库中?

【讨论】:

以上是关于当我链接动态库而不是静态库时,CMake 有效的主要内容,如果未能解决你的问题,请参考以下文章

CMake:是不是可以仅从静态库而不是源代码构建可执行文件?

cmake设置默认静态链接库

如何防止我的makefile由于静态库而重新链接

静态链接库的动态 DLL

链接构建的静态库而不是使用 add_subdirectory?

在链接/编译时静态包含所有库而不是库的一部分