PodToBUILD icon indicating copy to clipboard operation
PodToBUILD copied to clipboard

Module Maps for Obj-C/C/C++ include too many files

Open sayrer opened this issue 7 years ago • 2 comments

I noticed this with https://github.com/facebook/yoga

filegroup(
  name = "yoga_hdrs",
  srcs = glob(
    [
      "pod_support/Headers/Public/**/*.h"
    ],
    exclude_directories = 1
    ),
  visibility = [
    "//visibility:public"
  ]
  )
gen_module_map(
  "yoga",
  "yoga_module_map",
  "yoga",
  [
    "yoga_hdrs"
  ]
  )

It seems like pod_support/Headers/Public/ contains too many files (every yoga header, public or private), given that the podspec lists only three public headers: https://github.com/facebook/yoga/blob/master/Yoga.podspec#L28.

sayrer avatar May 22 '18 22:05 sayrer

Digging into this further, it looks like PodToBUILD doesn't yet create umbrella headers and the modulemap files to go with them. Yoga is a good demo. Here's a summary of what Cocoapods generates:

$ ls -l MyApp/Pods/Target\ Support\ Files/Yoga/
total 48
-rw-r--r--  1 sayrer  staff  828 May 23 08:12 Info.plist
-rw-r--r--  1 sayrer  staff  112 May 23 08:12 Yoga-dummy.m
-rw-r--r--  1 sayrer  staff  195 May 23 08:12 Yoga-prefix.pch
-rw-r--r--  1 sayrer  staff  358 May 23 08:12 Yoga-umbrella.h
-rw-r--r--  1 sayrer  staff   98 May 23 08:12 Yoga.modulemap
-rw-r--r--  1 sayrer  staff  399 May 23 08:12 Yoga.xcconfig

$ cat MyApp/Pods/Target\ Support\ Files/Yoga/Yoga-umbrella.h
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

#import "YGEnums.h"
#import "YGMacros.h"
#import "Yoga.h"

FOUNDATION_EXPORT double yogaVersionNumber;
FOUNDATION_EXPORT const unsigned char yogaVersionString[];

$ cat MyApp/Pods/Target\ Support\ Files/Yoga/Yoga.modulemap 
framework module yoga {
  umbrella header "Yoga-umbrella.h"

  export *
  module * { export * }
}

I ran into this issue because Yoga exports a C interface in its public headers, which is fine to use with a .m Obj-C file. At the moment, PodToBUILD exports all of the private headers in the modulemap. These include C++ files which can't be included in a .m file, and so my build fails.

sayrer avatar May 23 '18 15:05 sayrer

Hey @sayrer - the current behavior of module map includes all of the headers ( currently, whatever is symlinked into pod_support ), which every header right now. It symlinks every possible header into that directory, and there is an issue that causing garbage symlinks to be created. This is not good!

You're right, CocoaPods is generating an umbrella header which achieves a similar result as what the current code does, but they use public headers only. Ideally PodToBUILD follows an identical pattern: only including public headers in the module map, perhaps generating an umbrella header if needed. This would be awesome.

Until this is fixed, do you absolutely need the module map? If not, turn it off for now. That would be an easy workaround 🔨.

new_pod_repository(
  name = "Yoga",
  ....
  generate_module_map = False
 ) 

Then,

# Update the repository to disable module generation
Vendor/bin/update_pods.py

Otherwise it is possible to augment BUILD files and the generated directory in Vendor/Yoga:

  • turnoff the module map feature
  • put the ideal module map adjacent to the symlinked headers
new_pod_repository(
  name = "Yoga",
  ....
   # Turn of the default module map code gen
   generate_module_map = False

   install_script = """
   # Setup the Yoga repo by default
   __INIT_REPO__
   # Copy a module map that includes only public headers
   ditto path/to/ideal/module.modulemap Vendor/Yoga/pod_support/Headers/Public/Yoga/
   """
 ) 

jerrymarino avatar May 23 '18 17:05 jerrymarino