From 21f2a492f24914f80ffbb6e46ce050760b2bdc96 Mon Sep 17 00:00:00 2001 From: Peter Schmitt Date: Wed, 3 Jun 2015 15:44:23 +0000 Subject: Allow objc_{library,binary} to depend on cc_library. This is an early version of support for this feature, likely still missing a number of edge cases. However the basic functionality should work. To allow a dependency from objc to cc, the following flags will have to be passed to bazel: --experimental_enable_objc_cc_deps --cpu=ios_i386 --crosstool_top=//tools/objc/crosstool:crosstool The feature is also compatible with --ios_multi_cpus, with the familiar values for --ios_cpu (i386, x86_64, armv7, arm64; passed instead of --cpu above). This CL does not contain any Xcode support for CC dependencies yet, they will just not show up in the generated Xcode project. (Second submission after earlier accidental submit before this CL was ready). -- MOS_MIGRATED_REVID=95110081 --- .../lib/rules/objc/BinaryLinkingTargetFactory.java | 6 ++++ .../build/lib/rules/objc/CompilationSupport.java | 22 +++++++++++--- .../lib/rules/objc/ObjcCommandLineOptions.java | 7 +++++ .../devtools/build/lib/rules/objc/ObjcCommon.java | 30 +++++++++++++++++++ .../devtools/build/lib/rules/objc/ObjcLibrary.java | 6 ++++ .../build/lib/rules/objc/ObjcProvider.java | 8 ++++- .../build/lib/rules/objc/ObjcRuleClasses.java | 3 +- .../lib/rules/objc/ReleaseBundlingSupport.java | 34 +++++++++++++--------- 8 files changed, 97 insertions(+), 19 deletions(-) (limited to 'src/main/java/com/google') diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java index 9d165b561d..b59bbe30c9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java @@ -29,6 +29,8 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.RunfilesSupport; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; +import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; +import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; @@ -169,6 +171,10 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory .setCompilationArtifacts(compilationArtifacts) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) .addDepObjcProviders(ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class)) + .addDepCcHeaderProviders( + ruleContext.getPrerequisites("deps", Mode.TARGET, CppCompilationContext.class)) + .addDepCcLinkProviders( + ruleContext.getPrerequisites("deps", Mode.TARGET, CcLinkParamsProvider.class)) .addDepObjcProviders( ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) .addNonPropagatedDepObjcProviders( diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 0f9bbcc67e..bfd4b1819c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -49,6 +49,7 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.FileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.rules.cpp.LinkerInputs; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder; import com.google.devtools.build.lib.shell.ShellUtils; @@ -78,6 +79,8 @@ final class CompilationSupport { static final ImmutableList CLANG_COVERAGE_FLAGS = ImmutableList.of("-fprofile-arcs", "-ftest-coverage", "-fprofile-dir=./coverage_output"); + private static final String FRAMEWORK_SUFFIX = ".framework"; + /** * Iterable wrapper providing strong type safety for arguments to binary linking. */ @@ -282,27 +285,37 @@ final class CompilationSupport { Artifact linkedBinary = ObjcRuleClasses.intermediateArtifacts(ruleContext).singleArchitectureBinary(); + ImmutableList ccLibraries = ccLibraries(objcProvider); ruleContext.registerAction( ObjcRuleClasses.spawnOnDarwinActionBuilder() .setMnemonic("ObjcLink") .setShellCommand(ImmutableList.of("/bin/bash", "-c")) - .setCommandLine(linkCommandLine(extraLinkArgs, objcProvider, linkedBinary, dsymBundle)) + .setCommandLine( + linkCommandLine(extraLinkArgs, objcProvider, linkedBinary, dsymBundle, ccLibraries)) .addOutput(linkedBinary) .addOutputs(dsymBundle.asSet()) .addTransitiveInputs(objcProvider.get(LIBRARY)) .addTransitiveInputs(objcProvider.get(IMPORTED_LIBRARY)) .addTransitiveInputs(objcProvider.get(FRAMEWORK_FILE)) + .addInputs(ccLibraries) .addInputs(extraLinkInputs) .build(ruleContext)); } - private static final String FRAMEWORK_SUFFIX = ".framework"; + private ImmutableList ccLibraries(ObjcProvider objcProvider) { + ImmutableList.Builder ccLibraryBuilder = ImmutableList.builder(); + for (LinkerInputs.LibraryToLink libraryToLink : objcProvider.get(ObjcProvider.CC_LIBRARY)) { + ccLibraryBuilder.add(libraryToLink.getArtifact()); + } + return ccLibraryBuilder.build(); + } private CommandLine linkCommandLine(ExtraLinkArgs extraLinkArgs, - ObjcProvider objcProvider, Artifact linkedBinary, Optional dsymBundle) { + ObjcProvider objcProvider, Artifact linkedBinary, Optional dsymBundle, + ImmutableList ccLibraries) { ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); - final CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); + CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); if (objcProvider.is(USES_CPP)) { commandLine @@ -322,6 +335,7 @@ final class CompilationSupport { .addExecPath("-o", linkedBinary) .addExecPaths(objcProvider.get(LIBRARY)) .addExecPaths(objcProvider.get(IMPORTED_LIBRARY)) + .addExecPaths(ccLibraries) .add(dylibPaths(objcProvider)) .addBeforeEach("-force_load", Artifact.toExecPaths(objcProvider.get(FORCE_LOAD_LIBRARY))) .add(extraLinkArgs) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java index 9d9d1735bb..6e926bc4c5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java @@ -129,6 +129,13 @@ public class ObjcCommandLineOptions extends FragmentOptions { help = "Whether to add include path entries for every individual proto file.") public boolean perProtoIncludes; + @Option(name = "experimental_enable_objc_cc_deps", + defaultValue = "false", + category = "undocumented", + help = "Allows objc_* rules to depend on cc_library and causes any objc dependencies to be " + + "built with --cpu set to \"ios_<--ios_cpu>\" for any values in --ios_multi_cpu.") + public boolean enableCcDeps; + // This option exists because two configurations are not allowed to have the same cache key // (partially derived from options). Since we have multiple transitions (see // getPotentialSplitTransitions below) that may result in the same configuration values at runtime diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java index e3ed076467..e311bc3473 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java @@ -18,6 +18,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.ASSET_CATALO import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BREAKPAD_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_IMPORT_DIR; +import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FLAG; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_FOR_XCODEGEN; @@ -57,6 +58,8 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.rules.cpp.CcCommon; +import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; +import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.util.RegexFilter; import com.google.devtools.build.lib.vfs.PathFragment; @@ -237,6 +240,8 @@ public final class ObjcCommon { private Iterable extraImportLibraries = ImmutableList.of(); private Optional linkedBinary = Optional.absent(); private Optional breakpadFile = Optional.absent(); + private Iterable depCcHeaderProviders = ImmutableList.of(); + private Iterable depCcLinkProviders = ImmutableList.of(); Builder(RuleContext context) { this.context = Preconditions.checkNotNull(context); @@ -354,6 +359,22 @@ public final class ObjcCommon { return this; } + /** + * Sets information from {@code cc_library} dependencies to be used during compilation. + */ + public Builder addDepCcHeaderProviders(Iterable depCcHeaderProviders) { + this.depCcHeaderProviders = Iterables.concat(this.depCcHeaderProviders, depCcHeaderProviders); + return this; + } + + /** + * Sets information from {@code cc_library} dependencies to be used during linking. + */ + public Builder addDepCcLinkProviders(Iterable depCcLinkProviders) { + this.depCcLinkProviders = Iterables.concat(this.depCcLinkProviders, depCcLinkProviders); + return this; + } + ObjcCommon build() { Iterable bundleImports = BundleableFile.bundleImportsFromRule(context); @@ -373,6 +394,15 @@ public final class ObjcCommon { .addTransitiveAndPropagate(depObjcProviders) .addTransitiveWithoutPropagating(directDepObjcProviders); + for (CppCompilationContext headerProvider : depCcHeaderProviders) { + // TODO(bazel-team): Also account for custom include settings to go into header search paths + objcProvider.addTransitiveAndPropagate(HEADER, headerProvider.getDeclaredIncludeSrcs()); + } + for (CcLinkParamsProvider linkProvider : depCcLinkProviders) { + objcProvider.addTransitiveAndPropagate( + CC_LIBRARY, linkProvider.getCcLinkParams(true, false).getLibraries()); + } + if (compilationAttributes.isPresent()) { CompilationAttributes attributes = compilationAttributes.get(); ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(context); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java index 6b40bdc5e2..98f4fe9597 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java @@ -24,6 +24,8 @@ import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.Type; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; +import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; +import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; @@ -68,6 +70,10 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class)) .addNonPropagatedDepObjcProviders(ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class)) + .addDepCcHeaderProviders( + ruleContext.getPrerequisites("deps", Mode.TARGET, CppCompilationContext.class)) + .addDepCcLinkProviders( + ruleContext.getPrerequisites("deps", Mode.TARGET, CcLinkParamsProvider.class)) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) .setAlwayslink(alwayslink) .addExtraImportLibraries(extraImportLibraries) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java index ce344cf44b..e2fc6e9363 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java @@ -27,6 +27,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.rules.cpp.LinkerInputs; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.TargetControl; @@ -159,7 +160,7 @@ public final class ObjcProvider implements TransitiveInfoProvider { public static final Key NESTED_BUNDLE = new Key<>(STABLE_ORDER); /** - * Artifact containing information on debug symbols + * Artifact containing information on debug symbols. */ public static final Key DEBUG_SYMBOLS = new Key<>(STABLE_ORDER); @@ -184,6 +185,11 @@ public final class ObjcProvider implements TransitiveInfoProvider { */ public static final Key STRINGS = new Key<>(STABLE_ORDER); + /** + * Linking information from cc dependencies. + */ + public static final Key CC_LIBRARY = new Key<>(LINK_ORDER); + /** * Flags that apply to a transitive build dependency tree. Each item in the enum corresponds to a * flag. If the item is included in the key {@link #FLAG}, then the flag is considered set. diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java index 8342374937..dec8cc582c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java @@ -544,7 +544,8 @@ public class ObjcRuleClasses { "objc_import", "objc_framework", "objc_proto_library", - "j2objc_library"); + "j2objc_library", + "cc_library"); @Override public RuleClass build(Builder builder, RuleDefinitionEnvironment env) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java index 975600f5ca..0ae5036211 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java @@ -37,6 +37,7 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; +import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; @@ -246,19 +247,19 @@ public final class ReleaseBundlingSupport { + "\n" + "EOF\n" - + "if [[ -n \"${VERSION}\" ]]; then\n" - + " for KEY in CFBundleVersion CFBundleShortVersionString; do\n" - + " echo \" ${KEY}\n\" >> " - + getGeneratedVersionPlist().getExecPathString() + "\n" - + " echo \" ${VERSION}\n\" >> " - + getGeneratedVersionPlist().getExecPathString() + "\n" - + " done\n" - + "fi\n" - - + "cat >>" + getGeneratedVersionPlist().getExecPathString() + " <\n" - + "\n" - + "EOF\n" + + "if [[ -n \"${VERSION}\" ]]; then\n" + + " for KEY in CFBundleVersion CFBundleShortVersionString; do\n" + + " echo \" ${KEY}\n\" >> " + + getGeneratedVersionPlist().getExecPathString() + "\n" + + " echo \" ${VERSION}\n\" >> " + + getGeneratedVersionPlist().getExecPathString() + "\n" + + " done\n" + + "fi\n" + + + "cat >>" + getGeneratedVersionPlist().getExecPathString() + " <\n" + + "\n" + + "EOF\n" ) .build()) .addInput(buildInfo) @@ -831,6 +832,13 @@ public final class ReleaseBundlingSupport { private void setArchitectureOptions(BuildOptions splitOptions, String iosCpu) { splitOptions.get(ObjcCommandLineOptions.class).iosSplitCpu = iosCpu; splitOptions.get(ObjcCommandLineOptions.class).iosCpu = iosCpu; + if (splitOptions.get(ObjcCommandLineOptions.class).enableCcDeps) { + // Only set the (CC-compilation) CPU for dependencies if explicitly required by the user. + // This helps users of the iOS rules who do not depend on CC rules as these CPU values + // require additional flags to work (e.g. a custom crosstool) which now only need to be set + // if this feature is explicitly requested. + splitOptions.get(BuildConfiguration.Options.class).cpu = "ios_" + iosCpu; + } } @Override -- cgit v1.2.3