Automatically find externals#15158
Conversation
|
I think the core proposal in #1795 might be of interest for a broader discussion. The basic idea is that a package that is detected as an external can be symlinked into a Spack owned directory. This would ensure that:
|
I would like to give users the option to specify a subset of files (e.g. if a
I think this can be treated as a separate issue: we already allow users to add external packages which are located in system folders (and in that case they enter the system folder as the prefix). Spack's logic already handles this case so it should be the same for automatically adding externals with system prefixes.
Overall I'm not sure of the benefit of this (vs. detecting and using system prefixes). I admit it sounds good to me, but I think we already need to handle the existence of system prefixes, so I'm not sure if separating the files into a different prefix is beneficial. |
alalazo
left a comment
There was a problem hiding this comment.
I left a few comments, let me know what you think.
…o test the function
…package (e.g. with different versions)
…ce of multiple packages
…ances of a package (e.g. two instances of CMake stored in different paths)
…y (the logic was trying to os.listdir on it)
… as external packages
…g to create external package configs
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
… relevant exes found in that prefix; it can return multiple specs from a single call (although generally the package config can't distinguish the specs). determine_spec_details can return a single spec if the user doesn't want to implement the logic to detect multiple versions in a single prefix
|
I should add a section on things that are not yet addressed but I presume they could be handled with a later PR:
All other concerns are addressed at this point. |
…ndidate exe was not an instance of the package was triggering incorrectly. remove confusing and incorrect use of for/else python syntax
alalazo
left a comment
There was a problem hiding this comment.
LGTM. I think all the other points mentioned in the discussion can be implemented in subsequent PRs. I left a couple of minor comments.
| groups = defaultdict(set) | ||
| for p in paths: | ||
| groups[os.path.dirname(p)].add(p) | ||
| return groups.items() |
There was a problem hiding this comment.
I think we can return:
result = sorted([(prefix, sorted(s)) for prefix, s in groups.items()])to solve the TODO below
There was a problem hiding this comment.
That would do it, although the TODO I have in the code mentions that it might be better to do it based on order of prefixes in PATH (so the results are repeatable and follow an intuitive rule).
| match = re.search(r'cmake.*version\s+(\S+)', output) | ||
| if match: | ||
| version_str = match.group(1) | ||
| return Spec('cmake@{0}'.format(version_str)) |
There was a problem hiding this comment.
Maybe we can just:
| return Spec('cmake@{0}'.format(version_str)) | |
| return 'cmake@{0}'.format(version_str) |
and move the logic that parses the string into Specs in the command, as you suggested in a comment above.
tgamblin
left a comment
There was a problem hiding this comment.
@scheibelp: this LGTM. Can you please add documentation before we merge it?
| Specific limitations include: | ||
|
|
||
| * A package must define ``executables`` and ``determine_spec_details`` | ||
| for Spack to locate instances of that package. |
There was a problem hiding this comment.
This needs further explanation in the packaging guide -- what's the signature for the method, what should executables contain, and how is finding done based on those two things? Can you add that?
| * A package must define ``executables`` and ``determine_spec_details`` | ||
| for Spack to locate instances of that package. | ||
| * This is currently intended to find build dependencies rather than | ||
| library packages. |
There was a problem hiding this comment.
Probably should say why -- because it can only find executable programs right now.
| can help locate all external entries). | ||
| * Currently this logic is focused on examining ``PATH`` and does not | ||
| search through modules (although it should find the package if a | ||
| module is loaded for it). |
There was a problem hiding this comment.
I think this is related to the second bullet above and should be combined.
tgamblin
left a comment
There was a problem hiding this comment.
@scheibelp: can you add the documentation above in a follow-on PR?
|
It seems like |
|
Also, the P.S. I'm working on adding |
|
Ah, now that I have it working it seems to run this function for each unique prefix. What about when both Python 2 and 3 are installed to the same directory? |
@adamjstewart You might want to look at #16526 which builds on this PR and implements detection logic for |
|
Also, this PR suffers from the same issue as #12313, it reorganizes my |
|
Btw, I got bored, so I'm going to add $ egrep -ho 'depends_on\(.(\w+).*type=.build' */package.py | cut -c 13- | egrep -o '^[A-Za-z0-9-]+' | sort | uniq -c | sort -n
...
38 gmake
41 flex
53 bison
54 py-cython
61 python
79 xproto
155 m4
181 util-macros
187 automake
190 autoconf
195 libtool
286 cmake
347 pkgconfig
719 py-setuptools |
Add a
spack external findcommand which searches through$PATHand tries to create apackages.yamlof external packages. This focuses on finding build dependencies (currently onlycmake).To make a package discoverable with
spack external findthe package must define an.executablesclass attribute: a collection of executable names. If Spack finds these executables, it will create apackagesconfig entry for them. If the package also defines.determine_spec_details, the executables will be passed to that function, which can generate a more-specificpackages.yamlentry (including version, variants or whatever else the user decides to determine).This currently outputs the relevant yaml configuration to the terminal and doesn't have an option to generate a
packages.yamlfile.Closes #2507
Fixes #13198
Fixes #2116