Skip to content
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

Fix a pair of bugs for parallel (-jX) make install #12288

Closed

Conversation

samueldr
Copy link
Contributor

Hi!

See the commit bodies themselves for details. No changes to vim itself, only its build/install tooling.

In both instances, make -j24 in the build farm for Nixpkgs surfaced those spurious errors.

For the runtime install, I'm not entirely sure what the consequences of this failing at $(MAKE) VIMEXE=$(DEST_BIN)/$(VIMTARGET) vimtags would be. How broken would vim have been?

For the other issue, the consequences would be that spuriously (once to this date AFAICT) some of the additional tools that are symlinks to vim might be missing. For example ex is currently missing in one of our successful builds. (NixOS/nixpkgs#227677)

Don't hesitate to recommend alternatives to my exact changes.

There may be further parallelism issues, I don't have the full log to investigate on that one, and the few lines available may point to a red herring: NixOS/nixpkgs#224962 (comment).

@brammool
Copy link
Contributor

brammool commented Apr 23, 2023 via email

@samueldr
Copy link
Contributor Author

I suppose you did this by adding "installvimbin" as a dependency to
"installrtbase". That's not right, it should be possible to install Vim
in some other way. And "installrtbase" should not have the side effect
of installing more, see the explanation around line 128.

This happens when only using parallelism by adding -j24 on make install in an isolated build. Since it's isolated, there is no "previous" vim already installed.

The current installation steps refer to the DEST_BIN vim, which even outside entirely isolated builds, may not have been installed yet, or is being written to (VIMEXE=$(DEST_BIN)/$(VIMTARGET)). Since the target refers to that path, it must depend on it to satisfy dependencies.

I'll note that it's explained in lines 353-354 of runtime/doc/Makefile that the target “Can only be used when Vim has been compiled and installed.”

  • vim/runtime/doc/Makefile

    Lines 353 to 354 in 7b4164e

    # Use Vim to generate the tags file. Can only be used when Vim has been
    # compiled and installed. Supports multiple languages.

I'm not that familiar with arcane Makefile features, but I don't think there's a way to prevent or block a target from being used before another one is ran, but not depending on the target, right? (Anyway it wouldn't make sense for the dependency graph.)

Without depending on installvimbin, we can't make the build depend on the $(DEST_BIN)/$(VIMTARGET) path:

make[1]: *** No rule to make target '.../bin/vim', needed by 'installrtbase'.  Stop.

(Anyway it would technically amount to doing part of installvimbin if it worked...)

The alternative I can see would be to refer to the vim executable in the build directory, which would be presumed to exist at that point. It's a bit kludgey since the build cds into another directory; we need to remember where we were so the relative VIMTARGET becomes absolute.

The change on top of my current changes:

diff --git a/src/Makefile b/src/Makefile
index a82a46e49..131188a59 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2329,7 +2329,7 @@ installruntime: installrtbase installmacros installpack installtutor installspel
 
 # Install the help files; first adjust the contents for the final location.
 # Also install most of the other runtime files.
-installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) installvimbin $(DEST_RT) \
+installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(VIMTARGET) $(DEST_RT) \
                $(DEST_HELP) $(DEST_PRINT) $(DEST_COL) \
                $(DEST_SYN) $(DEST_SYN)/shared $(DEST_IND) \
                $(DEST_FTP) $(DEST_AUTO) $(DEST_AUTO)/dist $(DEST_AUTO)/xml \
@@ -2342,8 +2342,8 @@ installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) installvimbin $(DEST_RT) \
        cd $(HELPSOURCE); if test -z "$(CROSS_COMPILING)" -a -f tags; then \
                mv -f tags tags.dist; fi
        @echo generating help tags
-       -@cd $(HELPSOURCE); if test -z "$(CROSS_COMPILING)"; then \
-               $(MAKE) VIMEXE=$(DEST_BIN)/$(VIMTARGET) vimtags; fi
+       -@BUILD_DIR="$$PWD"; cd $(HELPSOURCE); if test -z "$(CROSS_COMPILING)"; then \
+               $(MAKE) VIMEXE=$$BUILD_DIR/$(VIMTARGET) vimtags; fi
        cd $(HELPSOURCE); \
                files=`ls *.txt tags`; \
                files="$$files `ls *.??x tags-?? 2>/dev/null || true`"; \

@brammool
Copy link
Contributor

brammool commented Apr 23, 2023 via email

@samueldr
Copy link
Contributor Author

Does this work everywhere? Note that the Makefile isn't written for any
specific version of make [...]

Most of the load-bearing change here is handled by the shell used by make.

The POSIX make documentation states:

The macro $$ shall be replaced by the single character '$'

https://pubs.opengroup.org/onlinepubs/009695299/utilities/make.html

Anyway $$ is used elsewhere in the same target. So this part is a non-issue.

Then as long as the shell provides $PWD (as POSIX shell states it should) it would work as authored. Since I can't know what other obscure platforms would do here, "pwd" (literal with backticks) can be used instead if you prefer.

@brammool
Copy link
Contributor

brammool commented Apr 24, 2023 via email

In sandboxed builds, when running with "high" parallelism (-j24), it is
possible that some installation phases run before the target directory
exists.

The failure is silently ignored due to the way the Makefile is made.
This makes it possible that packages end-up with *some* of the tools
provided by vim missing.

```
cd .../bin; ln -s vim ex
.../bin/bash: line 1: cd: .../bin: No such file or directory
```

By using `&&`, the error will not be silently ignored. Furthermore, to
prevent spurious errors on install, a dependency on DEST_BIN is added.
@samueldr samueldr force-pushed the fix/parallel-make-install-errors branch from 7b4164e to 1a3c0ec Compare April 24, 2023 16:58
With "high" parallelism during the install phase (-j24), it is possible
to end-up with a "successful" `make install`, but in actuality the
`installrtbase` target failed this way:

```
make[2]: Entering directory '/build/source/runtime/doc'
.../bin/bash: line 1: .../bin/vim: Text file busy
make[2]: *** [Makefile:356: vimtags] Error 126
make[2]: Leaving directory '/build/source/runtime/doc'
```

Using the build-time `vim` ensures the step succeeds.
@samueldr samueldr force-pushed the fix/parallel-make-install-errors branch from 1a3c0ec to dd724e0 Compare April 24, 2023 16:59
@samueldr
Copy link
Contributor Author

I'm not 100% sure $PWD works in every shell, while pwd should work everywhere. I'm a little bit worried about having spaces in the path. I guess adding quotes like this should help (haven't tried it yet): $(MAKE) VIMEXE="$$BUILD_DIR/$(VIMTARGET)" vimtags; fi

Yes, adding quotes is a good catch. Added that while force-pushing the requested changes.

@brammool brammool closed this in cfc788c Apr 24, 2023
@samueldr samueldr deleted the fix/parallel-make-install-errors branch April 25, 2023 00:58
dundargoc added a commit to dundargoc/neovim that referenced this pull request Dec 16, 2023
Problem:    Parallel make might not work.
Solution:   Add missing dependencies. (Samuel Dionne-Riel, closes vim/vim#12288)

vim/vim@cfc788c

Co-authored-by: Samuel Dionne-Riel <samuel@dionne-riel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants