// 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()); } }