Question about 'LIBRARY_SEARCH_PATHS' and static libraries.

In cmGlobalXCodeGenerator.cxx(3612) there is a section that skips setup of LIBRARY_SEARCH_PATHS for a target that is a STATIC_LIBRARY

Code Snippet:

// Skip link information for object libraries.
if (gt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
    gt->GetType() == cmStateEnums::STATIC_LIBRARY) {
  continue;
}

What is the reason for this? For our older projects that had manual xcode setups, we would link third party static libraries into our main static library that was part of the xcode project and our main application would then link that separately.

As far as I can see this is not possible in CMake as we cannot add a path to the third-party libraries (due to the above snippet). I would like to add ‘$(BUILD_DIR)’ so the default build location for a project is added as a library search location (this is needed for Cocoapods).

If anyone can offer any insight into the thought behind this it would be greatly appreciated.

Cc: @brad.king

Static libraries (and object libraries) don’t link, so there is no point in setting up a linker search path.

When using target_link_libraries(someStaticLib PRIVATE its dependencies), CMake will add the transitive dependencies to other targets that link to someStaticLib.

In xcode, the last step when building a static library ‘Create static library foo.a…’ is a call to Libtool which uses LIBRARY_SEARCH_PATHS to find other libraries that are to be included into that library.

To expand on the example I describe in the original post, we have our own library, utilities.a which has a wrapper around calls to the curl library (libcurl.a). The call to Libtool looks a little like this:

LibTool  /utilities.a normal (in target 'utilities' from project 'foo')
<xcodepath>/libtool -static <other settings> -L/path/to/curl -lcurl

If the path to curl is removed the build will fail with:

error: <xcodepath>/libtool: can't locate file for: -lcurl
error: <xcodepath>/libtool: file: -lcurl is not an object file (not allowed in a library)

Not being able to set LIBRARY_SEARCH_PATHS for the static library in our cmake project prevents us using cocoapods as it need to ‘link’ with the generated pod library.

I think this is the relevant section of the libtool docs: https://www.gnu.org/software/libtool/manual/libtool.html#Link-mode

GNU libtool has no relation to Xcode’s libtool (e.g., it has the typical “useless command line” behavior in that it lacks --help or --version). It is also lacking a GNU license statement and I imagine Apple is pretty strict about such things.

One possible fix would be to use the full path to libcurl rather than a pair of -L and -l flags.

And anyways, static libraries don’t get copied into each other without an explicit flag usually; the other libraries on the command line are there to do any symbol checking, not for anything resembling “linking”. See this SO question for more.

Just wanted to clarify what I’m referring to with an image of an example xcode (not cmake) project. Here shows a static library that ‘links’ to another binary. Xcode uses LIBRARY_SEARCH_PATHS to find this binary.

I need this setup to allow cocoapods to work, and to do this I need to be able to set LIBRARY_SEARCH_PATHS for a static library.

Have you tried the latest CMake release? Check out the XCODE_LINK_BUILD_PHASE_MODE, which is available since CMake 3.19. That should take care of the library search path for you where needed. For your example where you link to a library not built by your project, you probably need it to be set to KNOWN_LOCATION and specify the path to the library to be linked as a full absolute path.

I’m not sure if this is a semantic issue, but this is not true for native xcode projects. When building a static library in xcode, the object files from a ‘linked’ static library are copied in the new library (or archive). Any project can then include this library without the need to include the extra library.

Xcode might do that by default, but CMake’s static linking semantics don’t include that. CMake also doesn’t have an abstraction for doing that across all generators and such behavior differences based on the generator in use is not a happy situation for CMake users.