0

I am trying to decompose a make build system of a very large code base however I am unable to see every command the make invokes because it calls various make files in numerous directories outside of the current directory. I followed this answer and various other ones Making make print commands before executing when NOT using CMake

Though the above yielded some advancement and was quite illuminating it was not the home run I need. It offers solutions to see the commands that make invokes. Which is better than great. However, the issue is the various sub make commands that are invoked thereafter. I only see those commands as printed with no additional information of what is occurring sub make. I tried to alias make such that

alias make='make SHELL='\''/bin/bash -x'\'''

# or

alias make='make -n'

However the above fail to replace the invoked make commands with the alias. Is there another way I can dissect a large code base make build system out there?

> make
rmdir --ignore-fail-on-non-empty /somefolder* 2> /dev/null; true
cd /someotherfolder/; make cur-dir=somefolder dirs-to-build=somemorefolders/ env_variable another_variable someMakeRule # no output from this  make
make  TARGET=someTarget env_variable gdbinit source_dir someMakeRule; # no output from this  make
# ...
# output from first top makefile
# ...
make[1]: Nothing to be done for 'someMakeRule'.
LeanMan
  • 474
  • 1
  • 4
  • 18

2 Answers2

1

You cannot use an alias, because aliases only exist in interactive shells and are not present in non-interactive shells like the one make uses to invoke comments in recipes. Same with shell functions.

You also cannot set the SHELL variable to a command that uses arguments: the value of SHELL must be only a command name. You can, though, set the .SHELLFLAGS variable to extra options to pass to the shell. Don't forget you need the -c option in addition to whatever flags you add!

Something like .SHELLFLAGS=-xc

If your makefiles are all properly invoking their submakes then using make -n as the initial invocation should Just Work.

By "properly invoking" I mean, they should always use the $(MAKE) variable when invoking sub-makes and never use a raw make command.

If they do not invoke sub-make properly and you cannot fix that, then the best you can do is write a shell script called make that does what your aliases above do, then add that to your PATH so it's found first. Obviously inside the script you'll have to use a fully-qualified path to run the "real" make else you'll get infinite recursion :)

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • TY for quick reply. I searched for all instances of "make" and "$(MAKE)" using "grep -r expr --include=Makefile" to see what type of make was being called in the code. I thought I had found the smoking gun but it turned out that it was print statement. Whenever I do the specified query I do see $(MAKE) being used - though when I call make -n or variant, whenever the invoked command is a make command, it just says "make ..." and then doesn't expand on the commands. Also, there were a lot of hits that were "-include $(RELTOPDIR)/scripts/Makefile.submake" I don't know if that bypasses anything. – LeanMan May 28 '20 at 16:29
  • 1
    First, you won't see the option on the command line. It's passed through the environment. But it should still be in effect. Second, included makefiles aren't relevant here: it works exactly as if you'd taken the text of the other makefile and inserted it at the point where the `include` is. So all options etc. apply equally to included makefiles. – MadScientist May 28 '20 at 17:03
  • 1
    I guess, I'm not really sure exactly what the problem is you're seeing. If your sub-make invocations are using `$(MAKE)`, and you're not changing/overriding the `MAKEFLAGS` variable, then any options like `-n` in the parent make will definitely be passed to the sub-makes. – MadScientist May 28 '20 at 17:06
  • hm. OK! I will double check it all! See my OP of what the output looks like, I have to remove things since I can't show real output. – LeanMan May 28 '20 at 18:01
  • actually you're right, I was able to get it to work - I was being dumb. I needed to do a make clean first to force a rebuild. I'm assuming it didn't show any output because it saw the object files and ended up saying nothing to do. – LeanMan May 28 '20 at 18:18
  • now that I can see where the GCC command is being executed, is it possible for me to be able to see which makefile it comes from? That will go a long way in this debugging quest. – LeanMan May 28 '20 at 18:27
  • 1
    Sure, just run `make -d`. Or if that's too much info you can use `make --trace`. There are also partial debug options; see https://www.gnu.org/software/make/manual/html_node/Options-Summary.html – MadScientist May 28 '20 at 20:31
1

You can easily trace execution with --trace option. Consider the following example where someone had an idea to show clean output only without any option for being verbose:

$ cat Makefile
all: foo
        @echo Done with $@

foo: bar
        @echo Done with $@

bar:
        @$(MAKE) -f Makefile2 bar

.SILENT:

$ cat Makefile2
bar: baz
        @echo Done with $@

baz:
        @echo Done with $@

Regular build does not allow to check what's happening:

$ make
Done with baz
Done with bar
Done with foo
Done with all

But --trace will show what is happening and why:

$ make --trace
Makefile:8: target 'bar' does not exist
make -f Makefile2 bar
Makefile2:5: target 'baz' does not exist
echo Done with baz
Done with baz
Makefile2:2: update target 'bar' due to: baz
echo Done with bar
Done with bar
Makefile:5: update target 'foo' due to: bar
echo Done with foo
Done with foo
Makefile:2: update target 'all' due to: foo
echo Done with all
Done with all
raspy
  • 3,995
  • 1
  • 14
  • 18