Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions swift/internal/compiling.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ load(
"SWIFT_FEATURE_DECLARE_SWIFTSOURCEINFO",
"SWIFT_FEATURE_EMIT_BC",
"SWIFT_FEATURE_EMIT_C_MODULE",
"SWIFT_FEATURE_EMIT_DIAGNOSTICS",
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
"SWIFT_FEATURE_EMIT_SWIFTDOC",
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
Expand Down Expand Up @@ -438,6 +439,10 @@ def compile(
representations of constant values extracted from the source
files, if requested via a direct dependency.

* `diagnostics_files`: A list of `File`s that contains serialized
diagnostics (.dia) emitted by the compiler when the feature
`swift.emit_diagnostics` is enabled.

* `indexstore_directory`: A directory-type `File` that represents
the indexstore output files created when the feature
`swift.index_while_building` is enabled.
Expand Down Expand Up @@ -522,7 +527,7 @@ def compile(
if split_derived_file_generation:
all_compile_outputs = compact([
compile_outputs.indexstore_directory,
]) + compile_outputs.object_files + compile_outputs.const_values_files
]) + compile_outputs.object_files + compile_outputs.const_values_files + compile_outputs.diagnostics_files
all_derived_outputs = compact([
# The `.swiftmodule` file is explicitly listed as the first output
# because it will always exist and because Bazel uses it as a key for
Expand Down Expand Up @@ -550,7 +555,7 @@ def compile(
compile_outputs.generated_header_file,
compile_outputs.indexstore_directory,
compile_outputs.macro_expansion_directory,
]) + compile_outputs.object_files + compile_outputs.const_values_files
]) + compile_outputs.object_files + compile_outputs.const_values_files + compile_outputs.diagnostics_files
all_derived_outputs = []

# In `upstream` they call `merge_compilation_contexts` on passed in
Expand Down Expand Up @@ -830,6 +835,7 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
supplemental_outputs = struct(
ast_files = compile_outputs.ast_files,
const_values_files = compile_outputs.const_values_files,
diagnostics_files = compile_outputs.diagnostics_files,
indexstore_directory = compile_outputs.indexstore_directory,
macro_expansion_directory = compile_outputs.macro_expansion_directory,
),
Expand Down Expand Up @@ -1340,6 +1346,11 @@ def _declare_compile_outputs(
indexstore_directory = None
include_index_unit_paths = False

emit_diagnostics = is_feature_enabled(
feature_configuration = feature_configuration,
feature_name = SWIFT_FEATURE_EMIT_DIAGNOSTICS,
)

if not output_nature.emits_multiple_objects:
# If we're emitting a single object, we don't use an object map; we just
# declare the output file that the compiler will generate and there are
Expand All @@ -1356,6 +1367,18 @@ def _declare_compile_outputs(
const_values_files = [
actions.declare_file("{}.swiftconstvalues".format(target_name)),
]
if emit_diagnostics:
diagnostics_files = [
_declare_per_source_output_file(
actions = actions,
extension = "dia",
target_name = target_name,
src = srcs[0],
),
actions.declare_file("{}.dia".format(target_name)),
]
else:
diagnostics_files = []
output_file_map = None
derived_files_output_file_map = None
# TODO(b/147451378): Support indexing even with a single object file.
Expand Down Expand Up @@ -1389,6 +1412,7 @@ def _declare_compile_outputs(
# object files so that we can pass them all to the archive action.
output_info = _declare_multiple_outputs_and_write_output_file_map(
actions = actions,
emit_diagnostics = emit_diagnostics,
extract_const_values = extract_const_values,
is_wmo = output_nature.is_wmo,
emits_bc = emits_bc,
Expand All @@ -1400,6 +1424,7 @@ def _declare_compile_outputs(
object_files = output_info.object_files
ast_files = output_info.ast_files
const_values_files = output_info.const_values_files
diagnostics_files = output_info.diagnostics_files
output_file_map = output_info.output_file_map
derived_files_output_file_map = output_info.derived_files_output_file_map

Expand All @@ -1416,6 +1441,7 @@ def _declare_compile_outputs(
compile_outputs = struct(
ast_files = ast_files,
const_values_files = const_values_files,
diagnostics_files = diagnostics_files,
generated_header_file = generated_header,
generated_module_map_file = generated_module_map,
indexstore_directory = indexstore_directory,
Expand Down Expand Up @@ -1459,6 +1485,7 @@ def _declare_per_source_output_file(actions, extension, target_name, src):

def _declare_multiple_outputs_and_write_output_file_map(
actions,
emit_diagnostics,
extract_const_values,
is_wmo,
emits_bc,
Expand All @@ -1470,6 +1497,8 @@ def _declare_multiple_outputs_and_write_output_file_map(

Args:
actions: The object used to register actions.
emit_diagnostics: A Boolean value indicating whether serialized
diagnostics files (.dia) should be emitted during this compilation.
extract_const_values: A Boolean value indicating whether constant values
should be extracted during this compilation.
is_wmo: A Boolean value indicating whether whole-module-optimization was
Expand Down Expand Up @@ -1516,6 +1545,7 @@ def _declare_multiple_outputs_and_write_output_file_map(

# Output files that will be emitted by the compiler.
ast_files = []
diagnostics_files = []
output_objs = []
const_values_files = []

Expand All @@ -1526,6 +1556,13 @@ def _declare_multiple_outputs_and_write_output_file_map(
const_values_files.append(const_values_file)
whole_module_map["const-values"] = const_values_file.path

if emit_diagnostics and is_wmo:
diagnostics_file = actions.declare_file(
"{}.dia".format(target_name),
)
diagnostics_files.append(diagnostics_file)
whole_module_map["diagnostics"] = diagnostics_file.path

for src in srcs:
file_outputs = {}

Expand Down Expand Up @@ -1572,6 +1609,16 @@ def _declare_multiple_outputs_and_write_output_file_map(
const_values_files.append(const_values_file)
file_outputs["const-values"] = const_values_file.path

if emit_diagnostics and not is_wmo:
diagnostics_file = _declare_per_source_output_file(
actions = actions,
extension = "dia",
target_name = target_name,
src = src,
)
diagnostics_files.append(diagnostics_file)
file_outputs["diagnostics"] = diagnostics_file.path

output_map[src.path] = file_outputs

if whole_module_map:
Expand All @@ -1592,6 +1639,7 @@ def _declare_multiple_outputs_and_write_output_file_map(
ast_files = ast_files,
const_values_files = const_values_files,
derived_files_output_file_map = derived_files_output_map_file,
diagnostics_files = diagnostics_files,
object_files = output_objs,
output_file_map = output_map_file,
)
Expand Down
5 changes: 5 additions & 0 deletions swift/internal/feature_names.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,8 @@ SWIFT_FEATURE_ENABLE_CPP23_INTEROP = "swift.enable_cpp23_interop"
# automatically include it at compile time, and provide it to the linker at link time
# * alwayslink on swift_library() target will now default to False, as it is not required in embedded mode
SWIFT_FEATURE_ENABLE_EMBEDDED = "swift.enable_embedded"

# If enabled, requests the compiler to emit serialized diagnostics files (.dia)
# for each source file. These files contain machine-readable compiler
# diagnostics that can be consumed by IDEs and other tools.
SWIFT_FEATURE_EMIT_DIAGNOSTICS = "swift.emit_diagnostics"
5 changes: 5 additions & 0 deletions swift/internal/output_groups.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def supplemental_compilation_output_groups(
"""
ast_files = []
const_values_files = []
diagnostics_files = []
indexstore_files = list(additional_indexstore_files)
macro_expansions_files = []

Expand All @@ -45,6 +46,8 @@ def supplemental_compilation_output_groups(
ast_files.extend(outputs.ast_files)
if outputs.const_values_files:
const_values_files.extend(outputs.const_values_files)
if hasattr(outputs, "diagnostics_files") and outputs.diagnostics_files:
diagnostics_files.extend(outputs.diagnostics_files)
if outputs.indexstore_directory:
indexstore_files.append(outputs.indexstore_directory)
if outputs.macro_expansion_directory:
Expand All @@ -55,6 +58,8 @@ def supplemental_compilation_output_groups(
output_groups["swift_ast_file"] = depset(ast_files)
if const_values_files:
output_groups["const_values"] = depset(const_values_files)
if diagnostics_files:
output_groups["swift_diagnostics"] = depset(diagnostics_files)
if indexstore_files:
output_groups["swift_index_store"] = depset(indexstore_files)
if macro_expansions_files:
Expand Down
8 changes: 8 additions & 0 deletions swift/toolchains/config/compile_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ load(
"SWIFT_FEATURE_DISABLE_SYSTEM_INDEX",
"SWIFT_FEATURE_EMIT_BC",
"SWIFT_FEATURE_EMIT_C_MODULE",
"SWIFT_FEATURE_EMIT_DIAGNOSTICS",
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
"SWIFT_FEATURE_EMIT_SWIFTDOC",
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
Expand Down Expand Up @@ -159,6 +160,13 @@ def compile_action_configs(
features = [SWIFT_FEATURE_EMIT_BC],
),

# Emit serialized diagnostics file(s).
ActionConfigInfo(
actions = [SWIFT_ACTION_COMPILE],
configurators = [add_arg("-serialize-diagnostics")],
features = [SWIFT_FEATURE_EMIT_DIAGNOSTICS],
),

# Add the single object file or object file map, whichever is needed.
ActionConfigInfo(
actions = [SWIFT_ACTION_COMPILE],
Expand Down
3 changes: 3 additions & 0 deletions test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ load(":compiler_arguments_tests.bzl", "compiler_arguments_test_suite")
load(":const_values_tests.bzl", "const_values_test_suite")
load(":coverage_settings_tests.bzl", "coverage_settings_test_suite")
load(":debug_settings_tests.bzl", "debug_settings_test_suite")
load(":diagnostics_tests.bzl", "diagnostics_test_suite")
load(":environment_tests.bzl", "environment_test_suite")
load(":features_tests.bzl", "features_test_suite")
load(":generated_header_tests.bzl", "generated_header_test_suite")
Expand Down Expand Up @@ -45,6 +46,8 @@ coverage_settings_test_suite(name = "coverage_settings")

debug_settings_test_suite(name = "debug_settings")

diagnostics_test_suite(name = "diagnostics")

environment_test_suite(name = "environment")

features_test_suite(name = "features")
Expand Down
57 changes: 57 additions & 0 deletions test/diagnostics_tests.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2024 The Bazel Authors. All rights reserved.
#
# 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.

"""Tests for `swift.emit_diagnostics` feature."""

load(
"//test/rules:action_command_line_test.bzl",
"make_action_command_line_test_rule",
)
load(
"//test/rules:provider_test.bzl",
"provider_test",
)

diagnostics_command_line_test = make_action_command_line_test_rule(
config_settings = {
"//command_line_option:features": [
"swift.emit_diagnostics",
],
},
)

def diagnostics_test_suite(name, tags = []):
"""Test suite for `swift_library` producing .dia files.

Args:
name: The base name to be used in things created by this macro.
tags: Additional tags to apply to each test.
"""
all_tags = [name] + tags

diagnostics_command_line_test(
name = "{}_serialize_diagnostics_flag".format(name),
expected_argv = [
"-serialize-diagnostics",
],
mnemonic = "SwiftCompile",
tags = all_tags,
target_under_test = "//test/fixtures/basic:first",
)

native.test_suite(
name = name,
tags = all_tags,
)