blob: e4b13c7409a7c6e5b888c4e15e1589d571c15470 [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.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.vfs.PathFragment;
/**
* Represents an .xcdatamodel[d] directory - knowing all {@code Artifact}s contained therein - and
* the .zip file that it is compiled to which should be merged with the final application bundle.
* <p>
* An .xcdatamodel (here and below note that lack or presence of a d) directory contains the schema
* for a managed object, or a managed object model. It typically has two files: {@code layout} and
* {@code contents}, although this detail isn't addressed in Bazel code. Directories of this
* sort are compiled into a single .mom file. If the .xcdatamodel directory is inside a
* .xcdatamodeld directory, then the .mom file is placed inside a .momd directory. The .momd
* directory or .mom file is placed in the bundle root of the final bundle.
* <p>
* An .xcdatamodeld directory contains several .xcdatamodel directories, each corresponding to a
* different version. In addition the .xcdatamodeld directory contains a {@code .xccurrentversion}
* file which identifies the current version. (this file is also not handled explicitly by Bazel
* code).
* <p>
* When processing artifacts referenced by a {@code datamodels} attribute, we must determine if it
* is in a .xcdatamodeld directory or only a .xcdatamodel directory. We also must group the
* artifacts by their container, the container being an .xcdatamodeld directory if possible, and a
* .xcdatamodel directory otherwise. Every container is compiled with a single invocation of the
* Managed Object Model Compiler (momc) and corresponds to exactly one instance of this class. We
* invoke momc indirectly through the momczip tool (part of Bazel) which runs momc and zips the
* output. The files in this zip are placed in the bundle root of the final application, not unlike
* the zips generated by {@code actoolzip} or {@code ibtoolzip}.
*/
class Xcdatamodel extends Value<Xcdatamodel> {
private final Artifact outputZip;
private final ImmutableSet<Artifact> inputs;
private final PathFragment container;
Xcdatamodel(Artifact outputZip, ImmutableSet<Artifact> inputs, PathFragment container) {
super(ImmutableMap.of(
"outputZip", outputZip,
"inputs", inputs,
"container", container));
this.outputZip = outputZip;
this.inputs = inputs;
this.container = container;
}
public Artifact getOutputZip() {
return outputZip;
}
/**
* Returns every known file in the container. This is every input file that is processed by momc.
*/
public ImmutableSet<Artifact> getInputs() {
return inputs;
}
public PathFragment getContainer() {
return container;
}
/**
* The ARCHIVE_ROOT passed to momczip. The archive root is the name of the .mom file
* unversioned object models, and the name of the .momd directory for versioned object models.
*/
public String archiveRootForMomczip() {
return name() + (container.getBaseName().endsWith(".xcdatamodeld") ? ".momd" : ".mom");
}
/**
* The name of the data model. This is the name of the container without the extension. For
* instance, if the container is "foo/Information.xcdatamodel" or "bar/Information.xcdatamodeld",
* then the name is "Information".
*/
public String name() {
String baseContainerName = container.getBaseName();
int lastDot = baseContainerName.lastIndexOf('.');
return baseContainerName.substring(0, lastDot);
}
public static Iterable<Artifact> outputZips(Iterable<Xcdatamodel> models) {
return Iterables.transform(models, Xcdatamodel::getOutputZip);
}
}