Repository: spack/spack

Issue:
Buildcache: Catch warning from visit(root) in full_hash() call tree to allow completion of .spack file when using relative rpath option.
A warning prevents the completion of building a .spack file when the relative rpaths option is used.
See https://github.com/spack/spack/issues/13237 for details

The warning comes during this call
https://github.com/spack/spack/blob/b4383825be628e3493da316937995df4fef9ab00/lib/spack/spack/util/package_hash.py#L126

My solution is to put a try except statement around it the catch the warning so it does not propagate higher and prevent the yaml file needed for the .spack file from being created.
buildcache create ends without finishing, gives Warning: 'Name' object has no attribute 's'
Edit: Here is the output of running the buildcache create command with debug flag:
```spack -d buildcache create ... ```
LOG HERE ---> [bc_create.log](https://github.com/spack/spack/files/3744784/bc_create.log)

@becker33

`spack buildcache create` sometimes fails to finish, giving the warning shown below. I have only observed this with a small set of packages, which I will attach below -- the use case is the same for each of the packages in the list. First I install from a concrete spec yaml file:
```
$> spack install --no-cache --overwrite -y -f /hostmount/spack-env/llvm_nlxngt.spec.yaml
```

Then I try to cache the package and the following Warning is given:
```
$> spack buildcache create --no-deps -afr -d /hostmount -k prl -y /hostmount/spack-env/llvm_nlxngt.spec.yaml
==> Warning: 'Name' object has no attribute 's'
==> createtarball, reading spec from /hostmount/spack-env/llvm_nlxngt.spec.yaml
==> creating binary cache file for package llvm@9.0.0%gcc@7.3.0~all_targets build_type=Release +clang+compiler-rt+gold+internal_unwind+libcxx~link_dylib+lld+lldb~omp_tsan+polly~python~shared_libs arch=linux-rhel7-x86_64
```

At this point, if you check `build_cache` directory, you will find a directory entry `gcc-7.3.0/llvm-9.0.0` and it will contain a .tar.gz file. No .spec.yaml file is created for llvm as one would expect under build_cache/

I've attached the exact llvm concretized .spec.yaml file below.

Other packages where I have observed this:
* mesa@18.3.6%gcc@7.3.0+glx+llvm+opengl~opengles+osmesa
* swig@4.0.0%gcc@7.3.0 
* lvm@8.0.0%gcc@7.3.0~all_targets build_type=Release +clang+compiler-rt+gold+internal_unwind+libcxx~link_dylib+lld+lldb~omp_tsan 
* flang@20180921
* qwt@6.1.3%gcc@7.3.0~designer 
* qt@5.11.3%gcc@7.3.0~dbus~examples~framework freetype=spack ~gtk~krellpatch+opengl 
* catalyst@5.6.0%gcc@7.3.0
* glew@2.0.0%gcc@7.3.0

llvm_nlxngt.spec.yaml:
```
spec:
- llvm:
    version: 9.0.0
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      all_targets: false
      build_type: Release
      clang: true
      compiler-rt: true
      gold: true
      internal_unwind: true
      libcxx: true
      link_dylib: false
      lld: true
      lldb: true
      omp_tsan: false
      polly: true
      python: false
      shared_libs: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      binutils:
        hash: k5hdtpm2rtp6rzsidirns6gcyjqvyogt
        type:
        - build
        - link
      cmake:
        hash: y6txq3ykldssamyxuyvf6kzhdabawy5a
        type:
        - build
      libedit:
        hash: smthqopkg4tlnqnv3sfj5iyasd4rd467
        type:
        - build
        - link
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
      perl-data-dumper:
        hash: k2psjsodfsptekyb76jt6polar5cczhq
        type:
        - build
      python:
        hash: s7gu7ihz54ho442c25pnc6htm3i6vuus
        type:
        - build
      swig:
        hash: hunbwpumk3l7tonromnialk5ilzr532h
        type:
        - build
        - link
    hash: ooz4vxb7qaeoh2jogwwlkbolwczzglwo
    build_hash: nlxngtqnnbjjytyola34ntmy3pk6ibrz
- binutils:
    version: '2.32'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      gold: true
      headers: false
      libiberty: false
      nls: true
      plugins: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      gettext:
        hash: jqj7dlxxfo55zgq5me42mum5vyd32pqv
        type:
        - build
        - link
      zlib:
        hash: ldu43taplg2nbkxtem346zq4ibhad64i
        type:
        - build
        - link
    hash: oeg4auwjda3cn5y44ogveghnwj7bbb5b
    build_hash: k5hdtpm2rtp6rzsidirns6gcyjqvyogt
- gettext:
    version: 0.19.8.1
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      bzip2: true
      curses: true
      git: true
      libunistring: false
      libxml2: true
      patches:
      - 9acdb4e73f67c241b5ef32505c9ddf7cf6884ca8ea661692f21dca28483b04b8
      tar: true
      xz: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    patches:
    - 9acdb4e73f67c241b5ef32505c9ddf7cf6884ca8ea661692f21dca28483b04b8
    dependencies:
      bzip2:
        hash: 7zzahiwteusf7fwhp4htotoiuiykdpxq
        type:
        - build
        - link
      libxml2:
        hash: m7hhthrvmpapo4tkiarkhkqacxnikdzs
        type:
        - build
        - link
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
      tar:
        hash: 5ydwzw64c2cnwq5qk4foiwczgv2cpdnj
        type:
        - build
        - link
      xz:
        hash: 52pq7xrp2axthcs4pcn34ha5g6vwfuy5
        type:
        - build
        - link
        - run
    hash: g4b3z4ks3mbhxrxa274jzurpkdwcc4eh
    build_hash: jqj7dlxxfo55zgq5me42mum5vyd32pqv
- bzip2:
    version: 1.0.8
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      shared: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      diffutils:
        hash: 3e3nwr6wfitdrqvocayfqkypamquao5e
        type:
        - build
    hash: 7dgdglgrxgkjr6pqjnf73diprndokh4c
    build_hash: 7zzahiwteusf7fwhp4htotoiuiykdpxq
- diffutils:
    version: '3.7'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      libiconv:
        hash: tisngyii2rqgu6uvwwno4ji7i4ypijh2
        type:
        - build
        - link
    hash: 3e3nwr6wfitdrqvocayfqkypamquao5e
    build_hash: 3e3nwr6wfitdrqvocayfqkypamquao5e
- libiconv:
    version: '1.15'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: tisngyii2rqgu6uvwwno4ji7i4ypijh2
    build_hash: tisngyii2rqgu6uvwwno4ji7i4ypijh2
- libxml2:
    version: 2.9.9
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      python: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      libiconv:
        hash: tisngyii2rqgu6uvwwno4ji7i4ypijh2
        type:
        - build
        - link
      pkgconf:
        hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
        type:
        - build
      xz:
        hash: 52pq7xrp2axthcs4pcn34ha5g6vwfuy5
        type:
        - build
        - link
      zlib:
        hash: ldu43taplg2nbkxtem346zq4ibhad64i
        type:
        - build
        - link
    hash: sejmw3qjl2ncl3wzb4rhlo6ypdj7ze5z
    build_hash: m7hhthrvmpapo4tkiarkhkqacxnikdzs
- pkgconf:
    version: 1.6.1
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
    build_hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
- xz:
    version: 5.2.4
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: 52pq7xrp2axthcs4pcn34ha5g6vwfuy5
    build_hash: 52pq7xrp2axthcs4pcn34ha5g6vwfuy5
- zlib:
    version: 1.2.11
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      optimize: true
      pic: true
      shared: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: ldu43taplg2nbkxtem346zq4ibhad64i
    build_hash: ldu43taplg2nbkxtem346zq4ibhad64i
- ncurses:
    version: '6.1'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      symlinks: false
      termlib: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      pkgconf:
        hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
        type:
        - build
    hash: i6zkr74nebgmb6meyzexi4sg62qhnarp
    build_hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
- tar:
    version: '1.31'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: 5ydwzw64c2cnwq5qk4foiwczgv2cpdnj
    build_hash: 5ydwzw64c2cnwq5qk4foiwczgv2cpdnj
- cmake:
    version: 3.15.3
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      doc: false
      ncurses: true
      openssl: true
      ownlibs: true
      qt: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
      openssl:
        hash: 3d7h7mj2c3rvj6owksm7y6bjhudx2mdk
        type:
        - build
        - link
    hash: phicfpngfape3lnbrmipumntusjd2x77
    build_hash: y6txq3ykldssamyxuyvf6kzhdabawy5a
- openssl:
    version: 1.1.1c
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      systemcerts: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      perl:
        hash: fub3nmdugvhbmwiws4p32yathgl2dx7o
        type:
        - build
        - test
      zlib:
        hash: ldu43taplg2nbkxtem346zq4ibhad64i
        type:
        - build
        - link
    hash: v3yefyzyio4ltv6wsle5rff5dh3va6as
    build_hash: 3d7h7mj2c3rvj6owksm7y6bjhudx2mdk
- perl:
    version: 5.26.2
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cpanm: true
      patches:
      - 0eac10ed90aeb0459ad8851f88081d439a4e41978e586ec743069e8b059370ac
      shared: true
      threads: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    patches:
    - 0eac10ed90aeb0459ad8851f88081d439a4e41978e586ec743069e8b059370ac
    dependencies:
      gdbm:
        hash: tnhmrbreptwcxdl3uqfqbnmjrlet5ypx
        type:
        - build
        - link
    hash: c2rbjgnb5u7yybfnd64xc2bkfgrbhx6t
    build_hash: fub3nmdugvhbmwiws4p32yathgl2dx7o
- gdbm:
    version: 1.18.1
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      readline:
        hash: 7wsc3bp6lc3picrpbyk6ezgpyzdf325z
        type:
        - build
        - link
    hash: atuwrwr5arr5ywd4wzs5fztmk7aunti2
    build_hash: tnhmrbreptwcxdl3uqfqbnmjrlet5ypx
- readline:
    version: '7.0'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
    hash: iomtztdr32lxjensxi5jtwfpugjgbr7w
    build_hash: 7wsc3bp6lc3picrpbyk6ezgpyzdf325z
- libedit:
    version: 3.1-20170329
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
    hash: hsuvslbfjpclkq2mkxaakazsuexywkgs
    build_hash: smthqopkg4tlnqnv3sfj5iyasd4rd467
- perl-data-dumper:
    version: '2.173'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      perl:
        hash: fub3nmdugvhbmwiws4p32yathgl2dx7o
        type:
        - build
        - link
        - run
    hash: bnf2sj6aqlm3op6ermtmdgecglksco3t
    build_hash: k2psjsodfsptekyb76jt6polar5cczhq
- python:
    version: 2.7.16
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      bz2: true
      ctypes: true
      dbm: true
      lzma: true
      nis: false
      optimizations: false
      pic: true
      pyexpat: true
      pythoncmd: true
      readline: true
      shared: true
      sqlite3: true
      ssl: true
      tix: false
      tkinter: false
      ucs4: false
      uuid: false
      zlib: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      bzip2:
        hash: 7zzahiwteusf7fwhp4htotoiuiykdpxq
        type:
        - build
        - link
      expat:
        hash: oj46f5jzj7sifwx3owxgj2k2vptqphnm
        type:
        - build
        - link
      gdbm:
        hash: tnhmrbreptwcxdl3uqfqbnmjrlet5ypx
        type:
        - build
        - link
      gettext:
        hash: jqj7dlxxfo55zgq5me42mum5vyd32pqv
        type:
        - build
        - link
      libffi:
        hash: 23pznc42nxucd4aymz5mf4yfhprg2zam
        type:
        - build
        - link
      ncurses:
        hash: 37z4e5ayltdbfnukuel4vdbxm3uk7lqw
        type:
        - build
        - link
      openssl:
        hash: 3d7h7mj2c3rvj6owksm7y6bjhudx2mdk
        type:
        - build
        - link
      pkgconf:
        hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
        type:
        - build
      readline:
        hash: 7wsc3bp6lc3picrpbyk6ezgpyzdf325z
        type:
        - build
        - link
      sqlite:
        hash: mrizk5x23n4lcnxrmlga3sqlpqiyq763
        type:
        - build
        - link
      zlib:
        hash: ldu43taplg2nbkxtem346zq4ibhad64i
        type:
        - build
        - link
    hash: v4jof2rpqfyqzt3vgtnm4zpwncgdywbb
    build_hash: s7gu7ihz54ho442c25pnc6htm3i6vuus
- expat:
    version: 2.2.5
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      libbsd: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      libbsd:
        hash: kl3szpzehwn23t7uztplyni46mj4yr6r
        type:
        - build
        - link
    hash: oj46f5jzj7sifwx3owxgj2k2vptqphnm
    build_hash: oj46f5jzj7sifwx3owxgj2k2vptqphnm
- libbsd:
    version: 0.9.1
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: kl3szpzehwn23t7uztplyni46mj4yr6r
    build_hash: kl3szpzehwn23t7uztplyni46mj4yr6r
- libffi:
    version: 3.2.1
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: 23pznc42nxucd4aymz5mf4yfhprg2zam
    build_hash: 23pznc42nxucd4aymz5mf4yfhprg2zam
- sqlite:
    version: 3.29.0
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      column_metadata: false
      fts: true
      functions: false
      rtree: false
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      readline:
        hash: 7wsc3bp6lc3picrpbyk6ezgpyzdf325z
        type:
        - build
        - link
      zlib:
        hash: ldu43taplg2nbkxtem346zq4ibhad64i
        type:
        - build
        - link
    hash: weqsz23ippslxmkpmsayoqt6hyutazo2
    build_hash: mrizk5x23n4lcnxrmlga3sqlpqiyq763
- swig:
    version: 4.0.0
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    dependencies:
      pcre:
        hash: lpbkhhnurtvzuaome72xi6znkdjzmt2d
        type:
        - build
        - link
      pkgconf:
        hash: 7mp3movko767rt7gxskkeuhm7cfcdqrk
        type:
        - build
    hash: pyot7i3f3qx4mbeobr4ahnvtu2jfxe64
    build_hash: hunbwpumk3l7tonromnialk5ilzr532h
- pcre:
    version: '8.42'
    arch:
      platform: linux
      platform_os: rhel7
      target: x86_64
    compiler:
      name: gcc
      version: 7.3.0
    namespace: builtin
    parameters:
      jit: false
      multibyte: true
      utf: true
      cflags: []
      cppflags: []
      cxxflags: []
      fflags: []
      ldflags: []
      ldlibs: []
    hash: lpbkhhnurtvzuaome72xi6znkdjzmt2d
    build_hash: lpbkhhnurtvzuaome72xi6znkdjzmt2d
```


Discussion:
@tgamblin Can I merge this?
Looking forward to this making it in! I will immediately be able to use this to cache some important + large packages.
@tgamblin can this be merged?
Can you run 
spack find -l llvm
This gives the package hash as the first field. Then run 
spack -d buildcache create -ar /llvm-hash
Ah I see you are using the create relative option. I am trying to debug the warning now.
> Can you run
> spack find -l llvm
> This gives the package hash as the first field. Then run
> spack -d buildcache create -ar /llvm-hash

I added debug output to the top of the post (very top of original post), although using the exact command I was using, not the one you suggested in your first reply -- although based on your second reply I think this may be sufficient? Thanks for taking a look!
@becker33 
The warning is coming from this line
https://github.com/spack/spack/blob/b4383825be628e3493da316937995df4fef9ab00/lib/spack/spack/binary_distribution.py#L360
    spec_dict['full_hash'] = spec.full_hash()
because the spec does not have a 'full_hash'.
Drilling down the warning comes during this call
https://github.com/spack/spack/blob/b4383825be628e3493da316937995df4fef9ab00/lib/spack/spack/util/package_hash.py#L126
I am testing with swig. The swig dependency pcre has its buildcache created with no warning. The difference as far as I can tell is that swig has no patches applied. 
#13265 "fixes" the problem by skipping the call to full_hash() when 'buildcache create -r ' is called. I think it has something to do with the fact that the package has no patches. I am not sure why using the relative rpath option exposes this bug.
What is different about these packages vs others that makes this a problem? Because I use the exact same `spack buildcache` command in the exact same way with a ton of other packages and in almost all cases this doesn't happen.

@gartung 
Will these changes affect whether I can use `spack buildcache check` to determine if a package needs to be rebuilt? `spack buildcache check` uses full_hash to determine if a package needs rebuild.
As far as I can tell yes. The full_hash checks were not added by me so further debugging will have to be done by @becker33 et al.
I reverted the previous "fix" and put a try except around the fmm.visit(root) call to catch the warning. This prevent the highest level try except statement from catching the warning and bailing on the .spack file creation. I verified that full_hash is now written to the yaml file in the .spack file.
@eugeneswalker Can you please verify that this patch allows you to create buildcaches with relative rpaths and that 'spack buildcache check' also works. 
@gartung This looks good. `buildcache check` seems to behave as expected with this patch! Thank you!
From investigating this, it appears this occurs for packages which define a multimethod (https://spack.readthedocs.io/en/latest/spack.html#spack.multimethod.when) using a variable rather than a string literal. One example is `swig`. In that case, that package and any parent of the package will fail when one invokes `full_hash` on it. 

I'm inclined to say that for now, multimethods should be defined with string literals and that we should add logic to verify that this occurs in a package (invoking `content_hash` would be sufficient to verify this). Resolving the variable does not appear to be simple at least from an initial investigation of the logic.

I have also not determined yet whether all the examples provided in the PR description are parents of `swig` or how common this practice is in Spack packages. It is possible that an existing Spack package makes extensive use of this (although I doubt it).
> It is possible that an existing Spack package makes extensive use of this (although I doubt it).

I have written a script to check this and only `swig` fails (i.e. that is the only package which uses a variable reference vs. a string literal).

Rather than support variables in when declarations, I'm inclined to enforce that they be string literals because

* Recovering the variable value from the AST is not straightforward
* There is only one case where the multimethod is defined in this way

So @gartung I think it will be best if I submit a PR to update `swig` and add that check vs. using https://github.com/spack/spack/pull/13265 (but let's leave that open until I actually have a PR) - let me know if you disagree. I anticipate having a PR ready in the next day or two.
That's OK with me.
Thank you @gartung and @scheibelp ! I will be able to make use of this fix right away!

Resolving patch:
diff --git a/lib/spack/spack/util/package_hash.py b/lib/spack/spack/util/package_hash.py
--- a/lib/spack/spack/util/package_hash.py
+++ b/lib/spack/spack/util/package_hash.py
@@ -69,8 +69,17 @@ def visit_FunctionDef(self, node):  # noqa
         if node.decorator_list:
             dec = node.decorator_list[0]
             if isinstance(dec, ast.Call) and dec.func.id == 'when':
-                cond = dec.args[0].s
-                nodes.append((node, self.spec.satisfies(cond, strict=True)))
+                try:
+                    cond = dec.args[0].s
+                    nodes.append(
+                        (node, self.spec.satisfies(cond, strict=True)))
+                except AttributeError:
+                    # In this case the condition for the 'when' decorator is
+                    # not a string literal (for example it may be a Python
+                    # variable name). Therefore the function is added
+                    # unconditionally since we don't know whether the
+                    # constraint applies or not.
+                    nodes.append((node, None))
         else:
             nodes.append((node, None))
 
diff --git a/var/spack/repos/builtin.mock/packages/hash-test1/package.py b/var/spack/repos/builtin.mock/packages/hash-test1/package.py
--- a/var/spack/repos/builtin.mock/packages/hash-test1/package.py
+++ b/var/spack/repos/builtin.mock/packages/hash-test1/package.py
@@ -19,6 +19,9 @@ class HashTest1(Package):
     version('1.2', 'b' * 32)
     version('1.3', 'c' * 32)
     version('1.4', 'd' * 32)
+    version('1.5', 'd' * 32)
+    version('1.6', 'e' * 32)
+    version('1.7', 'f' * 32)
 
     patch('patch1.patch', when="@1.1")
     patch('patch2.patch', when="@1.4")
@@ -34,6 +37,10 @@ def install(self, spec, prefix):
         print("install 1")
         os.listdir(os.getcwd())
 
-    @when('@1.5')
+    @when('@1.5:')
     def install(self, spec, prefix):
         os.listdir(os.getcwd())
+
+    @when('@1.5,1.6')
+    def extra_phase(self, spec, prefix):
+        pass
diff --git a/var/spack/repos/builtin.mock/packages/hash-test3/package.py b/var/spack/repos/builtin.mock/packages/hash-test3/package.py
new file mode 100644
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/hash-test3/package.py
@@ -0,0 +1,42 @@
+# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack import *
+
+import os
+
+
+class HashTest3(Package):
+    """Used to test package hashing
+    """
+
+    homepage = "http://www.hashtest3.org"
+    url = "http://www.hashtest1.org/downloads/hashtest3-1.1.tar.bz2"
+
+    version('1.2', 'b' * 32)
+    version('1.3', 'c' * 32)
+    version('1.5', 'd' * 32)
+    version('1.6', 'e' * 32)
+    version('1.7', 'f' * 32)
+
+    variant('variantx', default=False, description='Test variant X')
+    variant('varianty', default=False, description='Test variant Y')
+
+    def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
+        pass
+
+    @when('@:1.4')
+    def install(self, spec, prefix):
+        print("install 1")
+        os.listdir(os.getcwd())
+
+    @when('@1.5:')
+    def install(self, spec, prefix):
+        os.listdir(os.getcwd())
+
+    for _version_constraint in ['@1.5', '@1.6']:
+        @when(_version_constraint)
+        def extra_phase(self, spec, prefix):
+            pass


Test patch:
diff --git a/lib/spack/spack/test/packages.py b/lib/spack/spack/test/packages.py
--- a/lib/spack/spack/test/packages.py
+++ b/lib/spack/spack/test/packages.py
@@ -16,6 +16,11 @@
 import spack.directives
 
 
+def _generate_content_strip_name(spec):
+    content = package_content(spec)
+    return content.replace(spec.package.__class__.__name__, '')
+
+
 @pytest.mark.usefixtures('config', 'mock_packages')
 class TestPackage(object):
     def test_load_package(self):
@@ -53,38 +58,43 @@ def test_package_class_names(self):
         assert '_3db' == mod_to_class('3db')
 
     def test_content_hash_all_same_but_patch_contents(self):
-        spec1 = Spec("hash-test1@1.1")
-        spec2 = Spec("hash-test2@1.1")
-        spec1.concretize()
-        spec2.concretize()
-        content1 = package_content(spec1)
-        content1 = content1.replace(spec1.package.__class__.__name__, '')
-        content2 = package_content(spec2)
-        content2 = content2.replace(spec2.package.__class__.__name__, '')
+        spec1 = Spec("hash-test1@1.1").concretized()
+        spec2 = Spec("hash-test2@1.1").concretized()
+        content1 = _generate_content_strip_name(spec1)
+        content2 = _generate_content_strip_name(spec2)
         assert spec1.package.content_hash(content=content1) != \
             spec2.package.content_hash(content=content2)
 
     def test_content_hash_different_variants(self):
-        spec1 = Spec("hash-test1@1.2 +variantx")
-        spec2 = Spec("hash-test2@1.2 ~variantx")
-        spec1.concretize()
-        spec2.concretize()
-        content1 = package_content(spec1)
-        content1 = content1.replace(spec1.package.__class__.__name__, '')
-        content2 = package_content(spec2)
-        content2 = content2.replace(spec2.package.__class__.__name__, '')
+        spec1 = Spec("hash-test1@1.2 +variantx").concretized()
+        spec2 = Spec("hash-test2@1.2 ~variantx").concretized()
+        content1 = _generate_content_strip_name(spec1)
+        content2 = _generate_content_strip_name(spec2)
         assert spec1.package.content_hash(content=content1) == \
             spec2.package.content_hash(content=content2)
 
+    def test_content_hash_cannot_get_details_from_ast(self):
+        """Packages hash-test1 and hash-test3 would be considered the same
+           except that hash-test3 conditionally executes a phase based on
+           a "when" directive that Spack cannot evaluate by examining the
+           AST. This test ensures that Spack can compute a content hash
+           for hash-test3. If Spack cannot determine when a phase applies,
+           it adds it by default, so the test also ensures that the hashes
+           differ where Spack includes a phase on account of AST-examination
+           failure.
+        """
+        spec3 = Spec("hash-test1@1.7").concretized()
+        spec4 = Spec("hash-test3@1.7").concretized()
+        content3 = _generate_content_strip_name(spec3)
+        content4 = _generate_content_strip_name(spec4)
+        assert(spec3.package.content_hash(content=content3) !=
+               spec4.package.content_hash(content=content4))
+
     def test_all_same_but_archive_hash(self):
-        spec1 = Spec("hash-test1@1.3")
-        spec2 = Spec("hash-test2@1.3")
-        spec1.concretize()
-        spec2.concretize()
-        content1 = package_content(spec1)
-        content1 = content1.replace(spec1.package.__class__.__name__, '')
-        content2 = package_content(spec2)
-        content2 = content2.replace(spec2.package.__class__.__name__, '')
+        spec1 = Spec("hash-test1@1.3").concretized()
+        spec2 = Spec("hash-test2@1.3").concretized()
+        content1 = _generate_content_strip_name(spec1)
+        content2 = _generate_content_strip_name(spec2)
         assert spec1.package.content_hash(content=content1) != \
             spec2.package.content_hash(content=content2)