-
-
Couldn't load subscription status.
- Fork 5.9k
Fix parallel make of object files #1259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The objects target creates the objects directory. The object files are created inside the objects directory, but the object file targets don't specify the objects target as a dependency. For a parallel make (e.g., make -j 4), this can lead to a build failure if an object file target is executed before the objects target is executed. For example, if the objects/os_macosx.o target is executed before the objects target, then the build will try to create os_macosx.o inside the objects directory, but that will fail because the objects directory does not exist yet. To fix this, add the objects target as a dependency of all object file targets, and add a -p option to mkdir in the objects target since the objects directory can already exist.
|
Lewis Muir wrote:
Parallel make isn't really supported. This patch causes "make" to build all the objects every time. The only backup you need is the one that you didn't have time for. /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \ |
To support parallel make by ensuring that the objects directory gets created before the object file targets write to it, the objects target was added as a dependency of the object file targets. This had the unfortunate side effect of causing all object files to be built every time (I assume because writing to the objects directory caused the last-modified time of the objects directory to be updated). Revert that dependency, and instead make each object file target create the objects directory before creating the object file in it.
|
On 11/17, Bram Moolenaar wrote:
OK, I didn't know that. Is your position that you don't want to support
Rats! Sorry about that. OK, I've pushed another commit that keeps the |
src/Makefile
Outdated
| mkdir -p objects | ||
|
|
||
| objects/arabic.o: arabic.c | ||
| objects/arabic.o: objects arabic.c |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use an order-only dependency so this file is not rebuilt when the directory timestamp changes:
objects/arabic.o: arabic.c | objects
...Although TBH I'm not sure if that's a GNU Make extension, or if it's portable enough to be acceptable to Vim...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I intentionally did not use that since it's a GNU Make feature. NetBSD's Make, for example, does not support that. (NetBSD's Make has a special .ORDER target that I think tries to solve a similar problem.) I thought the Vim developers wouldn't be too excited about making GNU Make a requirement for building. And even if they were OK with it, my personal preference would be to not introduce a requirement on a specific Make implementation.
BTW, I made a second commit that reverts the addition of the objects dependency on the object file targets since Bram noted that that caused the object files to be built every time. Now, each object file target ensures the objects directory is created before creating the object file in it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, each object file target ensures the objects directory is created before creating the
objectfile in it.
I think this might be slow. A different approach to consider is to depend on something like objects/.dirstamp and create objects directory in rules for objects/.dirstamp target. This is how automake and probably some other build systems do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, interesting. I like that better than having the mkdir in each of the object file targets. I just pushed another commit that implements your suggestion. Thanks!
The object file targets need to depend on the objects target to ensure the objects directory gets created before creating an object file in it. However, adding the objects target as a dependency has the undesirable side effect of causing Make to think that the object files are out of date whenever it tries to build them, so they are built every time. To overcome this, the creation of the objects directory was moved into each object file target. Then, it was suggested by GitHub user xaizek in a GitHub code review comment that a better approach would be to use the DIR/.dirstamp idiom for a dependency on directory DIR. This implements that suggestion, thereby removing the need to create the objects directory in each object file target.
|
On Fri, Nov 18, 2016 at 8:48 AM, Marius Gedminas
Isn't there a "gmake" (i.e. GNU make) program, available for use even Best regards, |
|
On 11/18, vim-dev ML wrote:
Yes, there are ports of GNU Make for Windows, but they don't come |
|
Ping? |
|
Hello, Bram! I see you did not commit my fix but rather something else to address the issue. That's fine with me, and thanks for committing it! Unfortunately, what you committed does not seem quite right; there's still a dependency bug which can be recreated by adding a delay to the Here's how to reproduce it: Add a delay (i.e., Run a parallel build: On macOS Sierra (10.12.1), this results in the following: |
|
src/Makefile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index a24eb7b..38f5cb2 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1705,7 +1705,7 @@ OBJ_MESSAGE_TEST = \
MESSAGE_TEST_OBJ = $(OBJ_COMMON) $(OBJ_MESSAGE_TEST)
-ALL_OBJ = $(OBJ_COMMON) $(OBJ_JSON_TEST) $(OBJ_MEMFILE_TEST) $(OBJ_MESSAGE_TEST)
+ALL_OBJ = $(OBJ) $(OBJ_JSON_TEST) $(OBJ_MEMFILE_TEST) $(OBJ_MESSAGE_TEST)
PRO_AUTO = \
@@ -2862,7 +2862,8 @@ auto/gui_gtk_gresources.h: gui_gtk_res.xml $(GUI_GTK_RES_INPUTS)
# commands understand putting object files in another directory, it must be
# specified for each file separately.
-objects objects/.dirstamp:
+objects: objects/.dirstamp
+objects/.dirstamp:
mkdir -p objects
touch objects/.dirstamp
|
|
Lewis Muir wrote:
Hello, Bram! I see you did not commit my fix but rather something else
to address the issue. That's fine with me, and thanks for committing it!
Unfortunately, what you committed does not seem quite right; there's
still a dependency bug which can be recreated by adding a delay to the
`objects objects/.dirstamp` target to force an unfavorable ordering for
a parallel build.
Here's how to reproduce it:
```
$ git clone https://github.com/vim/vim.git
$ cd vim
$ ./configure
```
Add a delay (i.e., `sleep 5` in this case) to the `objects objects/.dirstamp` target in `src/Makefile` to force an unfavorable ordering:
```
objects objects/.dirstamp:
sleep 5
mkdir -p objects
touch objects/.dirstamp
```
Run a parallel build:
```
$ make -j 4
```
On macOS Sierra (10.12.1), this results in the following:
```
Starting make in the src directory.
If there are problems, cd to the src directory and run make there
cd src && /Library/Developer/CommandLineTools/usr/bin/make first
sleep 5
sleep 5
CC="gcc -Iproto -DHAVE_CONFIG_H -DMACOS_X_UNIX " srcdir=. sh ./osdef.sh
creating auto/pathdef.c
cd xxd; CC="gcc" CFLAGS="-DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" LDFLAGS="-L/usr/local/lib" \
/Library/Developer/CommandLineTools/usr/bin/make -f Makefile
gcc -DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -L/usr/local/lib -DUNIX -o xxd xxd.c
gcc -c -I. -Iproto -DHAVE_CONFIG_H -DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -o objects/main.o main.c
error: unable to open output file 'objects/main.o': 'No such file or directory'
1 error generated.
make[1]: *** [objects/main.o] Error 1
make[1]: *** Waiting for unfinished jobs....
mkdir -p objects
mkdir -p objects
touch objects/.dirstamp
touch objects/.dirstamp
make: *** [first] Error 2
```
See if this patch fixes the problem:
*** ../vim-8.0.0124/src/Makefile 2016-12-01 21:46:09.860509973 +0100
--- src/Makefile 2016-12-05 22:38:43.651554629 +0100
***************
*** 1678,1689 ****
$(WSDEBUG_OBJ)
# The files included by tests are not in OBJ_COMMON.
! OBJ = $(OBJ_COMMON) \
objects/json.o \
objects/main.o \
objects/memfile.o \
objects/message.o
OBJ_JSON_TEST = \
objects/memfile.o \
objects/message.o \
--- 1678,1691 ----
$(WSDEBUG_OBJ)
# The files included by tests are not in OBJ_COMMON.
! OBJ_MAIN = \
objects/json.o \
objects/main.o \
objects/memfile.o \
objects/message.o
+ OBJ = $(OBJ_COMMON) $(OBJ_MAIN)
+
OBJ_JSON_TEST = \
objects/memfile.o \
objects/message.o \
***************
*** 1705,1711 ****
MESSAGE_TEST_OBJ = $(OBJ_COMMON) $(OBJ_MESSAGE_TEST)
! ALL_OBJ = $(OBJ_COMMON) $(OBJ_JSON_TEST) $(OBJ_MEMFILE_TEST) $(OBJ_MESSAGE_TEST)
PRO_AUTO = \
--- 1707,1717 ----
MESSAGE_TEST_OBJ = $(OBJ_COMMON) $(OBJ_MESSAGE_TEST)
! ALL_OBJ = $(OBJ_COMMON) \
! $(OBJ_MAIN) \
! $(OBJ_JSON_TEST) \
! $(OBJ_MEMFILE_TEST) \
! $(OBJ_MESSAGE_TEST)
PRO_AUTO = \
…--
From "know your smileys":
!-| I-am-a-Cylon-Centurian-with-one-red-eye-bouncing-back-and-forth
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
@brammool, yes, that patch works for me. FYI, not a big deal, but it executes the If you separated the targets and made the |
|
Lewis Muir wrote:
@brammool, yes, that patch works for me.
FYI, not a big deal, but it executes the `mkdir -p objects` and the
`touch objects/.dirstamp` twice: once for the `objects` target and a
second time for the `objects/.dirstamp` target:
```
$ make -j 4
Starting make in the src directory.
If there are problems, cd to the src directory and run make there
cd src && /Library/Developer/CommandLineTools/usr/bin/make first
CC="gcc -Iproto -DHAVE_CONFIG_H -DMACOS_X_UNIX " srcdir=. sh ./osdef.sh
creating auto/pathdef.c
cd xxd; CC="gcc" CFLAGS="-DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" LDFLAGS="-L/usr/local/lib" \
/Library/Developer/CommandLineTools/usr/bin/make -f Makefile
gcc -DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -L/usr/local/lib -DUNIX -o xxd xxd.c
mkdir -p objects
mkdir -p objects
touch objects/.dirstamp
touch objects/.dirstamp
gcc -c -I. -Iproto -DHAVE_CONFIG_H -DMACOS_X_UNIX -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -o objects/arabic.o arabic.c
[snip]
```
If you separated the targets and made the `objects` target have no
commands and just a dependency on the `objects/.dirstamp` target as
suggested by @xaizek, it would only execute those commands once.
I have merged that change.
…--
From "know your smileys":
:-)-O Smiling doctor with stethoscope
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
Problem: Parallel make fails. (J. Lewis Muir) Solution: Make sure the objects directory exists. (closes vim#1259)
A parallel make (e.g.,
make -j 4) can sometimes fail when making the object files because the object file targets do not depend on theobjectstarget which creates theobjectsdirectory in which the object files are to be created. If an object file target is executed before theobjectstarget (or at least before theobjectstarget finishes executing), the build will fail because theobjectsdirectory has not been created yet.Here's an example failure where the
objects/os_mac_conv.otarget has executed before theobjectstarget:The failure can be reliably reproduced by adding a delay to the
objectstarget insrc/Makefileto induce the bad execution ordering:Then run a parallel make (e.g.,
make -j 4).This pull request fixes the problem by adding the
objectstarget as a dependency of the object file targets and by adding a-poption to theobjectstarget'smkdirinvocation since theobjectsdirectory can exist.The same problem exists in Vim 7.4, so if a patch could be issued for that version too, that would be great! Thanks!