Python command, libraries, and headers#3367
Conversation
lib/spack/llnl/util/filesystem.py
Outdated
|
|
||
| .. code-block:: python | ||
|
|
||
| >>> find('/usr/local/bin', 'python', recurse=False) |
There was a problem hiding this comment.
I'm honestly considering just converting this to a wrapper around the system find. Thoughts? Either way, I think this would be a very useful command to have.
| def __init__(self, libraries): | ||
| self.libraries = list(libraries) | ||
| def __init__(self, files): | ||
| self.files = list(dedupe(files)) |
There was a problem hiding this comment.
@alalazo One change I made was to remove duplicates from the list when creating the object. Is there any reason this would be a problem?
| """Returns an iterable object containing a list of full paths to | ||
| headers if found. | ||
|
|
||
| Accepts any glob characters accepted by fnmatch: |
There was a problem hiding this comment.
New features, yay! This allows you to search for headers like *.h or libraries like *.so.
| elif os.path.exists(os.path.join(self.prefix.bin, 'python')): | ||
| exe = 'python' | ||
| else: | ||
| msg = 'Cannot locate python executable in {0}' |
There was a problem hiding this comment.
By including the search directory in the error message, I'm hoping that users who erroneously add /usr/bin/ to their packages.yaml will see that they actually need to use /usr.
| if headers: | ||
| return headers | ||
|
|
||
| msg = 'Cannot locate python headers in {0}' |
There was a problem hiding this comment.
This error message will be helpful for users who use an externally installed system python but don't have the development headers installed.
davydden
left a comment
There was a problem hiding this comment.
looks very nice! Thanks for extensive tests of the new HeaderList class. When the PR will be ready to merge, i can try building boost+python on Sierra with clang.
|
While the infrastructure in this PR looks useful, I suspect it's not really the right approach for Python. Python already has ways to tell you about its configuration (the
https://bugs.launchpad.net/python-uinput/+bug/1032773 Here's an example of where I use |
citibeth
left a comment
There was a problem hiding this comment.
Please try using Python's distutils/sysconfig before we resort to digging around in distros.
|
I'll take a look next week and see what I can do. Thanks @citibeth! |
| 'PYTHON_DIR': self.spec['python'].prefix, | ||
| 'PYTHON_BIN_DIR': self.spec['python'].prefix.bin, | ||
| 'PYTHON_DIR': self.spec['python'].home, | ||
| 'PYTHON_BIN_DIR': self.spec['python'].home.bin), |
There was a problem hiding this comment.
home.bin),
Has an extra stray ) that my python doesn't like.
| # Need this to allow python build to find the Python installation. | ||
| env['PYTHONHOME'], env['PYTHONPATH'] = prefix, prefix | ||
| env['MACOSX_DEPLOYMENT_TARGET'] = '10.6' | ||
| spack_env['PYTHONHOME'] = prefix |
There was a problem hiding this comment.
Shouldn't this (and the lines below) be:
spack_env.set('PYTHONHOME', prefix)?
There was a problem hiding this comment.
I wonder if we should allow both modes. Fixed.
|
So, to chime in, not all Python 3.x builds will have *m. This is an ABI flag, defined in PEP 3149 as part of the aftermath of PEP 384. The most common POSIX-y ABI flags we see are: d: built with Py_DEBUG set I've seen in dev environments: and for modules the entire string may bloat up to include interpreters and platform triplets. |
| env['MACOSX_DEPLOYMENT_TARGET'] = '10.6' | ||
| spack_env.set('PYTHONHOME', prefix) | ||
| spack_env.set('PYTHONPATH', prefix) | ||
| spack_env.set('MACOSX_DEPLOYMENT_TARGET', '10.6') |
There was a problem hiding this comment.
There is a way to get this number for a specific platform since 2.3, apparently:
from platform import mac_ver
mac_ver()[0]
It seems to return an empty string on other platforms, so it should be safe to use.
There was a problem hiding this comment.
I would assume so. Python's build is…unique to say the least :) .
|
|
||
| if '+python' in spec: | ||
| options.append('--with-python=%s' % python_exe) | ||
| options.append('--with-python=%s' % spec['python'].executable) |
There was a problem hiding this comment.
I'm getting an error here saying 'executable' is not defined.
I am using an external python here. Do these attributes get defined in that case?
There was a problem hiding this comment.
Looks the problem also exists for Spack-built Python. Apparently spec['python'] and spec['python'].package are very different. I think I have a fix. I'll push it out after some more testing.
There was a problem hiding this comment.
FYI: spec['python'] is a Spec, which is basically the sub-DAG. spec['python'].package is an instance of Package, which is the build system. If you want a decent way to think about the difference, here you go:
- Think of the
Specas a descriptor -- it's an arbitrary DAG describing a build configuration. You can instantiate a Spec forfoo^bar+baz%intelwithout knowing anything about packagesFooorBar. You cannot concretize or actually build thatSpecwithout aPackagecalledFooand another calledBar. - The
Packagedoes two things: at the class level, it gives you metadata used to concretizeSpecs(depends_on(),variant(), etc.). An instance ofPackageneeds to be constructed with aSpec, and it provides you with the build system for that package and its dependencies.
We could probably separate (2) out, but IMHO the metaphor of classes-as-package-definitions is a nice one, and it makes it easier for packagers to think about how they can code things up in Python. We stole that from Homebrew.
|
|
||
| cmd = 'from distutils.sysconfig import get_config_var; ' | ||
| cmd += self.print_string("get_config_var('{0}')".format(key)) | ||
|
|
There was a problem hiding this comment.
I'm getting an error here about 4 rather than 1 argument.
It would seem that the line is missing a pair of brackets. But since it's used elsewhere, it might be something less benign, due to the fact that I'm trying to install boost +python with python an external package?
There was a problem hiding this comment.
Looks like this problem exists for Spack-built Python as well. The problem was that I forgot to make self.python a @property. Fixed.
|
|
||
| if '+python' in spec: | ||
| options.append('--with-python=%s' % python_exe) | ||
| options.append('--with-python=%s' % spec['python'].executable) |
There was a problem hiding this comment.
When installing with python as an external package, spack complains 'executable' is not defined in 'spec' of type 'Spec'.
| descriptor `__get__` method | ||
| """ | ||
| name = 'lib' + spec.name | ||
| shared = '+shared' in spec |
There was a problem hiding this comment.
@alalazo Previously, any package without a shared variant would search for static libraries. I changed this behavior below.
There was a problem hiding this comment.
yes, indeed. This fixes the issue I encountered as well.
| descriptor `__get__` method | ||
| """ | ||
| return '-I' + spec.prefix.include | ||
| name = 'lib' + spec.name |
There was a problem hiding this comment.
I wonder if we should just search for all libraries instead of just lib{name}. My default header handler searches for all *.h files.
| assert len(libraries) == 1 | ||
|
|
||
| cppflags_expected = '-I' + spec.prefix.include | ||
| assert spec['zmpi'].cppflags == cppflags_expected |
There was a problem hiding this comment.
spec['zmpi'].headers.cpp_flags wasn't working for this test. Possibly because it's a fake installation and doesn't actually contain any header files.
There was a problem hiding this comment.
@adamjstewart I would rather modify the mocking if it needs to look "more real" than removing a test.
There was a problem hiding this comment.
How/where would I do that?
There was a problem hiding this comment.
@adamjstewart: You could change what install --fake puts in the target directory to include a dummy header (it contains a dummy library at the moment -- not sure about the header).
These are called "abiflags" and there are multiple ones available. |
|
Thanks for the testing everyone! I think I've resolved most of the bugs at this point. I was able to install |
|
I've just checks boost+python with an external python on a mac (installed the standard mac packager homebrew). Unfortunately, 'LIBDIR': '/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib' so LDLIBRARY is not just the filename ('Python' is a symlink to a .dylib), so the current code fails to find the python library. One solution might be to check if 'PYTHONFRAMEWORKPREFIX': '/usr/local/opt/python/Frameworks' is empty or not, and then check whether PYTHONFRAMEWORKPREFIX/LDLIBRARY is a thing: isfile(join(get_config_vars("PYTHONFRAMEWORKPREFIX")[0], get_config_vars("LDLIBRARY")[0])) |
|
Ugh, it sounds like macOS Python is drastically different from Linux Python. I'll take a look. |
dd139be to
c71d276
Compare
|
Did some comparisons across Anaconda, Homebrew, and system installations of Python 2 and 3: Everything looks correct except |
c71d276 to
cd6b18e
Compare
|
@mdavezac Can you try this again? |
ecc96ba to
490893f
Compare
|
Ping @tgamblin 😄 |
|
@adamjstewart: you can also |
|
Is there any benefit to that? Do you think we'll have problems with memory usage on Python 2? |
For small stuff, no. But |
| def _find_recursive(root, search_files): | ||
| found_files = [] | ||
|
|
||
| for path, _, list_files in os.walk(root): |
There was a problem hiding this comment.
@adamjstewart I think here you got the order of the for loops wrong: if you start walking the directory tree first and then search each file in a single sub-directory you may scramble the original order of search_files.
There was a problem hiding this comment.
I think you're completely right, good spot! To be fair, the original method I stole this from did it this way too. I don't think we ever noticed because most of the time the libraries are all in the same directory.
There was a problem hiding this comment.
I think you're completely right, good spot! To be fair, the original method I stole this from did it this way too
Hey, don't underestimate the fact that I was using a dictionary for that. I just didn't want to traverse the directories multiple times, but I recorded what I found there and reconstructed it in order. At least I think I did it 😄
Do you want to submit a PR? Or should I take a stab at it?
There was a problem hiding this comment.
I'll let you handle it, should only be a couple lines to change.
… output) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
… output) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
… output) (#72) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
… output) (#72) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
## Motivation Python installations are both important and unfortunately inconsistent. Depending on the Python version, OS, and the strength of the Earth's magnetic field when it was installed, the name of the Python executable, directory containing its libraries, library names, and the directory containing its headers can vary drastically. I originally got into this mess with spack#3274, where I discovered that Boost could not be built with Python 3 because the executable is called `python3` and we were telling it to use `python`. I got deeper into this mess when I started hacking on spack#3140, where I discovered just how difficult it is to find the location and name of the Python libraries and headers. Currently, half of the packages that depend on Python and need to know this information jump through hoops to determine the correct information. The other half are hard-coded to use `python`, `spec['python'].prefix.lib`, and `spec['python'].prefix.include`. Obviously, none of these packages would work for Python 3, and there's no reason to duplicate the effort. The Python package itself should contain all of the information necessary to use it properly. This is in line with the recent work by @alalazo and @davydden with respect to `spec['blas'].libs` and friends. ## Prefix For most packages in Spack, we assume that the installation directory is `spec['python'].prefix`. This generally works for anything installed with Spack, but gets complicated when we include external packages. Python is a commonly used external package (it needs to be installed just to run Spack). If it was installed with Homebrew, `which python` would return `/usr/local/bin/python`, and most users would erroneously assume that `/usr/local` is the installation directory. If you peruse through spack#2173, you'll immediately see why this is not the case. Homebrew actually installs Python in `/usr/local/Cellar/python/2.7.12_2` and symlinks the executable to `/usr/local/bin/python`. `PYTHONHOME` (and presumably most things that need to know where Python is installed) needs to be set to the actual installation directory, not `/usr/local`. Normally I would say, "sounds like user error, make sure to use the real installation directory in your `packages.yaml`". But I think we can make a special case for Python. That's what we decided in spack#2173 anyway. If we change our minds, I would be more than happy to simplify things. To solve this problem, I created a `spec['python'].home` attribute that works the same way as `spec['python'].prefix` but queries Python to figure out where it was actually installed. @tgamblin Is there any way to overwrite `spec['python'].prefix`? I think it's currently immutable. ## Command In general, Python 2 comes with both `python` and `python2` commands, while Python 3 only comes with a `python3` command. But this is up to the OS developers. For example, `/usr/bin/python` on Gentoo is actually Python 3. Worse yet, if someone is using an externally installed Python, all 3 commands may exist in the same directory! Here's what I'm thinking: If the spec is for Python 3, try searching for the `python3` command. If the spec is for Python 2, try searching for the `python2` command. If neither are found, try searching for the `python` command. ## Libraries Spack installs Python libraries in `spec['python'].prefix.lib`. Except on openSUSE 13, where it installs to `spec['python'].prefix.lib64` (see spack#2295 and spack#2253). On my CentOS 6 machine, the Python libraries are installed in `/usr/lib64`. Both need to work. The libraries themselves change name depending on OS and Python version. For Python 2.7 on macOS, I'm seeing: ``` lib/libpython2.7.dylib ``` For Python 3.6 on CentOS 6, I'm seeing: ``` lib/libpython3.so lib/libpython3.6m.so.1.0 lib/libpython3.6m.so -> lib/libpython3.6m.so.1.0 ``` Notice the `m` after the version number. Yeah, that's a thing. ## Headers In Python 2.7, I'm seeing: ``` include/python2.7/pyconfig.h ``` In Python 3.6, I'm seeing: ``` include/python3.6m/pyconfig.h ``` It looks like all Python 3 installations have this `m`. Tested with Python 3.2 and 3.6 on macOS and CentOS 6 Spack has really nice support for libraries (`find_libraries` and `LibraryList`), but nothing for headers. Fixed.
… output) (spack#4156) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
## Motivation Python installations are both important and unfortunately inconsistent. Depending on the Python version, OS, and the strength of the Earth's magnetic field when it was installed, the name of the Python executable, directory containing its libraries, library names, and the directory containing its headers can vary drastically. I originally got into this mess with spack#3274, where I discovered that Boost could not be built with Python 3 because the executable is called `python3` and we were telling it to use `python`. I got deeper into this mess when I started hacking on spack#3140, where I discovered just how difficult it is to find the location and name of the Python libraries and headers. Currently, half of the packages that depend on Python and need to know this information jump through hoops to determine the correct information. The other half are hard-coded to use `python`, `spec['python'].prefix.lib`, and `spec['python'].prefix.include`. Obviously, none of these packages would work for Python 3, and there's no reason to duplicate the effort. The Python package itself should contain all of the information necessary to use it properly. This is in line with the recent work by @alalazo and @davydden with respect to `spec['blas'].libs` and friends. ## Prefix For most packages in Spack, we assume that the installation directory is `spec['python'].prefix`. This generally works for anything installed with Spack, but gets complicated when we include external packages. Python is a commonly used external package (it needs to be installed just to run Spack). If it was installed with Homebrew, `which python` would return `/usr/local/bin/python`, and most users would erroneously assume that `/usr/local` is the installation directory. If you peruse through spack#2173, you'll immediately see why this is not the case. Homebrew actually installs Python in `/usr/local/Cellar/python/2.7.12_2` and symlinks the executable to `/usr/local/bin/python`. `PYTHONHOME` (and presumably most things that need to know where Python is installed) needs to be set to the actual installation directory, not `/usr/local`. Normally I would say, "sounds like user error, make sure to use the real installation directory in your `packages.yaml`". But I think we can make a special case for Python. That's what we decided in spack#2173 anyway. If we change our minds, I would be more than happy to simplify things. To solve this problem, I created a `spec['python'].home` attribute that works the same way as `spec['python'].prefix` but queries Python to figure out where it was actually installed. @tgamblin Is there any way to overwrite `spec['python'].prefix`? I think it's currently immutable. ## Command In general, Python 2 comes with both `python` and `python2` commands, while Python 3 only comes with a `python3` command. But this is up to the OS developers. For example, `/usr/bin/python` on Gentoo is actually Python 3. Worse yet, if someone is using an externally installed Python, all 3 commands may exist in the same directory! Here's what I'm thinking: If the spec is for Python 3, try searching for the `python3` command. If the spec is for Python 2, try searching for the `python2` command. If neither are found, try searching for the `python` command. ## Libraries Spack installs Python libraries in `spec['python'].prefix.lib`. Except on openSUSE 13, where it installs to `spec['python'].prefix.lib64` (see spack#2295 and spack#2253). On my CentOS 6 machine, the Python libraries are installed in `/usr/lib64`. Both need to work. The libraries themselves change name depending on OS and Python version. For Python 2.7 on macOS, I'm seeing: ``` lib/libpython2.7.dylib ``` For Python 3.6 on CentOS 6, I'm seeing: ``` lib/libpython3.so lib/libpython3.6m.so.1.0 lib/libpython3.6m.so -> lib/libpython3.6m.so.1.0 ``` Notice the `m` after the version number. Yeah, that's a thing. ## Headers In Python 2.7, I'm seeing: ``` include/python2.7/pyconfig.h ``` In Python 3.6, I'm seeing: ``` include/python3.6m/pyconfig.h ``` It looks like all Python 3 installations have this `m`. Tested with Python 3.2 and 3.6 on macOS and CentOS 6 Spack has really nice support for libraries (`find_libraries` and `LibraryList`), but nothing for headers. Fixed.
… output) (spack#4156) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
## Motivation Python installations are both important and unfortunately inconsistent. Depending on the Python version, OS, and the strength of the Earth's magnetic field when it was installed, the name of the Python executable, directory containing its libraries, library names, and the directory containing its headers can vary drastically. I originally got into this mess with spack#3274, where I discovered that Boost could not be built with Python 3 because the executable is called `python3` and we were telling it to use `python`. I got deeper into this mess when I started hacking on spack#3140, where I discovered just how difficult it is to find the location and name of the Python libraries and headers. Currently, half of the packages that depend on Python and need to know this information jump through hoops to determine the correct information. The other half are hard-coded to use `python`, `spec['python'].prefix.lib`, and `spec['python'].prefix.include`. Obviously, none of these packages would work for Python 3, and there's no reason to duplicate the effort. The Python package itself should contain all of the information necessary to use it properly. This is in line with the recent work by @alalazo and @davydden with respect to `spec['blas'].libs` and friends. ## Prefix For most packages in Spack, we assume that the installation directory is `spec['python'].prefix`. This generally works for anything installed with Spack, but gets complicated when we include external packages. Python is a commonly used external package (it needs to be installed just to run Spack). If it was installed with Homebrew, `which python` would return `/usr/local/bin/python`, and most users would erroneously assume that `/usr/local` is the installation directory. If you peruse through spack#2173, you'll immediately see why this is not the case. Homebrew actually installs Python in `/usr/local/Cellar/python/2.7.12_2` and symlinks the executable to `/usr/local/bin/python`. `PYTHONHOME` (and presumably most things that need to know where Python is installed) needs to be set to the actual installation directory, not `/usr/local`. Normally I would say, "sounds like user error, make sure to use the real installation directory in your `packages.yaml`". But I think we can make a special case for Python. That's what we decided in spack#2173 anyway. If we change our minds, I would be more than happy to simplify things. To solve this problem, I created a `spec['python'].home` attribute that works the same way as `spec['python'].prefix` but queries Python to figure out where it was actually installed. @tgamblin Is there any way to overwrite `spec['python'].prefix`? I think it's currently immutable. ## Command In general, Python 2 comes with both `python` and `python2` commands, while Python 3 only comes with a `python3` command. But this is up to the OS developers. For example, `/usr/bin/python` on Gentoo is actually Python 3. Worse yet, if someone is using an externally installed Python, all 3 commands may exist in the same directory! Here's what I'm thinking: If the spec is for Python 3, try searching for the `python3` command. If the spec is for Python 2, try searching for the `python2` command. If neither are found, try searching for the `python` command. ## Libraries Spack installs Python libraries in `spec['python'].prefix.lib`. Except on openSUSE 13, where it installs to `spec['python'].prefix.lib64` (see spack#2295 and spack#2253). On my CentOS 6 machine, the Python libraries are installed in `/usr/lib64`. Both need to work. The libraries themselves change name depending on OS and Python version. For Python 2.7 on macOS, I'm seeing: ``` lib/libpython2.7.dylib ``` For Python 3.6 on CentOS 6, I'm seeing: ``` lib/libpython3.so lib/libpython3.6m.so.1.0 lib/libpython3.6m.so -> lib/libpython3.6m.so.1.0 ``` Notice the `m` after the version number. Yeah, that's a thing. ## Headers In Python 2.7, I'm seeing: ``` include/python2.7/pyconfig.h ``` In Python 3.6, I'm seeing: ``` include/python3.6m/pyconfig.h ``` It looks like all Python 3 installations have this `m`. Tested with Python 3.2 and 3.6 on macOS and CentOS 6 Spack has really nice support for libraries (`find_libraries` and `LibraryList`), but nothing for headers. Fixed.
… output) (spack#4156) PR spack#3367 inadvertently changed the semantics of _find_recursive and _find_non_recursive so that the returned list are not ordered as the input search list. This commit restores the original semantic, and adds tests to verify it.
This PR includes the following changes: * Added JDK 10 * Changed the JDK version numbers according to the consensus reached in #2284 * Added spec['java'].home and spec['java'].libs, similar to #3367 (JDK and IcedTea) * Added a check to prevent people from installing JDK on macOS * Set CLASSPATH for packages depending on Java (JDK and IcedTea) * Add TODO for extending virtual packages (not currently possible) * Add TODO for adding Java dependents to views * Add TODO for packages which extend multiple packages (e.g. Java and Python)
This PR includes the following changes: * Added JDK 10 * Changed the JDK version numbers according to the consensus reached in spack#2284 * Added spec['java'].home and spec['java'].libs, similar to spack#3367 (JDK and IcedTea) * Added a check to prevent people from installing JDK on macOS * Set CLASSPATH for packages depending on Java (JDK and IcedTea) * Add TODO for extending virtual packages (not currently possible) * Add TODO for adding Java dependents to views * Add TODO for packages which extend multiple packages (e.g. Java and Python)
This PR includes the following changes: * Added JDK 10 * Changed the JDK version numbers according to the consensus reached in spack#2284 * Added spec['java'].home and spec['java'].libs, similar to spack#3367 (JDK and IcedTea) * Added a check to prevent people from installing JDK on macOS * Set CLASSPATH for packages depending on Java (JDK and IcedTea) * Add TODO for extending virtual packages (not currently possible) * Add TODO for adding Java dependents to views * Add TODO for packages which extend multiple packages (e.g. Java and Python)
This PR includes the following changes: * Added JDK 10 * Changed the JDK version numbers according to the consensus reached in spack#2284 * Added spec['java'].home and spec['java'].libs, similar to spack#3367 (JDK and IcedTea) * Added a check to prevent people from installing JDK on macOS * Set CLASSPATH for packages depending on Java (JDK and IcedTea) * Add TODO for extending virtual packages (not currently possible) * Add TODO for adding Java dependents to views * Add TODO for packages which extend multiple packages (e.g. Java and Python)
Fixes #3478.
Fixes #3594.
Fixes #4051.
Motivation
Python installations are both important and unfortunately inconsistent. Depending on the Python version, OS, and the strength of the Earth's magnetic field when it was installed, the name of the Python executable, directory containing its libraries, library names, and the directory containing its headers can vary drastically.
I originally got into this mess with #3274, where I discovered that Boost could not be built with Python 3 because the executable is called
python3and we were telling it to usepython. I got deeper into this mess when I started hacking on #3140, where I discovered just how difficult it is to find the location and name of the Python libraries and headers.Currently, half of the packages that depend on Python and need to know this information jump through hoops to determine the correct information. The other half are hard-coded to use
python,spec['python'].prefix.lib, andspec['python'].prefix.include. Obviously, none of these packages would work for Python 3, and there's no reason to duplicate the effort. The Python package itself should contain all of the information necessary to use it properly. This is in line with the recent work by @alalazo and @davydden with respect tospec['blas'].libsand friends.Prefix
For most packages in Spack, we assume that the installation directory is
spec['python'].prefix. This generally works for anything installed with Spack, but gets complicated when we include external packages. Python is a commonly used external package (it needs to be installed just to run Spack). If it was installed with Homebrew,which pythonwould return/usr/local/bin/python, and most users would erroneously assume that/usr/localis the installation directory. If you peruse through #2173, you'll immediately see why this is not the case. Homebrew actually installs Python in/usr/local/Cellar/python/2.7.12_2and symlinks the executable to/usr/local/bin/python.PYTHONHOME(and presumably most things that need to know where Python is installed) needs to be set to the actual installation directory, not/usr/local.Normally I would say, "sounds like user error, make sure to use the real installation directory in your
packages.yaml". But I think we can make a special case for Python. That's what we decided in #2173 anyway. If we change our minds, I would be more than happy to simplify things.To solve this problem, I created a
spec['python'].homeattribute that works the same way asspec['python'].prefixbut queries Python to figure out where it was actually installed. @tgamblin Is there any way to overwritespec['python'].prefix? I think it's currently immutable.Command
In general, Python 2 comes with both
pythonandpython2commands, while Python 3 only comes with apython3command. But this is up to the OS developers. For example,/usr/bin/pythonon Gentoo is actually Python 3. Worse yet, if someone is using an externally installed Python, all 3 commands may exist in the same directory! Here's what I'm thinking:If the spec is for Python 3, try searching for the
python3command.If the spec is for Python 2, try searching for the
python2command.If neither are found, try searching for the
pythoncommand.Libraries
Spack installs Python libraries in
spec['python'].prefix.lib. Except on openSUSE 13, where it installs tospec['python'].prefix.lib64(see #2295 and #2253). On my CentOS 6 machine, the Python libraries are installed in/usr/lib64. Both need to work.The libraries themselves change name depending on OS and Python version. For Python 2.7 on macOS, I'm seeing:
For Python 3.6 on CentOS 6, I'm seeing:
Notice the
mafter the version number. Yeah, that's a thing.Headers
In Python 2.7, I'm seeing:
In Python 3.6, I'm seeing:
It looks like all Python 3 installations have this
m. Tested with Python 3.2 and 3.6 on macOS and CentOS 6Spack has really nice support for libraries (
find_librariesandLibraryList), but nothing for headers. Fixed.Reviewing
This is obviously a big change, and will need thorough testing. I'm looking at the following people for reviews:
@alalazo @davydden I believe you did most of the existing work on
LibraryListandfind_libraries. Can you make sure my header-equivalents look solid?@citibeth You're one of the few Spack users who makes heavy use of Python 3. Can you check that things work?
@BarrySmith You went through hell to get Spack working for your Homebrew-installed Python. Can you confirm that my changes still work the way you need?
@mdavezac You got me into this mess. Can you test Boost for me?