1 /* Dependency generator for Makefile fragments.
2 Copyright (C) 2000-2025 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 : primary_output (NULL
), module_name (NULL
), cmi_name (NULL
)
85 , is_header_unit (false), is_exported (false), quote_lwm (0)
92 for (i
= targets
.size (); i
--;)
93 free (const_cast <char *> (targets
[i
]));
94 free (const_cast <char *> (primary_output
));
95 for (i
= fdeps_targets
.size (); i
--;)
96 free (const_cast <char *> (fdeps_targets
[i
]));
97 for (i
= deps
.size (); i
--;)
98 free (const_cast <char *> (deps
[i
]));
99 for (i
= vpath
.size (); i
--;)
100 XDELETEVEC (vpath
[i
].str
);
101 for (i
= modules
.size (); i
--;)
102 XDELETEVEC (modules
[i
]);
103 XDELETEVEC (module_name
);
104 free (const_cast <char *> (cmi_name
));
108 vec
<const char *> targets
;
109 vec
<const char *> deps
;
110 const char * primary_output
;
111 vec
<const char *> fdeps_targets
;
113 vec
<const char *> modules
;
116 const char *module_name
;
117 const char *cmi_name
;
120 unsigned short quote_lwm
;
123 /* Apply Make quoting to STR, TRAIL. Note that it's not possible to
124 quote all such characters - e.g. \n, %, *, ?, [, \ (in some
125 contexts), and ~ are not properly handled. It isn't possible to
126 get this right in any current version of Make. (??? Still true?
127 Old comment referred to 3.76.1.) */
130 munge (const char *str
, const char *trail
= nullptr)
132 static unsigned alloc
;
136 for (; str
; str
= trail
, trail
= nullptr)
138 unsigned slashes
= 0;
140 for (const char *probe
= str
; (c
= *probe
++);)
142 if (alloc
< dst
+ 4 + slashes
)
144 alloc
= alloc
* 2 + 32;
145 buf
= XRESIZEVEC (char, buf
, alloc
);
160 /* GNU make uses a weird quoting scheme for white space.
161 A space or tab preceded by 2N+1 backslashes
162 represents N backslashes followed by space; a space
163 or tab preceded by 2N backslashes represents N
164 backslashes at the end of a file name; and
165 backslashes in other contexts should not be
189 /* If T begins with any of the partial pathnames listed in d->vpathv,
190 then advance T to point beyond that pathname. */
192 apply_vpath (class mkdeps
*d
, const char *t
)
194 if (unsigned len
= d
->vpath
.size ())
195 for (unsigned i
= len
; i
--;)
197 if (!filename_ncmp (d
->vpath
[i
].str
, t
, d
->vpath
[i
].len
))
199 const char *p
= t
+ d
->vpath
[i
].len
;
200 if (!IS_DIR_SEPARATOR (*p
))
203 /* Do not simplify $(vpath)/../whatever. ??? Might not
205 if (p
[1] == '.' && p
[2] == '.' && IS_DIR_SEPARATOR (p
[3]))
209 t
= t
+ d
->vpath
[i
].len
+ 1;
215 /* Remove leading ./ in any case. */
216 while (t
[0] == '.' && IS_DIR_SEPARATOR (t
[1]))
219 /* If we removed a leading ./, then also remove any /s after the
221 while (IS_DIR_SEPARATOR (t
[0]))
228 /* Public routines. */
233 return new mkdeps ();
237 deps_free (class mkdeps
*d
)
242 /* Adds a target T. We make a copy, so it need not be a permanent
243 string. QUOTE is true if the string should be quoted. */
245 deps_add_target (class mkdeps
*d
, const char *t
, int quote
)
247 t
= xstrdup (apply_vpath (d
, t
));
251 /* Sometimes unquoted items are added after quoted ones.
252 Swap out the lowest quoted. */
253 if (d
->quote_lwm
!= d
->targets
.size ())
255 const char *lowest
= d
->targets
[d
->quote_lwm
];
256 d
->targets
[d
->quote_lwm
] = t
;
265 /* Sets the default target if none has been given already. An empty
266 string as the default target in interpreted as stdin. The string
267 is quoted for MAKE. */
269 deps_add_default_target (class mkdeps
*d
, const char *tgt
)
271 /* Only if we have no targets. */
272 if (d
->targets
.size ())
276 d
->targets
.push (xstrdup ("-"));
279 #ifndef TARGET_OBJECT_SUFFIX
280 # define TARGET_OBJECT_SUFFIX ".o"
282 const char *start
= lbasename (tgt
);
283 char *o
= (char *) alloca (strlen (start
)
284 + strlen (TARGET_OBJECT_SUFFIX
) + 1);
289 suffix
= strrchr (o
, '.');
291 suffix
= o
+ strlen (o
);
292 strcpy (suffix
, TARGET_OBJECT_SUFFIX
);
294 deps_add_target (d
, o
, 1);
298 /* Adds a target O. We make a copy, so it need not be a permanent
301 This is the target associated with the rule that (in a C++ modules build)
302 compiles the source that is being scanned for dynamic dependencies. It is
303 used to associate the structured dependency information with that rule as
306 fdeps_add_target (struct mkdeps
*d
, const char *o
, bool is_primary
)
308 o
= apply_vpath (d
, o
);
311 if (d
->primary_output
)
312 d
->fdeps_targets
.push (d
->primary_output
);
313 d
->primary_output
= xstrdup (o
);
315 d
->fdeps_targets
.push (xstrdup (o
));
319 deps_add_dep (class mkdeps
*d
, const char *t
)
323 t
= apply_vpath (d
, t
);
325 d
->deps
.push (xstrdup (t
));
329 deps_add_vpath (class mkdeps
*d
, const char *vpath
)
331 const char *elem
, *p
;
333 for (elem
= vpath
; *elem
; elem
= p
)
335 for (p
= elem
; *p
&& *p
!= ':'; p
++)
339 char *str
= XNEWVEC (char, elt
.len
+ 1);
341 memcpy (str
, elem
, elt
.len
);
350 /* Add a new module target (there can only be one). M is the module
354 deps_add_module_target (struct mkdeps
*d
, const char *m
,
355 const char *cmi
, bool is_header_unit
, bool is_exported
)
357 gcc_assert (!d
->module_name
);
359 d
->module_name
= xstrdup (m
);
360 d
->is_header_unit
= is_header_unit
;
361 d
->is_exported
= is_exported
;
362 d
->cmi_name
= xstrdup (cmi
);
365 /* Add a new module dependency. M is the module name. */
368 deps_add_module_dep (struct mkdeps
*d
, const char *m
)
370 d
->modules
.push (xstrdup (m
));
373 /* Write NAME, with a leading space to FP, a Makefile. Advance COL as
374 appropriate, wrap at COLMAX, returning new column number. Iff
375 QUOTE apply quoting. Append TRAIL. */
378 make_write_name (const char *name
, FILE *fp
, unsigned col
, unsigned colmax
,
379 bool quote
= true, const char *trail
= NULL
)
382 name
= munge (name
, trail
);
383 unsigned size
= strlen (name
);
387 if (colmax
&& col
+ size
> colmax
)
402 /* Write all the names in VEC via make_write_name. */
405 make_write_vec (const mkdeps::vec
<const char *> &vec
, FILE *fp
,
406 unsigned col
, unsigned colmax
, unsigned quote_lwm
= 0,
407 const char *trail
= NULL
)
409 for (unsigned ix
= 0; ix
!= vec
.size (); ix
++)
410 col
= make_write_name (vec
[ix
], fp
, col
, colmax
, ix
>= quote_lwm
, trail
);
414 /* Write the dependencies to a Makefile. */
417 make_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
419 const mkdeps
*d
= pfile
->deps
;
422 if (colmax
&& colmax
< 34)
425 /* Write out C++ modules information if no other `-fdeps-format=`
427 cpp_fdeps_format fdeps_format
= CPP_OPTION (pfile
, deps
.fdeps_format
);
428 bool write_make_modules_deps
= (fdeps_format
== FDEPS_FMT_NONE
429 && CPP_OPTION (pfile
, deps
.modules
));
433 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
434 if (write_make_modules_deps
&& d
->cmi_name
)
435 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
438 make_write_vec (d
->deps
, fp
, column
, colmax
);
440 if (CPP_OPTION (pfile
, deps
.phony_targets
))
441 for (unsigned i
= 1; i
< d
->deps
.size (); i
++)
442 fprintf (fp
, "%s:\n", munge (d
->deps
[i
]));
445 if (!write_make_modules_deps
)
448 if (d
->modules
.size ())
450 column
= make_write_vec (d
->targets
, fp
, 0, colmax
, d
->quote_lwm
);
452 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
455 column
= make_write_vec (d
->modules
, fp
, column
, colmax
, 0, ".c++-module");
463 /* module-name : cmi-name */
464 column
= make_write_name (d
->module_name
, fp
, 0, colmax
,
465 true, ".c++-module");
466 const char *module_basename
= nullptr;
467 if (d
->is_header_unit
)
469 /* Also emit a target for the include name, so for #include
470 <iostream> you'd make iostream.c++-header-unit, regardless of
471 what actual directory iostream lives in. We reconstruct the
472 include name by skipping the directory where we found it. */
473 auto *dir
= _cpp_get_file_dir (pfile
->main_file
);
474 gcc_assert (!strncmp (d
->module_name
, dir
->name
, dir
->len
));
475 module_basename
= (d
->module_name
+ dir
->len
+ 1);
476 column
= make_write_name (module_basename
, fp
, column
, colmax
,
477 true, ".c++-header-unit");
481 column
= make_write_name (d
->cmi_name
, fp
, column
, colmax
);
484 column
= fprintf (fp
, ".PHONY:");
485 column
= make_write_name (d
->module_name
, fp
, column
, colmax
,
486 true, ".c++-module");
488 column
= make_write_name (module_basename
, fp
, column
, colmax
,
489 true, ".c++-header-unit");
493 if (d
->cmi_name
&& !d
->is_header_unit
)
495 /* An order-only dependency.
496 cmi-name :| first-target
497 We can probably drop this this in favour of Make-4.3's grouped
499 column
= make_write_name (d
->cmi_name
, fp
, 0, colmax
);
502 column
= make_write_name (d
->targets
[0], fp
, column
, colmax
);
507 if (d
->modules
.size ())
509 column
= fprintf (fp
, "CXX_IMPORTS +=");
510 make_write_vec (d
->modules
, fp
, column
, colmax
, 0, ".c++-module");
515 /* Write out dependencies according to the selected format (which is
516 only Make at the moment). */
517 /* Really we should be opening fp here. */
520 deps_write (const cpp_reader
*pfile
, FILE *fp
, unsigned int colmax
)
522 make_write (pfile
, fp
, colmax
);
525 /* Write out a a filepath for P1689R5 output. */
528 p1689r5_write_filepath (const char *name
, FILE *fp
)
530 if (cpp_valid_utf8_p (name
, strlen (name
)))
533 for (const char* c
= name
; *c
; c
++)
535 // Escape control characters.
537 fprintf (fp
, "\\u%04x", *c
);
538 // JSON escape characters.
539 else if (*c
== '"' || *c
== '\\')
552 // TODO: print an error
556 /* Write a JSON array from a `vec` for P1689R5 output.
558 In P1689R5, all array values are filepaths. */
561 p1689r5_write_vec (const mkdeps::vec
<const char *> &vec
, FILE *fp
)
563 for (unsigned ix
= 0; ix
!= vec
.size (); ix
++)
565 p1689r5_write_filepath (vec
[ix
], fp
);
566 if (ix
< vec
.size () - 1)
572 /* Write out the P1689R5 format using the module dependency tracking
573 information gathered while scanning and/or compiling.
575 Ideally this (and the above `p1689r5_` functions) would use `gcc/json.h`,
576 but since this is `libcpp`, we cannot use `gcc/` code.
578 TODO: move `json.h` to libiberty. */
581 deps_write_p1689r5 (const struct mkdeps
*d
, FILE *fp
)
585 fputs ("\"rules\": [\n", fp
);
588 if (d
->primary_output
)
590 fputs ("\"primary-output\": ", fp
);
591 p1689r5_write_filepath (d
->primary_output
, fp
);
595 if (d
->fdeps_targets
.size ())
597 fputs ("\"outputs\": [\n", fp
);
598 p1689r5_write_vec (d
->fdeps_targets
, fp
);
604 fputs ("\"provides\": [\n", fp
);
607 fputs ("\"logical-name\": ", fp
);
608 p1689r5_write_filepath (d
->module_name
, fp
);
611 fprintf (fp
, "\"is-interface\": %s\n", d
->is_exported
? "true" : "false");
613 // TODO: header-unit information
619 fputs ("\"requires\": [\n", fp
);
620 for (size_t i
= 0; i
< d
->modules
.size (); i
++)
626 fputs ("\"logical-name\": ", fp
);
627 p1689r5_write_filepath (d
->modules
[i
], fp
);
630 // TODO: header-unit information
640 fputs ("\"version\": 0,\n", fp
);
641 fputs ("\"revision\": 0\n", fp
);
646 /* Write out a deps buffer to a file, in a form that can be read back
647 with deps_restore. Returns nonzero on error, in which case the
648 error number will be in errno. */
651 deps_save (class mkdeps
*deps
, FILE *f
)
656 /* The cppreader structure contains makefile dependences. Write out this
659 /* The number of dependences. */
660 size
= deps
->deps
.size ();
661 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
664 /* The length of each dependence followed by the string. */
665 for (i
= 0; i
< deps
->deps
.size (); i
++)
667 size
= strlen (deps
->deps
[i
]);
668 if (fwrite (&size
, sizeof (size
), 1, f
) != 1)
670 if (fwrite (deps
->deps
[i
], size
, 1, f
) != 1)
677 /* Read back dependency information written with deps_save into
678 the deps sizefer. The third argument may be NULL, in which case
679 the dependency information is just skipped, or it may be a filename,
680 in which case that filename is skipped. */
683 deps_restore (class mkdeps
*deps
, FILE *fd
, const char *self
)
689 /* Number of dependences. */
690 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
693 /* The length of each dependence string, followed by the string. */
694 for (unsigned i
= size
; i
--;)
696 /* Read in # bytes in string. */
697 if (fread (&size
, sizeof (size
), 1, fd
) != 1)
700 if (size
>= buf_size
)
702 buf_size
= size
+ 512;
703 buf
= XRESIZEVEC (char, buf
, buf_size
);
705 if (fread (buf
, 1, size
, fd
) != size
)
712 /* Generate makefile dependencies from .pch if -nopch-deps. */
713 if (self
!= NULL
&& filename_cmp (buf
, self
) != 0)
714 deps_add_dep (deps
, buf
);