Linking C shared library - Undefined symbols

Hi all,

Looking for a second pair of eyes. My CI is failing on macOS for my shared lib. I’m not sure why linking is failing.

My CMakeLists.txt

High level:

  1. C binary project builds a lib of itself
  2. Rust library uses and links to that lib
  3. C project uses Rust library and links to that

All works on my Fedora 41 workstation, but not my MacBook or CI.

I think I need the following, but for the ${CMAKE_PROJECT_NAME}_lib?

target_link_libraries(${CMAKE_PROJECT_NAME} -losipparser2)
target_link_libraries(${CMAKE_PROJECT_NAME} -lsqlite3)
target_link_libraries(${CMAKE_PROJECT_NAME} -luuid)
target_link_libraries(${CMAKE_PROJECT_NAME} -lmicrohttpd)
target_link_libraries(${CMAKE_PROJECT_NAME} -ljansson)
target_link_libraries(${CMAKE_PROJECT_NAME} -lcurl)
target_link_libraries(${CMAKE_PROJECT_NAME} -lpcre2-8)

as well as my binary (already there).

Thanks.

IMO, you should identify which targets need what things and then use target_link_libraries to establish the relationships between targets.

It’s a little bit wrinkly because you’re using dependencies from your environment, e.g. -lcurl, instead of a CMake target like curl::curl.

The “modern CMake” way of expressing these relationships is to use find_package to locate your dependencies on the system and then you should have imported targets on which you can express the relationships.

Starting with the first error:

[ 28%] Linking C shared library libsentrypeer.dylib
...
 _MHD_add_response_header, referenced from:
      _finalise_response in http_common.c.o
      _finalise_response in http_common.c.o
      _finalise_response in http_common.c.o
      _finalise_response in http_common.c.o

Says that http_common.c has a link dependency on MHD_add_response and presumably this symbol is supplied by -lmicrohttpd.

You’re building a shared library – libsentrypeer.dylib – and shared libraries, unlike static libraries, need to resolve all their symbols at link time.

So yes, you need to make your shared library target depend on -lmicrohttpd.

Fix the link errors one at a time, identifying the missing library and adding it until linking succeeds.

Once you’ve got it all linking and comitted, consider using find_package to locate your dependencies and express the relationships with imported alias targets instead of link command-line options.

1 Like

Thanks for the detailed reply Richard. I’ll have a look at this in the morning. Very much appreciated!

Why does it work on Linux though, e.g. on my Fedora workstation.

Different systems do different things. It’s what I call “working by accident” as opposed to “working by design”.

On your linux machine, something is picking up the necessary dependencies “automatically”.

1 Like