Repository: spack/spack

Issue:
Should the lmod package depend on tcl?
I'm new to Spack, this is as much a question about how Spack thinks as it is a question about the lmod package....

I'm working from a fairly minimal system image (Digital Ocean's CentOS 7 + the packages that LinuxBrew lists as prerequisites).

I just used spack to install _lmod_.  Along the way I discovered that _lmod_ requires _tclsh_.  I used spack to install _tcl_.  The _tcl_ package has a tclsh8.6 in it's bin, but
- w/out a module command there's no obvious way to get the _tcl_ package's `.../bin` on my path; and
- the _tcl_ package doesn't link `tclsh8.6` to `tclsh`.

I did both of these by hand so that I could make things work (I was working towards a working flake8 so that I could clean up my jdk PR), but clearly That's Not Right.  I'm trying to figure out what is the right way to handle this.

Perhaps tcl is considered a Spack prerequisite?  Is there a list of prerequisites?

Or would it be useful (is it possible?) for the lmod package to "depend_on" the tcl package if tclsh doesn't exist, and would satisfying that dependency (aka installing the _tcl_ package) set things up so that lmod's configure script would run successfully?



Discussion:
I can confirm that despite I didn't find mention of tcl in [the documentation](http://lmod.readthedocs.io/en/latest/030_installing.html#why-does-lmod-install-differently) of lmod, `configure` wants it to complete successfully. I would say that here a `depends_on('tcl')` is missing.

I just gave it a try and the simple this:

```
[throgg@flaky spack]$ git diff
diff --git a/var/spack/repos/builtin/packages/lmod/package.py b/var/spack/repos/builtin/packages/lmod/package.py
index efa235f..caa9ea1 100644
--- a/var/spack/repos/builtin/packages/lmod/package.py
+++ b/var/spack/repos/builtin/packages/lmod/package.py
@@ -44,6 +44,7 @@ class Lmod(Package):
     depends_on('lua@5.2:')
     depends_on('lua-luaposix', type=nolink)
     depends_on('lua-luafilesystem', type=nolink)
+    depends_on('tcl')

     parallel = False
```

is insufficient.

The generated log file says:

```
[...]
checking for ps... /usr/bin/ps
checking for expr... /usr/bin/expr
checking for basename... /usr/bin/basename
checking for git... /usr/bin/git
checking for less... /usr/bin/less
checking for sha1sum... /usr/bin/sha1sum
checking for tclsh... UNKNOWN

The tclsh program must be in your path. Quitting!

==> 'make' 'install'
make: *** No rule to make target `install'.  Stop.
```

Is there a way to get the tcl package's bin added to the build's PATH?

> Is there a way to get the tcl package's bin added to the build's PATH?

it actually should already be in the path during build as default dependency type is `build`+`link`, IIRC. You can check `spack-build.env` file in the build folder.

It might be a good idea to check the configure file and see what line looks for tclsh. If you can figure out exactly which filename it is looking for, then you can check to make sure Spack builds that file. If it's looking for `tclsh` and Spack builds `tclsh8.6`, you'll have to add a symlink via the tcl package.

@adamjstewart good point, Spack-bult `tcl` (at least on macOS) has `tclsh8.6` only.

@davydd -- checked the env file, tcl's bin is on PATH

It's definitely looking for `tclsh`, when I did it by hand I made a link myself.

I'll peek into the tcl package and either learn how to make the link or see if there's a configure option.

All good learning.  Thanks for the help!

{Home,Linux}brew have a command (`brew install -i package_name`) that grabs the tarball, unpacks it, and then plunks you into a shell with the environment set up just as it is during a non-interactive install.

Is there a way to do something similar in spack?

> I'll peek into the tcl package and either learn how to make the link or see if there's a configure option.

Check out the bzip2 package. You should be able to do something like:

``` python
with working_dir(prefix.bin):
    symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')
```

And put this at the end of tcl's install method.

> {Home,Linux}brew have a command (brew install -i package_name) that grabs the tarball, unpacks it, and then plunks you into a shell with the environment set up just as it is during a non-interactive install.
> 
> Is there a way to do something similar in spack?

@citibeth?

Thanks @adamjstewart!  I was heading in that general direction but was going to end up with something much less Pythonically graceful for pulling the version out of the existing scripts name.

Testing it now....

Ok, this lets _lmod_ build for me:

```
[throgg@flaky spack]$ git diff
diff --git a/var/spack/repos/builtin/packages/lmod/package.py b/var/spack/repos/builtin/packages/lmod/package.py
index efa235f..caa9ea1 100644
--- a/var/spack/repos/builtin/packages/lmod/package.py
+++ b/var/spack/repos/builtin/packages/lmod/package.py
@@ -44,6 +44,7 @@ class Lmod(Package):
     depends_on('lua@5.2:')
     depends_on('lua-luaposix', type=nolink)
     depends_on('lua-luafilesystem', type=nolink)
+    depends_on('tcl')

     parallel = False

diff --git a/var/spack/repos/builtin/packages/tcl/package.py b/var/spack/repos/builtin/packages/tcl/package.py
index a4d8b51..a3294d8 100644
--- a/var/spack/repos/builtin/packages/tcl/package.py
+++ b/var/spack/repos/builtin/packages/tcl/package.py
@@ -49,3 +49,5 @@ class Tcl(Package):
             configure("--prefix=%s" % prefix)
             make()
             make("install")
+        with working_dir(prefix.bin):
+            symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')
[throgg@flaky spack]$
```

I think this will be a change for folks who were previously using the system's tclsh.

Should (how should) I conditionalize it?

No need to conditionalize it, I think this is a perfectly fine change. Go ahead and submit a PR.


Resolving patch:
diff --git a/var/spack/repos/builtin/packages/lmod/package.py b/var/spack/repos/builtin/packages/lmod/package.py
--- a/var/spack/repos/builtin/packages/lmod/package.py
+++ b/var/spack/repos/builtin/packages/lmod/package.py
@@ -23,6 +23,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
 from spack import *
+from glob import glob
 
 
 class Lmod(Package):
@@ -44,6 +45,7 @@ class Lmod(Package):
     depends_on('lua@5.2:')
     depends_on('lua-luaposix', type=nolink)
     depends_on('lua-luafilesystem', type=nolink)
+    depends_on('tcl', type=nolink)
 
     parallel = False
 
@@ -53,6 +55,16 @@ def setup_environment(self, spack_env, run_env):
         spack_env.append_path('LUA_PATH', stage_lua_path.format(
             version=self.version), separator=';')
 
+    patch('fix_tclsh_paths.patch')
+
+    def patch(self):
+        """The tcl scripts should use the tclsh that was discovered
+           by the configure script.  Touch up their #! lines so that the
+           sed in the Makefile's install step has something to work on.
+           Requires the change in the associated patch file.fg"""
+        for tclscript in glob('src/*.tcl'):
+            filter_file(r'^#!.*tclsh', '#!@path_to_tclsh@', tclscript)
+
     def install(self, spec, prefix):
         configure('--prefix=%s' % prefix)
         make('install')
diff --git a/var/spack/repos/builtin/packages/tcl/package.py b/var/spack/repos/builtin/packages/tcl/package.py
--- a/var/spack/repos/builtin/packages/tcl/package.py
+++ b/var/spack/repos/builtin/packages/tcl/package.py
@@ -57,3 +57,5 @@ def install(self, spec, prefix):
             configure("--prefix={0}".format(prefix))
             make()
             make("install")
+        with working_dir(prefix.bin):
+            symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')


Test patch: