@Test
  public void compilationDatabaseFetchedFromCacheAlsoFetchesSymlinkTreeOrHeaderMap()
      throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    // This test only fails if the directory cache is enabled and we don't update
    // the header map/symlink tree correctly when fetching from the cache.
    workspace.enableDirCache();

    addLibraryHeaderFiles(workspace);

    BuildTarget target =
        BuildTargetFactory.newInstance("//:library_with_header#default,compilation-database");

    // Populate the cache with the built rule
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());

    Path headerSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR),
            "%s");
    Path exportedHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"),
                CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
            "%s");

    // Validate the symlink tree/header maps
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h");

    // Delete the newly-added files and build again
    Files.delete(workspace.getPath("baz.h"));
    Files.delete(workspace.getPath("blech_private.h"));
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h");

    // Restore the headers, build again, and check the symlink tree/header maps
    addLibraryHeaderFiles(workspace);
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h");
  }
  @Test
  public void frameworkDependenciesDoNotContainTransitiveDependencies() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_with_library_dependencies", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#framework,macosx-x86_64");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(
                    filesystem,
                    BuildTarget.builder(target)
                        .addFlavors(AppleDebugFormat.DWARF.getFlavor())
                        .addFlavors(AppleDescriptions.INCLUDE_FRAMEWORKS_FLAVOR)
                        .build(),
                    "%s")
                .resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    Path frameworksPath = frameworkPath.resolve("Frameworks");
    assertThat(Files.exists(frameworksPath), is(true));
    Path depFrameworksPath = frameworksPath.resolve("TestLibraryDep.framework/Frameworks");
    assertThat(Files.exists(depFrameworksPath), is(false));
  }
  @Test
  public void testAppleLibraryBuildsFramework() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#framework,macosx-x86_64,no-debug");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(
                    filesystem,
                    BuildTarget.builder(target)
                        .addFlavors(AppleDescriptions.INCLUDE_FRAMEWORKS_FLAVOR)
                        .build(),
                    "%s")
                .resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    assertThat(Files.exists(frameworkPath.resolve("Resources/Info.plist")), is(true));
    Path libraryPath = frameworkPath.resolve("TestLibrary");
    assertThat(Files.exists(libraryPath), is(true));
    assertThat(
        workspace.runCommand("file", libraryPath.toString()).getStdout().get(),
        containsString("dynamically linked shared library"));
  }
  @Test
  public void noIncludeFrameworksDoesntContainFrameworkDependencies() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_with_library_dependencies", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#"
                + "dwarf-and-dsym,framework,macosx-x86_64,no-include-frameworks");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(filesystem, target, "%s").resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    assertThat(Files.exists(frameworkPath.resolve("Resources/Info.plist")), is(true));
    Path libraryPath = frameworkPath.resolve("TestLibrary");
    assertThat(Files.exists(libraryPath), is(true));
    assertThat(
        workspace.runCommand("file", libraryPath.toString()).getStdout().get(),
        containsString("dynamically linked shared library"));
    Path frameworksPath = frameworkPath.resolve("Contents/Frameworks");
    assertThat(Files.exists(frameworksPath), is(false));
  }
  @Test
  public void testAppleLibraryExportedHeaderSymlinkTree() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_header_symlink_tree", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget buildTarget =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#"
                + "default,"
                + CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR);
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", buildTarget.getFullyQualifiedName());
    result.assertSuccess();

    Path inputPath = workspace.getPath(buildTarget.getBasePath()).toRealPath();
    Path outputPath =
        workspace.getPath(BuildTargets.getGenPath(filesystem, buildTarget, "%s")).toRealPath();

    assertIsSymbolicLink(
        outputPath.resolve("TestLibrary/PublicHeader.h"), inputPath.resolve("PublicHeader.h"));
  }
  @Test
  public void testUberCompilationDatabase() throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp);
    workspace.setUp();
    BuildTarget target =
        BuildTargetFactory.newInstance("//:test#default,uber-compilation-database");
    ProjectFilesystem filesystem = new FakeProjectFilesystem();
    Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    Path rootPath = tmp.getRoot();
    assertEquals(
        BuildTargets.getGenPath(
            filesystem, target, "uber-compilation-database-%s/compile_commands.json"),
        rootPath.relativize(compilationDatabase));

    Path binaryHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR),
            "%s");
    Path binaryExportedHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"),
                CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
            "%s");

    Map<String, CxxCompilationDatabaseEntry> fileToEntry =
        CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase);
    assertEquals(1, fileToEntry.size());
    assertHasEntry(
        fileToEntry,
        "test.cpp",
        new ImmutableList.Builder<String>()
            .add(COMPILER_PATH)
            .add("-fPIC")
            .add("-fPIC")
            .add("-I")
            .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString())
            .add("-I")
            .add(headerSymlinkTreePath(binaryExportedHeaderSymlinkTreeFolder).toString())
            .addAll(getExtraFlagsForHeaderMaps(filesystem))
            .addAll(COMPILER_SPECIFIC_FLAGS)
            .add("-x")
            .add("c++")
            .add("-c")
            .add("-o")
            .add(
                BuildTargets.getGenPath(
                        filesystem,
                        target.withFlavors(
                            ImmutableFlavor.of("default"),
                            ImmutableFlavor.of("compile-pic-" + sanitize("test.cpp.o"))),
                        "%s/test.cpp.o")
                    .toString())
            .add(rootPath.resolve(Paths.get("test.cpp")).toRealPath().toString())
            .build());
  }
  @Test
  public void compilationDatabaseWithDepsFetchedFromCacheAlsoFetchesSymlinkTreeOrHeaderMapOfDeps()
      throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "compilation_database_with_deps", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    // This test only fails if the directory cache is enabled and we don't update
    // the header map/symlink tree correctly when fetching from the cache.
    workspace.enableDirCache();

    addDepLibraryHeaderFiles(workspace);

    BuildTarget target =
        BuildTargetFactory.newInstance("//:library_with_header#default,compilation-database");

    // Populate the cache with the built rule
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());

    Path dep1ExportedSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem, BuildTargetFactory.newInstance("//dep1:dep1#default,headers"), "%s");
    Path dep2ExportedSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem, BuildTargetFactory.newInstance("//dep2:dep2#default,headers"), "%s");

    // Validate the deps' symlink tree/header maps
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h", "dep1/dep1_new.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h", "dep2/dep2_new.h");

    // Delete the newly-added files and build again
    Files.delete(workspace.getPath("dep1/dep1_new.h"));
    Files.delete(workspace.getPath("dep2/dep2_new.h"));
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h");

    // Restore the headers, build again, and check the deps' symlink tree/header maps
    addDepLibraryHeaderFiles(workspace);
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h", "dep1/dep1_new.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h", "dep2/dep2_new.h");
  }
 @Nullable
 public String getBuildTargetForAliasAsString(String possiblyFlavoredAlias) {
   Pair<BuildTarget, Integer> buildTargetPoundIdx = getBuildTargetForAlias(possiblyFlavoredAlias);
   BuildTarget buildTarget = buildTargetPoundIdx.getFirst();
   int poundIdx = buildTargetPoundIdx.getSecond();
   if (buildTarget != null) {
     return buildTarget.getFullyQualifiedName()
         + (poundIdx == -1 ? "" : possiblyFlavoredAlias.substring(poundIdx));
   } else {
     return null;
   }
 }
  @Test
  public void testAppleLibraryIsHermetic() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_is_hermetic", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#static,iphonesimulator-x86_64");
    ProjectWorkspace.ProcessResult first =
        workspace.runBuckCommand(
            workspace.getPath("first"), "build", target.getFullyQualifiedName());
    first.assertSuccess();

    ProjectWorkspace.ProcessResult second =
        workspace.runBuckCommand(
            workspace.getPath("second"), "build", target.getFullyQualifiedName());
    second.assertSuccess();

    Path objectPath =
        BuildTargets.getGenPath(
                filesystem,
                target.withFlavors(
                    ImmutableFlavor.of("compile-" + sanitize("TestClass.m.o")),
                    ImmutableFlavor.of("iphonesimulator-x86_64")),
                "%s")
            .resolve("TestClass.m.o");
    MoreAsserts.assertContentsEqual(
        workspace.getPath(Paths.get("first").resolve(objectPath)),
        workspace.getPath(Paths.get("second").resolve(objectPath)));
    Path libraryPath =
        BuildTargets.getGenPath(filesystem, target, "%s").resolve("libTestLibrary.a");
    MoreAsserts.assertContentsEqual(
        workspace.getPath(Paths.get("first").resolve(libraryPath)),
        workspace.getPath(Paths.get("second").resolve(libraryPath)));
  }
  @Test
  public void testBuildEmptySourceAppleLibrary() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "empty_source_targets", tmp);
    workspace.setUp();
    BuildTarget target = workspace.newBuildTarget("//:real-none#iphonesimulator-x86_64,shared");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    Path binaryOutput =
        workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s/libreal-none.dylib"));
    assertThat(Files.exists(binaryOutput), is(true));
  }
  @Test
  public void testAppleLibraryBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary#static,default");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    assertTrue(Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s"))));
  }
  @Override
  protected void amendBuilder(
      AbstractBuildRuleBuilder abstractBuilder, BuildRuleFactoryParams params)
      throws NoSuchBuildTargetException {
    AndroidInstrumentationApk.Builder builder = (AndroidInstrumentationApk.Builder) abstractBuilder;
    BuildTarget target = params.target;

    // manifest
    String manifestAttribute = params.getRequiredStringAttribute("manifest");
    String manifestPath = params.resolveFilePathRelativeToBuildFileDirectory(manifestAttribute);
    builder.setManifest(manifestPath);

    // apk
    String apk = params.getRequiredStringAttribute("apk");
    ParseContext buildFileParseContext = ParseContext.forBaseName(target.getBaseName());
    BuildTarget buildTarget = params.buildTargetParser.parse(apk, buildFileParseContext);
    builder.setApk(buildTarget.getFullyQualifiedName());
  }
  @Test
  public void testAppleLibraryBuildsForWatchOS() throws IOException {
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.WATCHOS));

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary#watchos-armv7k,static");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    assertTrue(Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s"))));
  }
  @Test
  public void testAppleLibraryWithDefaultsInRuleBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_with_platform_and_type", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target = BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    BuildTarget implicitTarget =
        target.withAppendedFlavors(
            ImmutableFlavor.of("shared"), ImmutableFlavor.of("iphoneos-arm64"));
    Path outputPath = workspace.getPath(BuildTargets.getGenPath(filesystem, implicitTarget, "%s"));
    assertTrue(Files.exists(outputPath));
  }
  @Test
  public void testBuildAppleLibraryThatHasSwift() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "empty_source_targets", tmp);
    workspace.setUp();
    BuildTarget target = workspace.newBuildTarget("//:none-swift#iphonesimulator-x86_64,shared");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    Path binaryOutput =
        workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s/libnone-swift.dylib"));
    assertThat(Files.exists(binaryOutput), is(true));

    assertThat(
        workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
        containsString("libswiftCore.dylib"));
  }
Exemple #16
0
  @Test
  public void testBasicProjectCommand() throws Exception {
    BuildRuleResolver ruleResolver = new BuildRuleResolver();

    BuildTarget javaLibraryTargetName = BuildTargetFactory.newInstance("//javasrc:java-library");
    DefaultJavaLibraryRule javaLibraryRule =
        ruleResolver.buildAndAddToIndex(
            DefaultJavaLibraryRule.newJavaLibraryRuleBuilder(
                    new FakeAbstractBuildRuleBuilderParams())
                .setBuildTarget(javaLibraryTargetName)
                .addSrc("javasrc/JavaLibrary.java"));

    String projectConfigTargetName = "//javasrc:project-config";
    ProjectConfigRule ruleConfig =
        ruleResolver.buildAndAddToIndex(
            ProjectConfigRule.newProjectConfigRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
                .setBuildTarget(BuildTargetFactory.newInstance(projectConfigTargetName))
                .setSrcTarget(Optional.of(javaLibraryTargetName)));

    BuckConfig buckConfig =
        createBuckConfig(
            Joiner.on("\n").join("[project]", "initial_targets = " + javaLibraryTargetName));

    ProjectCommandForTest command = new ProjectCommandForTest();
    command.createPartialGraphCallReturnValues.push(
        createGraphFromBuildRules(ImmutableList.<BuildRule>of(ruleConfig)));

    command.runCommandWithOptions(createOptions(buckConfig));

    assertTrue(command.createPartialGraphCallReturnValues.isEmpty());

    // The PartialGraph comprises build config rules.
    RawRulePredicate projectConfigPredicate = command.createPartialGraphCallPredicates.get(0);
    checkPredicate(projectConfigPredicate, EMPTY_PARSE_DATA, javaLibraryRule, false);
    checkPredicate(projectConfigPredicate, EMPTY_PARSE_DATA, ruleConfig, true);

    BuildCommandOptions buildOptions = command.buildCommandOptions;
    MoreAsserts.assertContainsOne(
        buildOptions.getArguments(), javaLibraryTargetName.getFullyQualifiedName());
  }
Exemple #17
0
  /** @param rules the raw rule objects to parse. */
  @VisibleForTesting
  synchronized void parseRawRulesInternal(Iterable<Map<String, Object>> rules)
      throws BuildTargetException, IOException {
    for (Map<String, Object> map : rules) {

      if (isMetaRule(map)) {
        parseMetaRule(map);
        continue;
      }

      BuildRuleType buildRuleType = parseBuildRuleTypeFromRawRule(map);
      BuildTarget target = parseBuildTargetFromRawRule(map);
      BuildRuleFactory<?> factory = buildRuleTypes.getFactory(buildRuleType);
      if (factory == null) {
        throw new HumanReadableException(
            "Unrecognized rule %s while parsing %s.",
            buildRuleType, target.getBuildFile(projectFilesystem));
      }

      BuildFileTree buildFileTree;
      buildFileTree = buildFileTreeCache.getInput();

      BuildRuleBuilder<?> buildRuleBuilder =
          factory.newInstance(
              new BuildRuleFactoryParams(
                  map,
                  projectFilesystem,
                  buildFileTree,
                  buildTargetParser,
                  target,
                  ruleKeyBuilderFactory));
      Object existingRule = knownBuildTargets.put(target, buildRuleBuilder);
      if (existingRule != null) {
        throw new RuntimeException("Duplicate definition for " + target.getFullyQualifiedName());
      }
      parsedBuildFiles.put(normalize(target.getBuildFile(projectFilesystem).toPath()), map);
    }
  }
  @Test
  public void testAppleLibraryWithDefaultsInConfigBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    workspace.writeContentsToPath(
        "[defaults.apple_library]\n  platform = iphonesimulator-x86_64\n  type = shared\n",
        ".buckconfig.local");

    BuildTarget target = BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    BuildTarget implicitTarget =
        target.withAppendedFlavors(
            ImmutableFlavor.of("shared"), ImmutableFlavor.of("iphonesimulator-x86_64"));
    assertTrue(
        Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, implicitTarget, "%s"))));
  }
  @Test
  public void fieldsFromParentClassesShouldBeAddedAndFieldsRetainOverallAlphabeticalOrdering() {
    BuildTarget topLevelTarget = BuildTargetFactory.newInstance("//cheese:peas");
    SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
    BuildRule rule = new EmptyRule(topLevelTarget);

    DefaultRuleKeyBuilderFactory factory =
        new DefaultRuleKeyBuilderFactory(new NullFileHashCache(), pathResolver);
    RuleKeyBuilder builder = factory.newInstance(rule);

    builder.setReflectively("exoticCheese", "bavarian smoked");
    builder.setReflectively("target", topLevelTarget.getFullyQualifiedName());
    RuleKey expected = builder.build();

    class Parent extends EmptyRule {

      @AddToRuleKey private BuildTarget target;

      public Parent(BuildTarget target) {
        super(target);
        this.target = target;
      }
    }

    class Child extends Parent {

      @AddToRuleKey private String exoticCheese = "bavarian smoked";

      public Child(BuildTarget target) {
        super(target);
      }
    }

    RuleKey seen = factory.build(new Child(topLevelTarget));

    assertEquals(expected, seen);
  }
 @Override
 public String getFullyQualifiedName() {
   return target.getFullyQualifiedName();
 }
  @Test
  public void binaryWithDependenciesCompilationDatabase() throws IOException {
    BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_dep#compilation-database");
    Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    Path rootPath = tmp.getRoot();
    assertEquals(
        BuildTargets.getGenPath(filesystem, target, "__%s.json"),
        rootPath.relativize(compilationDatabase));

    Path binaryHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR),
            "%s");
    assertTrue(Files.exists(rootPath.resolve(binaryHeaderSymlinkTreeFolder)));

    BuildTarget libraryTarget = BuildTargetFactory.newInstance("//:library_with_header");
    Path libraryExportedHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            libraryTarget.withFlavors(
                ImmutableFlavor.of("default"),
                CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
            "%s");

    // Verify that symlink folders for headers are created and header file is linked.
    assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder)));
    assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder + "/bar.h")));

    Map<String, CxxCompilationDatabaseEntry> fileToEntry =
        CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase);
    assertEquals(1, fileToEntry.size());
    assertHasEntry(
        fileToEntry,
        "foo.cpp",
        new ImmutableList.Builder<String>()
            .add(COMPILER_PATH)
            .add("-I")
            .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString())
            .add("-I")
            .add(headerSymlinkTreePath(libraryExportedHeaderSymlinkTreeFolder).toString())
            .addAll(getExtraFlagsForHeaderMaps(filesystem))
            .addAll(COMPILER_SPECIFIC_FLAGS)
            .add("-x")
            .add("c++")
            .add("-c")
            .add("-o")
            .add(
                BuildTargets.getGenPath(
                        filesystem,
                        target.withFlavors(
                            ImmutableFlavor.of("default"),
                            ImmutableFlavor.of("compile-" + sanitize("foo.cpp.o"))),
                        "%s/foo.cpp.o")
                    .toString())
            .add(rootPath.resolve(Paths.get("foo.cpp")).toRealPath().toString())
            .build());
  }