// 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.xcode.xcodegen;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.xcode.util.Equaling;
import com.google.devtools.build.xcode.util.Value;
import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.TargetControl;
import com.facebook.buck.apple.xcode.xcodeproj.PBXBuildFile;
import com.facebook.buck.apple.xcode.xcodeproj.PBXReference.SourceTree;
import com.facebook.buck.apple.xcode.xcodeproj.PBXResourcesBuildPhase;
import com.facebook.buck.apple.xcode.xcodeproj.PBXTarget.ProductType;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
/**
* Contains information about resources in an Xcode project.
*/
public class Resources extends Value<Resources> {
private final ImmutableSetMultimap<TargetControl, PBXBuildFile> buildFiles;
private Resources(ImmutableSetMultimap<TargetControl, PBXBuildFile> buildFiles) {
super(buildFiles);
this.buildFiles = buildFiles;
}
/**
* Build files that should be added to the PBXResourcesBuildPhase for the given target.
*/
public ImmutableSetMultimap<TargetControl, PBXBuildFile> buildFiles() {
return buildFiles;
}
/**
* Returns the PBXResourcesBuildPhase for the given target, if applicable. It will return an
* absent {@code Optional} if the target is a library or there are no resources to compile.
*/
public PBXResourcesBuildPhase resourcesBuildPhase(TargetControl targetControl) {
PBXResourcesBuildPhase resourcesPhase = new PBXResourcesBuildPhase();
resourcesPhase.getFiles().addAll(buildFiles().get(targetControl));
return resourcesPhase;
}
public static Optional<String> languageOfLprojDir(Path child) {
Path parent = child.getParent();
if (parent == null) {
return Optional.absent();
}
String dirName = parent.getFileName().toString();
String lprojSuffix = ".lproj";
if (dirName.endsWith(lprojSuffix)) {
return Optional.of(dirName.substring(0, dirName.length() - lprojSuffix.length()));
} else {
return Optional.absent();
}
}
public static Resources fromTargetControls(
FileSystem fileSystem, PBXBuildFiles pbxBuildFiles, Iterable<TargetControl> targetControls) {
ImmutableSetMultimap.Builder<TargetControl, PBXBuildFile> buildFiles =
new ImmutableSetMultimap.Builder<>();
for (TargetControl targetControl : targetControls) {
List<PBXBuildFile> targetBuildFiles = new ArrayList<>();
Iterable<String> simpleImports =
Iterables.concat(targetControl.getXcassetsDirList(), targetControl.getBundleImportList());
// Add .bundle, .xcassets directories to the Project Navigator so they are visible from within
// Xcode.
// Bundle imports are handled very similarly to asset catalogs, so we just add them with the
// same logic. Xcode's automatic file type detection logic is smart enough to see it is a
// bundle and link it properly, and add the {@code lastKnownFileType} property.
for (String simpleImport : simpleImports) {
targetBuildFiles.add(
pbxBuildFiles.getStandalone(FileReference.of(simpleImport, SourceTree.GROUP)));
}
Iterables.addAll(
targetBuildFiles,
pbxBuildFiles.get(
AggregateReferenceType.PBXVariantGroup,
RelativePaths.fromStrings(fileSystem, targetControl.getGeneralResourceFileList())));
// If this target is a binary, save the build files. Otherwise, we don't need them. The file
// references we generated with fileObjects will be added to the main group later.
if (!Equaling.of(
ProductType.STATIC_LIBRARY, XcodeprojGeneration.productType(targetControl))) {
buildFiles.putAll(targetControl, targetBuildFiles);
}
}
return new Resources(buildFiles.build());
}
}