blob: b5d532a100aad9634b8f5bd5070f1cc1ccdbe337 [file] [log] [blame]
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.objc;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType;
import com.google.devtools.build.lib.rules.apple.DottedVersion;
import com.google.devtools.build.lib.rules.cpp.HeaderDiscovery;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import javax.annotation.Nullable;
/** A compiler configuration containing flags required for Objective-C compilation. */
@AutoCodec
@SkylarkModule(
name = "objc",
category = SkylarkModuleCategory.CONFIGURATION_FRAGMENT,
doc = "A configuration fragment for Objective-C."
)
@Immutable
public class ObjcConfiguration extends BuildConfiguration.Fragment {
@VisibleForTesting
static final ImmutableList<String> DBG_COPTS =
ImmutableList.of("-O0", "-DDEBUG=1", "-fstack-protector", "-fstack-protector-all", "-g");
@VisibleForTesting
static final ImmutableList<String> GLIBCXX_DBG_COPTS =
ImmutableList.of(
"-D_GLIBCXX_DEBUG", "-D_GLIBCXX_DEBUG_PEDANTIC", "-D_GLIBCPP_CONCEPT_CHECKS");
@VisibleForTesting
static final ImmutableList<String> OPT_COPTS =
ImmutableList.of(
"-Os", "-DNDEBUG=1", "-Wno-unused-variable", "-Winit-self", "-Wno-extra");
private final DottedVersion iosSimulatorVersion;
private final String iosSimulatorDevice;
private final DottedVersion watchosSimulatorVersion;
private final String watchosSimulatorDevice;
private final DottedVersion tvosSimulatorVersion;
private final String tvosSimulatorDevice;
private final boolean generateDsym;
private final boolean generateLinkmap;
private final boolean runMemleaks;
private final ImmutableList<String> copts;
private final CompilationMode compilationMode;
private final ImmutableList<String> fastbuildOptions;
private final boolean enableBinaryStripping;
private final boolean moduleMapsEnabled;
@Nullable private final String signingCertName;
private final boolean debugWithGlibcxx;
@Nullable private final Label extraEntitlements;
private final boolean deviceDebugEntitlements;
private final boolean enableAppleBinaryNativeProtos;
private final HeaderDiscovery.DotdPruningMode dotdPruningPlan;
private final boolean experimentalHeaderThinning;
private final int objcHeaderThinningPartitionSize;
private final Label objcHeaderScannerTool;
private final Label appleSdk;
private final boolean strictObjcModuleMaps;
ObjcConfiguration(ObjcCommandLineOptions objcOptions, BuildConfiguration.Options options) {
this.iosSimulatorDevice =
Preconditions.checkNotNull(objcOptions.iosSimulatorDevice, "iosSimulatorDevice");
this.iosSimulatorVersion =
Preconditions.checkNotNull(objcOptions.iosSimulatorVersion, "iosSimulatorVersion");
this.watchosSimulatorDevice =
Preconditions.checkNotNull(objcOptions.watchosSimulatorDevice, "watchosSimulatorDevice");
this.watchosSimulatorVersion =
Preconditions.checkNotNull(objcOptions.watchosSimulatorVersion, "watchosSimulatorVersion");
this.tvosSimulatorDevice =
Preconditions.checkNotNull(objcOptions.tvosSimulatorDevice, "tvosSimulatorDevice");
this.tvosSimulatorVersion =
Preconditions.checkNotNull(objcOptions.tvosSimulatorVersion, "tvosSimulatorVersion");
this.generateDsym = objcOptions.appleGenerateDsym;
this.generateLinkmap = objcOptions.generateLinkmap;
this.runMemleaks = objcOptions.runMemleaks;
this.copts = ImmutableList.copyOf(objcOptions.copts);
this.compilationMode = Preconditions.checkNotNull(options.compilationMode, "compilationMode");
this.fastbuildOptions = ImmutableList.copyOf(objcOptions.fastbuildOptions);
this.enableBinaryStripping = objcOptions.enableBinaryStripping;
this.moduleMapsEnabled = objcOptions.enableModuleMaps;
this.signingCertName = objcOptions.iosSigningCertName;
this.debugWithGlibcxx = objcOptions.debugWithGlibcxx;
this.extraEntitlements = objcOptions.extraEntitlements;
this.deviceDebugEntitlements = objcOptions.deviceDebugEntitlements;
this.enableAppleBinaryNativeProtos = objcOptions.enableAppleBinaryNativeProtos;
this.dotdPruningPlan =
objcOptions.useDotdPruning
? HeaderDiscovery.DotdPruningMode.USE
: HeaderDiscovery.DotdPruningMode.DO_NOT_USE;
this.experimentalHeaderThinning = objcOptions.experimentalObjcHeaderThinning;
this.objcHeaderThinningPartitionSize = objcOptions.objcHeaderThinningPartitionSize;
this.objcHeaderScannerTool = objcOptions.objcHeaderScannerTool;
this.appleSdk = objcOptions.appleSdk;
this.strictObjcModuleMaps = objcOptions.strictObjcModuleMaps;
}
@AutoCodec.Instantiator
ObjcConfiguration(
DottedVersion iosSimulatorVersion,
String iosSimulatorDevice,
DottedVersion watchosSimulatorVersion,
String watchosSimulatorDevice,
DottedVersion tvosSimulatorVersion,
String tvosSimulatorDevice,
boolean generateDsym,
boolean generateLinkmap,
boolean runMemleaks,
ImmutableList<String> copts,
CompilationMode compilationMode,
ImmutableList<String> fastbuildOptions,
boolean enableBinaryStripping,
boolean moduleMapsEnabled,
String signingCertName,
boolean debugWithGlibcxx,
Label extraEntitlements,
boolean deviceDebugEntitlements,
boolean enableAppleBinaryNativeProtos,
HeaderDiscovery.DotdPruningMode dotdPruningPlan,
boolean experimentalHeaderThinning,
int objcHeaderThinningPartitionSize,
Label objcHeaderScannerTool,
Label appleSdk,
boolean strictObjcModuleMaps) {
this.iosSimulatorVersion = iosSimulatorVersion;
this.iosSimulatorDevice = iosSimulatorDevice;
this.watchosSimulatorVersion = watchosSimulatorVersion;
this.watchosSimulatorDevice = watchosSimulatorDevice;
this.tvosSimulatorVersion = tvosSimulatorVersion;
this.tvosSimulatorDevice = tvosSimulatorDevice;
this.generateDsym = generateDsym;
this.generateLinkmap = generateLinkmap;
this.runMemleaks = runMemleaks;
this.copts = copts;
this.compilationMode = compilationMode;
this.fastbuildOptions = fastbuildOptions;
this.enableBinaryStripping = enableBinaryStripping;
this.moduleMapsEnabled = moduleMapsEnabled;
this.signingCertName = signingCertName;
this.debugWithGlibcxx = debugWithGlibcxx;
this.extraEntitlements = extraEntitlements;
this.deviceDebugEntitlements = deviceDebugEntitlements;
this.enableAppleBinaryNativeProtos = enableAppleBinaryNativeProtos;
this.dotdPruningPlan = dotdPruningPlan;
this.experimentalHeaderThinning = experimentalHeaderThinning;
this.objcHeaderThinningPartitionSize = objcHeaderThinningPartitionSize;
this.objcHeaderScannerTool = objcHeaderScannerTool;
this.appleSdk = appleSdk;
this.strictObjcModuleMaps = strictObjcModuleMaps;
}
/**
* Returns the type of device (e.g. 'iPhone 6') to simulate when running on the simulator.
*/
@SkylarkCallable(name = "ios_simulator_device", structField = true,
doc = "The type of device (e.g. 'iPhone 6') to use when running on the simulator.")
public String getIosSimulatorDevice() {
// TODO(bazel-team): Deprecate in favor of getSimulatorDeviceForPlatformType(IOS).
return iosSimulatorDevice;
}
@SkylarkCallable(name = "ios_simulator_version", structField = true,
doc = "The SDK version of the iOS simulator to use when running on the simulator.")
public DottedVersion getIosSimulatorVersion() {
// TODO(bazel-team): Deprecate in favor of getSimulatorVersionForPlatformType(IOS).
return iosSimulatorVersion;
}
@SkylarkCallable(
name = "simulator_device_for_platform_type",
doc = "The type of device (e.g., 'iPhone 6' to simulate when running on the simulator.")
public String getSimulatorDeviceForPlatformType(PlatformType platformType) {
switch (platformType) {
case IOS:
return iosSimulatorDevice;
case TVOS:
return tvosSimulatorDevice;
case WATCHOS:
return watchosSimulatorDevice;
default:
throw new IllegalArgumentException(
"ApplePlatform type " + platformType + " does not support " + "simulators.");
}
}
@SkylarkCallable(
name = "simulator_version_for_platform_type",
doc = "The SDK version of the simulator to use when running on the simulator.")
public DottedVersion getSimulatorVersionForPlatformType(PlatformType platformType) {
switch (platformType) {
case IOS:
return iosSimulatorVersion;
case TVOS:
return tvosSimulatorVersion;
case WATCHOS:
return watchosSimulatorVersion;
default:
throw new IllegalArgumentException(
"ApplePlatform type " + platformType + " does not support " + "simulators.");
}
}
/**
* Returns whether dSYM generation is enabled.
*/
@SkylarkCallable(
name = "generate_dsym",
doc = "Whether to generate debug symbol(.dSYM) artifacts.",
structField = true)
public boolean generateDsym() {
return generateDsym;
}
/**
* Returns whether linkmap generation is enabled.
*/
@SkylarkCallable(
name = "generate_linkmap",
doc = "Whether to generate linkmap artifacts.",
structField = true)
public boolean generateLinkmap() {
return generateLinkmap;
}
@SkylarkCallable(
name = "run_memleaks",
structField = true,
doc = "Returns a boolean indicating whether memleaks should be run during tests or not."
)
public boolean runMemleaks() {
return runMemleaks;
}
/**
* Returns the current compilation mode.
*/
public CompilationMode getCompilationMode() {
return compilationMode;
}
/**
* Returns the default set of clang options for the current compilation mode.
*/
@SkylarkCallable(name = "copts_for_current_compilation_mode", structField = true,
doc = "Returns a list of default options to use for compiling Objective-C in the current "
+ "mode.")
public ImmutableList<String> getCoptsForCompilationMode() {
switch (compilationMode) {
case DBG:
if (this.debugWithGlibcxx) {
return ImmutableList.<String>builder()
.addAll(DBG_COPTS)
.addAll(GLIBCXX_DBG_COPTS)
.build();
} else {
return DBG_COPTS;
}
case FASTBUILD:
return fastbuildOptions;
case OPT:
return OPT_COPTS;
default:
throw new AssertionError();
}
}
/**
* Returns options passed to (Apple) clang when compiling Objective C. These options should be
* applied after any default options but before options specified in the attributes of the rule.
*/
@SkylarkCallable(name = "copts", structField = true,
doc = "Returns a list of options to use for compiling Objective-C."
+ "These options are applied after any default options but before options specified in the "
+ "attributes of the rule.")
public ImmutableList<String> getCopts() {
return copts;
}
/**
* Whether module map generation and interpretation is enabled.
*/
public boolean moduleMapsEnabled() {
return moduleMapsEnabled;
}
/**
* Returns whether to perform symbol and dead-code strippings on linked binaries. The strippings
* are performed iff --compilation_mode=opt and --objc_enable_binary_stripping are specified.
*/
public boolean shouldStripBinary() {
return this.enableBinaryStripping && getCompilationMode() == CompilationMode.OPT;
}
/**
* Returns the flag-supplied certificate name to be used in signing or {@code null} if no such
* certificate was specified.
*/
@Nullable
@SkylarkCallable(name = "signing_certificate_name", structField = true, allowReturnNones = true,
doc = "Returns the flag-supplied certificate name to be used in signing, or None if no such "
+ "certificate was specified.")
public String getSigningCertName() {
return this.signingCertName;
}
/**
* Returns the extra entitlements plist specified as a flag or {@code null} if none was given.
*/
@Nullable
public Label getExtraEntitlements() {
return extraEntitlements;
}
/**
* Returns whether device debug entitlements should be included when signing an application.
*
* <p>Note that debug entitlements will be included only if the --device_debug_entitlements flag
* is set <b>and</b> the compilation mode is not {@code opt}.
*/
@SkylarkCallable(name = "uses_device_debug_entitlements", structField = true,
doc = "Returns whether device debug entitlements should be included when signing an "
+ "application.")
public boolean useDeviceDebugEntitlements() {
return deviceDebugEntitlements && compilationMode != CompilationMode.OPT;
}
/** Returns true if apple_binary targets should generate and link Objc protos. */
@SkylarkCallable(name = "enable_apple_binary_native_protos", structField = true,
doc = "Returns whether apple_binary should generate and link protos natively.")
public boolean enableAppleBinaryNativeProtos() {
return enableAppleBinaryNativeProtos;
}
/** Returns the DotdPruningPlan for compiles in this build. */
public HeaderDiscovery.DotdPruningMode getDotdPruningPlan() {
return dotdPruningPlan;
}
/** Returns true if header thinning of ObjcCompile actions is enabled to reduce action inputs. */
public boolean useExperimentalHeaderThinning() {
return experimentalHeaderThinning;
}
/** Returns the max number of source files to add to each header scanning action. */
public int objcHeaderThinningPartitionSize() {
return objcHeaderThinningPartitionSize;
}
/** Returns the label for the ObjC header scanner tool. */
public Label getObjcHeaderScannerTool() {
return objcHeaderScannerTool;
}
/** Returns the label for the Apple SDK for current build configuration. */
public Label getAppleSdk() {
return appleSdk;
}
/** Returns true if Objective-C module maps should only be propagated to direct dependencies. */
public boolean useStrictObjcModuleMaps() {
return strictObjcModuleMaps;
}
}