0

When I link a dynamic library with CMake, create the make file and then use make, it compiles and builds correctly.

When I link a static library, CMake doesn't complain but when I run make, it throws a linker error at me, even though all I did was replace the .dylib with a .a of the same name.

This is my CMake file linking to a static library:

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")

Any ideas?

Output for cmake:

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

Output for 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
John Doe
  • 1
  • 2
  • Welcome to Stack Overflow. Can you please add the error message you get to your question? Does your example work without CMake support? Meaning are you sure the dynamic library contains the same symbols and is build for the same platform then your static library? – Florian Jun 23 '18 at 06:25
  • @Florian I've added the error messages. Regarding your "does the static library have the same symbols as the dynamic library" question, I'm not really sure how to check but I would assume so. Both the dynamic and static libraries were downloaded as one package without anything to signify that they are different. – John Doe Jun 23 '18 at 16:33

2 Answers2

0

if you send error messages it'd be better , but try this:

link_directories(${CMAKE_SOURCE_DIR}/Dependencies/libpqxx/lib)
target_link_libraries (TEST pqxx)
  • I've updated the original post to include the error message. I've also tried your solution but to no avail. This is the error message I got: ``>> make[ 33%] Linking CXX executable TEST`` ``ld: library not found for -lpqxx`` ``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`` – John Doe Jun 23 '18 at 16:35
  • Dependencies/libpqxx/lib holds ``libpqxx-6.2.dylib`` ``libpqxx.a`` ``libpqxx.dylib`` ``pkgconfig/`` if that helps with anything – John Doe Jun 23 '18 at 16:42
0

I've figured it out. I was just missing some dependencies for the pqxx library. I've added a reference to libpq.a, libssl.a, and libcrypto.a as well as their include/ directories and it ended up working. I guess .dylib files link to dependencies by themselves but you have to manually include them with static libraries?

John Doe
  • 1
  • 2