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

Make setup-env.sh compatible with dash #4048

Merged
merged 3 commits into from
Jul 5, 2019

Conversation

tgamblin
Copy link
Member

@tgamblin tgamblin commented Apr 29, 2017

On the latest Ubuntu and Debian, and on Arch, the default system shell is dash, and there are systems out there that don't have bash. See Arch and Ubuntu's docs on this.

If you run as Spack in those environments, you get this:

+ export SPACK_ROOT=/spack
+ . /spack/share/spack/setup-env.sh
+ function spack {
/bin/sh: 59: /spack/share/spack/setup-env.sh: function: not found
ERROR: Aborting with RETVAL=255

This PR makes setup-env.sh dash-compatible 😄 . And less readable 😞 . I think it is worthwhile to be sh-compatible so that we can be used easily in these more and more popular minimal environments.

  • Replaced use of [[ with [
  • Replaced function foo { .. } with foo() { .. }
  • Wrapped some long lines
  • Add magic so that we can find the sourced file even in dash (whoa!)
  • Only do the complicated shell checks in one place; test $_sp_shell elsewhere.
  • Tests

@tgamblin tgamblin changed the title Make setup-env.sh compatible with dash on newer Ubuntus. Make setup-env.sh compatible with dash Apr 29, 2017
@adamjstewart
Copy link
Member

I agree with making the script more POSIX compatible. I might as well close #3736 then, as it introduces a lot of Bashisms. This checkbashisms script might be useful for testing purposes. We can also add a package for dash for testing.

@trws
Copy link
Contributor

trws commented Apr 30, 2017

Generally looks like an improvement. Any reason not to swap ${BASH_SOURCE[0]} for the equivalent ${BASH_SOURCE} to get around the evaluation issue?

@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch from 5b6167e to d16c9ea Compare April 30, 2017 05:29
bin/spack Outdated Show resolved Hide resolved
@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch from d16c9ea to d51f0b5 Compare April 30, 2017 21:35
@tgamblin tgamblin added the WIP label May 1, 2017
@mathstuf
Copy link
Contributor

mathstuf commented May 2, 2017

I'd recommend using ShellCheck to check for other bad patterns.

@adamjstewart
Copy link
Member

ShellCheck looks useful, but we may also want to include unit tests to make sure PRs don't break dash support. We should also consider making this change to the compiler wrappers as well. This could create a serious speed up of installation times on systems where /bin/sh links to dash.

@adamjstewart adamjstewart dismissed their stale review May 6, 2017 17:27

Accidental change was removed so I'm happy. Haven't yet tested this with dash though.

Copy link
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

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

This would be a nice one to have for 0.12.0

@adamjstewart adamjstewart added this to the v0.12.0 milestone Mar 24, 2018
ben-albrecht added a commit to chapel-lang/chapel that referenced this pull request Jan 17, 2019
Fixes to allow for external Spack in Mason

The main aim here is to allow for an external Spack installation.
If SPACK_ROOT is set, then the code uses that, instead of installing
a new version.

A few other minor fixes :
- When spawning a shell, we quote the PATH values to allow for spaces.
- Use . instead of source to run setup-env.sh to be POSIX compliant
  (especially on Ubuntu/Debian systems)
- Unfortunately, Spack's setup-env.sh uses bashisms (this is spack/spack#4048),
  but for now, we work around this by always using bash

[Contributed by @npadmana]
[Reviewed by @ben-albrecht && @Spartee]
@tgamblin tgamblin removed this from the v0.12.0 milestone May 28, 2019
@trontrytel
Copy link

trontrytel commented Jun 19, 2019

Hi! I'm trying to use spack to install blitz on Ubuntu 18.04. After doing this:

git clone https://github.com/spack/spack.git
. spack/share/spack/setup-env.sh

I get this error:
function spack {
/bin/sh: 42: spack/share/spack/setup-env.sh: function: not found

Would this pull request be a solution to my problem? Is there a chance for it to be merged? Or is there any workaround for me?

Thanks!

@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch 2 times, most recently from d2bbd4b to 6b2accc Compare July 1, 2019 04:16
@tgamblin
Copy link
Member Author

tgamblin commented Jul 1, 2019

@trontrytel: I rebased this PR on develop and updated it quite a bit -- see if it works for you now.

@tgamblin
Copy link
Member Author

tgamblin commented Jul 1, 2019

@citibeth: yes, it's still relevant.

@tgamblin
Copy link
Member Author

tgamblin commented Jul 1, 2019

Ok, this PR is updated and seems to actually work. In particular:

  • removed all bash-isms from setup-env.sh
  • I made it so that you do not have to set SPACK_ROOT even in dash.

The second one was rather surprising to me, but after googling around some, it turns out dash keeps the file descriptor of the sourced script open, and you can hack around with lsof to figure out where the script lives. lsof does not come standard in ubuntu, but I used the same trick to find the script in the /proc filesystem, and that seems to work.

The combination of the two techniques seems like it'll work on either stock macos or on most stock Linux containers, if you happen to be running dash in either of those environments. I mostly care about dash working on macos for testing -- the Linux one is where I would like Spack to work seamlessly out of the box.

We probably need to add some tests that just source this file in containers and make sure everything is set up properly.

@trontrytel
Copy link

@trontrytel: I rebased this PR on develop and updated it quite a bit -- see if it works for you now.

Hi @tgamblin. Thanks for looking into this. It works now (tested in vagrant on ubuntu 18.04)

For some reason when doing the same in vagrant while building a singularity image I got a lot of prints from spack (see below). But it seems to be working.

+ git clone https://github.com/spack/spack
Cloning into 'spack'...
remote: Enumerating objects: 49, done.
remote: Counting objects: 100% (49/49), done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 157672 (delta 22), reused 28 (delta 3), pack-reused 157623
Receiving objects: 100% (157672/157672), 54.83 MiB | 10.89 MiB/s, done.
Resolving deltas: 100% (72043/72043), done.
+ cd spack
+ git checkout features/sh-commpatible-setup-env
Branch 'features/sh-commpatible-setup-env' set up to track remote branch 'features/sh-commpatible-setup-env' from 'origin'.
Switched to a new branch 'features/sh-commpatible-setup-env'
+ . share/spack/setup-env.sh
+ _spack_determine_shell
+ [ -n  ]
+ [ -n  ]
+ xargs basename
+ sed s/^-//
+ awk {print $4}
+ tail -n 1
+ PS_FORMAT= ps -p 28789
+ export SPACK_SHELL=sh
+ [ sh = bash ]
+ [ sh = bash ]
+ [ sh = zsh ]
+ tail -1
+ sort -n
+ ls /proc/28789/fd
+ _sp_source_file_fd=10
+ readlink /proc/28789/fd/10
+ _sp_source_file=/spack/share/spack/setup-env.sh
+ [ ! -f /spack/share/spack/setup-env.sh ]
+ dirname /spack/share/spack/setup-env.sh
+ cd /spack/share/spack
+ pwd
+ _sp_share_dir=/spack/share/spack
+ dirname /spack/share/spack
+ dirname /spack/share
+ cd /spack
+ pwd
+ _sp_prefix=/spack
+ [ -x /spack/bin/spack ]
+ export SPACK_ROOT=/spack
+ _spack_pathadd PATH /spack/bin
+ _pa_varname=PATH
+ _pa_new_path=PATH
+ [ -n /spack/bin ]
+ _pa_varname=PATH
+ _pa_new_path=/spack/bin
+ eval _pa_oldvalue=${PATH:-}
+ _pa_oldvalue=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
+ _pa_canonical=:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:
+ [ -d /spack/bin ]
+ [ :/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin: != *:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin: ]
+ [ -n /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin ]
+ eval export PATH="/spack/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+ export PATH=/spack/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
+ need_module=no
+ _spack_fn_exists use
+ grep -q function
+ LANG= type use
+ _spack_fn_exists module
+ grep -q function
+ LANG= type module
+ need_module=yes
+ [ yes = yes ]
+ spack --print-shell-vars sh,modules
+ [ -n  ]
+ _sp_flags=
+ [ -print-shell-vars != --print-shell-vars ]
+ _sp_flags= --print-shell-vars
+ shift
+ [ sh,modules != sh,modules ]
+ [ -n  --print-shell-vars ]
+ [ ell-vars !=  --print-shell-vars ]
+ command spack --print-shell-vars sh,modules
+ return
+ eval _sp_sys_type='linux-ubuntu18.04-x86_64' _sp_tcl_roots='/spack/share/spack/modules' _sp_lmod_roots='/spack/share/spack/lmod' _sp_dotkit_roots='/spack/share/spack/dotkit' _sp_module_prefix='not_installed'
+ _sp_sys_type=linux-ubuntu18.04-x86_64 _sp_tcl_roots=/spack/share/spack/modules _sp_lmod_roots=/spack/share/spack/lmod _sp_dotkit_roots=/spack/share/spack/dotkit _sp_module_prefix=not_installed
+ [ not_installed != not_installed ]
+ _sp_multi_pathadd MODULEPATH /spack/share/spack/modules
+ local IFS=:
+ [ sh = zsh ]
+ _spack_pathadd MODULEPATH /spack/share/spack/modules/linux-ubuntu18.04-x86_64
+ _pa_varname=PATH
+ _pa_new_path=MODULEPATH
+ [ -n /spack/share/spack/modules/linux-ubuntu18.04-x86_64 ]
+ _pa_varname=MODULEPATH
+ _pa_new_path=/spack/share/spack/modules/linux-ubuntu18.04-x86_64
+ eval _pa_oldvalue=${MODULEPATH:-}
+ _pa_oldvalue=
+ _pa_canonical=::
+ [ -d /spack/share/spack/modules/linux-ubuntu18.04-x86_64 ]
+ _sp_multi_pathadd DK_NODE /spack/share/spack/dotkit
+ local IFS=:
+ [ sh = zsh ]
+ _spack_pathadd DK_NODE /spack/share/spack/dotkit/linux-ubuntu18.04-x86_64
+ _pa_varname=PATH
+ _pa_new_path=DK_NODE
+ [ -n /spack/share/spack/dotkit/linux-ubuntu18.04-x86_64 ]
+ _pa_varname=DK_NODE
+ _pa_new_path=/spack/share/spack/dotkit/linux-ubuntu18.04-x86_64
+ eval _pa_oldvalue=${DK_NODE:-}
+ _pa_oldvalue=
+ _pa_canonical=::
+ [ -d /spack/share/spack/dotkit/linux-ubuntu18.04-x86_64 ]
+ [ sh = bash ]
+ cd ../
+ spack install blitz
+ [ -n  ]
+ _sp_flags=
+ [ install != install ]
+ [ -n  ]
+ [  !=  ]
+ _sp_subcommand=
+ [ -n install ]
+ _sp_subcommand=install
+ shift
+ command spack install blitz
==> Installing blitz
==> Searching for binary cache of blitz
==> Warning: No Spack mirrors are currently configured
==> No binary for blitz found: installing from source
==> Fetching https://github.com/blitzpp/blitz/archive/1.0.1.tar.gz
     -#O=-#   #     #                                                         
==> Staging archive: /spack/var/spack/stage/blitz-1.0.1-ygzugsujglfbuugxrmyhewbuv6ythbbz/1.0.1.tar.gz
==> Created stage in /spack/var/spack/stage/blitz-1.0.1-ygzugsujglfbuugxrmyhewbuv6ythbbz
==> No patches needed for blitz
==> Building blitz [AutotoolsPackage]
==> Executing phase: 'autoreconf'
==> Executing phase: 'configure'
==> Executing phase: 'build'
==> Executing phase: 'install'
==> Successfully installed blitz

@tgamblin
Copy link
Member Author

tgamblin commented Jul 2, 2019

@trontrytel: Awesome!

It looks like vagrant might set -x in the shell before sourcing -- does it? Or does your vagrant script have a shebang line like #!/bin/sh -x? If so then that would explain the output. It looks like it is printing, e.g., cd spack and git checkout features/sh-commpatible-setup-env even before the setup script is sourced.

@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch 2 times, most recently from d89cd1d to 02863ed Compare July 3, 2019 08:58
@tgamblin tgamblin requested a review from scheibelp July 3, 2019 16:20
@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch 3 times, most recently from 3d8855d to 035efed Compare July 3, 2019 19:52
Copy link
Member

@scheibelp scheibelp left a comment

Choose a reason for hiding this comment

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

All minor requests:

  • 2 requests about comments
  • 1 typo

checkbashisms doesn't report any bash-specific syntax (that is not guarded by a bash-shell check). Running the tests with sh would be ideal except that it apparently usually links to bash (or in my Ubuntu docker instance to dash). dash is arguably bare-bones enough that running the tests with it is sufficient to establish sh-compatibility.

share/spack/qa/setup-env-test.sh Outdated Show resolved Hide resolved
share/spack/setup-env.sh Outdated Show resolved Hide resolved
share/spack/setup-env.sh Show resolved Hide resolved
@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch from 035efed to ea5df69 Compare July 3, 2019 21:22
- replace use of [[ with [

- replace function foo { .. } with foo() { .. }

- wrap some long lines

- add lsof and /proc/fd magic so that we can find the sourced file even in dash

- only do the complicated shell checks in one place; test $_sp_shell
  elsewhere.
@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch from ea5df69 to e76990d Compare July 5, 2019 17:51
- tests use a shell-script harness and test all Spack commands that
  require special shell support.

- tests work in bash, zsh, and dash

- run setup-env.sh tests on macos and linux builds.
  - we run them on macos and linux
- Add set -u to the setup-env.sh test script

- Refactor lines in setup-env.sh that tested potentially undefined
  variables to use the `[ -z ${var+x} ]` construct
@tgamblin tgamblin force-pushed the features/sh-commpatible-setup-env branch from e76990d to 5385dfa Compare July 5, 2019 18:45
@tgamblin tgamblin merged commit 5686c2a into develop Jul 5, 2019
@alalazo alalazo deleted the features/sh-commpatible-setup-env branch July 6, 2019 06:28
@adamjstewart
Copy link
Member

I thought $(...) was also a Bash-ism, but I see a lot of that in our scripts. Shouldn't we use `...`?

@scheibelp
Copy link
Member

check-bashisms from #4048 (review) did not complain about it at least. One of the reasons I decided to do that is because it can be difficult to determine what is actually bash-specific. I started doing searches for various syntax instances which looked bash-specific and it was difficult to figure out (e.g. something supported on sh but the bash scripting guide would be the top hit).

IMO the best way to proceed is to change something if someone reports an issue with it when running with sh. As these issues come up it might make sense to run other syntax checkers in addition to check-bashisms.

@trws
Copy link
Contributor

trws commented Jul 16, 2019 via email

@tgamblin
Copy link
Member Author

I thought $(...) was also a Bash-ism, but I see a lot of that in our scripts. Shouldn't we use ...?

What @trws said -- it's standard POSIX. dash is the main sh implementation I'm concerned about here, and it implements (rather strictly) the POSIX standard.

IMO the best way to proceed is to change something if someone reports an issue with it when running with sh. As these issues come up it might make sense to run other syntax checkers in addition to check-bashisms.

I think these are good ideas, but note also that the tests introduced here actually run setup-env.sh with dash. I don't think there is a better way to check for POSIX compliance :).

@adamjstewart
Copy link
Member

Yeah, I'm glad dash is so strict, makes testing really easy.

tjfulle added a commit to tjfulle/spack that referenced this pull request Oct 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants