Reputation: 49
In my current project, more than 200MB C files are present. While making targets I can able to see only < 100MB is used to create a binary. How, to identify what are the files are not touched while creating targets. So, that we can strip it off and make the codebase more sleek.
How, to identify the list of files created for target while compiling?
Upvotes: 2
Views: 610
Reputation: 8611
I think the best approach is to use one of the methods Linux offers for monitoring file system access:
You could also run the make
command with strace (strace -f make
) and parse the output for open()
calls.
That is what I used to do in the past.
Take your pick.
Upvotes: 1
Reputation: 61630
If your make
is GNU make
, as seems likely, you could consider
variations on the following approach. (For simplicity I'll assume that the only
source files of interest are .c
files.)
Say we have Makefile
in directory dir
that makes some default
target and possibly others, including intermediate targets.
You can use another makefile, say, unused_srcs.mk
that you include
in
Makefile
, such that in dir
you can run:
make unused_srcs
which will display a list of all the source files in dir
that don't
contribute to the default target. Or run:
make unused_srcs target=TARG
for some target TARG
, and get a list of all the source files in dir
that
don't contribute to TARG
.
This assumes that Makefile
has a clean
target, or maybe several
variants of clean[-???]
, that can suitably clean the default target or
any target you might be interested in, and that you don't mind
a suitable clean[-???]
being invoked for the unused_srcs
target.
For example, in dir
we have:
main.c
extern void boo(void);
int main(void)
{
boo();
return 0;
}
boo.c
#include <stdio.h>
void boo(void)
{
puts("Boo!");
}
noop.c
void noop(void){}
Makefile
.phony: all clean
all: boo
objs = main.o boo.o
boo: $(objs)
gcc -o $@ $^
clean-obj:
rm -f *.o
clean: clean-obj
rm -f boo
# include /some/standard/place/unused_srcs.mk
include unused_srcs.mk
And in some standard place which, for simplicity, we'll assume is again dir
,
we have:
unused_srcs.mk
.phony: unused_srcs
ifndef $(target)
target = all
endif
ifndef $(cleaner)
cleaner = clean
endif
all_srcs = $(wildcard *.c)
used_srcs = $(filter %.c,$(shell ($(MAKE) $(cleaner) && $(MAKE) -n -d $(target)) \
| grep -e 'Considering target file' | sed -e "s/[\`\']//g" -e "s/\.$$//g" -))
unused_srcs = $(filter-out $(used_srcs),$(all_srcs))
unused_srcs:
@echo $(unused_srcs)
In this project:-
noop.c
is unused by boo
(it is completely superfluous)noop.c
and main.c
are unused by boo.o
noop.c
and boo.c
are unused by main.o
And we can discover such facts with make unused_srcs
commands:
$ make unused_srcs
noop.c
$ make unused_srcs target=boo
noop.c
$ make unused_srcs target=boo.o
main.c noop.c
$ make unused_srcs cleaner=clean-obj target=boo.o
main.c noop.c
$ make unused_srcs target=main.o
boo.c noop.c
$ make unused_srcs target=clean
boo.c main.c noop.c
Clearly all the heavy-lifting is done in the evaluation of $(used_srcs)
and $(unused_srcs)
in unused_srcs.mk
, and mostly the former.
The evaluation of $(used_srcs)
exploits GNU make
's -d
option, which
generates fulsome debugging info, together with the fact that any source
file that does contribute to the chosen TARG must itself be considered
a potential target when TARG is made.
Together, these things mean that if we clean TARG and then run make -n -d TARG
the output will be the debugging info of a dry-run (-n
) of make TARG
,
and in this output a line like:
Considering target file `FILE.c'.
will appear for each .c
file FILE.c
that contributes to TARG
, and
for no other .c
files that may be present.
The evaluation of $(used_srcs)
generates that debugging info and filters
it to extract the names of the .c
files.
The evaluating of $(unused_srcs)
then just weeds out the $(used_srcs)
from the list of all the .c
files there are.
Upvotes: 0
Reputation: 136525
Another method is to open the (autogenerated) dependency files for you executables and shared libraries. They are going to contain .o
as prerequisites, which normally correspond to .c
.
This works best for non-recursive make build systems with complete dependency trees.
Upvotes: 0
Reputation: 400159
I would probably:
make clean
make 2>out
to capture the full log of the build to a filegrep
the out
file for gcc
invocationsgcc
invocationsOr something like that. Shouldn't be too hard.
Upvotes: 1