@@ -58,7 +58,7 @@ def remove_non_visible_lines(raw_output: bytes) -> str:
5858class BuildDir :
5959 def __init__ (self , build_ninja : str ):
6060 self .build_ninja = dedent (build_ninja )
61- self .d = None
61+ self .d : None | tempfile . TemporaryDirectory [ str ] = None
6262
6363 def __enter__ (self ):
6464 self .d = tempfile .TemporaryDirectory ()
@@ -70,8 +70,16 @@ def __enter__(self):
7070 def __exit__ (self , exc_type , exc_val , exc_tb ):
7171 self .d .cleanup ()
7272
73+ def write_file (self , path : str , content : str ) -> None :
74+ assert self .d
75+ file_path = os .path .join (self .d .name , path )
76+ os .makedirs (os .path .dirname (file_path ), exist_ok = True )
77+ with open (file_path , "wt" ) as f :
78+ f .write (content )
79+
7380 @property
7481 def path (self ) -> str :
82+ assert self .d
7583 return os .path .realpath (self .d .name )
7684
7785
@@ -111,13 +119,13 @@ def run(
111119 try :
112120 if pipe :
113121 output = subprocess .check_output (
114- [ninja_cmd ], shell = True , cwd = self .d . name , env = env )
122+ [ninja_cmd ], shell = True , cwd = self .path , env = env )
115123 elif platform .system () == 'Darwin' :
116124 output = subprocess .check_output (['script' , '-q' , '/dev/null' , 'bash' , '-c' , ninja_cmd ],
117- cwd = self .d . name , env = env )
125+ cwd = self .path , env = env )
118126 else :
119127 output = subprocess .check_output (['script' , '-qfec' , ninja_cmd , '/dev/null' ],
120- cwd = self .d . name , env = env )
128+ cwd = self .path , env = env )
121129 except subprocess .CalledProcessError as err :
122130 if print_err_output :
123131 sys .stdout .buffer .write (err .output )
@@ -366,8 +374,8 @@ def test_depfile_directory_creation(self) -> None:
366374 self .assertEqual (b .run ('' , pipe = True ), dedent ('''\
367375 [1/1] touch somewhere/out && echo "somewhere/out: extra" > somewhere_else/out.d
368376 ''' ))
369- self .assertTrue (os .path .isfile (os .path .join (b .d . name , "somewhere" , "out" )))
370- self .assertTrue (os .path .isfile (os .path .join (b .d . name , "somewhere_else" , "out.d" )))
377+ self .assertTrue (os .path .isfile (os .path .join (b .path , "somewhere" , "out" )))
378+ self .assertTrue (os .path .isfile (os .path .join (b .path , "somewhere_else" , "out.d" )))
371379
372380 def test_status (self ) -> None :
373381 self .assertEqual (run ('' ), 'ninja: no work to do.\n ' )
@@ -468,6 +476,39 @@ def test_tool_inputs(self) -> None:
468476 f'''in1\0 out1\0 out 2\0 '''
469477 )
470478
479+ def test_tool_inputs_with_depfile_entries (self ) -> None :
480+ build_ninja = '''
481+ rule touch
482+ command = touch $out && echo "$out: $extras" > $depfile
483+ depfile = $out.d
484+
485+ build out1: touch in1
486+ deps = gcc
487+ extras = extra extra2
488+
489+ build out2: touch in2
490+ extras = extra3 extra4
491+ # No deps = gcc here intentionally
492+ '''
493+ with BuildDir (build_ninja ) as b :
494+ # Do not run the build (empty deps log).
495+ self .assertEqual (b .run (flags = '-t inputs out1' ), 'in1\n ' )
496+ self .assertEqual (b .run (flags = '-t inputs --depfile out1' ), 'in1\n ' )
497+
498+ self .assertEqual (b .run (flags = '-t inputs out2' ), 'in2\n ' )
499+ self .assertEqual (b .run (flags = '-t inputs --depfile out2' ), 'in2\n ' )
500+
501+ # Run the plan and create the log entry for 'out'
502+ b .write_file ("in1" , "" )
503+ b .write_file ("in2" , "" )
504+ b .run ('out1 out2' )
505+
506+ # Check with a full deps log.
507+ self .assertEqual (b .run (flags = '-t inputs out1' ), 'in1\n ' )
508+ self .assertEqual (b .run (flags = '-t inputs --depfile out1' ), 'extra\n extra2\n in1\n ' )
509+
510+ self .assertEqual (b .run (flags = '-t inputs out2' ), 'in2\n ' )
511+ self .assertEqual (b .run (flags = '-t inputs --depfile out2' ), 'extra3\n extra4\n in2\n ' )
471512
472513 def test_tool_compdb_targets (self ) -> None :
473514 plan = '''
@@ -556,6 +597,90 @@ def test_tool_multi_inputs(self) -> None:
556597 )
557598
558599
600+ def test_tool_multi_inputs_with_depfile_entries (self ) -> None :
601+ build_ninja = '''
602+ rule touch1
603+ command = touch $out && echo "$out: extra extra2" > $depfile
604+ depfile = $out.d
605+ deps = gcc
606+
607+ rule touch2
608+ command = touch $out && echo "$out: extra extra3" > $depfile
609+ depfile = $out.d
610+ # Do not use deps = gcc here intentionally
611+
612+ build out1: touch1 in1
613+ build out2: touch2 in2
614+ '''
615+
616+ # Helper function to replace <TAB> with real tabs in input text.
617+ def t (text ):
618+ if text [0 ] == '\n ' : # skip initial newline if any.
619+ text = text [1 :]
620+ return text .replace ("<TAB>" , "\t " )
621+
622+ with BuildDir (build_ninja ) as b :
623+ # Run the plan and create the log entries for 'out1' and 'out2'
624+ b .write_file ("in1" , "1" )
625+ b .write_file ("in2" , "2" )
626+ b .run ('out1 out2' )
627+
628+ self .assertEqual (b .run (flags = '-t multi-inputs' ), t ('''
629+ out1<TAB>in1
630+ out2<TAB>in2
631+ ''' ))
632+ self .assertEqual (b .run (flags = '-t multi-inputs out1' ), t ('out1<TAB>in1\n ' ))
633+ self .assertEqual (b .run (flags = '-t multi-inputs out2' ), t ('out2<TAB>in2\n ' ))
634+ self .assertEqual (b .run (flags = '-t multi-inputs out1 out2' ), t ('''
635+ out1<TAB>in1
636+ out2<TAB>in2
637+ ''' ))
638+ self .assertEqual (b .run (flags = '-t multi-inputs out2 out1' ), t ('''
639+ out2<TAB>in2
640+ out1<TAB>in1
641+ ''' ))
642+
643+ self .assertEqual (b .run (flags = '-t multi-inputs --depfile' ), t ('''
644+ out1<TAB>in1
645+ out1<TAB>extra
646+ out1<TAB>extra2
647+ out2<TAB>in2
648+ out2<TAB>extra
649+ out2<TAB>extra3
650+ ''' ))
651+
652+ self .assertEqual (b .run (flags = '-t multi-inputs --depfile out1' ), t ('''
653+ out1<TAB>in1
654+ out1<TAB>extra
655+ out1<TAB>extra2
656+ ''' ))
657+
658+ self .assertEqual (b .run (flags = '-t multi-inputs --depfile out2' ), t ('''
659+ out2<TAB>in2
660+ out2<TAB>extra
661+ out2<TAB>extra3
662+ ''' ))
663+
664+ self .assertEqual (b .run (flags = '-t multi-inputs --depfile out1 out2' ), t ('''
665+ out1<TAB>in1
666+ out1<TAB>extra
667+ out1<TAB>extra2
668+ out2<TAB>in2
669+ out2<TAB>extra
670+ out2<TAB>extra3
671+ ''' ))
672+
673+ self .assertEqual (b .run (flags = '-t multi-inputs --depfile out2 out1' ), t ('''
674+ out2<TAB>in2
675+ out2<TAB>extra
676+ out2<TAB>extra3
677+ out1<TAB>in1
678+ out1<TAB>extra
679+ out1<TAB>extra2
680+ ''' ))
681+
682+
683+
559684 def test_explain_output (self ):
560685 b = BuildDir ('''\
561686 build .FORCE: phony
0 commit comments