Menu

#4 Unbreak parallel builds (make -jX)

v1.0_(example)
closed
nobody
None
5
2014-02-19
2013-09-03
No

Inside Makefile.in, there are several lines like "cd foo && $(MAKE)" in targets' recipes. For -jX builds, it is not guaranteed that current directory will stay the same, and thus makes Makefile broken for many make(1) implementations. Correct way is to avoid using cd at all, but use make's -C switch instead.

To fix, just run: sed -E 's,cd (.+) && (\$(MAKE)),\2 -C \1,' Makefile.in > Makefile.in.fixed

Or just edit Makefile manually.

Discussion

  • Benjamin Moody

    Benjamin Moody - 2013-09-04

    Thank you for reporting this issue. What version of make are you using? I use -j (with GNU make) all the time and have never seen the problem you're describing.

    Your explanation doesn't make sense to me. "cd foo && $(MAKE)" has nothing to do with parallelism - it's two commands executed in sequence, and any version of make that tried to execute "cd foo" and "$(MAKE)" simultaneously would be severely broken, not just for this case but for any number of other cases. (In general the point of a parallel build is to run several independent commands simultaneously; running commands in parallel when the Makefile explicitly says they are to be run sequentially would be a very bad thing.)

    Could it be that your version of make passes all of the commands in a rule to a single shell, in which case it would attempt to execute the later commands starting from the first subdirectory? I had never heard of such a thing - and I'm a little surprised since "cd foo && make" is a common idiom I've seen in many makefiles - but POSIX claims it is allowed. (Again, though, this has nothing to do with parallelism.)

    The solution, I guess, is to enclose each line in parentheses (run each as a sub-shell.) This seems to be what automake does at least in some cases. The -C option, for what it's worth, is not specified by POSIX and apparently not supported by some versions of make.

     
  • Alexey Dokuchaev

    What version of make are you using? I use -j (with GNU make) all the time and have never seen the problem you're describing.

    Correct; it does not happen with GNU make. In fact, previously, GNU make was forced as a workaround, until I decided to fix it for real.

    The problem occurs with BSD make, both old one (fmake) and new (bmake).

    Your explanation doesn't make sense to me. "cd foo && $(MAKE)" has nothing to do with parallelism - it's two commands executed in sequence [...]

    Sorry, I guess I was not clear. "cd .. && $(make)" alone does not run in parallel of course. The problem is that you had several lines like that in your recipes, one after another. It is not guaranteed that $cwd will stay the same between the lines:

    Consider this simple Makefile:

    all:
        @cd /tmp && sleep 1
        @pwd
        @cd / && sleep 1
        @pwd

    With BSD make and GNU make:

    $ make
    /tmp
    /tmp
    $ make -j2
    /tmp                <<<<<<<<
    /                   <<<<<<<<
    $ gmake
    /tmp
    /tmp
    $ gmake -j2
    /tmp
    /tmp

    The solution, I guess, is to enclose each line in parentheses (run each as a sub-shell.)

    Yes, that would fix the issue.

    This seems to be what automake does at least in some cases. The -C option, for what it's worth, is not specified by POSIX and apparently not supported by some versions of make.

    Well, all major make implementations I've seen on *nix support it. But if you don't like it, or adhere to strict POSIX compliance, parenthesis should be sufficient.

     
  • contra-sh

    contra-sh - 2014-02-19

    Thank you for the report.

    Fixed with r740 (https://sourceforge.net/p/tilem/code/740/)

    Best regards

     
  • contra-sh

    contra-sh - 2014-02-19
    • status: open --> closed
     

Log in to post a comment.