Monday, April 11, 2022

[SOLVED] Xcode, CMake unable to link C++ library with ObjC++ library

Issue

I have created a minimalistic C++ library that I want to use in my Xcode project. It has this directory structure -

library/
 
    - CMakeLists.txt
    - build/    // build files will reside here 
    - iOS.cmake // toolchain file
    - core/
        - CMakeLists.txt
        - squareroot.h
        - squareroot.cpp
    - platform/
        - CMakeLists.txt
        - squrerootwrapper.h
        - squarerootwrapper.mm

Project link - https://github.com/devojoyti/CMakeLibrary

Inside build/ I am doing -

  • cmake ../ -G Xcode -D CMAKE_TOOLCHAIN_FILE=../iOS.cmake -D IOS_PLATFORM=SIMULATOR
  • xcodebuild -target install -configuration Debug

Basically what is happening, is I am building two libraries, one inside core/ which calculates the squareroot of a number, another in platform/ which is a ObjC wrapper on the C++ squareroot computation library. I am linking the core/ library inside platform/ library.

Problem:

Problem is, I am unable to link the library generated inside core/, with that of generated inside platform/. The code builds just fine, and the library (and the corresponding .h header file) is generated.

However, if I try to use it in my Xcode, it says this:

enter image description here

Clearly, the core/ library functions are not accessible inside platform/.

I have tried fiddling with C and CXX flags, trying to add library using find_library first, and using different toolchain, for example, this one here as well.

Platform specifications:

  • MacOS Big Sur, 11.6.5, 2.3 Ghz i9
  • CMake - 3.22.2
  • Xcode - 13.2.1

Solution

Alright, I finally got what was the problem.

  • The libraries I was generating, were static libraries.
  • Static libraries cannot resolve their dependencies on their own (i.e., here, library in platform/ cannot resolve its dependency of core/) unless I explicitly add both of them to Xcode.
  • It started working after I added both libraries (core/ library and platform/) in Xcode.

Explanation:

  • Static Library: Though you specify a dependency, it's not resolved by the toolchain. You'd have to specify all dependencies to the final executable.

    • e.g: libB depends on libA then when linking hello.exe which only calls methods of libB you've to specify both libB.a AND libA.a too for it to work
  • Dynamic/Shared Library: Dependencies b/w libraries are resolved; just specifying the dependency needed by the final executable is good enough

    • You'd still have to make sure both .dylibs are in the same directory for libB.dylib to load libA.dylib

So, either create a dynamic library or add all the dependencies of the static library in Xcode as well.



Answered By - devojoyti
Answer Checked By - Terry (WPSolving Volunteer)