<commit_before>/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.ocaml;

import com.facebook.buck.cxx.CxxDeps;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleCreationContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.CommonDescriptionArg;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.HasDeclaredDeps;
import com.facebook.buck.rules.ImplicitDepsInferringDescription;
import com.facebook.buck.rules.args.Arg;
import com.facebook.buck.rules.coercer.OcamlSource;
import com.facebook.buck.rules.coercer.PatternMatchedCollection;
import com.facebook.buck.rules.macros.StringWithMacros;
import com.facebook.buck.toolchain.ToolchainProvider;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.facebook.buck.versions.VersionRoot;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Optional;
import org.immutables.value.Value;

public class OcamlBinaryDescription
    implements Description<OcamlBinaryDescriptionArg>,
        ImplicitDepsInferringDescription<OcamlBinaryDescription.AbstractOcamlBinaryDescriptionArg>,
        VersionRoot<OcamlBinaryDescriptionArg> {

  private final ToolchainProvider toolchainProvider;

  public OcamlBinaryDescription(ToolchainProvider toolchainProvider) {
    this.toolchainProvider = toolchainProvider;
  }

  @Override
  public Class<OcamlBinaryDescriptionArg> getConstructorArgType() {
    return OcamlBinaryDescriptionArg.class;
  }

  @Override
  public BuildRule createBuildRule(
      BuildRuleCreationContext context,
      BuildTarget buildTarget,
      BuildRuleParams params,
      OcamlBinaryDescriptionArg args) {

    OcamlToolchain ocamlToolchain =
        toolchainProvider.getByName(OcamlToolchain.DEFAULT_NAME, OcamlToolchain.class);
    OcamlPlatform ocamlPlatform = ocamlToolchain.getDefaultOcamlPlatform();

    CxxDeps allDeps =
        CxxDeps.builder().addDeps(args.getDeps()).addPlatformDeps(args.getPlatformDeps()).build();

    ImmutableList<OcamlSource> srcs = args.getSrcs();

    ImmutableList<Arg> flags =
        OcamlRuleBuilder.getFlags(
            buildTarget,
            context.getCellPathResolver(),
            context.getBuildRuleResolver(),
            ocamlPlatform,
            args.getCompilerFlags(),
            args.getWarningsFlags());

    BuildTarget compileBuildTarget = OcamlRuleBuilder.createOcamlLinkTarget(buildTarget);

    ImmutableList<BuildRule> rules;
    if (OcamlRuleBuilder.shouldUseFineGrainedRules(context.getBuildRuleResolver(), srcs)) {
      OcamlGeneratedBuildRules result =
          OcamlRuleBuilder.createFineGrainedBuildRules(
              buildTarget,
              ocamlPlatform,
              compileBuildTarget,
              context.getProjectFilesystem(),
              params,
              context.getBuildRuleResolver(),
              allDeps.get(context.getBuildRuleResolver(), ocamlPlatform.getCxxPlatform()),
              srcs,
              /* isLibrary */ false,
              args.getBytecodeOnly().orElse(false),
              flags,
              args.getOcamldepFlags(),
              /* buildNativePlugin */ false);
      rules = result.getRules();
    } else {

      OcamlBuild ocamlLibraryBuild =
          OcamlRuleBuilder.createBulkCompileRule(
              buildTarget,
              ocamlPlatform,
              compileBuildTarget,
              context.getProjectFilesystem(),
              params,
              context.getBuildRuleResolver(),
              allDeps.get(context.getBuildRuleResolver(), ocamlPlatform.getCxxPlatform()),
              srcs,
              /* isLibrary */ false,
              args.getBytecodeOnly().orElse(false),
              flags,
              args.getOcamldepFlags());
      rules = ImmutableList.of(ocamlLibraryBuild);
    }

    return new OcamlBinary(
        buildTarget,
        context.getProjectFilesystem(),
        params.withDeclaredDeps(
            Suppliers.ofInstance(
                ImmutableSortedSet.<BuildRule>naturalOrder()
                    .addAll(params.getDeclaredDeps().get())
                    .addAll(rules)
                    .build())),
        rules.get(0));
  }

  @Override
  public void findDepsForTargetFromConstructorArgs(
      BuildTarget buildTarget,
      CellPathResolver cellRoots,
      AbstractOcamlBinaryDescriptionArg constructorArg,
      ImmutableCollection.Builder<BuildTarget> extraDepsBuilder,
      ImmutableCollection.Builder<BuildTarget> targetGraphOnlyDepsBuilder) {
    targetGraphOnlyDepsBuilder.addAll(
        OcamlUtil.getParseTimeDeps(
            toolchainProvider
                .getByName(OcamlToolchain.DEFAULT_NAME, OcamlToolchain.class)
                .getDefaultOcamlPlatform()));
  }

  @BuckStyleImmutable
  @Value.Immutable
  interface AbstractOcamlBinaryDescriptionArg extends CommonDescriptionArg, HasDeclaredDeps {
    ImmutableList<OcamlSource> getSrcs();

    ImmutableList<StringWithMacros> getCompilerFlags();

    ImmutableList<String> getLinkerFlags();

    ImmutableList<String> getOcamldepFlags();

    Optional<String> getWarningsFlags();

    Optional<Boolean> getBytecodeOnly();

    @Value.Default
    default PatternMatchedCollection<ImmutableSortedSet<BuildTarget>> getPlatformDeps() {
      return PatternMatchedCollection.of();
    }
  }
}<commit_msg>ocaml: add `platform` parameter to `ocaml_binary` rules<commit_after>/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.ocaml;

import com.facebook.buck.cxx.CxxDeps;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.FlavorDomain;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleCreationContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.CommonDescriptionArg;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.HasDeclaredDeps;
import com.facebook.buck.rules.ImplicitDepsInferringDescription;
import com.facebook.buck.rules.args.Arg;
import com.facebook.buck.rules.coercer.OcamlSource;
import com.facebook.buck.rules.coercer.PatternMatchedCollection;
import com.facebook.buck.rules.macros.StringWithMacros;
import com.facebook.buck.toolchain.ToolchainProvider;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.facebook.buck.versions.VersionRoot;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Optional;
import org.immutables.value.Value;

public class OcamlBinaryDescription
    implements Description<OcamlBinaryDescriptionArg>,
        ImplicitDepsInferringDescription<OcamlBinaryDescription.AbstractOcamlBinaryDescriptionArg>,
        VersionRoot<OcamlBinaryDescriptionArg> {

  private final ToolchainProvider toolchainProvider;

  public OcamlBinaryDescription(ToolchainProvider toolchainProvider) {
    this.toolchainProvider = toolchainProvider;
  }

  @Override
  public Class<OcamlBinaryDescriptionArg> getConstructorArgType() {
    return OcamlBinaryDescriptionArg.class;
  }

  private OcamlPlatform getPlatform(Optional<Flavor> platformFlavor) {
    OcamlToolchain ocamlToolchain =
        toolchainProvider.getByName(OcamlToolchain.DEFAULT_NAME, OcamlToolchain.class);
    FlavorDomain<OcamlPlatform> ocamlPlatforms = ocamlToolchain.getOcamlPlatforms();
    return platformFlavor
        .map(ocamlPlatforms::getValue)
        .orElse(ocamlToolchain.getDefaultOcamlPlatform());
  }

  @Override
  public BuildRule createBuildRule(
      BuildRuleCreationContext context,
      BuildTarget buildTarget,
      BuildRuleParams params,
      OcamlBinaryDescriptionArg args) {

    OcamlPlatform ocamlPlatform = getPlatform(args.getPlatform());

    CxxDeps allDeps =
        CxxDeps.builder().addDeps(args.getDeps()).addPlatformDeps(args.getPlatformDeps()).build();

    ImmutableList<OcamlSource> srcs = args.getSrcs();

    ImmutableList<Arg> flags =
        OcamlRuleBuilder.getFlags(
            buildTarget,
            context.getCellPathResolver(),
            context.getBuildRuleResolver(),
            ocamlPlatform,
            args.getCompilerFlags(),
            args.getWarningsFlags());

    BuildTarget compileBuildTarget = OcamlRuleBuilder.createOcamlLinkTarget(buildTarget);

    ImmutableList<BuildRule> rules;
    if (OcamlRuleBuilder.shouldUseFineGrainedRules(context.getBuildRuleResolver(), srcs)) {
      OcamlGeneratedBuildRules result =
          OcamlRuleBuilder.createFineGrainedBuildRules(
              buildTarget,
              ocamlPlatform,
              compileBuildTarget,
              context.getProjectFilesystem(),
              params,
              context.getBuildRuleResolver(),
              allDeps.get(context.getBuildRuleResolver(), ocamlPlatform.getCxxPlatform()),
              srcs,
              /* isLibrary */ false,
              args.getBytecodeOnly().orElse(false),
              flags,
              args.getOcamldepFlags(),
              /* buildNativePlugin */ false);
      rules = result.getRules();
    } else {

      OcamlBuild ocamlLibraryBuild =
          OcamlRuleBuilder.createBulkCompileRule(
              buildTarget,
              ocamlPlatform,
              compileBuildTarget,
              context.getProjectFilesystem(),
              params,
              context.getBuildRuleResolver(),
              allDeps.get(context.getBuildRuleResolver(), ocamlPlatform.getCxxPlatform()),
              srcs,
              /* isLibrary */ false,
              args.getBytecodeOnly().orElse(false),
              flags,
              args.getOcamldepFlags());
      rules = ImmutableList.of(ocamlLibraryBuild);
    }

    return new OcamlBinary(
        buildTarget,
        context.getProjectFilesystem(),
        params.withDeclaredDeps(
            Suppliers.ofInstance(
                ImmutableSortedSet.<BuildRule>naturalOrder()
                    .addAll(params.getDeclaredDeps().get())
                    .addAll(rules)
                    .build())),
        rules.get(0));
  }

  @Override
  public void findDepsForTargetFromConstructorArgs(
      BuildTarget buildTarget,
      CellPathResolver cellRoots,
      AbstractOcamlBinaryDescriptionArg constructorArg,
      ImmutableCollection.Builder<BuildTarget> extraDepsBuilder,
      ImmutableCollection.Builder<BuildTarget> targetGraphOnlyDepsBuilder) {
    targetGraphOnlyDepsBuilder.addAll(
        OcamlUtil.getParseTimeDeps(getPlatform(constructorArg.getPlatform())));
  }

  @BuckStyleImmutable
  @Value.Immutable
  interface AbstractOcamlBinaryDescriptionArg extends CommonDescriptionArg, HasDeclaredDeps {
    ImmutableList<OcamlSource> getSrcs();

    ImmutableList<StringWithMacros> getCompilerFlags();

    ImmutableList<String> getLinkerFlags();

    ImmutableList<String> getOcamldepFlags();

    Optional<String> getWarningsFlags();

    Optional<Boolean> getBytecodeOnly();

    Optional<Flavor> getPlatform();

    @Value.Default
    default PatternMatchedCollection<ImmutableSortedSet<BuildTarget>> getPlatformDeps() {
      return PatternMatchedCollection.of();
    }
  }
}
{'fraction_non_alphanumeric': 0.08427276310603074, 'fraction_numerical': 0.0014189988175009854, 'mean_word_length': 3.4018043025676614, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5827860', 'n_tokens_mistral': 3530, 'n_tokens_neox': 3423, 'n_words': 605}