Skip to content

Commit

Permalink
Read cxxflags from cxx_toolchain instead of buckconfig
Browse files Browse the repository at this point in the history
Summary:
The cxxflags et al. are read from Cxx Toolchain instead of from the buckconfig. Moving forward these flags will no longer be in the config and only in the Cxx Toolchain (T213442427).  There is no observable behavior change.

The main motivation behind (T213442427) is to improve buck-build-graph caching between dev and opt build-modes by moving the cxx toolchain out of config files and directly into the toolchain target.

The cxxflags on the `CxxToolchainInfo` need to be indirectly read with `actions.dynamic_output` because they are type `cmd_args`.

### flags containing string parameter macros
I do nothing about string parameter macros (e.g., `$(location ...)`) in flags  because 1/ I do not see string parameter macros in the flags of the CxxToolchain, and 2/ the ambiguity of how to handle them.  They will need to be handled if/when they become a problem. I mention the string parameter macros because before this change, when the flags were read from the buckconfig, the code would filter out strings with `$(` and `)`.

### CxxToolchain Info
The CxxToolchainInfo is loaded from `toolchains//:cxx` that is configured to the platform `ovr_config//platform/linux:platform010-clang` based off where the flags are currently read from (`fbcode-platform-cxx#platform010-clang`).

Reviewed By: scottcao

Differential Revision: D69617220

fbshipit-source-id: 958f94cb4674d6904432d594ec5938c64dd1067d
  • Loading branch information
skrueger authored and facebook-github-bot committed Feb 19, 2025
1 parent dc3a761 commit 0aaae3f
Showing 1 changed file with 55 additions and 11 deletions.
66 changes: 55 additions & 11 deletions prelude/ide_integrations/visual_studio/gen_mode_configs.bxl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxToolchainInfo")
load("constants.bxl", "ANDROID", "CLANG", "CXXFLAGS", "CXXPPFLAGS", "FLAGS_LOCATION", "LANGUAGE_STANDARD", "LDFLAGS", "TOOLSET", "VS2019", "VS2022")
load("flags_parser_utils.bxl", "get_compiler_settings_from_flags", "get_linker_settings_from_flags")
load("get_compiler_settings.bxl", "gen_compiler_settings")
Expand All @@ -16,25 +17,21 @@ STD_CXXPPFLAGS = read_root_config("cxx_#default", "cxxppflags") or ""
STD_CXXFLAGS = read_root_config("cxx_#default", "cxxflags") or ""
STD_LDFLAGS = read_root_config("cxx_#default", "ldflags") or ""

ANDROID_CXXPPFLAGS = read_root_config("fbcode-platform-cxx#platform010-clang", "cxxppflags") or ""
ANDROID_CXXFLAGS = read_root_config("fbcode-platform-cxx#platform010-clang", "cxxflags") or ""
ANDROID_LDFLAGS = read_root_config("fbcode-platform-cxx#platform010-clang", "ldflags") or ""

# Simple enum used to determine where flags come from.
_FlagsLocation = enum(
# Flags come from the dict itsself
"dict",
# Flags come from the CxxToolchain
"CxxToolchain", # @unused, Will use in a future change.
"CxxToolchain",
)

# @unsorted-dict-items
LANGUAGE_STANDARD_AND_TOOLSET_MAP = {
ANDROID: {
FLAGS_LOCATION: _FlagsLocation("dict"),
CXXFLAGS: ANDROID_CXXFLAGS,
CXXPPFLAGS: ANDROID_CXXPPFLAGS,
LDFLAGS: ANDROID_LDFLAGS,
FLAGS_LOCATION: _FlagsLocation("CxxToolchain"),
CXXFLAGS: None,
CXXPPFLAGS: None,
LDFLAGS: None,
LANGUAGE_STANDARD: None,
TOOLSET: "Clang_5_0",
},
Expand Down Expand Up @@ -109,8 +106,54 @@ def _get_path(target: str, bxl_ctx):
absolute_path = _get_provider_output_path(providers[DefaultInfo], bxl_ctx)
return absolute_path

def _produce_proj_artifact_with_async_cxx_toolchain(bxl_ctx, actions, fbsource: bool, output_artifact: Artifact, root: str, platform: str) -> None:
"""Reads the cxx_toolchain's flags with `actions.dynamic_output` before continuing to produce the final output project artifact.

The cxx_toolchain's flags cannot be directly read because they are type `cmd_args`.
The flags are indirectly read after dynamically materializing them to an output artifact
(i.e., write them to an artifact, and read them inside of `dynamic_output`'s callback).
"""
cxx_toolchain_analysis_result = bxl_ctx.analysis("toolchains//:cxx", target_platform = "ovr_config//platform/linux:platform010-clang")
cxx_toolchain = cxx_toolchain_analysis_result.providers().get(CxxToolchainInfo)

cxxflags_artifact, cxxflags_macro_artifacts = actions.write("cxxflags", cxx_toolchain.cxx_compiler_info.compiler_flags, allow_args = True)

cxxppflags_artifact, cxxppflags_macro_artifacts = actions.write("cxxppflags", cxx_toolchain.cxx_compiler_info.preprocessor_flags, allow_args = True)

ldflags_artifact, ldflags_macro_artifacts = actions.write("ldflags", cxx_toolchain.linker_info.linker_flags, allow_args = True)

def dyn_output_continuation(ctx, dynamic: dict[Artifact, ArtifactValue], outputs: dict[Artifact, typing.Any]) -> None:
"""async continuation/callback for the `dynamic_output` call that reads the cxx_toolchain flags from materialized artifacts and continues to produce the final project file artifact.

The cxx_toolchain flags are stored in `dynamic` and are now readable becuase their artifacts were materialized by the `dynamic_output`.
"""
cxxflags = dynamic[cxxflags_artifact].read_string().splitlines()
cxxppflags = dynamic[cxxppflags_artifact].read_string().splitlines()
ldflags = dynamic[ldflags_artifact].read_string().splitlines()
cxx_toolchain_flags = _CxxToolchainFlags(
cxxflags = cxxflags,
cxxppflags = cxxppflags,
ldflags = ldflags,
)

# the actions are grabbed again because the outer ones cannot be frozen
actions = ctx.bxl_actions().actions
hidden_artifacts = cxxflags_macro_artifacts + cxxppflags_macro_artifacts + ldflags_macro_artifacts
_produce_proj_artifact(ctx, actions, fbsource, cxx_toolchain_flags, outputs[output_artifact], root = root, platform = platform, hidden_artifacts = hidden_artifacts)

dyn_artifacts = [
cxxflags_artifact,
cxxppflags_artifact,
ldflags_artifact,
]
actions.dynamic_output(dynamic = dyn_artifacts, inputs = [], outputs = [output_artifact.as_output()], f = dyn_output_continuation)

bxl_ctx.output.ensure_multiple(dyn_artifacts)

def _main(bxl_ctx):
actions = bxl_ctx.bxl_actions().actions

# Capture `fbsource` and `root` because those attributes on `bxl_ctx` are not avaliable on the dynamic_output's ctx and `bxl_ctx` cannot be captured.
fbsource = bxl_ctx.cli_args.fbsource
root = bxl_ctx.root()

Expand All @@ -131,13 +174,13 @@ def _main(bxl_ctx):
)
_produce_proj_artifact(bxl_ctx, actions, fbsource, cxx_toolchain_flags, output_artifact, root = root, platform = platform)
elif flags_location == _FlagsLocation("CxxToolchain"):
fail("Not Implemented Yet flags_location '%s' in platform '%s'" % (flags_location, platform))
_produce_proj_artifact_with_async_cxx_toolchain(bxl_ctx, actions, fbsource, output_artifact, root = root, platform = platform)
else:
fail("Unknown flags_location '%s' in platform '%s'" % (flags_location, platform))

bxl_ctx.output.print(bxl_ctx.output.ensure(output_artifact).abs_path())

def _produce_proj_artifact(bxl_ctx, actions, fbsource: bool, cxx_toolchain_flags: _CxxToolchainFlags, output_artifact: Artifact, root: str, platform: str):
def _produce_proj_artifact(bxl_ctx, actions, fbsource: bool, cxx_toolchain_flags: _CxxToolchainFlags, output_artifact: Artifact, root: str, platform: str, hidden_artifacts: None | list[Artifact] = None):
"""Produce the <Project> file output artifact"""
compiler_settings = _get_compiler_settings(cxx_toolchain_flags)
linker_settings = _get_linker_settings(cxx_toolchain_flags, root)
Expand Down Expand Up @@ -192,6 +235,7 @@ def _produce_proj_artifact(bxl_ctx, actions, fbsource: bool, cxx_toolchain_flags
""" </ImportGroup>""",
"""</Project>""",
delimiter = "\n",
hidden = hidden_artifacts or [],
)

actions.write(output_artifact.as_output(), content, allow_args = True)
Expand Down

0 comments on commit 0aaae3f

Please sign in to comment.