Repository: spack/spack

Issue:
[Question] External packages module requirement to work with Spack?
Suppose I have following external module:

```
module show nix/bgq/cmake/3.3.2
-------------------------------------------------------------------
/gpfs-path-xxx//modules-bgq-lugano-all/nix/bgq/cmake/3.3.2:

module-whatis	 cmake for BGQ backend  generated by nix
prepend-path	 PATH /gpfs-path/store/636l7bvg95fvdyffddw8g94cxwsrb1v8-generated-env-module-cmake/bin
-------------------------------------------------------------------
```

Then I add entry in `packages.yaml` as :

```
    cmake:
        modules:
            cmake@3.3.2%xl@12.1 arch=bgq-cnk-ppc64: nix/bgq/cmake/3.3.2
        buildable: False
        version: [3.3.2]
```

While installation I see:

```
==> cmake@3.9.0 : generating module file
==> Error: 'NoneType' object has no attribute 'startswith'
```

Debug shows :

```
==> cmake@3.3.2 : generating module file
==> SKIP: shebang filtering [external package]
==> READ LOCK: /gpfs/bbp.cscs.ch/home/kumbhar/spack_install/bgq/.spack-db/lock[0:0] [Acquiring]
==> READ LOCK: /gpfs/bbp.cscs.ch/home/kumbhar/spack_install/bgq/.spack-db/lock[0:0] [Acquired]
==> READ LOCK: /gpfs/bbp.cscs.ch/home/kumbhar/spack_install/bgq/.spack-db/lock[0:0] [Released]
==> 	WRITE : cmake@3.3.2%xl@12.1~doc+ncurses+openssl+ownlibs~qt arch=bgq-cnk-ppc64 /gshkzty [/gpfs/bbp.cscs.ch/home/kumbhar/spack_modules/bgq/tcl/bgq-cnk-ppc64/cmake-3.3.2-xl-12.1-gshkzty]
Traceback (most recent call last):
  File "/gpfs-path/softwares/sources/spack/bin/spack", line 81, in <module>
    sys.exit(spack.main.main())
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/main.py", line 552, in main
    return _main(command, parser, args, unknown)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/main.py", line 444, in _main
    return _invoke_spack_command(command, parser, args, unknown_args)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/main.py", line 355, in _invoke_spack_command
    return_val = command(parser, args)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/cmd/install.py", line 361, in install
    package.do_install(**kwargs)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/package.py", line 1272, in do_install
    **kwargs
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/package.py", line 1272, in do_install
    **kwargs
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/package.py", line 1233, in do_install
    return self._process_external_package(explicit)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/package.py", line 1175, in _process_external_package
    spack.hooks.post_install(self.spec)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/hooks/__init__.py", line 73, in __call__
    hook(*args, **kwargs)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/hooks/module_file_generation.py", line 32, in post_install
    generator.write()
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/modules.py", line 380, in write
    env = inspect_path(self.spec.prefix)
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/spec.py", line 1364, in prefix
    return Prefix(spack.store.layout.path_for_spec(self))
  File "/gpfs-path/softwares/sources/spack/lib/spack/spack/directory_layout.py", line 127, in path_for_spec
    assert(not path.startswith(self.root))
AttributeError: 'NoneType' object has no attribute 'startswith'
```

So are there any prerequisite for external modules to play nicely with Spack?

cc: @alalazo 
Fix problem in package root directory detection for modules
Fix #12684

In package root directory detection, instead of always returning a path if an entry `LD_LIBRARY_PATH` or `PATH` is present in the module, it checks that the path follows the expected structure (`/lib` or `/bin` suffixes) before using it, otherwise skips and lets other detection methods to try.


Discussion:
Sorry about the late response: 

It seems Spack is generating a module file for the package even though the external package has a module. It probably shouldn't do that.

Could you list the command you are using which leads to this error? Something appears to have changed in your last 2 examples because the printouts are different with and without the debug:

`==> cmake@3.9.0 : generating module file`

and 

`==> cmake@3.3.2 : generating module file`

It also appears you are running with a version of Spack other than develop.
I am trying now from develop. Here is module:

```
$ module show cmake/3.5.2
-------------------------------------------------------------------
/cineca/prod/opt/modulefiles/base/tools/cmake/3.5.2:

conflict	cmake
setenv	CMAKE_HOME	/cineca/prod/opt/tools/cmake/3.5.2/none
prepend-path	PATH	/cineca/prod/opt/tools/cmake/3.5.2/none/bin	:
module-whatis	cmake build system
-------------------------------------------------------------------
```

All cleanup:
```
$ spack module refresh --delete-tree -y
==> Regenerating tcl module files
$ rm -rf ~/SPACK_INSTALL/*
```

```
$ spack -d install -v reportinglib %intel
==> Reading config file /marconi/home/userexternal/pkumbhar/spack/etc/spack/defaults/packages.yaml
==> Reading config file /marconi/home/userexternal/pkumbhar/.spack/linux/packages.yaml
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Released]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Released]
==> Reading config file /marconi/home/userexternal/pkumbhar/.spack/linux/compilers.yaml
==> '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'list'
==> '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'show' 'cmake/3.5.2'
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Acquiring]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Released]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Released]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[676478728866344491:1] [Released]
==> Installing reportinglib dependencies
==> cmake@3.5.2 : has external module in cmake/3.5.2
==> cmake@3.5.2 : is actually installed in None
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Released]
==> cmake@3.5.2 : generating module file
==> SKIP: shebang filtering [external package]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Released]
==> 	BLACKLIST : cmake@3.5.2%intel@17.0.4~doc+ncurses+openssl+ownlibs~qt arch=linux-centos7-x86_64 /betoegn [matches : cmake  ]
==> cmake@3.5.2 : registering into DB
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Released]
==> Installing reportinglib
==> Error: AttributeError: 'NoneType' object has no attribute 'startswith'
AttributeError: AttributeError: 'NoneType' object has no attribute 'startswith'

/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/build_environment.py:576, in child_process:
     26
     27                # build up some context from the offending package so we can
     28                # show that, too.
  >> 29                package_context = get_package_context(tb)
```

 `==> cmake@3.5.2 : is actually installed in None` gives hint?
Another issue  (may be related to  #4667 ?):

I haven compiler entry into `compilers.yaml` as:

```
- compiler:
    environment: {}
    extra_rpaths: []
    flags: {}
    modules: [intel/pe-xe-2017--binary]
    operating_system: centos7
    paths:
      cc: /marconi/prod/opt/compilers/intel/pe-xe-2017/binary/bin/icc
      cxx: /marconi/prod/opt/compilers/intel/pe-xe-2017/binary/bin/icpc
      f77: /marconi/prod/opt/compilers/intel/pe-xe-2017/binary/bin/ifort
      fc: /marconi/prod/opt/compilers/intel/pe-xe-2017/binary/bin/ifort
    spec: intel@17.0.4
    target: x86_64
```

And install gives: 

```
$ spack -d install -v everytrace +mpi %intel ^intel-mpi
==> Reading config file /marconi/home/userexternal/pkumbhar/spack/etc/spack/defaults/packages.yaml
==> Reading config file /marconi/home/userexternal/pkumbhar/.spack/linux/packages.yaml
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.builtin-index.yaml.lock[0:0] [Released]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/.spack/cache/providers/.bbp-index.yaml.lock[0:0] [Released]
==> Reading config file /marconi/home/userexternal/pkumbhar/.spack/linux/compilers.yaml
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Acquiring]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/lock[0:0] [Released]
==> WRITE LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Released]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Acquiring]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Acquired]
==> READ LOCK: /marconi/home/userexternal/pkumbhar/SPACK_INSTALL/knl/.spack-db/prefix_lock[7436415997466657020:1] [Released]
==> Installing everytrace dependencies
==> intel-mpi@2017 : externally installed in /cineca/prod/opt/compilers/intel/pe-xe-2017/binary/impi/2017.3.196
==> intel-mpi@2017 : already registered in DB
==> cmake@3.5.2 : externally installed in /cineca/prod/opt/tools/cmake/3.5.2/none
==> cmake@3.5.2 : already registered in DB
==> Installing everytrace
==> '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'list'
==> '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'show' 'intel/pe-xe-2017--binary'
==> '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'unload' 'intel'
==> Error: SyntaxError: invalid syntax (<string>, line 1)
SyntaxError: SyntaxError: invalid syntax (<string>, line 1)

/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/build_environment.py:572, in child_process:
     26
     27                # build up some context from the offending package so we can
     28                # show that, too.
  >> 29                package_context = get_package_context(tb)
     30
     31                build_log = None
     32                if hasattr(pkg, 'log_path'):


Traceback (most recent call last):
  File "/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/build_environment.py", line 553, in child_process
    setup_package(pkg, dirty=dirty)
  File "/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/build_environment.py", line 484, in setup_package
    set_compiler_environment_variables(pkg, spack_env)
  File "/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/build_environment.py", line 174, in set_compiler_environment_variables
    load_module(mod)
  File "/marconi/home/userexternal/pkumbhar/spack/lib/spack/spack/util/module_cmd.py", line 134, in load_module
    error=str), '<string>', 'exec'))
  File "<string>", line 1, in <module>
  File "<string>", line 1
    /tmp/modulescript_32885_0
    ^
SyntaxError: invalid syntax
```

that file in `/tmp` looks like:

```
$ cat  /tmp/modulescript_32885_0
os.unlink('/tmp/modulescript_32885_0')
import os
os.environ['MANPATH'] = '/usr/local/share/man:/usr/share/man:/cineca/sysprod/pbs/default/man:'
os.environ['_LMFILES_'] = '/cineca/prod/opt/modulefiles/profiles/profile/base'
os.environ['LOADEDMODULES'] = 'profile/base'
os.environ['MANPATH_modshare'] = '/usr/local/share/man:1:/cineca/sysprod/pbs/default/man:1::1:/usr/share/man:1'
os.environ['_LMFILES__modshare'] = '/cineca/prod/opt/modulefiles/profiles/profile/base:1'
os.environ['LOADEDMODULES_modshare'] = 'profile/base:1'
os.environ['PATH'] = '/marconi/home/userexternal/pkumbhar/spack/bin:/cineca/bin:/usr/lib64/qt-3.3/bin:/cineca/sysprod/pbs/default/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/marconi/home/userexternal/pkumbhar/.local/bin:/marconi/home/userexternal/pkumbhar/bin'
os.environ['PATH_modshare'] = '/usr/sbin:1:/usr/bin:1:/cineca/sysprod/pbs/default/bin:1:/marconi/home/userexternal/pkumbhar/.local/bin:1:/marconi/home/userexternal/pkumbhar/bin:1:/cineca/bin:1:/usr/local/sbin:1:/usr/lib64/qt-3.3/bin:1:/usr/local/bin:1:/marconi/home/userexternal/pkumbhar/spack/bin:1'
os.environ['LD_LIBRARY_PATH'] = ''
del os.environ['LD_LIBRARY_PATH']
os.environ['CXX'] = ''
del os.environ['CXX']
os.environ['INTEL_HOME'] = ''
del os.environ['INTEL_HOME']
os.environ['INTEL_LICENSE_FILE'] = ''
del os.environ['INTEL_LICENSE_FILE']
os.environ['LIBPATH_modshare'] = ''
del os.environ['LIBPATH_modshare']
os.environ['F90'] = ''
del os.environ['F90']
os.environ['ITAC_2017_DIR'] = ''
del os.environ['ITAC_2017_DIR']
os.environ['FC'] = ''
del os.environ['FC']
os.environ['LD_LIBRARY_PATH_modshare'] = ''
del os.environ['LD_LIBRARY_PATH_modshare']
os.environ['F77'] = ''
del os.environ['F77']
os.environ['LIBPATH'] = ''
del os.environ['LIBPATH']
os.environ['CC'] = ''
del os.environ['CC']
os.environ['INSPECTOR_2017_DIR'] = ''
del os.environ['INSPECTOR_2017_DIR']
```

If I manually execute that unload command I get:

```
$ '/marconi/prod/opt/environment/module/3.2.10/none/modulecmd.tcl' 'python' 'unload' 'intel'
exec '/tmp/modulescript_34000_0'
```

On this [MARCONI system](http://www.hpc.cineca.it/news/marconi-new-cineca-supercomputer) I am not able use any modules. Any hints?

EDIT: updated full compiler spec.
> Another issue (may be related to #4667 ?)

IMO it would be best to report this as a separate issue (and if you feel it is related then include a pointer to here).

I don't know if this is causing the problem you mention in https://github.com/LLNL/spack/issues/5273#issuecomment-328363658, but I notice two things:

* Your compiler entry doesn't include a `spec`
* The modules for the compiler entry is `intel/pe-xe-2017--binary` - is it supposed to contain two dashes?
> IMO it would be best to report this as a separate issue 

ok, will do.

> Your compiler entry doesn't include a spec

updated full spec (Initially I copied just part of it)

> The modules for the compiler entry is intel/pe-xe-2017--binary - is it supposed to contain two dashes?

yes, all modules have two dashes:

```
petsc/3.7.5_complex--intelmpi--2017--binary
pnetcdf/1.7--intelmpi--2017--binary
....
```
Hi @alalazo I was wondering about your opinion on https://github.com/LLNL/spack/issues/5273#issuecomment-328248907 (namely that we shouldn't be generating module files for packages with `external-module`)
> namely that we shouldn't be generating module files for packages with external-module

@alalazo ? Wouldn't it better use/load existing modules? 
@scheibelp Sorry for the late reply, I lost this among a lot of other Github notifications. I can think of at least one case in which we still want to generate module files for externals: `lmod` + the external provides a virtual spec that is part of the hierarchy. If you don't have the module in place, you won't be able to access to anything that depends on it.


@pramodk Is this still an issue?
@alalazo : I tried latest develop now and updated [this comment](https://github.com/LLNL/spack/issues/5273#issuecomment-328363658). If you have suggestions / need any debug info, let me know. This is on Marconi system @ Cineca.
@pramodk This issue seems to me specific to Marconi, right? It's difficult to push this further without access to the system :smirk: 
yeah true, I am not actively working on marconi at the moment. If require we can close this for now. (when I get back to marconi, will try to get more debug info and then will reopen again)
While you're digging around in the same code, did you see anything suspicious that might cause #12662?

Resolving patch:
diff --git a/lib/spack/spack/util/module_cmd.py b/lib/spack/spack/util/module_cmd.py
--- a/lib/spack/spack/util/module_cmd.py
+++ b/lib/spack/spack/util/module_cmd.py
@@ -77,7 +77,7 @@ def load_module(mod):
     module('load', mod)
 
 
-def get_path_arg_from_module_line(line):
+def get_path_args_from_module_line(line):
     if '(' in line and ')' in line:
         # Determine which lua quote symbol is being used for the argument
         comma_index = line.index(',')
@@ -92,7 +92,9 @@ def get_path_arg_from_module_line(line):
         path_arg = words_and_symbols[-2]
     else:
         path_arg = line.split()[2]
-    return path_arg
+
+    paths = path_arg.split(':')
+    return paths
 
 
 def get_path_from_module(mod):
@@ -119,37 +121,68 @@ def get_path_from_module_contents(text, module_name):
         pkg_var_prefix = components[-2]
     tty.debug("Package directory variable prefix: " + pkg_var_prefix)
 
-    # If it sets the LD_LIBRARY_PATH or CRAY_LD_LIBRARY_PATH, use that
-    for line in text:
-        pattern = r'\W(CRAY_)?LD_LIBRARY_PATH'
-        if re.search(pattern, line):
-            path = get_path_arg_from_module_line(line)
-            return path[:path.find('/lib')]
+    path_occurrences = {}
 
-    # If it lists its package directory, return that
-    for line in text:
-        pattern = r'\W{0}_DIR'.format(pkg_var_prefix)
+    def strip_path(path, endings):
+        for ending in endings:
+            if path.endswith(ending):
+                return path[:-len(ending)]
+            if path.endswith(ending + '/'):
+                return path[:-(len(ending) + 1)]
+        return path
+
+    def match_pattern_and_strip(line, pattern, strip=[]):
         if re.search(pattern, line):
-            return get_path_arg_from_module_line(line)
+            paths = get_path_args_from_module_line(line)
+            for path in paths:
+                path = strip_path(path, strip)
+                path_occurrences[path] = path_occurrences.get(path, 0) + 1
+
+    def match_flag_and_strip(line, flag, strip=[]):
+        flag_idx = line.find(flag)
+        if flag_idx >= 0:
+            end = line.find(' ', flag_idx)
+            if end >= 0:
+                path = line[flag_idx + len(flag):end]
+            else:
+                path = line[flag_idx + len(flag):]
+            path = strip_path(path, strip)
+            path_occurrences[path] = path_occurrences.get(path, 0) + 1
+
+    lib_endings = ['/lib64', '/lib']
+    bin_endings = ['/bin']
+    man_endings = ['/share/man', '/man']
 
-    # If it lists a -rpath instruction, use that
     for line in text:
-        rpath = line.find('-rpath/')
-        if rpath >= 0:
-            return line[rpath + 6:line.find('/lib')]
+        # Check entries of LD_LIBRARY_PATH and CRAY_LD_LIBRARY_PATH
+        pattern = r'\W(CRAY_)?LD_LIBRARY_PATH'
+        match_pattern_and_strip(line, pattern, lib_endings)
 
-    # If it lists a -L instruction, use that
-    for line in text:
-        lib_paths = line.find('-L/')
-        if lib_paths >= 0:
-            return line[lib_paths + 2:line.find('/lib')]
+        # Check {name}_DIR entries
+        pattern = r'\W{0}_DIR'.format(pkg_var_prefix)
+        match_pattern_and_strip(line, pattern)
 
-    # If it sets the PATH, use it
-    for line in text:
+        # Check {name}_ROOT entries
+        pattern = r'\W{0}_ROOT'.format(pkg_var_prefix)
+        match_pattern_and_strip(line, pattern)
+
+        # Check entries that update the PATH variable
         pattern = r'\WPATH'
-        if re.search(pattern, line):
-            path = get_path_arg_from_module_line(line)
-            return path[:path.find('/bin')]
+        match_pattern_and_strip(line, pattern, bin_endings)
+
+        # Check entries that update the MANPATH variable
+        pattern = r'MANPATH'
+        match_pattern_and_strip(line, pattern, man_endings)
+
+        # Check entries that add a `-rpath` flag to a variable
+        match_flag_and_strip(line, '-rpath', lib_endings)
+
+        # Check entries that add a `-L` flag to a variable
+        match_flag_and_strip(line, '-L', lib_endings)
+
+    # Whichever path appeared most in the module, we assume is the correct path
+    if len(path_occurrences) > 0:
+        return max(path_occurrences.items(), key=lambda x: x[1])[0]
 
-    # Unable to find module path
+    # Unable to find path in module
     return None


Test patch:
diff --git a/lib/spack/spack/test/module_parsing.py b/lib/spack/spack/test/module_parsing.py
--- a/lib/spack/spack/test/module_parsing.py
+++ b/lib/spack/spack/test/module_parsing.py
@@ -10,7 +10,7 @@
 from spack.util.module_cmd import (
     module,
     get_path_from_module,
-    get_path_arg_from_module_line,
+    get_path_args_from_module_line,
     get_path_from_module_contents
 )
 
@@ -89,14 +89,23 @@ def test_get_path_from_module_contents():
 whatis("Version: 3.9.2")
 whatis("Category: Tools")
 whatis("URL: https://cmake.org/")
-prepend_path("PATH","/path/to/cmake-3.9.2/bin")
+prepend_path("LD_LIBRARY_PATH","/bad/path")
+prepend_path("PATH","/path/to/cmake-3.9.2/bin:/other/bad/path")
 prepend_path("MANPATH","/path/to/cmake/cmake-3.9.2/share/man")
+prepend_path("LD_LIBRARY_PATH","/path/to/cmake-3.9.2/lib64")
 """
     module_show_lines = module_show_output.split('\n')
+
+    # PATH and LD_LIBRARY_PATH outvote MANPATH and the other PATH and
+    # LD_LIBRARY_PATH entries
     assert (get_path_from_module_contents(module_show_lines, 'cmake-3.9.2') ==
             '/path/to/cmake-3.9.2')
 
 
+def test_get_path_from_empty_module():
+    assert get_path_from_module_contents('', 'test') is None
+
+
 def test_pkg_dir_from_module_name():
     module_show_lines = ['setenv FOO_BAR_DIR /path/to/foo-bar']
 
@@ -108,16 +117,25 @@ def test_pkg_dir_from_module_name():
 
 
 def test_get_argument_from_module_line():
-    lines = ['prepend-path LD_LIBRARY_PATH /lib/path',
-             'prepend-path  LD_LIBRARY_PATH  /lib/path',
-             "prepend_path('PATH' , '/lib/path')",
-             'prepend_path( "PATH" , "/lib/path" )',
-             'prepend_path("PATH",' + "'/lib/path')"]
+    simple_lines = ['prepend-path LD_LIBRARY_PATH /lib/path',
+                    'prepend-path  LD_LIBRARY_PATH  /lib/path',
+                    "prepend_path('PATH' , '/lib/path')",
+                    'prepend_path( "PATH" , "/lib/path" )',
+                    'prepend_path("PATH",' + "'/lib/path')"]
+
+    complex_lines = ['prepend-path LD_LIBRARY_PATH /lib/path:/pkg/path',
+                     'prepend-path  LD_LIBRARY_PATH  /lib/path:/pkg/path',
+                     "prepend_path('PATH' , '/lib/path:/pkg/path')",
+                     'prepend_path( "PATH" , "/lib/path:/pkg/path" )',
+                     'prepend_path("PATH",' + "'/lib/path:/pkg/path')"]
 
     bad_lines = ['prepend_path(PATH,/lib/path)',
                  'prepend-path (LD_LIBRARY_PATH) /lib/path']
 
-    assert all(get_path_arg_from_module_line(l) == '/lib/path' for l in lines)
+    assert all(get_path_args_from_module_line(l) == ['/lib/path']
+               for l in simple_lines)
+    assert all(get_path_args_from_module_line(l) == ['/lib/path', '/pkg/path']
+               for l in complex_lines)
     for bl in bad_lines:
         with pytest.raises(ValueError):
-            get_path_arg_from_module_line(bl)
+            get_path_args_from_module_line(bl)