Skip to content

Shell changes towards enabling an alternative shell (backward compatible with bash)#127736

Merged
happysalada merged 38 commits intoNixOS:stagingfrom
happysalada:a_new_hope
Jul 6, 2021
Merged

Shell changes towards enabling an alternative shell (backward compatible with bash)#127736
happysalada merged 38 commits intoNixOS:stagingfrom
happysalada:a_new_hope

Conversation

@happysalada
Copy link
Copy Markdown
Contributor

@happysalada happysalada commented Jun 22, 2021

Motivation for this change

Oil shell is a new shell that aims to retain compatibility with bash but brings in new feature that simplify shell scripting. Using it in nix would make shell scripting more accessible to many people (IMO). The drawback being that osh has not reached 1.0 yet and that there might still be some bugs.

This PR starts with a mix of shellcheck fixes, the ultimate goal being to be able to change the default shell shipped with stdenv.

Current state: Only shell fixes have been added to this PR at the moment, so stdenv should build fine. I am currently working on making the shell change work. The current error is related to a shell reference being included in the stdenv-stage3. At the moment stdenv-stage3 explicitely defines an allowedRequisites for bash.

@zimbatm I'm wondering who else might be interested by this. Specifically who we should make sure to expose early enough to know if this will be a no-go or not.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • 21.11 Release Notes
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

This is not the "correct" way to check if a variable is non null in
bash. There is already an instance of the "right" way to do it in
setup.sh. Bash is "generous" enough to accept the original input though.
I couldn't find the relevant shellcheck.
this one is a little more controversial
see oils-for-unix/oils#864
for more information
@github-actions github-actions bot added the 6.topic: stdenv Standard environment label Jun 22, 2021
@happysalada happysalada marked this pull request as draft June 22, 2021 01:33
@ofborg ofborg bot added 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. 10.rebuild-linux-stdenv This PR causes stdenv to rebuild on Linux and must target a staging branch. 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 5001+ This PR causes many rebuilds on Linux and must target the staging branches. labels Jun 22, 2021
@happysalada
Copy link
Copy Markdown
Contributor Author

happysalada commented Jun 22, 2021

Here is the last error I got, after explicitely adding oil to the set of allowedRequisites

error: output '/nix/store/v0vs6aw6mpxcy2lsdnz3k5q0a8kr4jyf-bootstrap-stage3-stdenv-darwin' is not allowed to refer to the following paths:
         /nix/store/aqj0kzpan8z7y39qsy7mfawppvik50gm-ncurses-6.2
         /nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08

I verified that the resulting setup file (inside bootstrap-stage3-stdenv-darwin) doesn't contain explicit references to those.
However at the top of the file, there are the 3 following lines

export SHELL=/nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil/bin/bash
initialPath="/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools"
defaultNativeBuildInputs="/nix/store/4q88vhj678qfp5zz72k2vkmxfh6qn0h5-xz-5.2.5-bin /nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh /nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh /nix/store/cl3qd985p1yxyfkj96v0hqxiy3w69xq5-compress-man-pages.sh /nix/store/h54dzwd7rdh2jlcv91424csl6d0ccgjy-strip.sh /nix/store/bnj8d7mvbkg3vdb07yz74yhl3g107qq5-patch-shebangs.sh /nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh /nix/store/1i5y55x4b4m9qkx5dqbmr1r6bvrqbanw-multiple-outputs.sh /nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh /nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh /nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh /nix/store/pr6nzbscdpg94yvr151lrif2kg0csx7b-reproducible-builds.sh /nix/store/swshwzk51022n8wl4vbq5mlaayd2syhq-bootstrap-stage0-clang-wrapper-7.1.0"
defaultBuildInputs="/nix/store/s952sjn7hj8z1z0j3yq5f3gklyvvqji5-swift-corefoundation /nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil"

Perhaps the forbidden references are in one of those.

Here are the forbidden dependency

 nix why-depends /nix/store/swshwzk51022n8wl4vbq5mlaayd2syhq-bootstrap-stage0-clang-wrapper-7.1.0 /nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08
/nix/store/swshwzk51022n8wl4vbq5mlaayd2syhq-bootstrap-stage0-clang-wrapper-7.1.0
└───bin/clang: …#! /nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil/bin/bash.set -eu -o pi…
    → /nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil
    └───bin/bash: …#!/nix/store/3g99zqw1dzgaxnm9macy1h2w5lqsbi2s-oil-0.8.11/bin/osh.exec /nix/st…
        → /nix/store/3g99zqw1dzgaxnm9macy1h2w5lqsbi2s-oil-0.8.11
        └───bin/oil.ovm: ….p.................../nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08
            → /nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08

❯ nix why-depends /nix/store/swshwzk51022n8wl4vbq5mlaayd2syhq-bootstrap-stage0-clang-wrapper-7.1.0 /nix/store/aqj0kzpan8z7y39qsy7mfawppvik50gm-ncurses-6.2
/nix/store/swshwzk51022n8wl4vbq5mlaayd2syhq-bootstrap-stage0-clang-wrapper-7.1.0
└───bin/clang: …#! /nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil/bin/bash.set -eu -o pi…
    → /nix/store/r40yk9kxjf6s4r97jz71nkjb33y0kmiv-bash-oil
    └───bin/bash: …#!/nix/store/3g99zqw1dzgaxnm9macy1h2w5lqsbi2s-oil-0.8.11/bin/osh.exec /nix/st…
        → /nix/store/3g99zqw1dzgaxnm9macy1h2w5lqsbi2s-oil-0.8.11
        └───bin/oil.ovm: ….p.................../nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08
            → /nix/store/hv7s7fgnlqrprld2xpp3brj24am0j2vb-readline-6.3p08
            └───lib/libhistory.6.3.dylib: ….h.................../nix/store/aqj0kzpan8z7y39qsy7mfawppvik50g
                → /nix/store/aqj0kzpan8z7y39qsy7mfawppvik50gm-ncurses-6.2

so no matter what we do, we need to have those in allowed requisites otherwise the build will fail.
In darwin bootstrap-tools stage 4 there is a line of code to explicitely remove dependency on ncurses, so I wonder if that really is a good thing to add ncurses to the dependency tree.

@happysalada
Copy link
Copy Markdown
Contributor Author

Next:
I'm trying to separate oil into an interactive version and a non-interactive one. (including readline or not, since it seems readline is used for interactivity).
I'm adding ncurses6 to the list of allowed requisites of stdenv stage3 since oil depends on it.

@happysalada
Copy link
Copy Markdown
Contributor Author

adding the dependencies to allowedRequisites lead me to the next failure

❯ nix log /nix/store/kwb08d6ikz5hqkn2l83j2ap91953mfp0-gawk-5.1.0.drv
+ source '/nix/store/rl2wxq8qakzgxh1hslggk6vn7xgq5g5w-bootstrap-stage3-stdenv-darwin/setup'
+ export SHELL='/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin/bash'
+ initialPath='/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools'
+ defaultNativeBuildInputs='/nix/store/4q88vhj678qfp5zz72k2vkmxfh6qn0h5-xz-5.2.5-bin /nix/store/mjjy30kxz7
+ defaultBuildInputs='/nix/store/h7ryjlg66nzh253m98zpcf6f8fjf09nc-swift-corefoundation /nix/store/yynw6wnd
+ export NIX_ENFORCE_NO_NATIVE=1
+ export NIX_ENFORCE_PURITY=1
+ export NIX_IGNORE_LD_THROUGH_GCC=1
+ unset SDKROOT
+ export gl_cv_func_getcwd_abort_bug=no
+ stripAllFlags=' '
+ export PATH='/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin:/path-not-set'
+ export PATH_LOCALE='/nix/store/a37a66i5xl1ad3cdxsyjapcwhc0wa83x-adv_cmds-119-locale/share/locale'
+ export NIX_DONT_SET_RPATH_FOR_BUILD=1
+ export NIX_DONT_SET_RPATH=1
+ export NIX_NO_SELF_RPATH=1
+ export MACOSX_DEPLOYMENT_TARGET=10.12
+ set -eu
+ set -o pipefail
+ (( "${NIX_DEBUG:-0}" >= 6 ))
+ ':' 'out info man'
+ trap exitHandler EXIT
+ export SOURCE_DATE_EPOCH=
+ ':' 315532800
+ shopt -s nullglob
+ PATH=''
+ HOST_PATH=''
+ '[' '/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools' '=' '/' ']'
+ addToSearchPath PATH '/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ addToSearchPathWithCustomDelimiter ':' PATH '/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools
+ local delimiter=':'
+ local varName=PATH
+ local dir='/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ [[ -d "$dir" && "${!varName:+${delimiter}${!varName}${delimiter}}" \ ...
+ export PATH='/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ '[' -z '' ']'
+ addToSearchPath HOST_PATH '/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ addToSearchPathWithCustomDelimiter ':' HOST_PATH '/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-
+ local delimiter=':'
+ local varName=HOST_PATH
+ local dir='/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ [[ -d "$dir" && "${!varName:+${delimiter}${!varName}${delimiter}}" \ ...
+ export HOST_PATH='/nix/store/6jysbyhc43sjvfiyh1bpvi1n3zbz212r-bootstrap-tools/bin'
+ unset i
+ (( "${NIX_DEBUG:-0}" >= 1 ))
+ '[' -z '/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin/bash' ']'
+ BASH='/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin/bash'
+ export CONFIG_SHELL='/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin/bash'
+ '[' -z '' ']'
+ export shell='/nix/store/yynw6wnds9q3kzbald33cia3prmd3qmy-bash-oil/bin/bash'
+ runHook preHook
...skipping...
+ local hook=
+ _eval '_callImplicitHook 0 failureHook'
+ eval '_callImplicitHook 0 failureHook'
+ _callImplicitHook 0 failureHook
+ local def=0
+ local hookName=failureHook
+ declare -F failureHook
+ type -p failureHook
type: 'failureHook' not found
+ '[' -n '' ']'
+ return
+ return
+ '[' -n '' ']'
+ exit 1

The offending function is the following

# Run the named hook, either by calling the function with that name or
# by evaluating the variable with that name. This allows convenient
# setting of hooks both from Nix expressions (as attributes /
# environment variables) and from shell scripts (as functions). If you
# want to allow multiple hooks, use runHook instead.
_callImplicitHook() {
    local def="$1"
    local hookName="$2"
    if declare -F "$hookName" > /dev/null ; then
        "$hookName"
    elif type -p "$hookName" > /dev/null ; then
        source "$hookName"
    elif [ -n "${!hookName:-}" ]; then
        eval "${!hookName}"
    else
        return "$def"
    fi
    # `_eval` expects hook to need nounset disable and leave it
    # disabled anyways, so Ok to to delegate. The alternative of a
    # return trap is no good because it would affect nested returns.
}

since osh has errexit set by default and type fails, I think that is the problem here.
I'm going to try replacing the > /dev/null with || false

@happysalada
Copy link
Copy Markdown
Contributor Author

That did not work. on strict errexit, adding || false still generated the exit code 1 and made the thing fail.
I guess that the type -p can't be used here. I'm trying test -e which is to test if a file exists (I thought it was to test if a variable exists).

type -p will exit 1 on failure.
Test makes the intent clearer here.
@happysalada
Copy link
Copy Markdown
Contributor Author

happysalada commented Jun 23, 2021

That was a superficial error hiding the following error

mapOffset relHostOffset
+ local -r pkg='/nix/store/y8j86z5r2a604ir8hckk30fvbgy5frr4-xz-5.2.5-bin'
+ local -r inputOffset=relHostOffset
+ declare -a envHostHostHooks= envHostTargetHooks=
+ local -r hostOffset=-1
+ (( "$inputOffset" <= 0 ))
          if (( "$inputOffset" <= 0 )); then
                ^
/nix/store/9zrxgrc25zb33pj1nhkga60wajzjmbj3-bootstrap-stage3-stdenv-darwin/setup:402: fatal: Invalid integer constant 'relHostOffset'

I have to say I'm a little puzzled at the mapOffset function being called with arguments that are variables that are not expanded. Here is the map offset function

    # The current package's host and target offset together
    # provide a <=-preserving homomorphism from the relative
    # offsets to current offset
    local mapOffsetResult
    function mapOffset() {
        local -r inputOffset="$1"
        if (( "$inputOffset" <= 0 )); then
            local -r outputOffset=$(( inputOffset + hostOffset ))
        else
            local -r outputOffset=$(( inputOffset - 1 + targetOffset ))
        fi
        mapOffsetResult="$outputOffset"
    }

and it's being called like

local relHostOffset
... (doing stuff with relHostOffset)
        mapOffset relHostOffset

I don't understand why it's not mapOffset "$relHostOffset"
I'm going to give it a try

@happysalada
Copy link
Copy Markdown
Contributor Author

I now get a different error, so I guess it was the right call
Here is the next error

[' -e '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' ']'
+ local hostOffsetNext=-2
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local mapOffsetResult=
+ local relHostOffset=
+ continue
+ local files=propagatedBuildDepFiles
+ eval 'pkgsBuildHost+=("$pkg")'
+ mapOffset -1
+ local files=propagatedHostDepFiles
+ mapOffset 0
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ mapOffsetResult=-1
+ local hostOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ pkgsBuildHost+=( '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' )
+ '[' -e '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' ']'
+ local mapOffsetResult=
+ local relHostOffset=
+ local files=propagatedBuildDepFiles
+ local -r inputOffset=-1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-2
+ mapOffsetResult=-2
+ local hostOffsetNext=-2
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ continue
+ local files=propagatedHostDepFiles
+ mapOffset 0
+ local relTargetOffset=
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ mapOffset -1
+ local -r inputOffset=-1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-2
+ mapOffsetResult=-2
+ local hostOffsetNext=-2
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ mapOffsetResult=-1
+ local fileRef='propagatedHostDepFiles[0]'
+ local file=propagated-host-host-deps
+ unset -v fileRef
+ mapOffset 0
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ local hostOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local relTargetOffset=
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[0]'
+ local file=propagated-host-host-deps
+ unset -v fileRef
+ mapOffsetResult=-1
+ mapOffset 0
+ local targetOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local -r inputOffset=0
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[1]'
+ local file=propagated-build-inputs
+ continue
+ local files=propagatedHostDepFiles
+ mapOffset 0
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ mapOffsetResult=-1
+ local targetOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ local -r outputOffset=-1
+ continue
+ unset -v fileRef
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local targetOffsetNext=0
+ mapOffsetResult=-1
+ local hostOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local relTargetOffset=
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[0]'
+ local file=propagated-host-host-deps
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[1]'
+ local file=propagated-build-inputs
+ unset -v fileRef
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ findInputs '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' -1 0
+ local -r pkg='/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin'
+ local -r hostOffset=-1
+ local -r targetOffset=0
+ (( "$hostOffset" <= "$targetOffset" ))
+ local varVar=pkgBuildAccumVars
+ local varRef='pkgBuildAccumVars[1]'
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ unset -v fileRef
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local var=pkgsBuildHost
+ unset -v varVar varRef
+ local files=propagatedTargetDepFiles
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ mapOffset 0
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ local targetOffsetNext=0
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ local files=propagatedTargetDepFiles
+ local varSlice='pkgsBuildHost[*]'
+ unset -v varSlice
+ eval 'pkgsBuildHost+=("$pkg")'
+ mapOffsetResult=-1
+ mapOffsetResult=0
+ local hostOffsetNext=0
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local relTargetOffset=
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local targetOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[1]'
+ local file=propagated-build-inputs
+ unset -v fileRef
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local hostOffsetNext=0
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local relTargetOffset=
+ pkgsBuildHost+=( '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' )
+ '[' -e '/nix/store/nr1ii2ss7fdp326ypqdlmndc3bq49mc4-xz-5.2.5-bin' ']'
+ local mapOffsetResult=
+ local relHostOffset=
+ local files=propagatedBuildDepFiles
+ mapOffset -1
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ mapOffset 1
+ local fileRef='propagatedTargetDepFiles[0]'
+ local file=propagated-target-target-deps
+ unset -v fileRef
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ local -r inputOffset=-1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ local -r outputOffset=-2
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ mapOffsetResult=0
+ local targetOffsetNext=0
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedTargetDepFiles[0]'
+ local file=propagated-target-target-deps
+ mapOffsetResult=-2
+ local hostOffsetNext=-2
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ continue
+ local files=propagatedHostDepFiles
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local targetOffsetNext=0
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ findInputs '/nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh' -1 0
+ local files=propagatedTargetDepFiles
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local hostOffsetNext=0
+ unset -v fileRef
+ mapOffset 1
+ local -r inputOffset=1
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=0
+ mapOffsetResult=0
+ local targetOffsetNext=0
+ mapOffset 0
+ local -r inputOffset=0
+ (( "$inputOffset" <= 0 ))
+ local -r outputOffset=-1
+ mapOffsetResult=-1
+ local hostOffsetNext=-1
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ local relTargetOffset=
+ local -r pkg='/nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh'
+ [[ "${allPlatOffsets[*]}" = *"$hostOffsetNext"*  ]]
+ [[ "${allPlatOffsets[*]}" = *"$targetOffsetNext"* ]]
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local -r hostOffset=-1
+ local -r targetOffset=0
+ (( "$hostOffset" <= "$targetOffset" ))
+ local varVar=pkgBuildAccumVars
+ local relTargetOffset=
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ continue
+ [[ -f "$pkg/nix-support/$file" ]]
+ continue
+ findInputs '/nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh' -1 0
+ continue
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local fileRef='propagatedHostDepFiles[0]'
+ local file=propagated-host-host-deps
+ local varRef='pkgBuildAccumVars[1]'
+ local var=pkgsBuildHost
+ (( "$relHostOffset" <= "$relTargetOffset" ))
+ local -r pkg='/nix/store/mjjy30kxz775bhhi6j9phw81qh6dsbrf-move-docs.sh'
+ unset -v fileRef
+ unset -v varVar varRef
+ local fileRef='propagatedTargetDepFiles[0]'
+ local file=propagated-target-target-deps
+ local -r hostOffset=-1
+ local -r targetOffset=0
+ mapOffset 0
+ local -r inputOffset=0
+ local varSlice='pkgsBuildHost[*]'
      case "${!varSlice-}" in
           ^
/nix/store/4sc142mdwjahf3qg06a0zs8rcvh9rppd-bootstrap-stage3-stdenv-darwin/setup:384: fatal: This word should yield a string, but it contains an array

# implements.
findInputs() {
local -r pkg="$1"
local -ri hostOffset="$2"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does shellcheck say to not do this? It seems reasonable to set -i:

The variable is to be treated as an integer;
arithmetic evaluation is performed when the
variable is assigned a value.

https://ss64.com/bash/declare.html

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the more controversial change. -i does not work at the moment with osh.
Apparently, -i is basically a no-op in bash. The recommended way to do arithmetic is to use ((...)) where the -i does not make a difference.
There was a longer discussion though between the creator of osh and zimbatm
oils-for-unix/oils#864
(I tried to link it in the commit message)

the -i does not come from shellcheck and could be made to work with osh, it would be a matter of making a PR upstream. At the moment it does not, so I just removed it.
(perhaps the commit title could have been clearer)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Here is more relevant things around this at http://mywiki.wooledge.org/BashGuide/Parameters
Specifically

However, in practice the use of declare -i is exceedingly rare. In large part, this is because it creates behavior that can be surprising to anyone trying to maintain the script, who misses the declare statement. Most experienced shell scripters prefer to use explicit arithmetic commands (with ((...)) or let) when they want to perform arithmetic. 

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Abandon all hopes of types, it's bash :D

If I remember correctly, -i changes the parser on the fly. It also doesn't catch errors so it's not super useful. Eg: declare -ri foo=bar && echo $foo will output 0

# shellcheck disable=SC2086
local flagsArray=(
$configureFlags ${configureFlagsArray+"${configureFlagsArray[@]}"}
IFS=" " read -r -a configureFlagsTemp <<< "$configureFlags"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not super familiar with this, but this looks like it works in the way we want, while avoiding the shellcheck warning.

/cc @Ericson2314

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This might be one of those things that was only an issue pre-Bash4?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is coming from https://github.com/koalaman/shellcheck/wiki/SC2206
it's not so pretty, but it seems to work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Additionally reading up on arrays, I found this, which recommends the same
http://mywiki.wooledge.org/BashGuide/Arrays

@matthewbauer
Copy link
Copy Markdown
Member

👍 on this! I think all of these changes to the shell (or bashish) scripts are reasonable on their own. Any stats on comparisons to bash would be interesting, though.

That varSlice part can probably be rewritten based on the todo. It should just return 0 if $pkg is in the $var map.

@happysalada
Copy link
Copy Markdown
Contributor Author

@matthewbauer thank you for the explanation. I also found a reference commit here

I'm guessing it could be rewritten as

    case "${var[@]}" in
        *" $pkg "*) return 0 ;;
    esac

testing this right now

…onditional

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
@happysalada
Copy link
Copy Markdown
Contributor Author

I had some commits break building bash. After a couple of git bisect, I removed the commits.
I will re-work the problematic commits and include them in the next PR.
I plan on leaving this open until monday.

@happysalada
Copy link
Copy Markdown
Contributor Author

It seems the eval has not started yet. I'm going to change the branch to master to see if this will trigger a faster eval.
I don't intend to merge on master, I will just change it back once the eval is done.

@happysalada happysalada changed the base branch from staging to master July 5, 2021 01:12
@happysalada happysalada changed the base branch from master to staging July 6, 2021 00:27
@happysalada happysalada merged commit 8752c32 into NixOS:staging Jul 6, 2021
@happysalada
Copy link
Copy Markdown
Contributor Author

eval passed, I'm merging this on staging.
I've kept all the other changes. I'm going to make a smaller PR next.
I'll keep notice of what can be controversial and will only try to submit things that should be ok.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. and removed 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. 10.rebuild-linux-stdenv This PR causes stdenv to rebuild on Linux and must target a staging branch. 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 5001+ This PR causes many rebuilds on Linux and must target the staging branches. labels Jul 6, 2021
Copy link
Copy Markdown

@andychu andychu left a comment

Choose a reason for hiding this comment

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

(author of Oil here)

I realize this is already merged, but I just saw it and figured I would make some comments. Feel free to ignore them :)

To be honest I find the commit description misleading, because it feels like 90% of the changes have nothing to do with making it run under OSH? The changes I see that Oil probably won't run are:

  • the export FOO+= one.
  • the local -ri changes

Other changes seem to have more to do with ShellCheck than OSH? And just misc style changes like changing [ to [[ (which I generally agree with, but not really related to OSH).

ShellCheck and OSH are mostly complementary, but for my own edification and that of future OSH users/migrators, I would have liked to see the two groups of changes separated. Personally I would be scared to make all these foundational changes to what looks like fairly fundamental code in one big bunch, but you know the code better than I !


if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then
export NIX_LDFLAGS${role_post}+=" -L$1/lib64"
varName=NIX_LDFLAGS${role_post}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I would add local varName so it doesn't "leak". Also it seems like the style is local var_name, e.g. akin to role_post ?

It took me awhile to figure this code out but I get what it's doing now... it is indeed very dynamic.

I think export "$var_name" is sufficient?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FWIW I don't believe this should be affected by OSH but I can see why you would want to change it

echo "defaultBuildInputs=\"$defaultBuildInputs\""
echo "$preHook"
cat "$setup"
} > "$out/setup"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a great change! One of my pet peeves :)

The >> style is less readable and actually causes a ton of open() and close() syscalls

# in stdenv.
mkdir $out/nix-support
if [ "$propagatedUserEnvPkgs" ]; then
if [ -n "${propagatedUserEnvPkgs:-}" ]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A few comments:

  1. FWIW this shouldn't be affected by OSH. That is, strictly speaking, no change is necessary (I worry about people being confused based on the PR).
  2. And it seems like the :- is a behavior change and not a style change? Maybe that is intended.
  3. Since you're using [[ everywhere, you could also use it here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually this is interesting.
I've been running it as /bin/osh -x -O strict:all
just to be able to debug and to get "potential" bugs early.
This variable was actually undefined in some cases and so the script could fail.
What you are saying is that I should not run it with strict:all and just try to see what comes out of it?

times > "$NIX_BUILD_TOP/.times"
local -a times=($(cat "$NIX_BUILD_TOP/.times"))
local -a buildTimesArray
IFS=" " read -r -a buildTimesArray < "$NIX_BUILD_TOP/.times"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FWIW I thought the original was OK, and this shouldn't be affected by OSH? I would be interested to learn otherwise.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This one was just a shell check


local varVar="${pkgAccumVarVars[$hostOffset + 1]}"
local varRef="$varVar[\$targetOffset - \$hostOffset]"
local varVar="${pkgAccumVarVars[$(( hostOffset + 1 ))]}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BTW this can be ${vars[hostOffset + 1]}, because whatever is within ${a[i]} is parsed like arithemetic. Maybe that is too subtle for some but I'm used to it.

(Also now I notice the naming style is sometimes camelCase and sometimes role_host)

I guess it is pretty confusing because below you there is some "lazy evaluation" with ${varVar}[ $(( expr )) ], which indeed does need $(( )), because it's constructing a string to be evaluated later. This code is very confusing :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't like these references that much, but it seems that logic is in various places, I'm still trying to find a "better" solution, but I have to be able to understand the code holistically and I'm not there.

for depHostOffset in "${allPlatOffsets[@]}"; do
local hookVar="${pkgHookVarVars[$depHostOffset + 1]}"
local pkgsVar="${pkgAccumVarVars[$depHostOffset + 1]}"
local hookVar="${pkgHookVarVars[$(( depHostOffset + 1 ))]}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ditto here and throughout, $(( )) is optional in a bash/ksh array subscript

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for this one, I'll keep this in mind!

@happysalada
Copy link
Copy Markdown
Contributor Author

@andychu Thanks again for your comment!
I've been running under /bin/osh -x -O strict:all and that was probably why some stuff where changed. I'm going to just try running it with -O oil:basic and see if it changes for the better. I guess trying to run it under strict is a little overoptimistic for now. I'll cc you in the next PR!

@andychu
Copy link
Copy Markdown

andychu commented Jul 7, 2021

Ah OK so strict:all turns on errexit, which can cause many changes. (oil:basic also turns on errexit.)

It's not surprising that turning on errexit requires changes to shell code, which aren't strictly necessary for OSH.

If you're NOT running this script under bash with set -e, and are not planning to, then it could have caused you to change some stuff that isn't strictly necessary, like using ${x:-} instead of $x.

But maybe you are planning to, and it's fine! It's up to you either way, but I guess I would expect the PR to also set -e in bash if that's the case.

I also wonder if we should turn off errexit in strict:all but keep it on in oil:basic. I'm open to feedback on that. Step 1 here is to just run osh myscript.sh, and we don't necessarily mention strict:all, although I think it's useful: https://github.com/oilshell/oil/wiki/Gradually-Upgrading-Shell-to-Oil


Also it's true that if you're going to eventually upgrade to the "OIl language", you want to run with errexit, since we assume it's on. But it's valid to use OSH without errexit.

@happysalada
Copy link
Copy Markdown
Contributor Author

Thank you for sharing.
Just like you shared in the resource, I think the next step would be to not run it with any options at all and see what errors come out then. Perhaps try to fix those first.
I'll make it clearer on the next PR which fixes are for errexit and which are not, at least people have more information to judge if they want the fixes or not.

@vcunat
Copy link
Copy Markdown
Member

vcunat commented Jul 10, 2021

This seems to cause a weird regression in some cases: #129506 (comment)

I suspect it's cases where stdenv is used in some more complex way, e.g. the 64+32-bit for wine. Anyway, if we can't pinpoint it rather soon, I'd suggest to revert for now until we can solve it, so other changes don't get blocked by this.

@aszlig
Copy link
Copy Markdown
Member

aszlig commented Jul 10, 2021

@vcunat: bf99a81#r53315516 is causing the regression, so I'd suggest reverting that commit for now instead of the whole pull request.

vcunat added a commit that referenced this pull request Jul 16, 2021
I suspect that some of the stdenv changes (PR #127736 maybe?)
affected how the newline was handled.  Anyway, it was ugly,
so let's use a more standard approach.
vcunat added a commit that referenced this pull request Jul 17, 2021
At least for now.  Such changes are risky (we have very many packages),
and apparently it needs more testing/review without blocking other
changes.

This reverts the whole range 4d0e398^..8752c32,
except for one commit that got reverted in 6f239d7 already.
(that MR didn't even get its merge commit)
@vcunat
Copy link
Copy Markdown
Member

vcunat commented Jul 17, 2021

For reference, this whole PR got reverted (for now). It caused multiple unexpected regressions. If you want to redo this, I suggest that:

  • you pick some good commit from https://hydra.nixos.org/jobset/nixpkgs/trunk/evals and (re-)base the work on that;
  • poke someone (probably me) to create a separate Hydra jobset for your branch (say, just x86_64-linux), so we can then better see and solve any regressions before merging this again (Hydra can show diffs);
  • ideally also get a bit more review of the code.

@happysalada
Copy link
Copy Markdown
Contributor Author

I'm going to try to separate this into logical parts so hopefully the simple fixes can be merged first.
I'll cc you on the first PR and includes the subsequent PRs in the description.

@happysalada happysalada mentioned this pull request Jul 19, 2021
11 tasks
@happysalada happysalada deleted the a_new_hope branch April 28, 2023 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: stdenv Standard environment 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants