6

Is there a way to test for missing dependencies that shows up when compiling a project with multiple jobs (-jN where N > 1)?

I often encounter packages, mostly open source, where the build process works fine as long as I use -j1, or -jN where N is a relatively low value such as 4 or 8 but if I used higher values likes 48, a little uncommon, it starts to fail due to missing dependencies.

I attempted to build myself a bash script that would, given a target, figure out all the dependencies and try to build explicitly each of those dependency with -j1 in order to validate that none are missing dependencies on their own. It appears to work with small / medium package but fails on more important one like uClibc for example.

I am sharing my script in here, as some people may understand better what I mean by reading code. I also hope that a more robust solution exists and could be shared back.

#!/bin/bash
TARGETS=$*
echo "TARGETS=$TARGETS"

for target in $TARGETS
do
    MAKE="make"
    RULE=`make -j1 -n -p | grep "^$target:"`
    if [ -z "$RULE" ]; then
        continue
    fi

    NEWTARGETS=${RULE#* }
    if [ -z "$NEWTARGETS" ]; then
        continue
    fi

    if [ "${NEWTARGETS}" = "${RULE}" ]; then
        # leaf target, we do not want to test.
        continue
    fi

    echo "RULE=$RULE"
#   echo "NEWTARGETS=$NEWTARGETS"
    $0 $NEWTARGETS
    if [ $? -ne 0 ]; then
        exit 1
    fi

    echo "Testing target $target"
    make clean && make -j1 $target 
    if [ $? -ne 0 ]; then
        echo "Make parallel will fail with target $target"
        exit 1
    fi
done
  • 2
    I'm not sure exactly what the question is... I don't think there's any better method for exhaustively verifying parallel correctness than the one you've described: running a build for each target and verify that it works. I don't think, though, that you have to restrict the builds to `-j1`. If they are going to fail at `-j1` then they'll definitely fail at higher `-j` as well, so you might as well speed up your builds. – MadScientist Sep 23 '14 at 17:50
  • How does this fall down on larger projects? Does it fail in a practical manner or just from a time to run/difficulty of manual invocation perspective? – Etan Reisner Sep 23 '14 at 17:59
  • I think forcing `-j1` masks as many prereq issues as it forces into the open. Assuming prereqs are built in the order listed then any `target: prereqA prereqB` where `prereqA` depends on `prereqB` without declaring that will fail with `-j1` but might pass with `-jN`. Invert the order of those prereqs (`prereqB prereqA`) and `-j1` will never fail but `-jN` might (but equally well might not, you'd have to fuzz the prereq order to be sure). – Etan Reisner Sep 23 '14 at 18:09
  • On larger projects, I saw it fails in two different ways so far. One is that makefile would like a dependency rules such as "exec1: exec1.o" but in reality in the Makefile such dependency doesn't exists and the real target is "exec1: exec1.S" for example, which cause the make to fail when requesting to build exec1.o as there are no target defined for this. I am unclear why Make report such a rule in such case. The other situation I have seen it fail is when there are target specified like this "exec1 exec2: $(OBJS)" my scripts right now is not handling such case. – Yannick Koehler Sep 23 '14 at 18:30
  • I believe you are right that I could remove the -j1, since I am testing all targets. While -j1 will hide missing dependencies such as "all: dir1 dir2" where dir2 depends on dir1 but no rules such as "dir2: dir1" has been specified, it also help in getting a proper output for debugging once an error has occur. – Yannick Koehler Sep 23 '14 at 18:36
  • MadScientist the question is, is there a better way than my above hand made script to test a Makefile... I would have hoped that with such a long development time such tool would have existed, or that someone would have built another hand-made tools that is way more evolved then mine. Since I really just wrote that to see if it would be possible and also to better explain the issue I am trying to solve. – Yannick Koehler Sep 23 '14 at 18:38

1 Answers1

1

I'm not aware of any open source solution, but this is exactly the problem that ElectricAccelerator, a high-performance implementation of GNU make, was created to solve. It will execute the build in parallel and dynamically detect and correct for missing dependencies, so that the build output is the same as if it had been run serially. It can produce an annotated build log which includes details about the missing dependencies. For example, this simple makefile has an undeclared dependency between abc and def:

all: abc def

abc:
        echo PASS > abc

def:
        cat abc

Run this with emake instead of gmake and enable --emake-annodetail=history, and the resulting annotation file includes this:

<job id="Jf42015c0" thread="f4bfeb40" start="5" end="6" type="rule" name="def" file="Makefile" line="6" neededby="Jf42015f8">
<command line="7">
<argv>cat abc</argv>
<output>cat abc
</output>
<output src="prog">PASS
</output>
</command>
<depList>
<dep writejob="Jf4201588" file="/tmp/foo/abc"/>
</depList>
<timing invoked="0.356803" completed="0.362634" node="chester-1"/>
</job>

In particular the <depList> section shows that this job, Jf42015c0 (in other words, def), depends on job Jf4201588, because the latter modified the file /tmp/foo/abc.

You can give it a try for free with ElectricAccelerator Huddle.

(Disclaimer: I'm the architect of ElectricAccelerator)

Eric Melski
  • 16,432
  • 3
  • 38
  • 52
  • Yes, second that. I know ElectricAccelerator from personal experience in multiple large-scale corporate software environments. It is the best thing since sliced bread, as far as I am concerned. Dislaimer: I am not an employee or in any way attached to ElectricCloud. – Mark Galeck Oct 02 '14 at 03:57
  • Well, the electric accelerator software does a lot more than what I am asking here, it actually solves the missing dependencies. What I was hoping for is a way to validate/certify that there was no such issue (without necessarily solving them). We used EA for a while, but it also fails in a lot of situation causing us to stop using it. We are now more focused on finding the missing deps and fixing them by a human, which tends to works a lot better so far in the stability area. Yet, I was hoping that somehow GNU Make could provide some output as to make that task easier. – Yannick Koehler Nov 24 '20 at 15:19
  • Accelerator has come a long way since this answer was originally written, with lots of fixes and improvements -- more than 2,000 individual tickets, by my count. There's a good chance than whatever failures you were running into have been solved, or could be solved with small changes to the way you use it. `--emake-readdir-conflicts` in particular comes to mind as a valuable addition in that regard. If not it would be great to contact support at CloudBees.com so we can try to fix up whatever is troubling your usage. – Eric Melski Nov 29 '20 at 20:03