-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reworking of lapack_shared_libs
and similar properties
#1682
Reworking of lapack_shared_libs
and similar properties
#1682
Conversation
from llnl.util.filesystem import LibraryList | ||
|
||
|
||
class LibraryListTest(unittest.TestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davydden Can you take a look at this test file and tell me if there are other operations you would like to perform on a list of libraries ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, will have a look tomorrow...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as far as i can tell,
- get list of names with defined separator, i.e.
foo bar baz
- get list of directories where libraries are (i.e.
/path/to/openblas/lib
) - complete link flags
-L/path/to/dir -lfoo -lbar -lbaz
- list of full paths with separator, i.e.
path/to/libfoo.so path/to/libbar.so
Looks like this should be enough.
there are two functions in the utilities |
self.libraries = list(libraries) | ||
|
||
@property | ||
def directories(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
donno what's the convention, but maybe one-line doc-string for properties? Especially for things like libnames
vs names
.
Looks good! |
@davydden Thanks for the thorough review! I'll start working on the PR + cleaning and documenting the code.I'll come back to you when all this will be ready for a test-drive 😄 |
]) | ||
options.extend([ | ||
'--with-blas={0}'.format( | ||
' '.join(spec['blas'].blas_libs.ld_flags) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before anybody says anything : since ' '.join(ld_flags)
seems a common idiom I'll modify the PR to avoid having to write the join in the package 😄
fce956b
to
b27a904
Compare
def blas_libs(self): | ||
shared = True if '+shared' in self.spec else False | ||
suffix = dso_suffix if '+shared' in self.spec else 'a' | ||
mkl_integer = ['libmkl_intel_lp64'] if '+ilp64' in self.spec else ['libmkl_intel_ilp64'] # NOQA: ignore=E501 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ~ilp64
lapack_shared_libs
and similar propertieslapack_shared_libs
and similar properties
@tgamblin @adamjstewart ready to be reviewed |
@alalazo is it rebased on top of |
@davydden Yes, it should be |
fix : failing unit tests due to missing `self`
@adamjstewart I would do it in another PR, as it requires some thinking on the searching logic |
39df558
to
be14686
Compare
@KineticTheory: if this does not clobber your changes from #1539, I think it's ready to merge. Can you take a look? |
This PR looks pretty good. There's only a couple of things I think it's missing. I would like |
@adamjstewart let's get it merged and then fix minor issues in follow up PRs. |
NOTE: this is not a request for changes. This is a proposal for how this PR should evolve because I think it's heading in the right direction and it solves a problem that other packages have. One thing I thought about when looking at this PR: I don't really like it that some dependents still search for their dependencies libraries, though I realize that it can be necessary. Basically there are two guiding principles here:
(2) breaks down for external packages, which Spack didn't install and which may even be laid out differently than Spack would lay them out (e.g. a install of boost might have al the weird lib suffixes that boost supports, and I think Spack wouldn't currently know what to do with that). Even better is that This PR follows both of these principles for I think this PR makes it clearer to me what a good convention for passing args among packages in a build should look like. You want to ask the package for a property, and the package needs to know a) the property name and b) the I guess the question is whether this should be a convention or a more formal interface. The convention currently looks like: spec['blas'].blas_libs
spec['lapack'].lapack_libs Slightly annoying things about it:
So, think we could have a convention like this: def provider_property(function):
"""Decorator for provider properties that get info from dependencies."""
def __init__(self, name):
self.name = name
def __call__(self, provider):
"""Get provider-specific property if available, or default to generic property."""
specific = provider.replace('-', '_') + '_' + self.name
dep = spec[provider]
if hasattr(dep, specific):
return getattr(dep, specific)
else:
return getattr(dep, self.name) # default to generic attribute
class Spec(object):
...
libs = provider_property('libs')
includes = provider_property('includes') Now the interface looks like this: spec.libs('blas')
spec.libs('lapack') And you've got a convention for properties to add to packages ( class Package(object):
...
def libs(self):
# requiring installation allows us to be more generic b/c we can search,
# but it does restrict when you can call the method.
assert(self.installed)
return find_libraries(... something that returns all the libs in `lib` or `lib64`...) And packages that need to can add things like I guess the question is whether the interface above is so much better than the simple convention we've got that it's worthwhile. The current convention is not so bad. I think it boils down which is simpler to document and teach to package authors. The other question is whether this convention is worthwhile for non-virtuals. Sometimes the client needs to be specific about which lib names it needs, in which case find_libraries seems like the right thing to do. What do you all think? |
one have to do that because a single package can provide different virtual packages (e.g. mkl provides blas and lapack and scalapack). Would the convention you suggested work here as well?
i would say for most packages the library names are simple ( So i would not adopt this approach to every package, but only to a few virtuals ( What should be systematically addressed is |
@tgamblin p.s. maybe you copy-paste your comment into a separate issue to continue the discussion? |
@alalazo @tgamblin I just updated to the latest develop and now I'm seeing infinite error messages:
If I checkout the commit before this PR was merged, everything works fine. There must be some infinite recursion going on here. |
To reproduce the bug, just try installing any package. Even ones that don't depend on blas/lapack/etc. Maybe a getattribute problem? |
# This line is to avoid infinite recursion in case package is | ||
# not present among self attributes | ||
package = super(Spec, self).__getattribute__('package') | ||
return getattr(package, item) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've confirmed that these changes caused the bug I'm seeing. When I comment this function out, Spack works again. What was this added for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today I succeeded installing cp2k
before pushing changes and right now I correctly installed hdf5
on a fresh develop
checkout... sorry I can't reproduce the problem...
The two lines are needed to forward requests for non-existing attributes from Spec
to Package
. It's what makes :
blas = spec['blas'].blas_libs
possible instead of :
blas = spec['blas'].package.blas_libs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, this is weird. Spack works on my laptop but not on our cluster. Going to investigate further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ouch... could reproduce with python@2.6. I wonder why Travis never fired up a warning about that
EDIT : Travis seems to be running with 2.6.9 and no issues. Python 2.6.6 instead shows the problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On my cluster, Spack works with Python 2.7 but crashes with the system Python 2.6 Can you try 2.6 on your end to see if you can reproduce the problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm running Python 2.6.6 too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alalazo: if you're working on a fix I'll merge it asap, otherwise I'll work on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT : Travis seems to be running with 2.6.9 and no issues. Python 2.6.6 instead shows the problem.
If only we could just drop 2.6. Sigh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tgamblin Sorry for the trouble. I couldn't find a solution that works for both python versions right now. If you couldn't solve it right away, feel free to revert the merge and I'll work it out without impacting everyone...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suffix = dso_suffix if '+shared' in self.spec else 'a' | ||
mkl_integer = ['libmkl_intel_ilp64'] if '+ilp64' in self.spec else ['libmkl_intel_lp64'] # NOQA: ignore=E501 | ||
mkl_threading = ['libmkl_sequential'] | ||
if '+openmp' in spec: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alalazo : this should be self.spec ?
if '+openmp' in spec:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pramodk True! Feel free to submit a PR to fix this. Otherwise, if you prefer, I'll take care of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am testing now Atlas and MKL and i will create a PR today, need to fix a few extra minor things in MKL.
choice of ``Blas`` implementation, each package which provides it | ||
sets up ``self.spec.blas_shared_lib`` and ``self.spec.blas_static_lib`` to | ||
point to the shared and static ``Blas`` libraries, respectively. The same |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blas-->BLAS
choice of ``Blas`` implementation, each package which provides it | ||
sets up ``self.spec.blas_shared_lib`` and ``self.spec.blas_static_lib`` to | ||
point to the shared and static ``Blas`` libraries, respectively. The same | ||
applies to packages which provide ``Lapack``. Package developers are advised to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lapack-->LAPACK
Fixes #1670
Modifications
LibraryList
+ unit testsfind_libraries
anddedupe
setup_dependent_package
and define properties insteadintel-parallel-studio
andmkl
atlas