Skip to content

Commit

Permalink
Add direct sources, headers, and module maps to ObjcProvider
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 2446880
  • Loading branch information
DavidGoldman authored and copybara-github committed Apr 22, 2019
1 parent deca59b commit 5ba7cf6
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
Expand All @@ -39,6 +40,7 @@
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.skylarkbuildapi.apple.ObjcProviderApi;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.vfs.PathFragment;
Expand Down Expand Up @@ -342,10 +344,25 @@ public enum Flag {
}

private final StarlarkSemantics semantics;

// Items which are propagated transitively to dependents.
private final ImmutableMap<Key<?>, NestedSet<?>> items;

/**
* This is intended to be used by clients which need to collect transitive information without
* paying the O(n^2) behavior to flatten it during analysis time.
*
* <p>For example, IDEs may use this to identify all direct header files for a target and fetch
* all transitive headers from its dependencies by recursing through this field.
*/
private final ImmutableListMultimap<Key<?>, ?> directItems;

// Items which should not be propagated to dependents.
private final ImmutableMap<Key<?>, NestedSet<?>> nonPropagatedItems;

// Items which should be passed to strictly direct dependers, but not transitive dependers.
private final ImmutableMap<Key<?>, NestedSet<?>> strictDependencyItems;

/** All keys in ObjcProvider that will be passed in the corresponding Skylark provider. */
static final ImmutableList<Key<?>> KEYS_FOR_SKYLARK =
ImmutableList.<Key<?>>of(
Expand Down Expand Up @@ -401,6 +418,22 @@ public enum Flag {
XCDATAMODEL,
XIB);

/**
* Keys that should be kept as directItems. This is limited to a few keys that have larger
* performance implications when flattened in a transitive fashion and/or require non-transitive
* access (e.g. what module map did a target generate?).
*
* <p>Keys:
*
* <ul>
* <li>HEADER: To expose all header files, including generated proto header files, to IDEs.
* <li>SOURCE: To expose all source files, including generated J2Objc source files, to IDEs.
* <li>MODULE_MAP: To expose generated module maps to IDEs (only one is expected per target).
* </ul>
*/
static final ImmutableSet<Key<?>> KEYS_FOR_DIRECT =
ImmutableSet.<Key<?>>of(HEADER, MODULE_MAP, SOURCE);

@Override
public NestedSet<Artifact> assetCatalog() {
return get(ASSET_CATALOG);
Expand Down Expand Up @@ -448,6 +481,11 @@ public NestedSet<Artifact> header() {
return get(HEADER);
}

@Override
public SkylarkList<Artifact> directHeaders() {
return getDirect(HEADER);
}

@Override
public NestedSet<Artifact> importedLibrary() {
return get(IMPORTED_LIBRARY);
Expand Down Expand Up @@ -513,6 +551,11 @@ public NestedSet<Artifact> moduleMap() {
return get(MODULE_MAP);
}

@Override
public SkylarkList<Artifact> directModuleMaps() {
return getDirect(MODULE_MAP);
}

@Override
public NestedSet<Artifact> multiArchDynamicLibraries() {
return get(MULTI_ARCH_DYNAMIC_LIBRARIES);
Expand Down Expand Up @@ -549,6 +592,11 @@ public NestedSet<Artifact> source() {
return get(SOURCE);
}

@Override
public SkylarkList<Artifact> directSources() {
return getDirect(SOURCE);
}

@Override
public NestedSet<Artifact> staticFrameworkFile() {
return get(STATIC_FRAMEWORK_FILE);
Expand Down Expand Up @@ -652,22 +700,21 @@ static boolean isDeprecatedResourceKey(Key<?> key) {
return DEPRECATED_RESOURCE_KEYS.contains(key);
}

// Items which should be passed to strictly direct dependers, but not transitive dependers.
private final ImmutableMap<Key<?>, NestedSet<?>> strictDependencyItems;

/** Skylark constructor and identifier for ObjcProvider. */
public static final BuiltinProvider<ObjcProvider> SKYLARK_CONSTRUCTOR = new Constructor();

private ObjcProvider(
StarlarkSemantics semantics,
ImmutableMap<Key<?>, NestedSet<?>> items,
ImmutableMap<Key<?>, NestedSet<?>> nonPropagatedItems,
ImmutableMap<Key<?>, NestedSet<?>> strictDependencyItems) {
ImmutableMap<Key<?>, NestedSet<?>> strictDependencyItems,
ImmutableListMultimap<Key<?>, ?> directItems) {
super(SKYLARK_CONSTRUCTOR, Location.BUILTIN);
this.semantics = semantics;
this.items = Preconditions.checkNotNull(items);
this.nonPropagatedItems = Preconditions.checkNotNull(nonPropagatedItems);
this.strictDependencyItems = Preconditions.checkNotNull(strictDependencyItems);
this.directItems = Preconditions.checkNotNull(directItems);
}

/**
Expand All @@ -689,6 +736,15 @@ public <E> NestedSet<E> get(Key<E> key) {
return builder.build();
}

/** All direct artifacts, bundleable files, etc. of the type specified by {@code key}. */
@SuppressWarnings({"rawtypes", "unchecked"})
public <E> SkylarkList<E> getDirect(Key<E> key) {
if (directItems.containsKey(key)) {
return SkylarkList.createImmutable((List) directItems.get(key));
}
return SkylarkList.createImmutable(ImmutableList.of());
}

/**
* Returns all keys that have at least one value in this provider (values may be propagable,
* non-propagable, or strict).
Expand Down Expand Up @@ -998,6 +1054,10 @@ public static final class Builder {
private final Map<Key<?>, NestedSetBuilder<?>> nonPropagatedItems = new HashMap<>();
private final Map<Key<?>, NestedSetBuilder<?>> strictDependencyItems = new HashMap<>();

// Only includes items or lists added directly, never flattens any NestedSets.
private final ImmutableListMultimap.Builder<Key<?>, ?> directItems =
new ImmutableListMultimap.Builder<>();

public Builder(StarlarkSemantics semantics) {
this.starlarkSemantics = semantics;
}
Expand All @@ -1013,8 +1073,14 @@ private void uncheckedAddAll(Key key, Iterable toAdd, Map<Key<?>, NestedSetBuild
}

@SuppressWarnings({"rawtypes", "unchecked"})
private void uncheckedAddTransitive(Key key, NestedSet toAdd,
Map<Key<?>, NestedSetBuilder<?>> set) {
private void uncheckedAddAllDirect(
Key key, Iterable<?> toAdd, ImmutableListMultimap.Builder<Key<?>, ?> builder) {
builder.putAll(key, (Iterable) toAdd);
}

@SuppressWarnings({"rawtypes", "unchecked"})
private void uncheckedAddTransitive(
Key key, NestedSet toAdd, Map<Key<?>, NestedSetBuilder<?>> set) {
maybeAddEmptyBuilder(set, key);
set.get(key).addTransitive(toAdd);
}
Expand Down Expand Up @@ -1088,6 +1154,9 @@ public Builder addAsDirectDeps(ObjcProvider provider) {
*/
public <E> Builder add(Key<E> key, E toAdd) {
uncheckedAddAll(key, ImmutableList.of(toAdd), this.items);
if (ObjcProvider.KEYS_FOR_DIRECT.contains(key)) {
uncheckedAddAllDirect(key, ImmutableList.of(toAdd), this.directItems);
}
return this;
}

Expand All @@ -1096,6 +1165,9 @@ public <E> Builder add(Key<E> key, E toAdd) {
*/
public <E> Builder addAll(Key<E> key, Iterable<? extends E> toAdd) {
uncheckedAddAll(key, toAdd, this.items);
if (ObjcProvider.KEYS_FOR_DIRECT.contains(key)) {
uncheckedAddAllDirect(key, toAdd, this.directItems);
}
return this;
}

Expand Down Expand Up @@ -1124,11 +1196,15 @@ public <E> Builder addAllForDirectDependents(Key<E> key, Iterable<? extends E> t
}

/**
* Add elements in toAdd with the given key from skylark. An error is thrown if toAdd is not
* an appropriate SkylarkNestedSet.
* Add elements in toAdd with the given key from skylark. An error is thrown if toAdd is not an
* appropriate SkylarkNestedSet.
*/
void addElementsFromSkylark(Key<?> key, Object toAdd) {
uncheckedAddAll(key, ObjcProviderSkylarkConverters.convertToJava(key, toAdd), this.items);
void addElementsFromSkylark(Key<?> key, Object skylarkToAdd) {
Iterable<?> toAdd = ObjcProviderSkylarkConverters.convertToJava(key, skylarkToAdd);
uncheckedAddAll(key, toAdd, this.items);
if (ObjcProvider.KEYS_FOR_DIRECT.contains(key)) {
uncheckedAddAllDirect(key, toAdd, this.directItems);
}
}

/**
Expand Down Expand Up @@ -1203,7 +1279,8 @@ public ObjcProvider build() {
starlarkSemantics,
propagatedBuilder.build(),
nonPropagatedBuilder.build(),
strictDependencyBuilder.build());
strictDependencyBuilder.build(),
directItems.build());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;

Expand Down Expand Up @@ -97,6 +98,14 @@ public interface ObjcProviderApi<FileApiT extends FileApi> extends SkylarkValue
)
public NestedSet<FileApiT> header();

@SkylarkCallable(
name = "direct_headers",
structField = true,
doc =
"Header files from this target directly (no transitive headers). "
+ "These may be either public or private headers.")
public SkylarkList<FileApiT> directHeaders();

@SkylarkCallable(name = "imported_library",
structField = true,
doc = "Imported precompiled static libraries (.a files) to be linked into the binary."
Expand Down Expand Up @@ -183,6 +192,14 @@ public interface ObjcProviderApi<FileApiT extends FileApi> extends SkylarkValue
)
public NestedSet<FileApiT> moduleMap();

@SkylarkCallable(
name = "direct_module_maps",
structField = true,
doc =
"Module map files from this target directly (no transitive module maps). "
+ "Used to enforce proper use of private header files and for Swift compilation.")
public SkylarkList<FileApiT> directModuleMaps();

@SkylarkCallable(name = "multi_arch_dynamic_libraries",
structField = true,
doc = "Combined-architecture dynamic libraries to include in the final bundle."
Expand Down Expand Up @@ -227,6 +244,12 @@ public interface ObjcProviderApi<FileApiT extends FileApi> extends SkylarkValue
)
public NestedSet<FileApiT> source();

@SkylarkCallable(
name = "direct_sources",
structField = true,
doc = "All direct source files from this target (no transitive files).")
public SkylarkList<FileApiT> directSources();

@SkylarkCallable(
name = "static_framework_file",
structField = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
import com.google.devtools.build.lib.skylarkbuildapi.apple.ObjcProviderApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;

/**
Expand Down Expand Up @@ -70,6 +71,11 @@ public NestedSet<FileApi> header() {
return null;
}

@Override
public SkylarkList<FileApi> directHeaders() {
return null;
}

@Override
public NestedSet<FileApi> importedLibrary() {
return null;
Expand Down Expand Up @@ -135,6 +141,11 @@ public NestedSet<FileApi> moduleMap() {
return null;
}

@Override
public SkylarkList<FileApi> directModuleMaps() {
return null;
}

@Override
public NestedSet<FileApi> multiArchDynamicLibraries() {
return null;
Expand Down Expand Up @@ -170,6 +181,11 @@ public NestedSet<FileApi> source() {
return null;
}

@Override
public SkylarkList<FileApi> directSources() {
return null;
}

@Override
public NestedSet<FileApi> staticFrameworkFile() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/rules/cpp",
"//src/main/java/com/google/devtools/build/lib/rules/objc",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
"//src/main/java/com/google/devtools/common/options",
"//src/main/protobuf:bundlemerge_java_proto",
"//src/main/protobuf:plmerge_java_proto",
Expand Down
Loading

0 comments on commit 5ba7cf6

Please sign in to comment.