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

Python script packaged with (python3.withPackages ...) as build input not working on Darwin (shebang issue?) #65351

Open
anderslundstedt opened this issue Jul 24, 2019 · 8 comments
Labels
0.kind: bug 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 6.topic: darwin Running or building packages on Darwin 6.topic: python

Comments

@anderslundstedt
Copy link
Contributor

Describe the bug
If I package a Python script with python3.withPackages ... as build input then the script will build but not run on Darwin.

To Reproduce
Steps to reproduce the behavior:

  1. Use MacOS.
  2. Create default.nix:
let
  pkgs = import <nixpkgs> { };
  python = pkgs.python3.withPackages (_: []);
in
  pkgs.stdenv.mkDerivation rec {
    name = "py-test";
    buildInputs = [ python ];
    unpackPhase = "true";
    installPhase = ''
      mkdir -p $out/bin
      touch $out/bin/py-test
      chmod +x $out/bin/py-test
      echo "#!${python}/bin/python" >> $out/bin/py-test
      echo "print(0)" >> $out/bin/py-test
    '';
  }
  1. Build and run:
nix-build
./result/bin/py-test
  1. Observe unexpected behaviour.
  • In bash:
./result/bin/py-test: line 2: syntax error near unexpected token `0'
./result/bin/py-test: line 2: `print(0)'
  • In zsh:
zsh: exec format error: ./result/bin/py-test

Expected behavior
Output:

0

Additional context
Everything works as expected if we replace pkgs.python3.withPackages ... with pkgs.python3. The only difference in the result is the shebang.

  • ./result/bin/py-test with pkgs.python3.withPackages ...:
#!/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env/bin/python
print(0)
  • ./result/bin/py-test with pkgs.python3:
#!/nix/store/8r52cdbn9g3sl9pz8vm4xcf7rhrqjqin-python3-3.7.4/bin/python
print(0)

Executing the python executable in the shebang works, as does executing py-test with the same executable, that is

/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env/bin/python result/bin/py-test

gives the expected output.

Existing Darwin shebang-related issues:

However, it does not seem like a problem with the character limit in this case?

Metadata
Please run nix run nixpkgs.nix-info -c nix-info -m and paste the result.

 - system: `"x86_64-darwin"`
 - host os: `Darwin 16.7.0, macOS 10.12.6`
 - multi-user?: `no`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.2.2`
 - channels(anders): `""`
 - nixpkgs: `/Users/anders/nixpkgs`
@FRidh FRidh added 6.topic: darwin Running or building packages on Darwin 6.topic: python labels Jul 25, 2019
@FRidh
Copy link
Member

FRidh commented Jul 25, 2019

Nothing was changed in the Python infra that could have caused this so I think it's Darwin.

@jonringer
Copy link
Contributor

if you used echo "#!/usr/bin/env python" >> $out/bin/py-test does it still fail?

If you're hitting the character limit, then this is one solution.

Possibly related article as to why this works on linux here https://lwn.net/Articles/779997/

@anderslundstedt
Copy link
Contributor Author

Nothing was changed in the Python infra that could have caused this so I think it's Darwin.

Yes, everything works as expected on NixOS.

if you used echo "#!/usr/bin/env python" >> $out/bin/py-test does it still fail?

Yes, that shebang is (correctly) replaced by

#!/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env/bin/python

Possibly related article as to why this works on linux here https://lwn.net/Articles/779997/

I do not think we exceed the character limit on Linux. The shebang is 74 characters long. Neither should this exceed the character limit on Darwin?

@FRidh
Copy link
Member

FRidh commented Jul 28, 2019

How does #!/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env/bin/python look? It should be a wrapper. Maybe it is generated incorrectly?.

@anderslundstedt
Copy link
Contributor Author

How does #!/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env/bin/python look? It should be a wrapper. Maybe it is generated incorrectly?.

#! /nix/store/bbw1rwzgb43dda7gw9qjxbbpzb847n4z-bash-4.4-p23/bin/bash -e
export PYTHONHOME='/nix/store/jhbikg6nir868g3wfypi7vppn5mbjhp5-python3-3.7.4-env'
export PYTHONNOUSERSITE='true'
exec "/nix/store/8r52cdbn9g3sl9pz8vm4xcf7rhrqjqin-python3-3.7.4/bin/python"  "${extraFlagsArray[@]}" "$@"

@FRidh
Copy link
Member

FRidh commented Jul 28, 2019

I think I recall the issue. On Darwin it is not possible to use a wrapper as a shebang.

@anderslundstedt
Copy link
Contributor Author

@stale
Copy link

stale bot commented Jun 2, 2020

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 2, 2020
adrian-gierakowski added a commit to adrian-gierakowski/nixpkgs that referenced this issue Jul 24, 2020
On Darwin a script cannot be used as an interpreter in a shebang line, which
causes scripts produced with makeScriptWriter (and its derivatives) to fail at
run time if the used interpreter was wrapped with makeWrapper (as in the case
of python3.withPackages).

This commit fixes the problem by detecting if the interpreter is a script
and prepending its shebang to the final interpreter line.

For example if used interpreter is;
```
/nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

which is a script with following shebang:
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e
```

then the shebang line in the produced script will be
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e /nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

This works on Darwin since there does not seem to be a limit to the length
of the shabang line and the shebang lines support multiple arguments to
the interpreters (as opposed to linux where the kernel imposes a strict limit
on shebang lengh and everything following the interpreter is passed to it
as a single string).

fixes; NixOS#93609
related to: NixOS#65351 NixOS#11133 (and probably a bunch of others)

NOTE: scripts produced on platforms other tha Darwin will remain unmodified
by this PR. However it might worth considering extending this fix to BSD systems
in general. I didn't do it since I have no way of testing it on systems other
than MacOS and linux.
Lassulus pushed a commit that referenced this issue Jul 25, 2020
* writers.makeScriptWriter: fix on Darwin\MacOS

On Darwin a script cannot be used as an interpreter in a shebang line, which
causes scripts produced with makeScriptWriter (and its derivatives) to fail at
run time if the used interpreter was wrapped with makeWrapper (as in the case
of python3.withPackages).

This commit fixes the problem by detecting if the interpreter is a script
and prepending its shebang to the final interpreter line.

For example if used interpreter is;
```
/nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

which is a script with following shebang:
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e
```

then the shebang line in the produced script will be
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e /nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

This works on Darwin since there does not seem to be a limit to the length
of the shabang line and the shebang lines support multiple arguments to
the interpreters (as opposed to linux where the kernel imposes a strict limit
on shebang lengh and everything following the interpreter is passed to it
as a single string).

fixes; #93609
related to: #65351 #11133 (and probably a bunch of others)

NOTE: scripts produced on platforms other than Darwin will remain unmodified
by this PR. However it might worth considering extending this fix to BSD systems
in general. I didn't do it since I have no way of testing it on systems other
than MacOS and linux.

* writers.makeScriptWriter: fix typo in comment

* writers.makeScriptWriter: fail build if interpreter of interpreter is a script
adrian-gierakowski added a commit to rhinofi/nixpkgs that referenced this issue Jul 26, 2020
* writers.makeScriptWriter: fix on Darwin\MacOS

On Darwin a script cannot be used as an interpreter in a shebang line, which
causes scripts produced with makeScriptWriter (and its derivatives) to fail at
run time if the used interpreter was wrapped with makeWrapper (as in the case
of python3.withPackages).

This commit fixes the problem by detecting if the interpreter is a script
and prepending its shebang to the final interpreter line.

For example if used interpreter is;
```
/nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

which is a script with following shebang:
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e
```

then the shebang line in the produced script will be
```
#! /nix/store/knd85yc7iwli8344ghav3zli8d9gril0-bash-4.4-p23/bin/bash -e /nix/store/ynwv137n2650qy39swcflxbcygk5jwv1-python3-3.8.3-env/bin/python
```

This works on Darwin since there does not seem to be a limit to the length
of the shabang line and the shebang lines support multiple arguments to
the interpreters (as opposed to linux where the kernel imposes a strict limit
on shebang lengh and everything following the interpreter is passed to it
as a single string).

fixes; NixOS#93609
related to: NixOS#65351 NixOS#11133 (and probably a bunch of others)

NOTE: scripts produced on platforms other than Darwin will remain unmodified
by this PR. However it might worth considering extending this fix to BSD systems
in general. I didn't do it since I have no way of testing it on systems other
than MacOS and linux.

* writers.makeScriptWriter: fix typo in comment

* writers.makeScriptWriter: fail build if interpreter of interpreter is a script
@OPNA2608 OPNA2608 mentioned this issue Jun 9, 2021
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: bug 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md 6.topic: darwin Running or building packages on Darwin 6.topic: python
Projects
None yet
Development

No branches or pull requests

3 participants