nakiya
nakiya

Reputation: 14413

Linker cannot find symbols in library

I built a C library using CMake. Here's the CMakeLists file for the library:

cmake_minimum_required(VERSION 3.7)
project(sshserial)

set(CMAKE_C_STANDARD 99)

include_directories(BEFORE SYSTEM ${CMAKE_SOURCE_DIR}/common/include)
link_directories(${CMAKE_SOURCE_DIR}/common/lib)

set(SOURCE_FILES sshserial.c sshserial.h)
add_library(sshserial ${SOURCE_FILES})

TARGET_LINK_LIBRARIES(sshserial libssh.a)

I use this library in a C++ program. Here's the CMakeLists file for the program:

cmake_minimum_required(VERSION 3.7)
project(sshtest)

set(CMAKE_CXX_STANDARD 11)

include_directories(BEFORE SYSTEM ${CMAKE_SOURCE_DIR}/common/include)
link_directories(${CMAKE_SOURCE_DIR}/common/lib)

set(SOURCE_FILES main.cpp)
add_executable(sshtest ${SOURCE_FILES})

TARGET_LINK_LIBRARIES(sshtest libsshserial.a)

I have copied the library in the correct folder. When I run nm on the library I get this:

$ nm libsshserial.a 

libsshserial.a(sshserial.c.o):
                 U ___error
                 U ___stack_chk_fail
                 U ___stack_chk_guard
                 U ___stderrp
                 U ___stdinp
0000000000000330 T _create_session
                 U _exit
                 U _fgets
                 U _fprintf
                 U _free
                 U _getpass
0000000000000490 T _read_from_session
                 U _ssh_channel_close
                 U _ssh_channel_free
                 U _ssh_channel_new
                 U _ssh_channel_open_session
                 U _ssh_channel_read
                 U _ssh_channel_request_exec
                 U _ssh_channel_send_eof
                 U _ssh_connect
                 U _ssh_disconnect
                 U _ssh_free
                 U _ssh_get_error
                 U _ssh_get_hexa
                 U _ssh_get_pubkey_hash
                 U _ssh_is_server_known
                 U _ssh_new
                 U _ssh_options_set
                 U _ssh_print_hexa
                 U _ssh_userauth_password
                 U _ssh_write_knownhost
                 U _strerror
                 U _strncasecmp
0000000000000000 T _verify_knownhost
                 U _write

When I try to build the program, I get this linker errors:

Undefined symbols for architecture x86_64:
  "create_session()", referenced from:
      _main in main.cpp.o
  "read_from_session(ssh_session_struct*)", referenced from:
      _main in main.cpp.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[3]: *** [sshtest] Error 1
make[2]: *** [CMakeFiles/sshtest.dir/all] Error 2
make[1]: *** [CMakeFiles/sshtest.dir/rule] Error 2
make: *** [sshtest] Error 2

I've been stuck here for some time and I am sure I'm missing something trivial. What am I doing wrong?

P.S. I'm on Mac

$ uname -a
Darwin XXXXXX 15.6.0 Darwin Kernel Version 15.6.0: Tue Apr 11 16:00:51 PDT 2017; root:xnu-3248.60.11.5.3~1/RELEASE_X86_64 x86_64

Upvotes: 2

Views: 2616

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409216

The problem is that C++ uses name mangling. To inhibit that you need to declare the C functions with extern "C", but only when being compiled by a C++ compiler. You can check this with the __cplusplus macro, which is defined when compiling C++, but not when compiling C.

In the header file where you declare the function prototypes, do something like

#ifdef __cplusplus
// Being compiled by a C++ compiler, inhibit name mangling
extern "C" {
#endif

// All your function prototype declarations here

#ifdef __cplusplus
}  // End of extern "C"
#endif

Upvotes: 3

Related Questions