13
13
# limitations under the License.
14
14
15
15
# buildifier: disable=module-docstring
16
+ load ("@bazel_skylib//rules:common_settings.bzl" , "BuildSettingInfo" )
16
17
load (
17
18
"@bazel_tools//tools/build_defs/cc:action_names.bzl" ,
18
19
"CPP_LINK_EXECUTABLE_ACTION_NAME" ,
@@ -47,6 +48,22 @@ AliasableDepInfo = provider(
47
48
},
48
49
)
49
50
51
+ IncrementalInfo = provider (
52
+ doc = "Data relating to incremental compilation." ,
53
+ fields = {
54
+ "base" : "string: base folder to store incremental build products" ,
55
+ "prefixes" : "IncrementalPrefixInfo: prefixes to include and exclude" ,
56
+ },
57
+ )
58
+
59
+ IncrementalPrefixInfo = provider (
60
+ doc = "Prefixes to include and exclude in incremental compilation." ,
61
+ fields = {
62
+ "exclude" : "List[string]: prefixes that will exclude a label if matched" ,
63
+ "include" : "List[string]: prefixes that will include a label if matched" ,
64
+ },
65
+ )
66
+
50
67
_error_format_values = ["human" , "json" , "short" ]
51
68
52
69
ErrorFormatInfo = provider (
@@ -492,7 +509,8 @@ def rustc_compile_action(
492
509
crate_info ,
493
510
output_hash = None ,
494
511
rust_flags = [],
495
- environ = {}):
512
+ environ = {},
513
+ incremental_info = None ):
496
514
"""Create and run a rustc compile action based on the current rule's attributes
497
515
498
516
Args:
@@ -503,6 +521,7 @@ def rustc_compile_action(
503
521
output_hash (str, optional): The hashed path of the crate root. Defaults to None.
504
522
rust_flags (list, optional): Additional flags to pass to rustc. Defaults to [].
505
523
environ (dict, optional): A set of makefile expandable environment variables for the action
524
+ incremental_info (str, optional): path to store incremental build products in.
506
525
507
526
Returns:
508
527
list: A list of the following providers:
@@ -554,14 +573,34 @@ def rustc_compile_action(
554
573
else :
555
574
formatted_version = ""
556
575
576
+ if (incremental_info and
577
+ incremental_info .base and
578
+ _want_incremental_compile (ctx .label , incremental_info .prefixes )):
579
+ incremental_dir = "{}/{}_{}" .format (
580
+ incremental_base ,
581
+ ctx .var ["COMPILATION_MODE" ],
582
+ toolchain .target_triple ,
583
+ )
584
+ args .add ("--codegen" , "incremental=" + incremental_dir )
585
+
586
+ # with sandboxing enabled, subsequent rustc invocations will crash,
587
+ # as it doesn't expect the source files to have moved
588
+ execution_requirements = {"no-sandbox" : "1" }
589
+ mnemonic = "RustIncr"
590
+ else :
591
+ execution_requirements = {}
592
+ mnemonic = "Rustc"
593
+
557
594
ctx .actions .run (
558
595
executable = ctx .executable ._process_wrapper ,
559
596
inputs = compile_inputs ,
560
597
outputs = [crate_info .output ],
561
598
env = env ,
562
599
arguments = [args ],
563
- mnemonic = "Rustc" ,
564
- progress_message = "Compiling Rust {} {}{} ({} files)" .format (
600
+ mnemonic = mnemonic ,
601
+ execution_requirements = execution_requirements ,
602
+ progress_message = "Compiling {} {} {}{} ({} files)" .format (
603
+ mnemonic ,
565
604
crate_info .type ,
566
605
ctx .label .name ,
567
606
formatted_version ,
@@ -934,3 +973,75 @@ error_format = rule(
934
973
implementation = _error_format_impl ,
935
974
build_setting = config .string (flag = True ),
936
975
)
976
+
977
+ def _incremental_base_impl (ctx ):
978
+ """Implementation for the incremental_base() rule
979
+
980
+ Args:
981
+ ctx (ctx): The rule's context object
982
+
983
+ Returns:
984
+ BuildSettingInfo: an object with a `value` attribute containing the string.
985
+ """
986
+ value = ctx .build_setting_value
987
+ return BuildSettingInfo (value = value )
988
+
989
+ incremental_base = rule (
990
+ build_setting = config .string (flag = True ),
991
+ implementation = _incremental_base_impl ,
992
+ doc = "Declares a command line argument that accepts an arbitrary string." ,
993
+ )
994
+
995
+ def _incremental_prefixes_impl (ctx ):
996
+ """Implementation for the incremental_prefixes_flag() rule
997
+
998
+ Splits the provided string on commas, and then partitions prefixes starting
999
+ with a hypen into the exclude list, returning a provider with the include
1000
+ and exclude list. The hypens are stripped from the entries in the exclude list.
1001
+
1002
+ Args:
1003
+ ctx (ctx): The rule's context object
1004
+
1005
+ Returns:
1006
+ (IncrementalPrefixInfo): a list of prefixes to include and exclude
1007
+ """
1008
+ values = ctx .build_setting_value .split ("," )
1009
+ include = []
1010
+ exclude = []
1011
+ for value in ctx .build_setting_value .split ("," ):
1012
+ if not value :
1013
+ continue
1014
+ elif value .startswith ("-" ):
1015
+ exclude .append (value [1 :])
1016
+ else :
1017
+ include .append (value )
1018
+ return IncrementalPrefixInfo (include = include , exclude = exclude )
1019
+
1020
+ incremental_prefixes = rule (
1021
+ build_setting = config .string (flag = True ),
1022
+ implementation = _incremental_prefixes_impl ,
1023
+ doc = """Declares a command line argument for incremental prefixes.
1024
+
1025
+ See _incremental_prefixes_impl() for the details.
1026
+ """ ,
1027
+ )
1028
+
1029
+ def _want_incremental_compile (label , prefixes ):
1030
+ """True if the provided prefixes indicate the target should be incrementally compiled.
1031
+
1032
+ Args:
1033
+ label (Label): the label for a given target
1034
+ prefixes (IncrementalPrefixInfo): prefixes to include and exclude
1035
+
1036
+ Returns:
1037
+ bool
1038
+ """
1039
+ label = str (label )
1040
+ for prefix in prefixes .exclude :
1041
+ if label .startswith (prefix ):
1042
+ return False
1043
+ for prefix in prefixes .include :
1044
+ if label .startswith (prefix ):
1045
+ return True
1046
+
1047
+ return False
0 commit comments