Home > Software design >  Weak linking static library in Xcode
Weak linking static library in Xcode

Time:09-16

I'm trying to achieve weak linking with static libraries. I’ve read those two articles, "Static Library on iOS" and "How Jesse Pinkman cracked Dynamic Library on iOS", which are really helpful.

However, I’m in a situation that I cannot achieve what I want. I’ve developed two frameworks, let’s call them Main and Feature, they can be installed both as pods and swift packages.

Main doesn’t have a dependency on Feature, nor Feature on Main, but if both Main and Feature are present on the podfile of the developer, then Main can use Feature’s functionality. This is achieved by adding the Framework’s path on the Main’s framework search paths in its podspec.

Main.podspec

# This works when use_frameworks! is added in the podfile.
s.pod_target_xcconfig = {
    "FRAMEWORK_SEARCH_PATHS" => [
      "$(inherited)",
      "${PODS_CONFIGURATION_BUILD_DIR}/Feature",
    ],
}

This way, Main can use Feature’s functionality the following way

#if canImport(Feature)
print("SUCCESS!!!")
let feat = Feature()
feat.test()
#else
print(“Failed to import Feature“)
#endif

The problem starts when the integrating developer doesn’t include use_frameworks! In his podfile (e.g. React Native). Main and Feature are then built as static libraries, it compiles but it never gets inside the SUCCESS block.

After reading the above articles, I believe that the correct approach would be something like the following

Main.podspec

s.pod_target_xcconfig = {
    "LIBRARY_SEARCH_PATHS" => [
      "$(inherited)",
      "${PODS_CONFIGURATION_BUILD_DIR}/Feature",
    ],
    "SWIFT_INCLUDE_PATHS" => [
        "$(inherited)",
        "${PODS_CONFIGURATION_BUILD_DIR}/Feature",
    ],
  }

And maybe also add

  Main.podspec

  s.pod_target_xcconfig = {
   …
    'OTHER_LDFLAGS' => [
        "$(inherited)",
        '-ObjC',
        '-weak_library -l"Feature"'
    ],
    …
  }

I've tried the above with both Defines module = YES/NO on the Feature's side.

Feature.podspec

s.pod_target_xcconfig = {
    'DEFINES_MODULE' => 'YES'
}

However, none of the above worked. Does anyone have any idea of what I might be doing wrong, or point me in some direction?

CodePudding user response:

I ended up mocking what you need here.

But, I could solve only half (without use_frameworks) of your problem by:

Main.podspec

# To include Swift Module
'OTHER_SWIFT_FLAGS' => ['$(inherited)', '-Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Feature/Feature.modulemap"']

Podspec Side:

  • Not sure why modulemap file path is needed with cocoapod setup (may be when a library is weakly linked)

Podfile Side:

  • It will work without use_frameworks
  • It won't work with use_frameworks as modulemap file won't be found in the specified path (as it considers only for static path scenario) & Xcode will think it's needed. Not sure how to optionally specify a modulemap file in the Podspec.

I hope I was able to help even though it's half way.

CodePudding user response:

@e_pie I think what you are trying to do is a post_install stuff if you are clear about Main's dependency on Feature.

So, the things you tried are actually perfect, but should be put on post_install like this in App's Podfile:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == "Main"
      target.build_configurations.each do |config|
        config.build_settings['FRAMEWORK_SEARCH_PATHS'] = "${PODS_CONFIGURATION_BUILD_DIR}/Feature"
      end
    end
  end
end

I hope it helps, please let me know if it doesn't.

  • Related