blob: 62168a4500a6e14be71fe7f3595cc021fd0b3306 [file] [log] [blame]
// Copyright 2015 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 static com.google.devtools.build.lib.actions.Artifact.IS_TREE_ARTIFACT;
import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.rules.objc.XcodeProductType.LIBRARY_STATIC;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.PopulateTreeArtifactAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.AppleToolchain;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaGenJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaHelper;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
import com.google.devtools.build.lib.rules.java.Jvm;
import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraCompileArgs;
import com.google.devtools.build.lib.rules.objc.J2ObjcSource.SourceType;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
/**
* J2ObjC transpilation aspect for Java rules.
*/
public class J2ObjcAspect extends NativeAspectClass implements ConfiguredAspectFactory {
public static final String NAME = "J2ObjcAspect";
private final String toolsRepository;
private final BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect;
private static final ExtraCompileArgs EXTRA_COMPILE_ARGS = new ExtraCompileArgs(
"-fno-strict-overflow");
public J2ObjcAspect(String toolsRepository, BazelJ2ObjcProtoAspect bazelJ2ObjcProtoAspect) {
this.toolsRepository = toolsRepository;
this.bazelJ2ObjcProtoAspect = bazelJ2ObjcProtoAspect;
}
private static final Iterable<Attribute> DEPENDENT_ATTRIBUTES = ImmutableList.of(
new Attribute(":jre_lib", Mode.TARGET),
new Attribute("deps", Mode.TARGET),
new Attribute("exports", Mode.TARGET),
new Attribute("runtime_deps", Mode.TARGET));
private static final Label JRE_CORE_LIB =
Label.parseAbsoluteUnchecked("//third_party/java/j2objc:jre_core_lib");
private static final Label JRE_EMUL_LIB =
Label.parseAbsoluteUnchecked("//third_party/java/j2objc:jre_emul_lib");
private static final LateBoundLabel<BuildConfiguration> JRE_LIB =
new LateBoundLabel<BuildConfiguration>(JRE_CORE_LIB, J2ObjcConfiguration.class) {
@Override
public Label resolve(Rule rule, AttributeMap attributes, BuildConfiguration configuration) {
return configuration.getFragment(J2ObjcConfiguration.class).explicitJreDeps()
? JRE_CORE_LIB : JRE_EMUL_LIB;
}
};
/**
* Adds additional attribute aspects and attributes to the given AspectDefinition.Builder.
*/
protected AspectDefinition.Builder addAdditionalAttributes(
AspectDefinition.Builder builder) {
return builder.attributeAspect("deps", this, bazelJ2ObjcProtoAspect)
.attributeAspect("exports", this, bazelJ2ObjcProtoAspect)
.attributeAspect("runtime_deps", this, bazelJ2ObjcProtoAspect);
}
@Override
public AspectDefinition getDefinition(AspectParameters aspectParameters) {
return addAdditionalAttributes(new AspectDefinition.Builder("J2ObjCAspect"))
.requireProvider(JavaSourceInfoProvider.class)
.requireProvider(JavaCompilationArgsProvider.class)
.requiresConfigurationFragments(
AppleConfiguration.class,
J2ObjcConfiguration.class,
ObjcConfiguration.class)
.requiresHostConfigurationFragments(Jvm.class)
.add(attr("$j2objc", LABEL).cfg(HOST).exec()
.value(Label.parseAbsoluteUnchecked(
toolsRepository + "//tools/j2objc:j2objc_deploy.jar")))
.add(attr("$j2objc_wrapper", LABEL)
.allowedFileTypes(FileType.of(".py"))
.cfg(HOST)
.exec()
.singleArtifact()
.value(Label.parseAbsoluteUnchecked(
toolsRepository + "//tools/j2objc:j2objc_wrapper")))
.add(attr("$jre_emul_jar", LABEL).cfg(HOST)
.value(Label.parseAbsoluteUnchecked(
toolsRepository + "//third_party/java/j2objc:jre_emul.jar")))
.add(attr(":jre_lib", LABEL).value(JRE_LIB))
.add(attr("$xcrunwrapper", LABEL).cfg(HOST).exec()
.value(Label.parseAbsoluteUnchecked(
toolsRepository + "//tools/objc:xcrunwrapper")))
.add(attr(ObjcRuleClasses.LIBTOOL_ATTRIBUTE, LABEL).cfg(HOST).exec()
.value(Label.parseAbsoluteUnchecked(
toolsRepository + "//tools/objc:libtool")))
.add(attr(":xcode_config", LABEL)
.allowedRuleClasses("xcode_config")
.checkConstraints()
.direct_compile_time_input()
.cfg(HOST)
.value(new AppleToolchain.XcodeConfigLabel(toolsRepository)))
.add(attr("$zipper", LABEL)
.cfg(HOST)
.exec()
.value(Label.parseAbsoluteUnchecked(toolsRepository + "//tools/zip:zipper")))
.build();
}
@Override
public ConfiguredAspect create(
ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters)
throws InterruptedException {
ConfiguredAspect.Builder builder = new ConfiguredAspect.Builder(NAME, ruleContext);
JavaCompilationArgsProvider compilationArgsProvider =
base.getProvider(JavaCompilationArgsProvider.class);
JavaSourceInfoProvider sourceInfoProvider =
base.getProvider(JavaSourceInfoProvider.class);
JavaGenJarsProvider genJarProvider =
base.getProvider(JavaGenJarsProvider.class);
ImmutableSet<Artifact> javaInputFiles = ImmutableSet.<Artifact>builder()
.addAll(sourceInfoProvider.getSourceFiles())
.addAll(sourceInfoProvider.getSourceJars())
.addAll(sourceInfoProvider.getSourceJarsForJarFiles())
.build();
Optional<Artifact> genSrcJar;
boolean annotationProcessingEnabled = ruleContext.getFragment(J2ObjcConfiguration.class)
.annotationProcessingEnabled();
if (genJarProvider != null && annotationProcessingEnabled) {
genSrcJar = Optional.fromNullable(genJarProvider.getGenSourceJar());
} else {
genSrcJar = Optional.<Artifact>absent();
}
XcodeProvider xcodeProvider;
ObjcCommon common;
if (!javaInputFiles.isEmpty()) {
J2ObjcSource j2ObjcSource = buildJ2ObjcSource(ruleContext, javaInputFiles, genSrcJar);
J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider =
depJ2ObjcMappingFileProvider(ruleContext);
createJ2ObjcTranspilationAction(
ruleContext,
depJ2ObjcMappingFileProvider.getHeaderMappingFiles(),
depJ2ObjcMappingFileProvider.getClassMappingFiles(),
javaInputFiles,
compilationArgsProvider,
j2ObjcSource,
genSrcJar);
boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class)
.zipTreeArtifact();
if (genSrcJar.isPresent() && zipTreeArtifact) {
for (Action action : genJarTreeArtifactCreationActions(ruleContext)) {
ruleContext.registerAction(action);
}
}
common = common(
ruleContext,
j2ObjcSource.getObjcSrcs(),
j2ObjcSource.getObjcHdrs(),
j2ObjcSource.getHeaderSearchPaths(),
DEPENDENT_ATTRIBUTES);
xcodeProvider = xcodeProvider(
ruleContext,
common,
j2ObjcSource.getObjcHdrs(),
j2ObjcSource.getHeaderSearchPaths(),
DEPENDENT_ATTRIBUTES);
new CompilationSupport(ruleContext)
.registerCompileAndArchiveActions(common, EXTRA_COMPILE_ARGS)
.registerFullyLinkAction(common.getObjcProvider());
} else {
common = common(
ruleContext,
ImmutableList.<Artifact>of(),
ImmutableList.<Artifact>of(),
ImmutableList.<PathFragment>of(),
DEPENDENT_ATTRIBUTES);
xcodeProvider = xcodeProvider(
ruleContext,
common,
ImmutableList.<Artifact>of(),
ImmutableList.<PathFragment>of(),
DEPENDENT_ATTRIBUTES);
}
return builder
.addProvider(j2ObjcMappingFileProvider(ruleContext, !javaInputFiles.isEmpty()))
.addProvider(common.getObjcProvider())
.addProvider(xcodeProvider)
.build();
}
private J2ObjcMappingFileProvider j2ObjcMappingFileProvider(RuleContext ruleContext,
boolean hasTranslatedSource) {
J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider =
depJ2ObjcMappingFileProvider(ruleContext);
J2ObjcMappingFileProvider j2ObjcMappingFileProvider = depJ2ObjcMappingFileProvider;
if (hasTranslatedSource) {
// J2ObjC merges all input header mapping files into the output header mapping file, so we
// only need to export the output header mapping file here.
NestedSet<Artifact> headerMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
.add(j2ObjcOutputHeaderMappingFile(ruleContext))
.build();
NestedSet<Artifact> dependencyMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
.add(j2ObjcOutputDependencyMappingFile(ruleContext))
.addTransitive(depJ2ObjcMappingFileProvider.getDependencyMappingFiles())
.build();
NestedSet<Artifact> archiveSourceMappingFiles = NestedSetBuilder.<Artifact>stableOrder()
.add(j2ObjcOutputArchiveSourceMappingFile(ruleContext))
.addTransitive(depJ2ObjcMappingFileProvider.getArchiveSourceMappingFiles())
.build();
j2ObjcMappingFileProvider = new J2ObjcMappingFileProvider(
headerMappingFiles,
depJ2ObjcMappingFileProvider.getClassMappingFiles(),
dependencyMappingFiles,
archiveSourceMappingFiles);
}
return j2ObjcMappingFileProvider;
}
private List<Artifact> genJarOutputs(RuleContext ruleContext) {
boolean zipTreeArtifact = ruleContext
.getFragment(J2ObjcConfiguration.class)
.zipTreeArtifact();
if (zipTreeArtifact) {
return ImmutableList.of(
j2ObjcGenJarSourceZip(ruleContext),
j2ObjcGenJarSourceZipManifest(ruleContext),
j2ObjcGenJarHeaderZip(ruleContext),
j2ObjcGenJarHeaderZipManifest(ruleContext));
} else {
return ImmutableList.of(
j2ObjcGenJarTranslatedSourceFiles(ruleContext),
j2objcGenJarTranslatedHeaderFiles(ruleContext));
}
}
private List<String> genJarFlags(RuleContext ruleContext) {
boolean zipTreeArtifact = ruleContext.getFragment(J2ObjcConfiguration.class).zipTreeArtifact();
if (zipTreeArtifact) {
return ImmutableList.of(
"--output_gen_source_zip", j2ObjcGenJarSourceZip(ruleContext).getExecPathString(),
"--output_gen_header_zip", j2ObjcGenJarHeaderZip(ruleContext).getExecPathString());
} else {
return ImmutableList.of(
"--output_gen_source_dir",
j2ObjcGenJarTranslatedSourceFiles(ruleContext).getExecPathString(),
"--output_gen_header_dir",
j2objcGenJarTranslatedHeaderFiles(ruleContext).getExecPathString());
}
}
private List<Action> genJarTreeArtifactCreationActions(RuleContext ruleContext) {
Artifact sourceFiles = j2ObjcGenJarTranslatedSourceFiles(ruleContext);
Artifact headerFiles = j2objcGenJarTranslatedHeaderFiles(ruleContext);
ImmutableList.Builder<Action> actions = ImmutableList.builder();
actions.add(new PopulateTreeArtifactAction(
ruleContext.getActionOwner(),
j2ObjcGenJarSourceZip(ruleContext),
j2ObjcGenJarSourceZipManifest(ruleContext),
sourceFiles,
ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST)));
actions.add(new PopulateTreeArtifactAction(
ruleContext.getActionOwner(),
j2ObjcGenJarHeaderZip(ruleContext),
j2ObjcGenJarHeaderZipManifest(ruleContext),
headerFiles,
ruleContext.getExecutablePrerequisite("$zipper", Mode.HOST)));
return actions.build();
}
private void createJ2ObjcTranspilationAction(
RuleContext ruleContext,
NestedSet<Artifact> depsHeaderMappingFiles,
NestedSet<Artifact> depsClassMappingFiles,
Iterable<Artifact> sources,
JavaCompilationArgsProvider compArgsProvider,
J2ObjcSource j2ObjcSource,
Optional<Artifact> genSrcJar) {
CustomCommandLine.Builder argBuilder = CustomCommandLine.builder();
PathFragment javaExecutable = ruleContext.getFragment(Jvm.class, HOST).getJavaExecutable();
argBuilder.add("--java").add(javaExecutable.getPathString());
Artifact j2ObjcDeployJar = ruleContext.getPrerequisiteArtifact("$j2objc", Mode.HOST);
argBuilder.addExecPath("--j2objc", j2ObjcDeployJar);
argBuilder.add("--main_class").add("com.google.devtools.j2objc.J2ObjC");
argBuilder.addJoinExecPaths(
"--translated_source_files",
",",
Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT)));
argBuilder.add("--objc_file_path").addPath(j2ObjcSource.getObjcFilePath());
Artifact outputDependencyMappingFile = j2ObjcOutputDependencyMappingFile(ruleContext);
argBuilder.addExecPath("--output_dependency_mapping_file", outputDependencyMappingFile);
ImmutableList.Builder<Artifact> genSrcOutputFiles = ImmutableList.builder();
if (genSrcJar.isPresent()) {
genSrcOutputFiles.addAll(genJarOutputs(ruleContext));
argBuilder.addExecPath("--gen_src_jar", genSrcJar.get());
argBuilder.add(genJarFlags(ruleContext));
}
Iterable<String> translationFlags = ruleContext
.getFragment(J2ObjcConfiguration.class)
.getTranslationFlags();
argBuilder.add(translationFlags);
if (!depsHeaderMappingFiles.isEmpty()) {
argBuilder.addJoinExecPaths("--header-mapping", ",", depsHeaderMappingFiles);
}
Artifact outputHeaderMappingFile = j2ObjcOutputHeaderMappingFile(ruleContext);
argBuilder.addExecPath("--output-header-mapping", outputHeaderMappingFile);
if (!depsClassMappingFiles.isEmpty()) {
argBuilder.addJoinExecPaths("--mapping", ",", depsClassMappingFiles);
}
Artifact archiveSourceMappingFile = j2ObjcOutputArchiveSourceMappingFile(ruleContext);
argBuilder.addExecPath("--output_archive_source_mapping_file", archiveSourceMappingFile);
Artifact compiledLibrary = ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext).archive();
argBuilder.addExecPath("--compiled_archive_file_path", compiledLibrary);
Artifact bootclasspathJar = ruleContext.getPrerequisiteArtifact("$jre_emul_jar", Mode.HOST);
argBuilder.add("-Xbootclasspath:" + bootclasspathJar.getExecPathString());
argBuilder.add("-d").addPath(j2ObjcSource.getObjcFilePath());
// In J2ObjC, the jars you pass as dependencies must be precisely the same as the
// jars used to transpile those dependencies--we cannot use ijars here.
NestedSet<Artifact> compileTimeJars =
compArgsProvider.getRecursiveJavaCompilationArgs().getRuntimeJars();
if (!compileTimeJars.isEmpty()) {
argBuilder.addJoinExecPaths("-classpath", ":", compileTimeJars);
}
argBuilder.addExecPaths(sources);
Artifact paramFile = j2ObjcOutputParamFile(ruleContext);
ruleContext.registerAction(new ParameterFileWriteAction(
ruleContext.getActionOwner(),
paramFile,
argBuilder.build(),
ParameterFile.ParameterFileType.UNQUOTED,
ISO_8859_1));
SpawnAction.Builder builder = new SpawnAction.Builder()
.setMnemonic("TranspilingJ2objc")
.setExecutable(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
.addInput(ruleContext.getPrerequisiteArtifact("$j2objc_wrapper", Mode.HOST))
.addInput(j2ObjcDeployJar)
.addInput(bootclasspathJar)
.addInputs(sources)
.addInputs(genSrcJar.asSet())
.addTransitiveInputs(compileTimeJars)
.addTransitiveInputs(JavaHelper.getHostJavabaseInputs(ruleContext))
.addTransitiveInputs(depsHeaderMappingFiles)
.addTransitiveInputs(depsClassMappingFiles)
.addInput(paramFile)
.setCommandLine(CustomCommandLine.builder()
.addPaths("@%s", paramFile.getExecPath())
.build())
.addOutputs(Iterables.filter(j2ObjcSource.getObjcSrcs(), Predicates.not(IS_TREE_ARTIFACT)))
.addOutputs(Iterables.filter(j2ObjcSource.getObjcHdrs(), Predicates.not(IS_TREE_ARTIFACT)))
.addOutputs(genSrcOutputFiles.build())
.addOutput(outputHeaderMappingFile)
.addOutput(outputDependencyMappingFile)
.addOutput(archiveSourceMappingFile);
ruleContext.registerAction(builder.build(ruleContext));
}
private J2ObjcMappingFileProvider depJ2ObjcMappingFileProvider(RuleContext ruleContext) {
NestedSetBuilder<Artifact> depsHeaderMappingsBuilder = NestedSetBuilder.stableOrder();
NestedSetBuilder<Artifact> depsClassMappingsBuilder = NestedSetBuilder.stableOrder();
NestedSetBuilder<Artifact> depsDependencyMappingsBuilder = NestedSetBuilder.stableOrder();
NestedSetBuilder<Artifact> depsArchiveSourceMappingsBuilder = NestedSetBuilder.stableOrder();
for (J2ObjcMappingFileProvider mapping : getJ2ObjCMappings(ruleContext)) {
depsHeaderMappingsBuilder.addTransitive(mapping.getHeaderMappingFiles());
depsClassMappingsBuilder.addTransitive(mapping.getClassMappingFiles());
depsDependencyMappingsBuilder.addTransitive(mapping.getDependencyMappingFiles());
depsArchiveSourceMappingsBuilder.addTransitive(mapping.getArchiveSourceMappingFiles());
}
return new J2ObjcMappingFileProvider(
depsHeaderMappingsBuilder.build(),
depsClassMappingsBuilder.build(),
depsDependencyMappingsBuilder.build(),
depsArchiveSourceMappingsBuilder.build());
}
private static List<? extends J2ObjcMappingFileProvider> getJ2ObjCMappings(RuleContext context) {
ImmutableList.Builder<J2ObjcMappingFileProvider> mappingFileProviderBuilder =
new ImmutableList.Builder<>();
addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "deps");
addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "runtime_deps");
addJ2ObjCMappingsForAttribute(mappingFileProviderBuilder, context, "exports");
return mappingFileProviderBuilder.build();
}
private static void addJ2ObjCMappingsForAttribute(
ImmutableList.Builder<J2ObjcMappingFileProvider> builder, RuleContext context,
String attributeName) {
if (context.attributes().has(attributeName, BuildType.LABEL_LIST)) {
for (TransitiveInfoCollection dependencyInfoDatum :
context.getPrerequisites(attributeName, Mode.TARGET)) {
J2ObjcMappingFileProvider provider =
dependencyInfoDatum.getProvider(J2ObjcMappingFileProvider.class);
if (provider != null) {
builder.add(provider);
}
}
}
}
private static Artifact j2ObjcOutputHeaderMappingFile(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".mapping.j2objc");
}
private static Artifact j2ObjcOutputDependencyMappingFile(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".dependency_mapping.j2objc");
}
private static Artifact j2ObjcOutputParamFile(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".param.j2objc");
}
private static Artifact j2ObjcOutputArchiveSourceMappingFile(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(
ruleContext, ".archive_source_mapping.j2objc");
}
private static Artifact j2ObjcGenJarTranslatedSourceFiles(RuleContext ruleContext) {
PathFragment rootRelativePath = ruleContext
.getUniqueDirectory("_j2objc/gen_jar_files")
.getRelative("source_files");
return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory());
}
private static Artifact j2objcGenJarTranslatedHeaderFiles(RuleContext ruleContext) {
PathFragment rootRelativePath = ruleContext
.getUniqueDirectory("_j2objc/gen_jar_files")
.getRelative("header_files");
return ruleContext.getTreeArtifact(rootRelativePath, ruleContext.getBinOrGenfilesDirectory());
}
private static Artifact j2ObjcGenJarSourceZip(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.zip");
}
private static Artifact j2ObjcGenJarSourceZipManifest(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_source.txt");
}
private static Artifact j2ObjcGenJarHeaderZip(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.zip");
}
private static Artifact j2ObjcGenJarHeaderZipManifest(RuleContext ruleContext) {
return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".genjar_header.txt");
}
private J2ObjcSource buildJ2ObjcSource(RuleContext ruleContext,
Iterable<Artifact> javaInputSourceFiles, Optional<Artifact> genSrcJar) {
PathFragment objcFileRootRelativePath = ruleContext.getUniqueDirectory("_j2objc");
PathFragment objcFileRootExecPath = ruleContext
.getConfiguration()
.getBinFragment()
.getRelative(objcFileRootRelativePath);
Iterable<Artifact> objcSrcs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
objcFileRootRelativePath, ".m");
Iterable<Artifact> objcHdrs = getOutputObjcFiles(ruleContext, javaInputSourceFiles,
objcFileRootRelativePath, ".h");
Iterable<PathFragment> headerSearchPaths = J2ObjcLibrary.j2objcSourceHeaderSearchPaths(
ruleContext, objcFileRootExecPath, javaInputSourceFiles);
Optional<Artifact> genJarTranslatedSrcs = Optional.absent();
Optional<Artifact> genJarTranslatedHdrs = Optional.absent();
Optional<PathFragment> genJarFileHeaderSearchPaths = Optional.absent();
if (genSrcJar.isPresent()) {
genJarTranslatedSrcs = Optional.of(j2ObjcGenJarTranslatedSourceFiles(ruleContext));
genJarTranslatedHdrs = Optional.of(j2objcGenJarTranslatedHeaderFiles(ruleContext));
genJarFileHeaderSearchPaths = Optional.of(genJarTranslatedHdrs.get().getExecPath());
}
return new J2ObjcSource(
ruleContext.getRule().getLabel(),
Iterables.concat(objcSrcs, genJarTranslatedSrcs.asSet()),
Iterables.concat(objcHdrs, genJarTranslatedHdrs.asSet()),
objcFileRootExecPath,
SourceType.JAVA,
Iterables.concat(headerSearchPaths, genJarFileHeaderSearchPaths.asSet()));
}
private Iterable<Artifact> getOutputObjcFiles(RuleContext ruleContext,
Iterable<Artifact> javaSrcs, PathFragment objcFileRootRelativePath, String suffix) {
ImmutableList.Builder<Artifact> objcSources = ImmutableList.builder();
for (Artifact javaSrc : javaSrcs) {
objcSources.add(ruleContext.getRelatedArtifact(
objcFileRootRelativePath.getRelative(javaSrc.getExecPath()), suffix));
}
return objcSources.build();
}
/**
* Sets up and returns an {@link ObjcCommon} object containing the J2ObjC-translated code.
*
*/
static ObjcCommon common(RuleContext ruleContext, Iterable<Artifact> transpiledSources,
Iterable<Artifact> transpiledHeaders, Iterable<PathFragment> headerSearchPaths,
Iterable<Attribute> dependentAttributes) {
ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext);
IntermediateArtifacts intermediateArtifacts =
ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext);
if (!Iterables.isEmpty(transpiledSources) || !Iterables.isEmpty(transpiledHeaders)) {
CompilationArtifacts compilationArtifacts = new CompilationArtifacts.Builder()
.addNonArcSrcs(transpiledSources)
.setIntermediateArtifacts(intermediateArtifacts)
.setPchFile(Optional.<Artifact>absent())
.addAdditionalHdrs(transpiledHeaders)
.build();
builder.setCompilationArtifacts(compilationArtifacts);
builder.setHasModuleMap();
}
for (Attribute dependentAttribute : dependentAttributes) {
if (ruleContext.getAttribute(dependentAttribute.getName()) != null) {
builder.addDepObjcProviders(ruleContext.getPrerequisites(
dependentAttribute.getName(),
dependentAttribute.getAccessMode(),
ObjcProvider.class));
}
}
return builder
.addUserHeaderSearchPaths(headerSearchPaths)
.setIntermediateArtifacts(intermediateArtifacts)
.build();
}
/**
* Sets up and returns an {@link XcodeProvider} object containing the J2ObjC-translated code.
*
*/
static XcodeProvider xcodeProvider(RuleContext ruleContext, ObjcCommon common,
Iterable<Artifact> transpiledHeaders, Iterable<PathFragment> headerSearchPaths,
Iterable<Attribute> dependentAttributes) {
XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
XcodeSupport xcodeSupport = new XcodeSupport(ruleContext);
xcodeSupport.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC);
for (Attribute dependentAttribute : dependentAttributes) {
if (ruleContext.getAttribute(dependentAttribute.getName()) != null) {
xcodeSupport.addDependencies(xcodeProviderBuilder, dependentAttribute);
}
}
if (!Iterables.isEmpty(transpiledHeaders)) {
xcodeProviderBuilder
.addUserHeaderSearchPaths(headerSearchPaths)
.addCopts(ruleContext.getFragment(ObjcConfiguration.class).getCopts())
.addHeaders(transpiledHeaders);
}
if (common.getCompilationArtifacts().isPresent()) {
xcodeProviderBuilder.setCompilationArtifacts(common.getCompilationArtifacts().get());
}
return xcodeProviderBuilder.build();
}
}