Skip to content

[WIP] PythonPackage: RPATH link dependencies#4545

Closed
adamjstewart wants to merge 6 commits intospack:developfrom
adamjstewart:features/build-ext
Closed

[WIP] PythonPackage: RPATH link dependencies#4545
adamjstewart wants to merge 6 commits intospack:developfrom
adamjstewart:features/build-ext

Conversation

@adamjstewart
Copy link
Copy Markdown
Member

@adamjstewart adamjstewart commented Jun 19, 2017

See #4522 and #4521 for backstory.

Some Python packages depend on non-Python dependencies. For example, py-pillow depends on several imaging libraries. When building these Python packages, Python uses whatever compiler it was built with. Since we filter the compiler wrappers out of the Python installation, this means that we are not using Spack's compiler wrappers when installing Python packages, and hence we are not RPATHing dependencies.

Previously, we were building with:

$ python setup.py build
$ python setup.py install --prefix=...

Now, we build with:

$ python setup.py build_py
$ python setup.py build_ext --include-dirs=... --library-dirs=... --rpath=...
$ python setup.py build_clib
$ python setup.py build_scripts
$ python setup.py install --prefix=...

The build_ext phase allows us to explicitly declare what RPATH to use, solving the problem. Thanks to @mjwoods for the idea!

Additional changes included in this PR:

  • Added a missing build_scripts_args function
  • Default arguments like --prefix are added directly in the <phase> function
    • Previously, these arguments were added through <phase>_args. Overriding this function to try to add additional arguments would remove these default arguments
  • Don't run python setup.py test anymore
    • Even when a package implements it, the PyPI tarball rarely includes the test suite, and the tests usually fail
    • Instead, we now have test and install_test methods that can be overridden
  • extends implies type=('build', 'run') now
    • Previously, things like Python, R, and Perl were build/link/run dependencies, which doesn't really make much sense
    • You can now override the default type with extends('python', type=('build', 'link', 'run'))

This will likely take a while to test before it is safe to merge. I want to try building and activating every Python package in Spack before we decide to merge this. Who knows, this may even solve #3204 and numpy/numpy#8653.


def build_scripts_args(self, spec, prefix):
"""Arguments to pass to build_scripts."""
return []
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This phase was missing a <phase>_args function.

# because the package depends on py-setuptools. But the package doesn't
# actually build with `py-setuptools`, it just needs it at run-time.
# Until I can figure out how to query direct build dependencies only,
# override the default `install` method.
Copy link
Copy Markdown
Member Author

@adamjstewart adamjstewart Jun 23, 2017

Choose a reason for hiding this comment

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

Does anyone know how to tell if py-setuptools is a direct build dependency?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@adamjstewart: you can look in setup.py. If it's imported unconditionally and actually used, I consider it one. If it's conditionally imported (e.g. just for some options like building wheels) then you can look at how it's used to figure out if it's actually needed. For most spack use cases it's not needed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@tgamblin I mean in Spack world, not Python world. If you look at the install() method in PythonPackage, we add this flag for:

  1. packages named py-setuptools, or
  2. packages with a direct dependency on py-setuptools

But in the case of py-basemap, py-setuptools is a run-dependency only, not a build dependency. How do we check if its a direct build dependency, not just a direct dependency?

Copy link
Copy Markdown
Member

@tgamblin tgamblin Aug 21, 2017

Choose a reason for hiding this comment

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

'py-setuptools' in spec.dependencies_dict(deptype='build')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You want to look at dependencies_dict -- it gets you the immediate dependencies for a spec and allows filtering by deptype. There's dependencies_dict, dependents_dict, which get you dicts of specs keyed by name, and there are dependencies and dependents, which get you list of specs.

Currently these just fetch immediate dependencies, but I would like to make it easier to get different sets of dependencies based on relationship, e.g. it would be nice if you could get direct build dependencies plus their transitive run dependencies. Some regex-like syntax would work well there... e.g. spec.find_dependncies('br*'). I haven't thought through how the expression language would look for that.

@adamjstewart
Copy link
Copy Markdown
Member Author

Closing as I no longer have the time to work on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants