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

libtool: fix /usr/bin/file impurity affecting cross-compilation #166722

Closed
wants to merge 1 commit into from
Closed

libtool: fix /usr/bin/file impurity affecting cross-compilation #166722

wants to merge 1 commit into from

Conversation

ghost
Copy link

@ghost ghost commented Mar 31, 2022

Problem

libtool's libtool.m4 script assumes that file is available, and can be found at /usr/bin/file (this path is hardwired). This fails for sandboxed builds. Furthermore, the script with this assumption is vendored into the ./configure scripts of an enormous number of packages.

Solutions

Oftentimes the fact that /usr/bin/file does not exist will not prevent a package from building. When it does prevent a successful build, there are a few options:

  1. set NIX_REDIRECT=/usr/bin/file=${file}/bin/file

  2. fix libtool.m4 in the libtool package

    a. ... and use autoreconfHook manually in packages which need it (and do not break when autoreconf'ed with the latest autotools).

  3. Add substituteInPlace ./configure --replace /usr/bin/file ${file}/bin/file in one of these ways:

    a. in setup.sh's fixLibtool(), which exists for the same reason: impurities in pervasively-vendored libtool.m4

    b. manually to packages which need it

There are already 36 packages in nixpkgs which use 3(b).

Implementation

This commit makes two changes:

  • It implements 2 with a substituteInPlace in the libtool expression, to allow 2(a) where possible.

  • It implements 3(b) by adding a top-level expression fixPathToUsrBinFileInConfigureScript which implements the third approach, patterned after autoreconfHook.

If there is some way to cleverly get stdenv to inject fixPathToUsrBinFileInConfigureScript as an extra nativeBuildInput only when cross-compiling to certain hostPlatforms, I would like to include that in this PR. However I had a very hard time finding an appropriate place to add that. Suggestions are welcome. I tried adding it to pkgs/stdenv/cross/default.nix in extraNativeBuildInputs, where there is a similar workaround for cross-compiling to windows, but this didn't seem to work.

(Immediate) Motivation

When cross-compiling a libtool.m4-derived package to {x86_64, powerpc, s390, sparc, mips64*}-linux, x86_64-kfreebsd, *-solaris, *-irix, and *-hpux, the configure script will fail to generate shared libraries if file is not callable via /usr/bin/file. It seems that cross-compilations to darwin, riscv, and arm64 hosts are among the few exceptions to this issue, which is why nixpkgs hasn't encountered it until now.

This is currently preventing the generation of Hydra-built bootstrap-files for mips64el-linux-gnuabi64, and will affect almost any other new platform we try to bootstrap on.

The build of the pcre package (and a few others) emits these lines when its configure script is run:

  ./configure: line 9843: /usr/bin/file: No such file or directory
  ./configure: line 9851: /usr/bin/file: No such file or directory
  ./configure: line 9859: /usr/bin/file: No such file or directory
  ...
  checking whether to build shared libraries... no

The build does not fail until much later, when make-bootstrap-files.nix tries to make a copy libpcre.so, which was never built.

This commit allows the mips64el-linux-gnuabi64 bootstrap-files to be built in a sandbox (as required by Hydra) by implementing the two changes above, adding autoreconfHook to gmp and pcre, and fixPathToUsrBinFileInConfigureScript to mpfr (since mpfr breaks if autoreconf'ed with the latest autotools); this was verified with:

  nix-build \
    --option sandbox true \
    --option fallback false \
    pkgs/top-level/release-cross.nix \
    -A bootstrapTools.mips64el-linux-gnuabi64.build
Things done
  • Built on platform(s)
    • x86_64-linux
    • mips64el-linux-gnuabi64 cross from x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@ghost ghost marked this pull request as draft March 31, 2022 22:26
libtool's libtool.m4 script assumes that `file` is available, and can
be found at `/usr/bin/file` (this path is hardwired).  Furthermore,
the script with this assumption is vendored into the ./configure
scripts of an enormous number of packages.

This commit makes two changes:

  * It adds a `substituteInPlace` in the `libtool` expression so that
    autoreconfHook'ed packages will find `file` in the correct
    location.  This is currently guarded by a check for
    cross-compilation in order to prevent mass-rebuilds.

  * It adds a top-level `fixPathToUsrBinFileInConfigureScript` to
    `substituteInPlace` the `./configure` script of packages directly,
    for use with packages which would break if autoreconfHook'ed.

This commit allows the mips64el-linux-gnuabi64 bootstrap-files to be
built in a sandbox (as required by Hydra) by implementing the two
changes above, adding `autoreconfHook` to `gmp`, `pcre`, `isl`, and
`libmpc`, as well as adding `fixPathToUsrBinFileInConfigureScript` to
`mpfr` (since `mpfr` breaks if autoreconf'ed with the latest
autotools); this was verified with:

```
  nix-build \
    --option sandbox true \
    --option fallback false \
    pkgs/top-level/release-cross.nix \
    -A bootstrapTools.mips64el-linux-gnuabi64.build
```
@ghost ghost marked this pull request as ready for review March 31, 2022 22:59
# staging, not to be merged until after nixpkgs-22.05 branch-off,
# which deletes this conditional and this comment.
#
preBuild = if stdenv.buildPlatform == stdenv.targetPlatform
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would appreciate a review of this line in particular. I think of libtool as being a "compiler-like" package that has a targetPlatform but I'm not sure if nixpkgs thinks of it this way. Please let me know if I should change this from build==target to build==host.

@ghost
Copy link
Author

ghost commented Mar 31, 2022

@ofborg build hey-ofborg-you-build-them-bootstrapballs-now

@ghost
Copy link
Author

ghost commented Mar 31, 2022

@ofborg build hey-ofborg-you-build-them-bootstrapballs-now

Woo hoo!

@bjornfor bjornfor added the 6.topic: cross-compilation Building packages on a different platform than they will be used on label Apr 1, 2022
@ghost ghost mentioned this pull request Apr 1, 2022
14 tasks
@ghost
Copy link
Author

ghost commented Apr 1, 2022

I tried adding it to pkgs/stdenv/cross/default.nix ... but this didn't seem to work.

Okay, I figured out how to make this work. See #166879.

I prefer #166879 one over this PR, but I need to finish testing it first, and even if it works it probably needs to wait until the 22.05 branch-off (did that happen already?) and then go into staging since it messes around with the internals of stdenv. I don't want to be the guy who broke the builds a month before a release.

@ghost
Copy link
Author

ghost commented Apr 2, 2022

2. fix libtool.m4 in the libtool package

This has been fixed upstream in libtool 2.4.7.

However this still does not solve the problem of the fact that the old libtool.m4 is already vendored into an immense number of packages, some of which will not autoreconf properly with the latest version.

@ghost
Copy link
Author

ghost commented Apr 2, 2022

Marking this as draft in favor of #166879, which is going to be way more maintainable in the long run. If that PR is totally unacceptable we can revisit this one instead.

@ghost ghost marked this pull request as draft April 2, 2022 07:54
@ghost ghost closed this Apr 8, 2022
@ghost ghost deleted the libtool-purity-fix-autoreconfHook branch January 23, 2024 06:45
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: cross-compilation Building packages on a different platform than they will be used on 8.has: package (new) This PR adds a new package 10.rebuild-darwin: 1-10 10.rebuild-linux: 11-100
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant