1 /* Dependency generator for Makefile fragments.
2 Copyright (C) 2000-2019 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! */
27 /* Not set up to just include std::vector et al, here's a simple
30 /* Keep this structure local to this file, so clients don't find it
31 easy to start making assumptions. */
35 /* T has trivial cctor & dtor. */
46 : ary (NULL
), num (0), alloc (0)
54 unsigned size () const
58 const T
&operator[] (unsigned ix
) const
62 void push (const T
&elt
)
66 alloc
= alloc
? alloc
* 2 : 16;
67 ary
= XRESIZEVEC (T
, ary
, alloc
);
86 for (i
= targets
.size (); i
--;)
87 free (const_cast <char *> (targets
[i
]));
88 for (i
= deps
.size (); i
--;)
89 free (const_cast <char *> (deps
[i
]));
90 for (i
= vpath
.size (); i
--;)
91 XDELETEVEC (vpath
[i
].str
);
95 vec
<const char *> targets
;
96 vec
<const char *> deps
;
100 unsigned short quote_lwm
;
103 /* Apply Make quoting to STR, TRAIL etc. Note that it's not possible
104 to quote all such characters - e.g. \n, %, *, ?, [, \ (in some
105 contexts), and ~ are not properly handled. It isn't possible to
106 get this right in any current version of Make. (??? Still true?
107 Old comment referred to 3.76.1.) */
110 munge (const char *str
, const char *trail
= NULL
, ...)
112 static unsigned alloc
;
117 va_start (args
, trail
);
119 for (bool first
= true; str
; first
= false)
121 unsigned slashes
= 0;
123 for (const char *probe
= str
; (c
= *probe
++);)
125 if (alloc
< dst
+ 4 + slashes
)
127 alloc
= alloc
* 2 + 32;
128 buf
= XRESIZEVEC (char, buf
, alloc
);
143 /* GNU make uses a weird quoting scheme for white space.
144 A space or tab preceded by 2N+1 backslashes
145 represents N backslashes followed by space; a space
146 or tab preceded by 2N backslashes represents N
147 backslashes at the end of a file name; and
148 backslashes in other contexts should not be
171 str
= va_arg (args
, const char *);
180 /* If T begins with any of the partial pathnames listed in d->vpathv,
181 then advance T to point beyond that pathname. */
183 apply_vpath (struct mkdeps
*d
, const char *t
)
185 if (unsigned len
= d
->vpath
.size ())
186 for (unsigned i
= len
; i
--;)
188 if (!filename_ncmp (d
->vpath
[i
].str
, t
, d
->vpath
[i
].len
))
190 const char *p
= t
+ d
->vpath
[i
].len
;
191 if (!IS_DIR_SEPARATOR (*p
))
194 /* Do not simplify $(vpath)/../whatever. ??? Might not
196 if (p
[1] == '.' && p
[2] == '.' && IS_DIR_SEPARATOR (p
[3]))
200 t
= t
+ d
->vpath
[i
].len
+ 1;
206 /* Remove leading ./ in any case. */
207 while (t
[0] == '.' && IS_DIR_SEPARATOR (t
[1]))
210 /* If we removed a leading ./, then also remove any /s after the
212 while (IS_DIR_SEPARATOR (t
[0]))
219 /* Public routines. */
224 return new mkdeps ();
228 deps_free (struct mkdeps
*d
)
233 /* Adds a target T. We make a copy, so it need not be a permanent
234 string. QUOTE is true if the string should be quoted. */
236 deps_add_target (struct mkdeps
*d
, const char *t
, int quote
)
238 t
= apply_vpath (d
, t
);
241 gcc_assert (d
->quote_lwm
== d
->targets
.size ());
245 d
->targets
.push (xstrdup (t
));
248 /* Sets the default target if none has been given already. An empty
249 string as the default target in interpreted as stdin. The string
250 is quoted for MAKE. */
252 deps_add_default_target (struct mkdeps
*d
, const char *tgt
)
254 /* Only if we have no targets. */
255 if (d
->targets
.size ())
259 deps_add_target (d
, "-", 1);
262 #ifndef TARGET_OBJECT_SUFFIX
263 # define TARGET_OBJECT_SUFFIX ".o"
265 const char *start
= lbasename (tgt
);
266 char *o
= (char *) alloca (strlen (start
)
267 + strlen (TARGET_OBJECT_SUFFIX
) + 1);
272 suffix
= strrchr (o
, '.');
274 suffix
= o
+ strlen (o
);
275 strcpy (suffix
, TARGET_OBJECT_SUFFIX
);
277 deps_add_target (d
, o
, 1);
282 deps_add_dep (struct mkdeps
*d
, const char *t
)
286 t
= apply_vpath (d
, t
);
288 d
->deps
.push (xstrdup (t
));
292 deps_add_vpath (struct mkdeps
*d
, const char *vpath
)
294 const char *elem
, *p
;
296 for (elem
= vpath
; *elem
; elem
= p
)
298 for (p
= elem
; *p
&& *p
!= ':'; p
++)
302 char *str
= XNEWVEC (char, elt
.len
+ 1);
304 memcpy (str
, elem
, elt
.len
);
313 /* Write NAME, with a leading space to FP, a Makefile. Advance COL as
314 appropriate, wrap at COLMAX, returning new column number. Iff
315 QUOTE apply quoting. Append TRAIL. */
318 make_write_name (const char *name
, FILE *fp
, unsigned col
, unsigned colmax
,
319 bool quote
= true, const char *trail
= NULL
)
322 name
= munge (name
, trail
, NULL
);
323 unsigned size
= strlen (name
);
327 if (colmax
&& col
+ size
> colmax
)
342 /* Write all the names in VEC via make_write_name. */
345 make_write_vec (const mkdeps::vec
<const char *> &vec
, FILE *fp
,
346 unsigned col
, unsigned colmax
, unsigned quote_lwm
= 0,
347 const char *trail
= NULL
)
349 for (unsigned ix
= 0; ix
!= vec
.size (); ix
++)
350 col
= make_write_name (vec
[ix
], fp
, col
, colmax
, ix
>= quote_lwm
, trail
);
354 /* Write the dependencies to a Makefile. If PHONY is true, add
355 .PHONY targets for all the dependencies too. */
358 make_write (const struct mkdeps
*d
, FILE *fp
, bool phony
, unsigned int colmax
)
361 if (colmax
&& colmax
< 34)
366 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
369 column
= make_write_vec (d
->deps
, fp
, column
, colmax
);
372 for (unsigned i
= 1; i
< d
->deps
.size (); i
++)
373 fprintf (fp
, "%s:\n", munge (d
->deps
[i
]));
377 /* Write out dependencies according to the selected format (which is
378 only Make at the moment). */
381 deps_write (const struct mkdeps
*d
, FILE *fp
, bool phony
, unsigned int colmax
)
383 make_write (d
, fp
, phony
, colmax
);
386 /* Write out a deps buffer to a file, in a form that can be read back
387 with deps_restore. Returns nonzero on error, in which case the
388 error number will be in errno. */
391 deps_save (struct mkdeps
*deps
, FILE *f
)
396 /* The cppreader structure contains makefile dependences. Write out this
399 /* The number of dependences. */
400 size
= deps
->deps
.size ();
401 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
404 /* The length of each dependence followed by the string. */
405 for (i
= 0; i
< deps
->deps
.size (); i
++)
407 size
= strlen (deps
->deps
[i
]);
408 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
410 if (fwrite (deps
->deps
[i
], size
, 1, f
) != 1)
417 /* Read back dependency information written with deps_save into
418 the deps sizefer. The third argument may be NULL, in which case
419 the dependency information is just skipped, or it may be a filename,
420 in which case that filename is skipped. */
423 deps_restore (struct mkdeps
*deps
, FILE *fd
, const char *self
)
429 /* Number of dependences. */
430 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
433 /* The length of each dependence string, followed by the string. */
434 for (unsigned i
= size
; i
--;)
436 /* Read in # bytes in string. */
437 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
440 if (size
>= buf_size
)
442 buf_size
= size
+ 512;
443 buf
= XRESIZEVEC (char, buf
, buf_size
);
445 if (fread (buf
, 1, size
, fd
) != size
)
452 /* Generate makefile dependencies from .pch if -nopch-deps. */
453 if (self
!= NULL
&& filename_cmp (buf
, self
) != 0)
454 deps_add_dep (deps
, buf
);