当我 link 一个动态库而不是一个静态库时,CMake 工作

CMake works when I link a dynamic library but not a static library

当我 link 使用 CMake 创建动态库时,创建 make 文件然后使用 make,它会正确编译和构建。

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

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

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

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

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

我已经弄明白了。我只是缺少 pqxx 库的一些依赖项。我已经添加了对 libpq.alibssl.alibcrypto.a 以及它们的 include/ 目录的引用,它最终起作用了。我猜 .dylib 文件 link 自己依赖,但你必须手动将它们包含在静态库中?