Add best effort toolchain feature docs

Copybara Import from https://github.com/bazelbuild/rules_cc/pull/701

BEGIN_PUBLIC
Add best effort toolchain feature docs (#701)

I took a pass at doing some base level documentation for all the magic
features that apply to cc toolchains. This doesn't exhaustively list
their behavior, but it gives a useful bit of context for folks. This is
useful for folks who are trying to enable specific things and who are
writing their own toolchains. I tried to put enough comments in here
about how this doesn't mean it's treated as public API.

Closes #701
END_PUBLIC

Tested:
    TAP --sample ran all affected tests and none failed
    []
COPYBARA_INTEGRATE_REVIEW=https://github.com/bazelbuild/rules_cc/pull/701 from keith:ks/add-best-effort-toolchain-feature-docs a3d5890bb21f486f7efc3119d617fa75219a4fd0
PiperOrigin-RevId: 947387247
Change-Id: Ia10796f8289aa973bda5fc5226acf7d4a0558921
diff --git a/docs/features.md b/docs/features.md
new file mode 100644
index 0000000..bf430cc
--- /dev/null
+++ b/docs/features.md
@@ -0,0 +1,615 @@
+# CC Toolchain Features
+
+NOTE: It's possible this document has drifted, please file issues or
+submit PRs for any inaccuracies you find
+
+## Toolchain features
+
+CC toolchains are configured by creating features. Features are
+arbitrary strings for enabling or disabling behavior in the toolchain.
+
+Semantically there are 3 types of features:
+
+1. Features whose names are arbitrary, and are only used to carry
+   command line flags.
+2. Features with special names which are markers to bazel / `rules_cc`
+   that some behavior should be enabled or is supported by the toolchain
+3. Features with special names, that are also expected to pass the
+   various compiler / linker flags to enable some behavior.
+
+With all features, even though the feature name may have special meaning
+to `rules_cc`, it is still up to your toolchain to provide the correct
+compiler flags for your situation.
+
+Depending on how bazel / `rules_cc` read the features, you might need to
+define them differently.
+
+In some cases `rules_cc` checks if a feature is *supported*, or it
+automatically _enables_ it when it's relevant. In this case that means a
+feature with that name is defined in the toolchain. For example:
+
+```bzl
+return [
+    cc_common.create_cc_toolchain_config_info(
+        features = [
+            feature(name = "dbg"), # Supported by the toolchain but off by default
+        ],
+        ...
+    ),
+]
+```
+
+This is separate from if a feature is *enabled*, which either means a
+feature is defined in the toolchain _and_ automatically enabled:
+
+This is separate from when a feature is *enabled*, which means one of
+the following:
+
+- The feature is defined in the toolchain _and_ enabled by default in
+  its definition:
+
+   ```bzl
+   feature(
+      name = "archive_param_file",
+      enabled = True,  # Enabled by default when defined
+   ),
+   ```
+
+- the feature is enabled by a user passing
+  `--features=archive_param_file`, setting `features =
+  ["archive_param_file"]` or through other mechanisms in the toolchain
+  definition (not covered here).
+
+This distinction is important for when `rules_cc` checks if a feature is
+enabled, without automatically enabling it. This is common for "marker"
+features. If `rules_cc` checks for a feature being enabled, it not
+existing in the toolchain will be treated the same as it being disabled.
+This means a toolchain that does not want to support a feature can omit
+it.
+
+In some cases `rules_cc` bases behavior on the presence of a feature,
+but doesn't require it to be enabled. This is rare but mentioned for the
+relevant features below.
+
+NOTE: Feature names aren't really considered public API, and are subject
+to change more frequently than the rest of the API (even though their
+behavior likely doesn't change often).
+
+NOTE: While this document attempts to cover `rules_cc` behavior, it is
+possible for any custom rule to read the features of the toolchain and
+change its behavior based on them.
+
+## Legacy features
+
+By default, unless you add the
+[`no_legacy_features`](#no_legacy_features) feature to your toolchain,
+you will automatically inherit the features (and action configurations)
+defined in
+[`legacy_features.bzl`](../cc/private/toolchain_config/legacy_features.bzl).
+It is recommended that you override all features to avoid this
+potentially confusing behavior. You can read that file to see the
+current defaults.
+
+If you do not add a `no_legacy_features` feature, any features you add
+with the same name as a legacy feature will override the default
+behavior, but any that you omit will be added to your toolchain
+implicitly.
+
+## All features
+
+Below are all of the features names that currently have special meaning
+for bazel / `rules_cc`, or are commonly used directly by users.
+
+### `archive_param_file`
+
+A marker feature indicating that the archiver supports reading arguments
+from a `@params` file.
+
+This feature must be enabled if desired.
+
+### `compiler_param_file`
+
+A marker feature indicating that bazel / `rules_cc` should pass
+arguments to the compiler with a `@params` file.
+
+This feature must be enabled if desired.
+
+### `compiler_param_file_on_demand`
+
+A marker feature indicating that bazel / `rules_cc` should pass
+arguments to the compiler with a `@params` file only when it seems like
+it will be needed based on command length.
+
+This feature must be enabled if desired.
+
+### `compile_all_modules`
+
+A marker feature that causes all headers in the generated `modulemap`s
+for [`layering_check`](#layering_check) to be written as compilable
+`header` instead of `textual header`, which causes `clang` to attempt
+to build a compiled module from them. This is required for actually
+building modules from the generated `modulemap`s, which isn't
+necessary for common `layering_check` uses.
+
+Expected to be supported for Swift interop.
+
+This feature must be enabled if desired.
+
+### `copy_dynamic_libraries_to_binary`
+
+A marker feature that causes bazel to copy dependent shared libraries to
+the output directory of a `cc_binary` when linking against them. This is
+commonly used on Windows.
+
+This feature must be enabled if desired.
+
+### `coverage` / `gcc_coverage_map_format` / `llvm_coverage_map_format`
+
+Bazel / `rules_cc` automatically enables the `coverage` feature when
+using `bazel coverage` or `bazel build --collect_code_coverage`. It then
+either enables `gcc_coverage_map_format` (default) or
+`llvm_coverage_map_format` (if `--experimental_use_llvm_covmap` is set).
+At this point it is up to the toolchain to pass the correct compiler /
+linker flags to produce the instrumented binaries.
+
+These features are all off by default. Toolchains should make the format
+features dependent on `coverage` being enabled.
+
+### `cpp_modules`
+
+A marker feature for enabling C++20 modules. This also depends on
+`--experimental_cpp_modules` being passed.
+
+This feature must be enabled if desired.
+
+### `dbg` / `fastbuild` / `opt`
+
+These features are requested based on
+[`--compilation_mode`](https://bazel.build/reference/command-line-reference#flag--compilation_mode)
+and primarily useful for customizing other features in the toolchain.
+
+These features are mutually exclusive and one is always enabled. By
+default they are all disabled in a toolchain definition.
+
+### `dead_strip`
+
+This feature is requested based on
+[`--objc_enable_binary_stripping`](https://bazel.build/reference/command-line-reference#flag--objc_enable_binary_stripping)
+and commonly correlates with the `-dead_strip` linker flag.
+
+This feature should be off by default.
+
+### `disable_whole_archive_for_static_lib`
+
+Disable allowing `alwayslink = True` usage on a library.
+
+This feature should be off by default.
+
+### `dynamic_link_test_srcs`
+
+A marker feature that affects linking behavior of `cc_test` targets. See
+the source for details.
+
+This feature should be off by default.
+
+### `exclude_private_headers_in_module_maps`
+
+A marker feature for excluding private headers from the generated
+`modulemap`s for [`layering_check`](#layering_check). Otherwise private
+headers are included with `private header`.
+
+Expected to be supported for Swift interop.
+
+This feature should be off by default.
+
+### `external_include_paths`
+
+A marker feature indicating that all external bazel modules' include
+paths should be passed through `-isystem` instead of `-I`. This is still
+up to the toolchain to configure correctly, but this affects the
+toolchain variables the include paths are passed through.
+
+This feature should be off by default.
+
+### `force_no_whole_archive` / `legacy_whole_archive`
+
+Deprecated marker features to disable linking shared libraries with
+`--whole-archive` by default.
+
+These features should be off by default.
+
+### `fully_static_link`
+
+`fully_static_link` is not used by `rules_cc` directly but is
+recommended in the `cc_binary` documentation for producing fully
+statically linked binaries. If you want to support this it should be
+implemented in your toolchain. For example the default implementation is
+to pass `-static` to the linker when this feature is enabled.
+
+This feature is off by default.
+
+### `gcc_quoting_for_param_files` / `windows_quoting_for_param_files`
+
+Marker features to configure the quoting style of arguments in `@params`
+files. If neither are enabled, no quoting is applied.
+
+These features must be enabled if desired.
+
+### `generate_submodules`
+
+A marker feature for generating submodules for each header in the
+generated `modulemap`s for [`layering_check`](#layering_check).
+
+This feature should be off by default.
+
+### `has_configured_linker_path`
+
+A marker feature indicating that when creating an interface shared
+library, the toolchain calls the default configured linker. In this case
+it's up to the default linker and toolchain to correctly emit both the
+normal shared library, and the interface library. If this is not set
+`rules_cc` uses the `@bazel_tools//tools/cpp:link_dynamic_library`
+helper instead (which might not work with all toolchain configurations).
+
+This feature should be enabled if desired.
+
+### `header_module_codegen` / `header_modules` / `use_header_modules`
+
+Use `clang` modules for some cases. Read the source for details.
+
+These features should be off by default.
+
+### `generate_dsym_file` / `no_generate_debug_symbols`
+
+`generate_dsym_file` is requested based on
+[`--apple_generate_dsym`](https://bazel.build/reference/command-line-reference#flag--apple_generate_dsym)
+and indicates that the toolchain should generate a dsym file for
+debugging on Apple platforms. `no_generate_debug_symbols` is set in the opposite case.
+
+These features should be off by default.
+
+### `generate_linkmap`
+
+This feature is requested based on
+[`--objc_generate_linkmap`](https://bazel.build/reference/command-line-reference#flag--objc_generate_linkmap)
+and commonly correlates with the `-map` linker flag.
+
+This feature should be off by default.
+
+### `generate_pdb_file`
+
+This feature indicates a Windows `pdb` file should be created when
+linking a binary. This must be enabled by the user or the toolchain.
+
+This feature must be enabled if desired.
+
+### `lang_objc`
+
+A marker feature indicating that Objective-C or Objective-C++ is being
+built.
+
+This feature should be off by default.
+
+### `layering_check`
+
+Enable validation that a library directly depends on everything it uses.
+This is implemented using `clang`'s `modulemap` features. See the
+default toolchains for implementation examples. `rules_cc` does not
+reference this feature directly, but the name `layering_check` is used
+by users to enable this behavior, and disable it for incompatible
+targets.
+
+This feature should be off by default and turned on at the project /
+target level.
+
+### LTO features
+
+Bazel / `rules_cc` have many special features for LTO behavior:
+
+- `thin_lto` top level feature that is also used by users
+- `thin_lto_all_linkstatic_use_shared_nonlto_backends` read the source
+- `thin_lto_linkstatic_tests_use_shared_nonlto_backends` read the source
+- `no_use_lto_indexing_bitcode_file` read the source
+- `use_lto_native_object_directory` read the source
+
+These features must be enabled if desired.
+
+### `module_maps`
+
+A marker feature that should always be enabled if supported indicating
+that the compiler supports `modulemap` files (`clang`). This is required
+for `layering_check`.
+
+This feature should be enabled by default if supported.
+
+### `module_map_home_cwd`
+
+Whether a `modulemap` used with [`layering_check`](#layering_check)
+should use its current directory as the `cwd`. This affects relative
+paths in the generated `modulemap`s. This is only useful if you need to
+also pass the related `clang` flags.
+
+This feature should be off by default.
+
+### `module_map_without_extern_module`
+
+A marker feature to disable writing `extern module` declarations in the
+generated `modulemap`s for [`layering_check`](#layering_check).
+
+Expected to be supported for Swift interop.
+
+This feature should be off by default.
+
+### `no_dotd_file`
+
+A marker feature for disabling `.d` file generating and parsing by
+bazel. Dotd file parsing is also dependent on
+[`--cc_dotd_files`](https://bazel.build/reference/command-line-reference#flag--cc_dotd_files)
+and
+[`--objc_use_dotd_pruning`](https://bazel.build/reference/command-line-reference#flag--objc_use_dotd_pruning)
+
+This feature should be off by default.
+
+### `no_legacy_features`
+
+Disable `rules_cc` automatically adding the legacy features to the
+toolchain (discussed  above).
+
+This feature should be added if possible, but its enabled state does no
+matter.
+
+### `no_stripping`
+
+When enabled `rules_cc` does not strip a `cc_binary` to create the
+implicit `binary.stripped`, instead it is only symlinked.
+
+This feature should be off by default.
+
+### `only_doth_headers_in_module_maps`
+
+A marker feature for only including `.h` files in the generated
+`modulemap`s for [`layering_check`](#layering_check). Otherwise public
+headers with any extension are included.
+
+Expected to be supported for Swift interop.
+
+This should be off by default.
+
+### `parse_headers`
+
+This feature is used alongside
+[`--process_headers_in_dependencies`](https://bazel.build/reference/command-line-reference#flag--process_headers_in_dependencies)
+to run a separate action that validates header files are valid on their
+own. This feature is special to `rules_cc` but is also used by users to
+enable this behavior, and disable it for incompatible targets.
+
+See also [`layering_check`](#layering_check)
+
+This should be off by default and turned on at the project / target
+level.
+
+### `parse_headers_as_c`
+
+This feature is used alongside `parse_headers` to parse headers as C
+instead of C++. This is useful headers that are not valid C++.
+
+This should be off by default and turned on at the project / target
+level.
+
+### `parse_showincludes`
+
+A marker feature for enabling parsing of the output of `/showIncludes`
+to generate `.d` for parsing by bazel. Dotd file parsing is also
+dependent on
+[`--cc_dotd_files`](https://bazel.build/reference/command-line-reference#flag--cc_dotd_files)
+and
+[`--objc_use_dotd_pruning`](https://bazel.build/reference/command-line-reference#flag--objc_use_dotd_pruning)
+
+This feature should be enabled by default if supported.
+
+### `per_object_debug_info`
+
+This feature name, alongside the value of
+[`--fission`](https://bazel.build/reference/command-line-reference#flag--fission)
+is used to determine if debug info should be produced in a separate file
+from the object file.
+
+This feature is off by default.
+
+### `pic` / `supports_pic`
+
+Bazel / `rules_cc` checks if your toolchain has an enabled feature named
+`supports_pic` to determine if position independent code is supported at
+all. If so it also expects an enabled feature named `pic` which actually
+adds the relevant compiler flags in the correct cases (only when the
+`pic` variable is enabled). You should also add another feature that
+respects the `force_pic` variable, which reacts to the `--force_pic`
+flag.
+
+See also [`prefer_pic_for_opt_binaries`](#prefer_pic_for_opt_binaries)
+
+`pic`, `supports_pic`, and the optional `force_pic` feature, should all
+be enabled by default if PIC is supported. The implementation of these
+features should be contingent on the relevant variables being set. See
+the default toolchains for an example.
+
+### `prefer_pic_for_opt_binaries`
+
+A marker feature to automatically enable position independent code when
+using `--compilation_mode=opt`.
+
+This feature must be enabled if desired.
+
+### Profile guided optimization features
+
+`rules_cc` has quite a few PGO/FDO features, which are all automatically
+enabled based on various [`--fdo_*`](https://bazel.build/reference/command-line-reference#flag--fdo_instrument)
+flags it supports. To get the most up to date information on how all of
+these fit together it's best to look at the code. The combination of all
+of these features likely isn't well tested today.
+
+The current list of features (not all of these are provided by the
+legacy features) is:
+
+- `autofdo`
+- `cs_fdo_instrument`
+- `cs_fdo_optimize`
+- `enable_afdo_thinlto`
+- `enable_autofdo_memprof_optimize`
+- `enable_fdo_memprof_optimize`
+- `enable_fdo_split_functions`
+- `enable_fdo_thinlto`
+- `enable_fsafdo`
+- `enable_xbinaryfdo_thinlto`
+- `fdo_instrument`
+- `fdo_optimize`
+- `fdo_prefetch_hints`
+- `propeller_optimize_thinlto_compile_actions`
+- `propeller_optimize`
+- `xbinary_fdo`
+- `xbinaryfdo` (yes both of these exist)
+
+All of these features are off by default.
+
+
+### `no_copts_tokenization`
+
+A marker feature to disable shell tokenization of `copts` in the toolchain.
+This can be used by users to make sure special characters that are
+expected in `defines` / `copts` are not processed. This is required in
+some cases when you have quoted arguments.
+
+This feature takes effect even if the toolchain doesn't define it. There
+is no purpose in adding it to your toolchain unless you want to enable
+it everywhere.
+
+### `sanitize_pwd`
+
+A marker feature indicating the toolchain has sanitized the `PWD` from
+the outputs. Otherwise `rules_cc` will set `PWD=/proc/self/cwd` (unless
+on macOS) when linking a binary. This is commonly used when
+`-fdebug-prefix-map` is supported by the compiler.
+
+This feature must be enabled by default if supported.
+
+### `set_soname`
+
+A marker feature that causes interface libraries to respect the `soname`
+they have. Otherwise `-soname` is passed when creating interface libraries.
+
+This feature must be enabled by default if supported.
+
+### `serialized_diagnostics_file`
+
+A marker feature for enabling generating a serialized diagnostics file
+from the compiler. Commonly used with the `--serialize-diagonostics`
+`clang` flag.
+
+This feature should be off by default and requested through `--features`
+when desired.
+
+### `shorten_virtual_includes`
+
+A marker feature that causes virtual include paths generated by
+`strip_include_prefix` and friends to use a shorter path. This is useful
+on Windows to avoid long path issues.
+
+This feature must be enabled by default if desired.
+
+### `static_link_cpp_runtimes`
+
+A marker feature used by `rules_cc` to determine if the toolchain
+should statically link the C++ runtime libraries.
+
+This feature must be enabled if desired.
+
+### `supports_dynamic_linker`
+
+A marker feature that indicates 2 things:
+
+1. That `cc_library` targets can create "nodeps" shared libraries for
+   use with
+   [`--dynamic_mode`](https://bazel.build/reference/command-line-reference#flag--dynamic_mode).
+   This requires shared libraries can be created without seeing their
+   dependencies' symbols, which can lead to runtime crashes, but can
+   reduce large static links for small changes.
+2. Whether a `cc_binary` prefers linking static over shared libraries
+   when both are available for a target.
+
+This feature must be enabled if supported. Otherwise it should be
+omitted from the toolchain.
+
+### `supports_interface_shared_libraries`
+
+A marker feature indicating that the toolchain supports creating
+interface libraries for a shared libraries. This can be used to reduce
+input tree size of downstream linking actions.
+
+This feature must be enabled if supported.
+
+### `supports_start_end_lib`
+
+Whether the toolchain supports using the `--start-lib` / `--end-lib`
+linker flags. This is required for use with `LTO`.
+
+This feature must be enabled if supported.
+
+### `symbol_check`
+
+A feature automatically requested by `cc_static_library` that enables
+the toolchain to enable optional validation around the symbols in the
+produced static library.
+
+This feature should be off by default and is automatically requested by
+`cc_static_library`.
+
+### `system_include_paths`
+
+A marker feature indicating that include paths from the `includes`
+attribute of a target should be passed with `-isystem` instead of `-I`.
+This is still up to the toolchain to configure correctly, but this
+affects the toolchain variables the include paths are passed through.
+This is expected to be set by users when necessary (hopefully rarely).
+
+This feature takes effect even if the toolchain doesn't define it. There
+is no purpose in adding it to your toolchain unless you want to enable
+it everywhere.
+
+### `targets_windows`
+
+This is used by `rules_cc` to change the behavior in various places only
+when building for Windows. If your toolchain targets Windows this should
+be enabled.
+
+This feature must be enabled if targeting Windows.
+
+### `treat_warnings_as_errors`
+
+A user-enabled feature requesting that warnings are treated as errors.
+This is not special to `rules_cc`. This is commonly used with the
+`-Werror` compiler flag.
+
+This feature should be off by default.
+
+### `validates_layering_check_in_textual_hdrs`
+
+Whether `layering_check` should also apply to the `textual_hdrs`
+attribute of targets.
+
+See also [`layering_check`](#layering_check)
+
+This feature must be enabled if desired.
+
+### `windows_export_all_symbols` / `no_windows_export_all_symbols`
+
+Marker features to configure whether a `.def` should be created. The
+negating feature wins if both are enabled.
+
+This feature must be enabled if desired.
+
+### `warn_backrefs_defined`
+
+A marker feature indicating `-Wl,--warn-backrefs-exclude` should be
+passed when linking static libraries downstream of a `cc_import`
+
+This feature must be enabled if desired.