RMKDEPEND(1)

πŸ¦‹ RMKDEPEND πŸ¦‹ (section 1, General Commands Manual, bestie)

so like. this page is RMKDEPEND(1) β€” it lives in the General Commands Manual, and it's the ROOT-flavoured remix of a classic. sit down, grab a boba, we're generating dependencies in makefiles and we're gonna slay πŸ’…


✨ NAME ✨

rmkdepend β€” create dependencies in makefiles (ROOT Version)

like, it makes the dependency lines. that's the whole job. iconic behaviour honestly πŸ‘‘


✨ SYNOPSIS ✨

rmkdepend [ -Dname=def ] [ -Dname ] [ -Iincludedir ] [ -Yincludedir ] [
-a ] [ -fmakefile ] [ -oobjsuffix ] [ -pobjprefix ] [ -sstring ] [
-wwidth ] [ -v ] [ -m ] [ -- otheroptions -- ] sourcefile [
-ttargetfilename ] ...

no cap, that's a lot of brackets. we'll go through every single one, don't worry 🫢


✨ DESCRIPTION ✨

okay so here's the vibe: rmkdepend reads each sourcefile one after another, and it parses it like a C-preprocessor. it handles all of #include, #define, #undef, #ifdef, #ifndef, #endif, #if, #elif and #else directives, so it can actually tell which #include directives would get used in a compilation. and because those #include directives can point at files that have their own #include directives, it just keeps parsing into those files too. recursion, but make it fashion πŸŒ€

every file that a sourcefile includes β€” directly or indirectly β€” is what rmkdepend calls a dependency. those dependencies get written into a makefile in a way that makes make(1) know which object files have to be recompiled when a dependency changes. she's doing the mental load for you, fr.

by default, rmkdepend drops its output into the file named makefile if it exists, otherwise Makefile. wanna use a different one? -f has you covered. first it searches the makefile for the line

# DO NOT DELETE THIS LINE -- make depend depends on it.

or one you supplied with -s, and it uses that as a delimiter for the dependency output. if it finds it, everything from there to the end of the makefile gets deleted and the output goes right after that line. if it doesn't find it, the program appends the string to the end of the makefile and puts the output after that. bestie it's just gonna find a spot for itself πŸŽ€

for each sourcefile on the command line, rmkdepend puts lines in the makefile that look like

sourcefile.o: dfile ...

where sourcefile.o is the name from the command line with its suffix swapped for .o, and dfile is a dependency discovered in a #include directive while parsing sourcefile or one of the files it included. ✨


✨ NOTE ✨

so the tea β˜•: rmkdepend is based on makedepend(1) from the X Consortium, just modified a little to fit what the ROOT system needs. and this man(1) page is more or less identical to the manpage for makedepend(1) β€” except for this notice, and the SEE ALSO and AUTHORS sections. so if you've read that one, you already know the lore. iykyk πŸ’œ


✨ EXAMPLE ✨

normally you'd use rmkdepend inside a makefile target, so that typing make depend brings all the dependencies up to date for that makefile. like:

SRCS = file1.c file2.c ...
CFLAGS = -O -DHACK -I../foobar -xyz
depend:
    rmkdepend -- $(CFLAGS) -- $(SRCS)

see how the -- wrappers are holding $(CFLAGS) hostage so all that esoteric compiler nonsense gets safely ignored? that's the move. main character energy 🌈


✨ OPTIONS ✨

quick heads up before we dive in: the program will ignore any option that it does not understand, so you can literally throw the same arguments at it that you'd throw at cc(1). she's unbothered πŸ’…

  • -Dname=def or -Dname β€” Define. this puts a definition for name into rmkdepend's symbol table. if you leave off the =def, the symbol just becomes defined as 1. simple as.
  • -Iincludedir β€” Include directory. tells rmkdepend to prepend includedir to its list of directories to search when it hits a #include directive. by default rmkdepend only searches the standard include directories (usually /usr/include and possibly a compiler-dependent directory). so if your headers live somewhere quirky, this is your girl 🧚
  • -Yincludedir β€” replaces all of the standard include directories with the single specified include directory. and yes, you can just omit includedir entirely if you want to flat-out prevent searching the standard include directories. ghosting the standard dirs, honestly valid πŸ’€
  • -a β€” Append. the dependencies get appended to the end of the file instead of replacing them.
  • -fmakefile β€” Filename. lets you specify an alternate makefile for rmkdepend to put its output in. and if you pass - as the file name (i.e., -f-), the output goes to standard output instead of modifying an existing file. very demure, very stdout ✨
  • -oobjsuffix β€” Object file suffix. some systems have object files whose suffix isn't .o, and this lets you specify another one. like .b with -o.b, or :obj with -o:obj, and so forth. so many options, so much power πŸŽ€
  • -pobjprefix β€” Object file prefix. this prefix gets prepended to the name of the object file. usually it's used to point the object file at a different directory. the default is the empty string. (yes, empty. a whole lot of nothing. respect πŸ™ˆ)
  • -sstring β€” Starting string delimiter. lets you specify a different string for rmkdepend to look for in the makefile.
  • -wwidth β€” Line width. normally rmkdepend makes sure every output line it writes is no wider than 78 characters, for the sake of readability. this option lets you change that width. accessibility queen πŸ‘‘
  • -v β€” Verbose operation. makes rmkdepend emit the list of files included by each input file on standard output. she's telling you everything.
  • -m β€” Warn about multiple inclusion. makes rmkdepend produce a warning if any input file includes another file more than once. fun fact: in previous versions of rmkdepend this was the default behaviour, but the default got changed to better match what the C compiler does β€” and the C compiler does not consider multiple inclusion to be an error. so this option is here for backward compatibility, and to help you debug multiple-inclusion problems. legacy support, but make it cute πŸ’œ
  • -- options -- β€” if rmkdepend encounters a double hyphen (--) in the argument list, then any unrecognized argument following it gets silently ignored; a second double hyphen terminates this special treatment. this is how rmkdepend can be made to safely ignore esoteric compiler arguments that might normally show up in a CFLAGS make macro (peep the EXAMPLE section above πŸ‘€). but heads up: all options that rmkdepend recognizes and that appear between the pair of double hyphens still get processed normally. so it's not a blanket immunity shield, bestie.
  • -ttargetfilename β€” Filename. lets you specify an alternate target filename to be used for the preceding file. for example, if you call
rmkdepend -sobj -pbuild file.cxx -tlibrary.so

then rather than inserting the line

build/file.obj: ...

rmkdepend will insert:

library.so: ...

swapping the whole identity out mid-command. she contains multitudes πŸ¦‹


✨ ALGORITHM ✨

the approach used in this program lets it run an order of magnitude faster than any other "dependency generator" the author had ever seen. no cap, that's the actual claim. and it's all built on two assumptions:

  1. that all files compiled by a single makefile will be compiled with roughly the same -I and -D options; and
  2. that most files in a single directory will include largely the same files.

given those assumptions, rmkdepend expects to be called once for each makefile, with all the source files that are maintained by that makefile appearing on the command line. it parses each source and include file exactly once, keeping an internal symbol table for each one. so the first file on the command line takes an amount of time proportional to what a normal C preprocessor would take. but on the subsequent files, if it hits an include file it's already parsed, it does not parse it again. she remembers. she's efficient. she's that girl 🧠✨

for example, imagine you're compiling two files, file1.c and file2.c. they each include the header file header.h, and header.h in turn includes the files def1.h and def2.h. when you run the command

rmkdepend file1.c file2.c

rmkdepend will parse file1.c and consequently header.h and then def1.h and def2.h. it then decides that the dependencies for this file are

file1.o: header.h def1.h def2.h

but when the program parses file2.c and discovers that it, too, includes header.h, it does not parse the file β€” it simply adds header.h, def1.h and def2.h to the list of dependencies for file2.o. cached, served, no re-work required πŸ’…


✨ SEE ALSO ✨

also go look at the ROOT webpages: http://root.cern 🌐


✨ BUGS ✨

okay time for the reality check, and these are real, so listen up 🫢

rmkdepend parses, but does not currently evaluate, the SVR4 #predicate(token-list) preprocessor expression. such expressions are simply assumed to be true. this may cause the wrong #include directives to be evaluated. so like… she's guessing. and sometimes she guesses wrong. 😭

and here's the second one, and it's a big deal:

imagine you are parsing two files, say file1.c and file2.c, each includes the file def.h. the list of files that def.h includes might truly be different when def.h is included by file1.c than when it is included by file2.c. but once rmkdepend arrives at a list of dependencies for a file, it is cast in concrete. 🧱

no take-backs. no second thoughts. the dependency list is permanent, bestie. that's the trade-off for the speed, and you gotta know it going in πŸ’€


✨ AUTHOR ✨

Todd Brunhoff, Tektronix, Inc. and MIT Project Athena. Modified by Christian Holm Christensen <cholm@nbi.dk> for the ROOT distribution. 🫑 legends, all of them.


and that's the whole page!! this came out of the 4th Berkeley Distribution, it's Version 3, and yeah it's literally just RMKDEPEND(1) again at the bottom but we're saying it with love πŸ’– go make depend, bestie, you've got this πŸŽ€βœ¨πŸ¦‹

πŸ“¦ where this page comes from