1 /* Dependency generator for Makefile fragments.
2 Copyright (C) 2000-2020 Free Software Foundation, Inc.
3 Contributed by Zack Weinberg, Mar 2000
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>.
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding! */
28 /* Not set up to just include std::vector et al, here's a simple
31 /* Keep this structure local to this file, so clients don't find it
32 easy to start making assumptions. */
36 /* T has trivial cctor & dtor. */
47 : ary (NULL
), num (0), alloc (0)
55 unsigned size () const
59 const T
&operator[] (unsigned ix
) const
63 T
&operator[] (unsigned ix
)
67 void push (const T
&elt
)
71 alloc
= alloc
? alloc
* 2 : 16;
72 ary
= XRESIZEVEC (T
, ary
, alloc
);
91 for (i
= targets
.size (); i
--;)
92 free (const_cast <char *> (targets
[i
]));
93 for (i
= deps
.size (); i
--;)
94 free (const_cast <char *> (deps
[i
]));
95 for (i
= vpath
.size (); i
--;)
96 XDELETEVEC (vpath
[i
].str
);
100 vec
<const char *> targets
;
101 vec
<const char *> deps
;
105 unsigned short quote_lwm
;
108 /* Apply Make quoting to STR, TRAIL. Note that it's not possible to
109 quote all such characters - e.g. \n, %, *, ?, [, \ (in some
110 contexts), and ~ are not properly handled. It isn't possible to
111 get this right in any current version of Make. (??? Still true?
112 Old comment referred to 3.76.1.) */
115 munge (const char *str
, const char *trail
= nullptr)
117 static unsigned alloc
;
121 for (; str
; str
= trail
, trail
= nullptr)
123 unsigned slashes
= 0;
125 for (const char *probe
= str
; (c
= *probe
++);)
127 if (alloc
< dst
+ 4 + slashes
)
129 alloc
= alloc
* 2 + 32;
130 buf
= XRESIZEVEC (char, buf
, alloc
);
145 /* GNU make uses a weird quoting scheme for white space.
146 A space or tab preceded by 2N+1 backslashes
147 represents N backslashes followed by space; a space
148 or tab preceded by 2N backslashes represents N
149 backslashes at the end of a file name; and
150 backslashes in other contexts should not be
175 /* If T begins with any of the partial pathnames listed in d->vpathv,
176 then advance T to point beyond that pathname. */
178 apply_vpath (class mkdeps
*d
, const char *t
)
180 if (unsigned len
= d
->vpath
.size ())
181 for (unsigned i
= len
; i
--;)
183 if (!filename_ncmp (d
->vpath
[i
].str
, t
, d
->vpath
[i
].len
))
185 const char *p
= t
+ d
->vpath
[i
].len
;
186 if (!IS_DIR_SEPARATOR (*p
))
189 /* Do not simplify $(vpath)/../whatever. ??? Might not
191 if (p
[1] == '.' && p
[2] == '.' && IS_DIR_SEPARATOR (p
[3]))
195 t
= t
+ d
->vpath
[i
].len
+ 1;
201 /* Remove leading ./ in any case. */
202 while (t
[0] == '.' && IS_DIR_SEPARATOR (t
[1]))
205 /* If we removed a leading ./, then also remove any /s after the
207 while (IS_DIR_SEPARATOR (t
[0]))
214 /* Public routines. */
219 return new mkdeps ();
223 deps_free (class mkdeps
*d
)
228 /* Adds a target T. We make a copy, so it need not be a permanent
229 string. QUOTE is true if the string should be quoted. */
231 deps_add_target (class mkdeps
*d
, const char *t
, int quote
)
233 t
= xstrdup (apply_vpath (d
, t
));
237 /* Sometimes unquoted items are added after quoted ones.
238 Swap out the lowest quoted. */
239 if (d
->quote_lwm
!= d
->targets
.size ())
241 const char *lowest
= d
->targets
[d
->quote_lwm
];
242 d
->targets
[d
->quote_lwm
] = t
;
251 /* Sets the default target if none has been given already. An empty
252 string as the default target in interpreted as stdin. The string
253 is quoted for MAKE. */
255 deps_add_default_target (class mkdeps
*d
, const char *tgt
)
257 /* Only if we have no targets. */
258 if (d
->targets
.size ())
262 d
->targets
.push (xstrdup ("-"));
265 #ifndef TARGET_OBJECT_SUFFIX
266 # define TARGET_OBJECT_SUFFIX ".o"
268 const char *start
= lbasename (tgt
);
269 char *o
= (char *) alloca (strlen (start
)
270 + strlen (TARGET_OBJECT_SUFFIX
) + 1);
275 suffix
= strrchr (o
, '.');
277 suffix
= o
+ strlen (o
);
278 strcpy (suffix
, TARGET_OBJECT_SUFFIX
);
280 deps_add_target (d
, o
, 1);
285 deps_add_dep (class mkdeps
*d
, const char *t
)
289 t
= apply_vpath (d
, t
);
291 d
->deps
.push (xstrdup (t
));
295 deps_add_vpath (class mkdeps
*d
, const char *vpath
)
297 const char *elem
, *p
;
299 for (elem
= vpath
; *elem
; elem
= p
)
301 for (p
= elem
; *p
&& *p
!= ':'; p
++)
305 char *str
= XNEWVEC (char, elt
.len
+ 1);
307 memcpy (str
, elem
, elt
.len
);
316 /* Write NAME, with a leading space to FP, a Makefile. Advance COL as
317 appropriate, wrap at COLMAX, returning new column number. Iff
318 QUOTE apply quoting. Append TRAIL. */
321 make_write_name (const char *name
, FILE *fp
, unsigned col
, unsigned colmax
,
322 bool quote
= true, const char *trail
= NULL
)
325 name
= munge (name
, trail
);
326 unsigned size
= strlen (name
);
330 if (colmax
&& col
+ size
> colmax
)
345 /* Write all the names in VEC via make_write_name. */
348 make_write_vec (const mkdeps::vec
<const char *> &vec
, FILE *fp
,
349 unsigned col
, unsigned colmax
, unsigned quote_lwm
= 0,
350 const char *trail
= NULL
)
352 for (unsigned ix
= 0; ix
!= vec
.size (); ix
++)
353 col
= make_write_name (vec
[ix
], fp
, col
, colmax
, ix
>= quote_lwm
, trail
);
357 /* Write the dependencies to a Makefile. If PHONY is true, add
358 .PHONY targets for all the dependencies too. */
361 make_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
363 const mkdeps
*d
= pfile
->deps
;
366 if (colmax
&& colmax
< 34)
371 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
374 make_write_vec (d
->deps
, fp
, column
, colmax
);
376 if (CPP_OPTION (pfile
, deps
.phony_targets
))
377 for (unsigned i
= 1; i
< d
->deps
.size (); i
++)
378 fprintf (fp
, "%s:\n", munge (d
->deps
[i
]));
382 /* Write out dependencies according to the selected format (which is
383 only Make at the moment). */
384 /* Really we should be opening fp here. */
387 deps_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
389 make_write (pfile
, fp
, colmax
);
392 /* Write out a deps buffer to a file, in a form that can be read back
393 with deps_restore. Returns nonzero on error, in which case the
394 error number will be in errno. */
397 deps_save (class mkdeps
*deps
, FILE *f
)
402 /* The cppreader structure contains makefile dependences. Write out this
405 /* The number of dependences. */
406 size
= deps
->deps
.size ();
407 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
410 /* The length of each dependence followed by the string. */
411 for (i
= 0; i
< deps
->deps
.size (); i
++)
413 size
= strlen (deps
->deps
[i
]);
414 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
416 if (fwrite (deps
->deps
[i
], size
, 1, f
) != 1)
423 /* Read back dependency information written with deps_save into
424 the deps sizefer. The third argument may be NULL, in which case
425 the dependency information is just skipped, or it may be a filename,
426 in which case that filename is skipped. */
429 deps_restore (class mkdeps
*deps
, FILE *fd
, const char *self
)
435 /* Number of dependences. */
436 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
439 /* The length of each dependence string, followed by the string. */
440 for (unsigned i
= size
; i
--;)
442 /* Read in # bytes in string. */
443 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
446 if (size
>= buf_size
)
448 buf_size
= size
+ 512;
449 buf
= XRESIZEVEC (char, buf
, buf_size
);
451 if (fread (buf
, 1, size
, fd
) != size
)
458 /* Generate makefile dependencies from .pch if -nopch-deps. */
459 if (self
!= NULL
&& filename_cmp (buf
, self
) != 0)
460 deps_add_dep (deps
, buf
);