]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libcpp/mkdeps.c
1 /* Dependency generator for Makefile fragments.
2 Copyright (C) 2000-2021 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
);
84 : module_name (NULL
), cmi_name (NULL
), is_header_unit (false), quote_lwm (0)
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
);
97 for (i
= modules
.size (); i
--;)
98 XDELETEVEC (modules
[i
]);
99 XDELETEVEC (module_name
);
100 free (const_cast <char *> (cmi_name
));
104 vec
<const char *> targets
;
105 vec
<const char *> deps
;
107 vec
<const char *> modules
;
110 const char *module_name
;
111 const char *cmi_name
;
113 unsigned short quote_lwm
;
116 /* Apply Make quoting to STR, TRAIL. Note that it's not possible to
117 quote all such characters - e.g. \n, %, *, ?, [, \ (in some
118 contexts), and ~ are not properly handled. It isn't possible to
119 get this right in any current version of Make. (??? Still true?
120 Old comment referred to 3.76.1.) */
123 munge (const char *str
, const char *trail
= nullptr)
125 static unsigned alloc
;
129 for (; str
; str
= trail
, trail
= nullptr)
131 unsigned slashes
= 0;
133 for (const char *probe
= str
; (c
= *probe
++);)
135 if (alloc
< dst
+ 4 + slashes
)
137 alloc
= alloc
* 2 + 32;
138 buf
= XRESIZEVEC (char, buf
, alloc
);
153 /* GNU make uses a weird quoting scheme for white space.
154 A space or tab preceded by 2N+1 backslashes
155 represents N backslashes followed by space; a space
156 or tab preceded by 2N backslashes represents N
157 backslashes at the end of a file name; and
158 backslashes in other contexts should not be
183 /* If T begins with any of the partial pathnames listed in d->vpathv,
184 then advance T to point beyond that pathname. */
186 apply_vpath (class mkdeps
*d
, const char *t
)
188 if (unsigned len
= d
->vpath
.size ())
189 for (unsigned i
= len
; i
--;)
191 if (!filename_ncmp (d
->vpath
[i
].str
, t
, d
->vpath
[i
].len
))
193 const char *p
= t
+ d
->vpath
[i
].len
;
194 if (!IS_DIR_SEPARATOR (*p
))
197 /* Do not simplify $(vpath)/../whatever. ??? Might not
199 if (p
[1] == '.' && p
[2] == '.' && IS_DIR_SEPARATOR (p
[3]))
203 t
= t
+ d
->vpath
[i
].len
+ 1;
209 /* Remove leading ./ in any case. */
210 while (t
[0] == '.' && IS_DIR_SEPARATOR (t
[1]))
213 /* If we removed a leading ./, then also remove any /s after the
215 while (IS_DIR_SEPARATOR (t
[0]))
222 /* Public routines. */
227 return new mkdeps ();
231 deps_free (class mkdeps
*d
)
236 /* Adds a target T. We make a copy, so it need not be a permanent
237 string. QUOTE is true if the string should be quoted. */
239 deps_add_target (class mkdeps
*d
, const char *t
, int quote
)
241 t
= xstrdup (apply_vpath (d
, t
));
245 /* Sometimes unquoted items are added after quoted ones.
246 Swap out the lowest quoted. */
247 if (d
->quote_lwm
!= d
->targets
.size ())
249 const char *lowest
= d
->targets
[d
->quote_lwm
];
250 d
->targets
[d
->quote_lwm
] = t
;
259 /* Sets the default target if none has been given already. An empty
260 string as the default target in interpreted as stdin. The string
261 is quoted for MAKE. */
263 deps_add_default_target (class mkdeps
*d
, const char *tgt
)
265 /* Only if we have no targets. */
266 if (d
->targets
.size ())
270 d
->targets
.push (xstrdup ("-"));
273 #ifndef TARGET_OBJECT_SUFFIX
274 # define TARGET_OBJECT_SUFFIX ".o"
276 const char *start
= lbasename (tgt
);
277 char *o
= (char *) alloca (strlen (start
)
278 + strlen (TARGET_OBJECT_SUFFIX
) + 1);
283 suffix
= strrchr (o
, '.');
285 suffix
= o
+ strlen (o
);
286 strcpy (suffix
, TARGET_OBJECT_SUFFIX
);
288 deps_add_target (d
, o
, 1);
293 deps_add_dep (class mkdeps
*d
, const char *t
)
297 t
= apply_vpath (d
, t
);
299 d
->deps
.push (xstrdup (t
));
303 deps_add_vpath (class mkdeps
*d
, const char *vpath
)
305 const char *elem
, *p
;
307 for (elem
= vpath
; *elem
; elem
= p
)
309 for (p
= elem
; *p
&& *p
!= ':'; p
++)
313 char *str
= XNEWVEC (char, elt
.len
+ 1);
315 memcpy (str
, elem
, elt
.len
);
324 /* Add a new module target (there can only be one). M is the module
328 deps_add_module_target (struct mkdeps
*d
, const char *m
,
329 const char *cmi
, bool is_header_unit
)
331 gcc_assert (!d
->module_name
);
333 d
->module_name
= xstrdup (m
);
334 d
->is_header_unit
= is_header_unit
;
335 d
->cmi_name
= xstrdup (cmi
);
338 /* Add a new module dependency. M is the module name. */
341 deps_add_module_dep (struct mkdeps
*d
, const char *m
)
343 d
->modules
.push (xstrdup (m
));
346 /* Write NAME, with a leading space to FP, a Makefile. Advance COL as
347 appropriate, wrap at COLMAX, returning new column number. Iff
348 QUOTE apply quoting. Append TRAIL. */
351 make_write_name (const char *name
, FILE *fp
, unsigned col
, unsigned colmax
,
352 bool quote
= true, const char *trail
= NULL
)
355 name
= munge (name
, trail
);
356 unsigned size
= strlen (name
);
360 if (colmax
&& col
+ size
> colmax
)
375 /* Write all the names in VEC via make_write_name. */
378 make_write_vec (const mkdeps::vec
<const char *> &vec
, FILE *fp
,
379 unsigned col
, unsigned colmax
, unsigned quote_lwm
= 0,
380 const char *trail
= NULL
)
382 for (unsigned ix
= 0; ix
!= vec
.size (); ix
++)
383 col
= make_write_name (vec
[ix
], fp
, col
, colmax
, ix
>= quote_lwm
, trail
);
387 /* Write the dependencies to a Makefile. If PHONY is true, add
388 .PHONY targets for all the dependencies too. */
391 make_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
393 const mkdeps
*d
= pfile
->deps
;
396 if (colmax
&& colmax
< 34)
401 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
402 if (CPP_OPTION (pfile
, deps
.modules
) && d
->cmi_name
)
403 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
406 make_write_vec (d
->deps
, fp
, column
, colmax
);
408 if (CPP_OPTION (pfile
, deps
.phony_targets
))
409 for (unsigned i
= 1; i
< d
->deps
.size (); i
++)
410 fprintf (fp
, "%s:\n", munge (d
->deps
[i
]));
413 if (!CPP_OPTION (pfile
, deps
.modules
))
416 if (d
->modules
.size ())
418 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
420 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
423 column
= make_write_vec (d
->modules
, fp
, column
, colmax
, 0, ".c++m");
431 /* module-name : cmi-name */
432 column
= make_write_name (d
->module_name
, fp
, 0, colmax
,
436 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
439 column
= fprintf (fp
, ".PHONY:");
440 column
= make_write_name (d
->module_name
, fp
, column
, colmax
,
445 if (d
->cmi_name
&& !d
->is_header_unit
)
447 /* An order-only dependency.
448 cmi-name :| first-target
449 We can probably drop this this in favour of Make-4.3's grouped
451 column
= make_write_name (d
->cmi_name
, fp
, 0, colmax
);
454 column
= make_write_name (d
->targets
[0], fp
, column
, colmax
);
459 if (d
->modules
.size ())
461 column
= fprintf (fp
, "CXX_IMPORTS +=");
462 make_write_vec (d
->modules
, fp
, column
, colmax
, 0, ".c++m");
467 /* Write out dependencies according to the selected format (which is
468 only Make at the moment). */
469 /* Really we should be opening fp here. */
472 deps_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
474 make_write (pfile
, fp
, colmax
);
477 /* Write out a deps buffer to a file, in a form that can be read back
478 with deps_restore. Returns nonzero on error, in which case the
479 error number will be in errno. */
482 deps_save (class mkdeps
*deps
, FILE *f
)
487 /* The cppreader structure contains makefile dependences. Write out this
490 /* The number of dependences. */
491 size
= deps
->deps
.size ();
492 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
495 /* The length of each dependence followed by the string. */
496 for (i
= 0; i
< deps
->deps
.size (); i
++)
498 size
= strlen (deps
->deps
[i
]);
499 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
501 if (fwrite (deps
->deps
[i
], size
, 1, f
) != 1)
508 /* Read back dependency information written with deps_save into
509 the deps sizefer. The third argument may be NULL, in which case
510 the dependency information is just skipped, or it may be a filename,
511 in which case that filename is skipped. */
514 deps_restore (class mkdeps
*deps
, FILE *fd
, const char *self
)
520 /* Number of dependences. */
521 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
524 /* The length of each dependence string, followed by the string. */
525 for (unsigned i
= size
; i
--;)
527 /* Read in # bytes in string. */
528 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
531 if (size
>= buf_size
)
533 buf_size
= size
+ 512;
534 buf
= XRESIZEVEC (char, buf
, buf_size
);
536 if (fread (buf
, 1, size
, fd
) != size
)
543 /* Generate makefile dependencies from .pch if -nopch-deps. */
544 if (self
!= NULL
&& filename_cmp (buf
, self
) != 0)
545 deps_add_dep (deps
, buf
);