CocoaPods 1.5.0 static library should work with pod with custom modulemap file.

Created on 5 Apr 2018  ·  13Comments  ·  Source: CocoaPods/CocoaPods

Report

What did you do?

Build all my pods as static library.

What did you expect to happen?

All those pods should be able to build with use_framework! removed.

What happened instead?

The pod ReactiveCocoa can be build as static library but the target using it have an error:

/Users/ainopara/Library/Developer/Xcode/DerivedData/Bangumi-cjecudnzgwxhqqhaklqnhmcaqmqn/Build/Products/Debug-iphonesimulator/ReactiveCocoa/ReactiveCocoa.modulemap:2:18: error: umbrella header 'ReactiveCocoa.h' not found
        umbrella header "ReactiveCocoa.h"
                        ^
<unknown>:0: error: could not build Objective-C module 'ReactiveCocoa'

How do I fix it in my project

Target ReactiveCocoa has a build phase Copy generated compatibility header which contains

COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
MODULE_MAP_PATH="${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap"

ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${COMPATIBILITY_HEADER_PATH}"
ditto "${PODS_ROOT}/Headers/Private/ReactiveCocoa/ReactiveCocoa.modulemap" "${MODULE_MAP_PATH}"
ditto "${PODS_ROOT}/Headers/Private/ReactiveCocoa/ReactiveCocoa-umbrella.h" "${BUILT_PRODUCTS_DIR}"
printf "\n\nmodule ${PRODUCT_MODULE_NAME}.Swift {\n  header \"${COMPATIBILITY_HEADER_PATH}\"\n  requires objc\n}\n" >> "${MODULE_MAP_PATH}"

I have noticed that ${PODS_ROOT}/Headers/Private/ReactiveCocoa/ReactiveCocoa-umbrella.h does not exist since the pod ReactiveCocoa choosed to use its own module map and its own umbrella header ReactiveCocoa.h.

The content of ReactiveCocoa.modulemap is

module ReactiveCocoa [system] {
    umbrella header "ReactiveCocoa.h"
    private header "ObjCRuntimeAliases.h"

    export *
    module * { export * }
}

Becuase my project will throw an error while building if ${BUILT_PRODUCTS_DIR} does not contain all the headers ReactiveCocoa.h and ObjCRuntimeAliases.h, I change the content of Copy generated compatibility header build phase to

COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
MODULE_MAP_PATH="${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap"

ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${COMPATIBILITY_HEADER_PATH}"
ditto "${PODS_ROOT}/Headers/Private/ReactiveCocoa/ReactiveCocoa.modulemap" "${MODULE_MAP_PATH}"
ditto "${PODS_ROOT}/Headers/Private/ReactiveCocoa/ReactiveCocoa.h" "${BUILT_PRODUCTS_DIR}"
ditto "${PODS_ROOT}/Headers/Private/ReactiveCocoa/ObjCRuntimeAliases.h" "${BUILT_PRODUCTS_DIR}"
printf "\n\nmodule ${PRODUCT_MODULE_NAME}.Swift {\n  header \"${COMPATIBILITY_HEADER_PATH}\"\n  requires objc\n}\n" >> "${MODULE_MAP_PATH}"

The project can be build successfully after the change. So I think this is a CocoaPods issue.

If I'm not missing something, this issue can be easily fixed by changing Copy generated compatibility header build phase script to copy all *.h files in ${PODS_ROOT}/Headers/Private/ReactiveCocoa to ${BUILT_PRODUCTS_DIR} rather than only trying to copy ReactiveCocoa-umbrella.h.

confirmed defect

Most helpful comment

I succeed to use the static swift library in objective c by adding a script_phase to copy ${PRODUCT_MODULE_NAME}-Swift.h" to header search path.

s.script_phase = { :name => 'Copy Swift Header',
:script => 'COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"; ditto "${COMPATIBILITY_HEADER_PATH}" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"',
:execution_position => :after_compile }

All 13 comments

The same is also true with https://github.com/groue/GRDB.swift. The content of GRDB.swift.modulemap is

module GRDB [system] {
    umbrella header "GRDB.h"

    export *
    module * { export * }

    header "grdb_config.h"
}

Please share an example project that can be used to reproduce the issue

CustomModulemapSample.zip
Note that the error occures when the project trying to import ReactiveCocoa.

@segiddins you can check https://github.com/bmichotte/CocoaPodGRDB

first commit uses use_framework! and compiles fine while second commit removes the use_framework! and fails

Is there anything I can do to help move this forward? Any hints on how to work around this?

@daveanderson the best way is to make a PR for it. There will be a 1.5.1 release hopefully this week (no promises).

Sorry I can't give you an ETA as most people who work on the project work on their free time.

我们也遇到了同样的问题。希望尽快给出解答。

@dnkoutso Was this fixed in that 1.5.1 release? It doesn't _seem_ to be for me but I could be doing something wrong.

Nope I dont think there is support for custom module maps with Swift static libraries yet.

I succeed to use the static swift library in objective c by adding a script_phase to copy ${PRODUCT_MODULE_NAME}-Swift.h" to header search path.

s.script_phase = { :name => 'Copy Swift Header',
:script => 'COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"; ditto "${COMPATIBILITY_HEADER_PATH}" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"',
:execution_position => :after_compile }

I succeed to use the static swift library in objective c by adding a script_phase to copy ${PRODUCT_MODULE_NAME}-Swift.h" to header search path.

s.script_phase = { :name => 'Copy Swift Header',
:script => 'COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"; ditto "${COMPATIBILITY_HEADER_PATH}" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"',
:execution_position => :after_compile }

按你的方法也可以这样做,在Podfile中这样写:

post_install do |installer|
  installer.pods_project.targets.each do |target|
        compatibilityPhase = target.build_phases.find { |ph| ph.display_name == 'Copy generated compatibility header' }
        if compatibilityPhase
            build_phase = target.new_shell_script_build_phase('Copy Swift Header')
            build_phase.shell_script = <<-SH.strip_heredoc
                COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
                ditto "${COMPATIBILITY_HEADER_PATH}" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"
            SH
        end
  end
end

Going over issues, this is a duplicate of https://github.com/CocoaPods/CocoaPods/issues/9023 which is enhancement for supporting custom module maps for Swift static library targets.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

intelliot picture intelliot  ·  3Comments

pronebird picture pronebird  ·  3Comments

hmistry picture hmistry  ·  3Comments

lzwjava picture lzwjava  ·  3Comments

k06a picture k06a  ·  3Comments