20
20
from .. import dependencies
21
21
from .. import compilers
22
22
from ..mesonlib import File , MesonException , get_compiler_for_source , Popen_safe
23
- from .backends import InstallData
23
+ from .backends import CleanTrees , InstallData
24
24
from ..build import InvalidArguments
25
25
import os , sys , pickle , re
26
26
import subprocess , shutil
@@ -2109,6 +2109,22 @@ def generate_shlib_aliases(self, target, outdir):
2109
2109
except OSError :
2110
2110
mlog .debug ("Library versioning disabled because we do not have symlink creation privileges." )
2111
2111
2112
+ def generate_custom_target_clean (self , outfile , trees ):
2113
+ e = NinjaBuildElement (self .all_outputs , 'clean-ctlist' , 'CUSTOM_COMMAND' , 'PHONY' )
2114
+ d = CleanTrees (self .environment .get_build_dir (), trees )
2115
+ d_file = os .path .join (self .environment .get_scratch_dir (), 'cleantrees.dat' )
2116
+ script_root = self .environment .get_script_dir ()
2117
+ clean_script = os .path .join (script_root , 'cleantrees.py' )
2118
+ e .add_item ('COMMAND' , [sys .executable ,
2119
+ self .environment .get_build_command (),
2120
+ '--internal' , 'cleantrees' , d_file ])
2121
+ e .add_item ('description' , 'Cleaning CustomTarget directories' )
2122
+ e .write (outfile )
2123
+ # Write out the data file passed to the script
2124
+ with open (d_file , 'wb' ) as ofile :
2125
+ pickle .dump (d , ofile )
2126
+ return 'clean-ctlist'
2127
+
2112
2128
def generate_gcov_clean (self , outfile ):
2113
2129
gcno_elem = NinjaBuildElement (self .all_outputs , 'clean-gcno' , 'CUSTOM_COMMAND' , 'PHONY' )
2114
2130
script_root = self .environment .get_script_dir ()
@@ -2136,14 +2152,19 @@ def generate_utils(self, outfile):
2136
2152
2137
2153
def generate_ending (self , outfile ):
2138
2154
targetlist = []
2155
+ ctlist = []
2139
2156
for t in self .build .get_targets ().values ():
2140
2157
# RunTargets are meant to be invoked manually
2141
2158
if isinstance (t , build .RunTarget ):
2142
2159
continue
2143
- # CustomTargets that aren't installed should only be built if they
2144
- # are used by something else or are meant to be always built
2145
- if isinstance (t , build .CustomTarget ) and not (t .install or t .build_always ):
2146
- continue
2160
+ if isinstance (t , build .CustomTarget ):
2161
+ # Create a list of all custom target outputs
2162
+ for o in t .get_outputs ():
2163
+ ctlist .append (os .path .join (self .get_target_dir (t ), o ))
2164
+ # CustomTargets that aren't installed should only be built if
2165
+ # they are used by something else or are to always be built
2166
+ if not (t .install or t .build_always ):
2167
+ continue
2147
2168
# Add the first output of each target to the 'all' target so that
2148
2169
# they are all built
2149
2170
targetlist .append (os .path .join (self .get_target_dir (t ), t .get_outputs ()[0 ]))
@@ -2160,6 +2181,14 @@ def generate_ending(self, outfile):
2160
2181
elem = NinjaBuildElement (self .all_outputs , 'clean' , 'CUSTOM_COMMAND' , 'PHONY' )
2161
2182
elem .add_item ('COMMAND' , [ninja_command , '-t' , 'clean' ])
2162
2183
elem .add_item ('description' , 'Cleaning' )
2184
+ # If we have custom targets in this project, add all their outputs to
2185
+ # the list that is passed to the `cleantrees.py` script. The script
2186
+ # will manually delete all custom_target outputs that are directories
2187
+ # instead of files. This is needed because on platforms other than
2188
+ # Windows, Ninja only deletes directories while cleaning if they are
2189
+ # empty. https://github.com/mesonbuild/meson/issues/1220
2190
+ if ctlist :
2191
+ elem .add_dep (self .generate_custom_target_clean (outfile , ctlist ))
2163
2192
if 'b_coverage' in self .environment .coredata .base_options and \
2164
2193
self .environment .coredata .base_options ['b_coverage' ].value :
2165
2194
self .generate_gcov_clean (outfile )
0 commit comments