xref: /third_party/openssl/util/add-depends.pl (revision e1051a39)
1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ciuse strict;
10e1051a39Sopenharmony_ciuse warnings;
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ciuse lib '.';
13e1051a39Sopenharmony_ciuse configdata;
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ciuse File::Spec::Functions qw(:DEFAULT rel2abs);
16e1051a39Sopenharmony_ciuse File::Compare qw(compare_text);
17e1051a39Sopenharmony_ciuse feature 'state';
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci# When using stat() on Windows, we can get it to perform better by avoid some
20e1051a39Sopenharmony_ci# data.  This doesn't affect the mtime field, so we're not losing anything...
21e1051a39Sopenharmony_ci${^WIN32_SLOPPY_STAT} = 1;
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_cimy $debug = $ENV{ADD_DEPENDS_DEBUG};
24e1051a39Sopenharmony_cimy $buildfile = $config{build_file};
25e1051a39Sopenharmony_cimy $build_mtime = (stat($buildfile))[9];
26e1051a39Sopenharmony_cimy $configdata_mtime = (stat('configdata.pm'))[9];
27e1051a39Sopenharmony_cimy $rebuild = 0;
28e1051a39Sopenharmony_cimy $depext = $target{dep_extension} || ".d";
29e1051a39Sopenharmony_cimy @depfiles =
30e1051a39Sopenharmony_ci    sort
31e1051a39Sopenharmony_ci    grep {
32e1051a39Sopenharmony_ci        # This grep has side effects.  Not only does if check the existence
33e1051a39Sopenharmony_ci        # of the dependency file given in $_, but it also checks if it's
34e1051a39Sopenharmony_ci        # newer than the build file or older than configdata.pm, and if it
35e1051a39Sopenharmony_ci        # is, sets $rebuild.
36e1051a39Sopenharmony_ci        my @st = stat($_);
37e1051a39Sopenharmony_ci        $rebuild = 1
38e1051a39Sopenharmony_ci            if @st && ($st[9] > $build_mtime || $st[9] < $configdata_mtime);
39e1051a39Sopenharmony_ci        scalar @st > 0;         # Determines the grep result
40e1051a39Sopenharmony_ci    }
41e1051a39Sopenharmony_ci    map { (my $x = $_) =~ s|\.o$|$depext|; $x; }
42e1051a39Sopenharmony_ci    ( ( grep { $unified_info{sources}->{$_}->[0] =~ /\.cc?$/ }
43e1051a39Sopenharmony_ci            keys %{$unified_info{sources}} ),
44e1051a39Sopenharmony_ci      ( grep { $unified_info{shared_sources}->{$_}->[0] =~ /\.cc?$/ }
45e1051a39Sopenharmony_ci            keys %{$unified_info{shared_sources}} ) );
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ciexit 0 unless $rebuild;
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ci# Ok, primary checks are done, time to do some real work
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_cimy $producer = shift @ARGV;
52e1051a39Sopenharmony_cidie "Producer not given\n" unless $producer;
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_cimy $srcdir = $config{sourcedir};
55e1051a39Sopenharmony_cimy $blddir = $config{builddir};
56e1051a39Sopenharmony_cimy $abs_srcdir = rel2abs($srcdir);
57e1051a39Sopenharmony_cimy $abs_blddir = rel2abs($blddir);
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci# Convenient cache of absolute to relative map.  We start with filling it
60e1051a39Sopenharmony_ci# with mappings for the known generated header files.  They are relative to
61e1051a39Sopenharmony_ci# the current working directory, so that's an easy task.
62e1051a39Sopenharmony_ci# NOTE: there's more than C header files that are generated.  They will also
63e1051a39Sopenharmony_ci# generate entries in this map.  We could of course deal with C header files
64e1051a39Sopenharmony_ci# only, but in case we decide to handle more than just C files in the future,
65e1051a39Sopenharmony_ci# we already have the mechanism in place here.
66e1051a39Sopenharmony_ci# NOTE2: we lower case the index to make it searchable without regard for
67e1051a39Sopenharmony_ci# character case.  That could seem dangerous, but as long as we don't have
68e1051a39Sopenharmony_ci# files we depend on in the same directory that only differ by character case,
69e1051a39Sopenharmony_ci# we're fine.
70e1051a39Sopenharmony_cimy %depconv_cache =
71e1051a39Sopenharmony_ci    map { catfile($abs_blddir, $_) => $_ }
72e1051a39Sopenharmony_ci    keys %{$unified_info{generate}};
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cimy %procedures = (
75e1051a39Sopenharmony_ci    'gcc' =>
76e1051a39Sopenharmony_ci        sub {
77e1051a39Sopenharmony_ci            (my $objfile = shift) =~ s|\.d$|.o|i;
78e1051a39Sopenharmony_ci            my $line = shift;
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci            # Remove the original object file
81e1051a39Sopenharmony_ci            $line =~ s|^.*\.o: | |;
82e1051a39Sopenharmony_ci            # All we got now is a dependency, shave off surrounding spaces
83e1051a39Sopenharmony_ci            $line =~ s/^\s+//;
84e1051a39Sopenharmony_ci            $line =~ s/\s+$//;
85e1051a39Sopenharmony_ci            # Also, shave off any continuation
86e1051a39Sopenharmony_ci            $line =~ s/\s*\\$//;
87e1051a39Sopenharmony_ci
88e1051a39Sopenharmony_ci            # Split the line into individual header files, and keep those
89e1051a39Sopenharmony_ci            # that exist in some form
90e1051a39Sopenharmony_ci            my @headers;
91e1051a39Sopenharmony_ci            for (split(/\s+/, $line)) {
92e1051a39Sopenharmony_ci                my $x = rel2abs($_);
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci                if (!$depconv_cache{$x}) {
95e1051a39Sopenharmony_ci                    if (-f $x) {
96e1051a39Sopenharmony_ci                        $depconv_cache{$x} = $_;
97e1051a39Sopenharmony_ci                    }
98e1051a39Sopenharmony_ci                }
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ci                if ($depconv_cache{$x}) {
101e1051a39Sopenharmony_ci                    push @headers, $_;
102e1051a39Sopenharmony_ci                } else {
103e1051a39Sopenharmony_ci                    print STDERR "DEBUG[$producer]: ignoring $objfile <- $line\n"
104e1051a39Sopenharmony_ci                        if $debug;
105e1051a39Sopenharmony_ci                }
106e1051a39Sopenharmony_ci            }
107e1051a39Sopenharmony_ci            return ($objfile, join(' ', @headers)) if @headers;
108e1051a39Sopenharmony_ci            return undef;
109e1051a39Sopenharmony_ci    },
110e1051a39Sopenharmony_ci    'makedepend' =>
111e1051a39Sopenharmony_ci        sub {
112e1051a39Sopenharmony_ci            # makedepend, in its infinite wisdom, wants to have the object file
113e1051a39Sopenharmony_ci            # in the same directory as the source file.  This doesn't work too
114e1051a39Sopenharmony_ci            # well with out-of-source-tree builds, so we must resort to tricks
115e1051a39Sopenharmony_ci            # to get things right.  Fortunately, the .d files are always placed
116e1051a39Sopenharmony_ci            # parallel with the object files, so all we need to do is construct
117e1051a39Sopenharmony_ci            # the object file name from the dep file name.
118e1051a39Sopenharmony_ci            (my $objfile = shift) =~ s|\.d$|.o|i;
119e1051a39Sopenharmony_ci            my $line = shift;
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci            # Discard comments
122e1051a39Sopenharmony_ci            return undef if $line =~ /^(#.*|\s*)$/;
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci            # Remove the original object file
125e1051a39Sopenharmony_ci            $line =~ s|^.*\.o: | |;
126e1051a39Sopenharmony_ci            # Also, remove any dependency that starts with a /, because those
127e1051a39Sopenharmony_ci            # are typically system headers
128e1051a39Sopenharmony_ci            $line =~ s/\s+\/(\\.|\S)*//g;
129e1051a39Sopenharmony_ci            # Finally, discard all empty lines
130e1051a39Sopenharmony_ci            return undef if $line =~ /^\s*$/;
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci            # All we got now is a dependency, just shave off surrounding spaces
133e1051a39Sopenharmony_ci            $line =~ s/^\s+//;
134e1051a39Sopenharmony_ci            $line =~ s/\s+$//;
135e1051a39Sopenharmony_ci            return ($objfile, $line);
136e1051a39Sopenharmony_ci        },
137e1051a39Sopenharmony_ci    'VMS C' =>
138e1051a39Sopenharmony_ci        sub {
139e1051a39Sopenharmony_ci            state $abs_srcdir_shaved = undef;
140e1051a39Sopenharmony_ci            state $srcdir_shaved = undef;
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci            unless (defined $abs_srcdir_shaved) {
143e1051a39Sopenharmony_ci                ($abs_srcdir_shaved = $abs_srcdir) =~ s|[>\]]$||;
144e1051a39Sopenharmony_ci                ($srcdir_shaved = $srcdir) =~ s|[>\]]$||;
145e1051a39Sopenharmony_ci            }
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci            # current versions of DEC / Compaq / HP / VSI C strips away all
148e1051a39Sopenharmony_ci            # directory information from the object file, so we must insert it
149e1051a39Sopenharmony_ci            # back.  To make life simpler, we simply replace it with the
150e1051a39Sopenharmony_ci            # corresponding .D file that's had its extension changed.  Since
151e1051a39Sopenharmony_ci            # .D files are always written parallel to the object files, we
152e1051a39Sopenharmony_ci            # thereby get the directory information for free.
153e1051a39Sopenharmony_ci            (my $objfile = shift) =~ s|\.D$|.OBJ|i;
154e1051a39Sopenharmony_ci            my $line = shift;
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci            # Shave off the target.
157e1051a39Sopenharmony_ci            #
158e1051a39Sopenharmony_ci            # The pattern for target and dependencies will always take this
159e1051a39Sopenharmony_ci            # form:
160e1051a39Sopenharmony_ci            #
161e1051a39Sopenharmony_ci            #   target SPACE : SPACE deps
162e1051a39Sopenharmony_ci            #
163e1051a39Sopenharmony_ci            # This is so a volume delimiter (a : without any spaces around it)
164e1051a39Sopenharmony_ci            # won't get mixed up with the target / deps delimiter.  We use this
165e1051a39Sopenharmony_ci            # to easily identify what needs to be removed.
166e1051a39Sopenharmony_ci            m|\s:\s|; $line = $';
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci            # We know that VMS has system header files in text libraries,
169e1051a39Sopenharmony_ci            # extension .TLB.  We also know that our header files aren't stored
170e1051a39Sopenharmony_ci            # in text libraries.  Finally, we know that VMS C produces exactly
171e1051a39Sopenharmony_ci            # one dependency per line, so we simply discard any line ending with
172e1051a39Sopenharmony_ci            # .TLB.
173e1051a39Sopenharmony_ci            return undef if /\.TLB\s*$/;
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci            # All we got now is a dependency, just shave off surrounding spaces
176e1051a39Sopenharmony_ci            $line =~ s/^\s+//;
177e1051a39Sopenharmony_ci            $line =~ s/\s+$//;
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci            # VMS C gives us absolute paths, always.  Let's see if we can
180e1051a39Sopenharmony_ci            # make them relative instead.
181e1051a39Sopenharmony_ci            $line = canonpath($line);
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ci            unless (defined $depconv_cache{$line}) {
184e1051a39Sopenharmony_ci                my $dep = $line;
185e1051a39Sopenharmony_ci                # Since we have already pre-populated the cache with
186e1051a39Sopenharmony_ci                # mappings for generated headers, we only need to deal
187e1051a39Sopenharmony_ci                # with the source tree.
188e1051a39Sopenharmony_ci                if ($dep =~ s|^\Q$abs_srcdir_shaved\E([\.>\]])?|$srcdir_shaved$1|i) {
189e1051a39Sopenharmony_ci                    # Also check that the header actually exists
190e1051a39Sopenharmony_ci                    if (-f $line) {
191e1051a39Sopenharmony_ci                        $depconv_cache{$line} = $dep;
192e1051a39Sopenharmony_ci                    }
193e1051a39Sopenharmony_ci                }
194e1051a39Sopenharmony_ci            }
195e1051a39Sopenharmony_ci            return ($objfile, $depconv_cache{$line})
196e1051a39Sopenharmony_ci                if defined $depconv_cache{$line};
197e1051a39Sopenharmony_ci            print STDERR "DEBUG[$producer]: ignoring $objfile <- $line\n"
198e1051a39Sopenharmony_ci                if $debug;
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci            return undef;
201e1051a39Sopenharmony_ci        },
202e1051a39Sopenharmony_ci    'VC' =>
203e1051a39Sopenharmony_ci        sub {
204e1051a39Sopenharmony_ci            # With Microsoft Visual C the flags /Zs /showIncludes give us the
205e1051a39Sopenharmony_ci            # necessary output to be able to create dependencies that nmake
206e1051a39Sopenharmony_ci            # (or any 'make' implementation) should be able to read, with a
207e1051a39Sopenharmony_ci            # bit of help.  The output we're interested in looks something
208e1051a39Sopenharmony_ci            # like this (it always starts the same)
209e1051a39Sopenharmony_ci            #
210e1051a39Sopenharmony_ci            #   Note: including file: {whatever header file}
211e1051a39Sopenharmony_ci            #
212e1051a39Sopenharmony_ci            # This output is localized, so for example, the German pack gives
213e1051a39Sopenharmony_ci            # us this:
214e1051a39Sopenharmony_ci            #
215e1051a39Sopenharmony_ci            #   Hinweis: Einlesen der Datei:   {whatever header file}
216e1051a39Sopenharmony_ci            #
217e1051a39Sopenharmony_ci            # To accomodate, we need to use a very general regular expression
218e1051a39Sopenharmony_ci            # to parse those lines.
219e1051a39Sopenharmony_ci            #
220e1051a39Sopenharmony_ci            # Since there's no object file name at all in that information,
221e1051a39Sopenharmony_ci            # we must construct it ourselves.
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ci            (my $objfile = shift) =~ s|\.d$|.obj|i;
224e1051a39Sopenharmony_ci            my $line = shift;
225e1051a39Sopenharmony_ci
226e1051a39Sopenharmony_ci            # There are also other lines mixed in, for example compiler
227e1051a39Sopenharmony_ci            # warnings, so we simply discard anything that doesn't start with
228e1051a39Sopenharmony_ci            # the Note:
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci            if (/^[^:]*: [^:]*: */) {
231e1051a39Sopenharmony_ci                (my $tail = $') =~ s/\s*\R$//;
232e1051a39Sopenharmony_ci
233e1051a39Sopenharmony_ci                # VC gives us absolute paths for all include files, so to
234e1051a39Sopenharmony_ci                # remove system header dependencies, we need to check that
235e1051a39Sopenharmony_ci                # they don't match $abs_srcdir or $abs_blddir.
236e1051a39Sopenharmony_ci                $tail = canonpath($tail);
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci                unless (defined $depconv_cache{$tail}) {
239e1051a39Sopenharmony_ci                    my $dep = $tail;
240e1051a39Sopenharmony_ci                    # Since we have already pre-populated the cache with
241e1051a39Sopenharmony_ci                    # mappings for generated headers, we only need to deal
242e1051a39Sopenharmony_ci                    # with the source tree.
243e1051a39Sopenharmony_ci                    if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) {
244e1051a39Sopenharmony_ci                        # Also check that the header actually exists
245e1051a39Sopenharmony_ci                        if (-f $line) {
246e1051a39Sopenharmony_ci                            $depconv_cache{$tail} = $dep;
247e1051a39Sopenharmony_ci                        }
248e1051a39Sopenharmony_ci                    }
249e1051a39Sopenharmony_ci                }
250e1051a39Sopenharmony_ci                return ($objfile, '"'.$depconv_cache{$tail}.'"')
251e1051a39Sopenharmony_ci                    if defined $depconv_cache{$tail};
252e1051a39Sopenharmony_ci                print STDERR "DEBUG[$producer]: ignoring $objfile <- $tail\n"
253e1051a39Sopenharmony_ci                    if $debug;
254e1051a39Sopenharmony_ci            }
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci            return undef;
257e1051a39Sopenharmony_ci        },
258e1051a39Sopenharmony_ci    'embarcadero' =>
259e1051a39Sopenharmony_ci        sub {
260e1051a39Sopenharmony_ci            # With Embarcadero C++Builder's preprocessor (cpp32.exe) the -Sx -Hp
261e1051a39Sopenharmony_ci            # flags give us the list of #include files read, like the following:
262e1051a39Sopenharmony_ci            #
263e1051a39Sopenharmony_ci            #   Including ->->{whatever header file}
264e1051a39Sopenharmony_ci            #
265e1051a39Sopenharmony_ci            # where each "->" indicates the nesting level of the #include.  The
266e1051a39Sopenharmony_ci            # logic here is otherwise the same as the 'VC' scheme.
267e1051a39Sopenharmony_ci            #
268e1051a39Sopenharmony_ci            # Since there's no object file name at all in that information,
269e1051a39Sopenharmony_ci            # we must construct it ourselves.
270e1051a39Sopenharmony_ci
271e1051a39Sopenharmony_ci            (my $objfile = shift) =~ s|\.d$|.obj|i;
272e1051a39Sopenharmony_ci            my $line = shift;
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_ci            # There are also other lines mixed in, for example compiler
275e1051a39Sopenharmony_ci            # warnings, so we simply discard anything that doesn't start with
276e1051a39Sopenharmony_ci            # the Note:
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ci            if (/^Including (->)*/) {
279e1051a39Sopenharmony_ci                (my $tail = $') =~ s/\s*\R$//;
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ci                # C++Builder gives us relative paths when possible, so to
282e1051a39Sopenharmony_ci                # remove system header dependencies, we convert them to
283e1051a39Sopenharmony_ci                # absolute paths and check that they don't match $abs_srcdir
284e1051a39Sopenharmony_ci                # or $abs_blddir, just as the 'VC' scheme.
285e1051a39Sopenharmony_ci                $tail = rel2abs($tail);
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci                unless (defined $depconv_cache{$tail}) {
288e1051a39Sopenharmony_ci                    my $dep = $tail;
289e1051a39Sopenharmony_ci                    # Since we have already pre-populated the cache with
290e1051a39Sopenharmony_ci                    # mappings for generated headers, we only need to deal
291e1051a39Sopenharmony_ci                    # with the source tree.
292e1051a39Sopenharmony_ci                    if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) {
293e1051a39Sopenharmony_ci                        # Also check that the header actually exists
294e1051a39Sopenharmony_ci                        if (-f $line) {
295e1051a39Sopenharmony_ci                            $depconv_cache{$tail} = $dep;
296e1051a39Sopenharmony_ci                        }
297e1051a39Sopenharmony_ci                    }
298e1051a39Sopenharmony_ci                }
299e1051a39Sopenharmony_ci                return ($objfile, '"'.$depconv_cache{$tail}.'"')
300e1051a39Sopenharmony_ci                    if defined $depconv_cache{$tail};
301e1051a39Sopenharmony_ci                print STDERR "DEBUG[$producer]: ignoring $objfile <- $tail\n"
302e1051a39Sopenharmony_ci                    if $debug;
303e1051a39Sopenharmony_ci            }
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci            return undef;
306e1051a39Sopenharmony_ci        },
307e1051a39Sopenharmony_ci);
308e1051a39Sopenharmony_cimy %continuations = (
309e1051a39Sopenharmony_ci    'gcc' => "\\",
310e1051a39Sopenharmony_ci    'makedepend' => "\\",
311e1051a39Sopenharmony_ci    'VMS C' => "-",
312e1051a39Sopenharmony_ci    'VC' => "\\",
313e1051a39Sopenharmony_ci    'embarcadero' => "\\",
314e1051a39Sopenharmony_ci);
315e1051a39Sopenharmony_ci
316e1051a39Sopenharmony_cidie "Producer unrecognised: $producer\n"
317e1051a39Sopenharmony_ci    unless exists $procedures{$producer} && exists $continuations{$producer};
318e1051a39Sopenharmony_ci
319e1051a39Sopenharmony_cimy $procedure = $procedures{$producer};
320e1051a39Sopenharmony_cimy $continuation = $continuations{$producer};
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_cimy $buildfile_new = "$buildfile-$$";
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_cimy %collect = ();
325e1051a39Sopenharmony_ciforeach my $depfile (@depfiles) {
326e1051a39Sopenharmony_ci    open IDEP,$depfile or die "Trying to read $depfile: $!\n";
327e1051a39Sopenharmony_ci    while (<IDEP>) {
328e1051a39Sopenharmony_ci        s|\R$||;                # The better chomp
329e1051a39Sopenharmony_ci        my ($target, $deps) = $procedure->($depfile, $_);
330e1051a39Sopenharmony_ci        $collect{$target}->{$deps} = 1 if defined $target;
331e1051a39Sopenharmony_ci    }
332e1051a39Sopenharmony_ci    close IDEP;
333e1051a39Sopenharmony_ci}
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_ciopen IBF, $buildfile or die "Trying to read $buildfile: $!\n";
336e1051a39Sopenharmony_ciopen OBF, '>', $buildfile_new or die "Trying to write $buildfile_new: $!\n";
337e1051a39Sopenharmony_ciwhile (<IBF>) {
338e1051a39Sopenharmony_ci    last if /^# DO NOT DELETE THIS LINE/;
339e1051a39Sopenharmony_ci    print OBF or die "$!\n";
340e1051a39Sopenharmony_ci}
341e1051a39Sopenharmony_ciclose IBF;
342e1051a39Sopenharmony_ci
343e1051a39Sopenharmony_ciprint OBF "# DO NOT DELETE THIS LINE -- make depend depends on it.\n";
344e1051a39Sopenharmony_ci
345e1051a39Sopenharmony_ciforeach my $target (sort keys %collect) {
346e1051a39Sopenharmony_ci    my $prefix = $target . ' :';
347e1051a39Sopenharmony_ci    my @deps = sort keys %{$collect{$target}};
348e1051a39Sopenharmony_ci
349e1051a39Sopenharmony_ci    while (@deps) {
350e1051a39Sopenharmony_ci        my $buf = $prefix;
351e1051a39Sopenharmony_ci        $prefix = '';
352e1051a39Sopenharmony_ci
353e1051a39Sopenharmony_ci        while (@deps && ($buf eq ''
354e1051a39Sopenharmony_ci                         || length($buf) + length($deps[0]) <= 77)) {
355e1051a39Sopenharmony_ci            $buf .= ' ' . shift @deps;
356e1051a39Sopenharmony_ci        }
357e1051a39Sopenharmony_ci        $buf .= ' '.$continuation if @deps;
358e1051a39Sopenharmony_ci
359e1051a39Sopenharmony_ci        print OBF $buf,"\n" or die "Trying to print: $!\n"
360e1051a39Sopenharmony_ci    }
361e1051a39Sopenharmony_ci}
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ciclose OBF;
364e1051a39Sopenharmony_ci
365e1051a39Sopenharmony_ciif (compare_text($buildfile_new, $buildfile) != 0) {
366e1051a39Sopenharmony_ci    rename $buildfile_new, $buildfile
367e1051a39Sopenharmony_ci        or die "Trying to rename $buildfile_new -> $buildfile: $!\n";
368e1051a39Sopenharmony_ci}
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ciEND {
371e1051a39Sopenharmony_ci    # On VMS, we want to remove all generations of this file, in case there
372e1051a39Sopenharmony_ci    # are more than one, so we loop.
373e1051a39Sopenharmony_ci    if (defined $buildfile_new) {
374e1051a39Sopenharmony_ci        while (unlink $buildfile_new) {}
375e1051a39Sopenharmony_ci    }
376e1051a39Sopenharmony_ci}
377