bazelbuild / bazel

a fast, scalable, multi-language and extensible build system
https://bazel.build
Apache License 2.0
22.88k stars 4.01k forks source link

Starlarkify Xcode rules #20218

Open susinmotion opened 9 months ago

susinmotion commented 9 months ago

Description of the feature request:

The logic for Xcode selection and the associated rules are currently written in native code, which makes maintenance more challenging.

It would be wonderful to pull the following rules into Starlark: available_xcodes xcode_config xcode_version

The logic that uses them in XcodeConfig.java may also be able to be ported, though some provider definitions will need to exist in native code.

It may be possible to modify xcode_version's definition to support full paths to Xcode versions and avoid doing Xcode location as part of the build. But the first step before optimizations like these is probably starlarkification.

Any other information, logs, or outputs that you want to share?

Here's an overview of how Xcode selection works.

Overview

Xcode selection is determined by two options:

–xcode_version_config, a mandatory option that points to an xcode_config target containing information about the Xcode versions available to the build.

–xcode_version an optional option that points to an xcode_version target describing the desired Xcode version for the build.

If –xcode_version is not set, the build will use the default Xcode version described in the xcode_config target pointed to by –xcode_version_config. If –xcode_version is set, the build will use the version it points to, if it is one of the available Xcode versions described in the xcode_config target.

Details

Xcode users typically use xcode-select to set an Xcode version to use, so we use the xcode-selected version as the default for Bazel by using this as the default version within the generated xcode_config target in the file. Respecting xcode-select for version setting is the reason we don’t know the default value for –xcode_version ahead of the build, and it leads to a lot of complexity.

There are two major shapes of xcode_config targets. The available_xcodes shape points to a set of locally available Xcode versions and a set of remotely available Xcode versions. This allows Bazel to select the newest mutually available Xcode version as a performance optimization toggled by –experimental_prefer_mutual_xcode. The old xcode_versions shape contains a single set of Xcode versions.

As part of the build, Bazel uses xcode_configure.bzl to create a BUILD file containing an xcode_config target and a series of xcode_version targets so that the build is aware of locally available XCodes. Since this process can be slow, and you need to shut down Bazel in order to pick up on new Xcodes, some users have created their own custom tools to create this BUILD file outside the build. This may be useful to implement more broadly.

The bulk of the logic for Xcode selection is in XcodeConfig.java, which implements the following control flow: Did the user specify an Xcode version? Yes. Select this version if it is available, otherwise fail the build (no change). No. Determine the default. Are both local and remote versions available? Yes (dynamic execution). Are there mutually available versions available? Yes. From the mutually available versions, prefer the remote default, followed by the local default, followed by the most recent (highest) version. No. Choose the local default, and warn “Xcode version X was specified, but is not available remotely. Actions requiring Xcode will be run locally, which could make your build slower. Consider specifying an Xcode version from [mutually available Xcodes], or downloading one of [remote Xcodes]”. No (local or remote execution). Select the default local version, or the default remote version. No warnings.

brentleyjones commented 9 months ago

Duplicate of #16798 (though this one has additional information).