Skip to content
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

libpciaccess cannot be built with PGI compilers #481

Closed
wants to merge 1 commit into from

Conversation

adamjstewart
Copy link
Member

I don't think libpciaccess can be built with PGI compilers. The only way I was able to build OpenMPI was to trick Spack into thinking I installed libpciaccess as was done for Darwin in #257. If anyone can figure out how to build libpciaccess with PGI I will be more than happy to close this PR.

See https://groups.google.com/forum/#!topic/spack/JX2hsOyXSdk for the relevant discussion. Thanks to @eschnett for the suggestion.

@adamjstewart
Copy link
Member Author

Actually, hold off on merging this for now. There's something I want to test first...

@adamjstewart
Copy link
Member Author

Unfortunately, my changes in #493 didn't fix this problem, so I'm reopening this PR. If anyone can figure out how to get PGI to install libpciaccess without this hack, please let me know.

@adamjstewart adamjstewart reopened this Mar 4, 2016
@adamjstewart
Copy link
Member Author

While I was at it, I submitted a bug report with Xorg to see if they can get to the bottom of why I am unable to install libpciaccess.

@tgamblin
Copy link
Member

tgamblin commented Mar 5, 2016

Keep me posted. Does it make sense to merge in the meantime? I am not a huge fan of the "just make a lib directory" stuff (as I would rather have an optional dependency from things that depend on this). Would that be a better temporary fix?

@adamjstewart
Copy link
Member Author

I would also prefer to have an optional dependency than a "fake" install. This is just what @eschnett suggested since he did the same for OS X. But that may have been before optional dependencies had been implemented.

On Monday I'm going to contact PGI to see if they can help. In the meantime, I guess this can be left alone since no one else has complained about it and I don't need it right away. If PGI can't help me, I'll rewrite this PR to make libpciaccess an optional dependency of hwloc for OS X and PGI. I'll close this for now.

@adamjstewart
Copy link
Member Author

I submitted a bug report with PGI and they confirmed that this is a bug. Since they haven't yet offered a patch, I'm reopening this PR.

We have two options:

  1. Do a fake build of libpciaccess. This is what is currently in the PR.
  2. Make hwloc, and any other package that depends_on libpciaccess, have an optional dependency.

@tgamblin: It sounds like you would prefer option 2. hwloc and py-pandas are currently the only packages that depend on libpciaccess, so it wouldn't be that bad. Is there currently any way to specify that a package depends_on another package when multiple conditions are not met? Specifically, the architecture is not =darwin-i686 or =darwin-x86_64 and the compiler is not %pgi?

@adamjstewart adamjstewart reopened this Mar 14, 2016
@eschnett
Copy link
Contributor

You probably want to make this a variant, since building both with and without should work in the "normal" cases. The variant's default can be as complex as needs to be, as it's a simple boolean expression. The dependency is then simply enabled by the variant. This also makes the package decision explicit.

@adamjstewart
Copy link
Member Author

That was my second thought. But the problem is that I can't use spec in a variant because that variable doesn't exist in normal context, only within install. If I don't have access to spec then I don't know any other way to get the compiler. My third thought was to use something super hacky like command injection in the when statement. We might need to add more complexity to conditional dependencies if we want to do this right.

@eschnett
Copy link
Contributor

You can access the architecture as sys.platform.

If a compiler is broken (or a package is broken with a particular compiler), then maybe it's not a good idea to change the default behaviour. Instead, maybe an error message would be best, recommending to manually choose a variant that works.

@tgamblin
Copy link
Member

You can get away with Erik's suggestion at least for the darwin part. e.g., you could do this:

if sys.platform != 'darwin':
    depends_on('libpciaccess')

And that will work, because we don't do cross-compiles (yet), and you know that Spack is running on the same arch it builds on.

The better platform/OS/target support that we've talked about at telcons should allow you to do this kind of thing with when= more easily. But it doesn't solve the issue with filtering on compilers -- we'd have to add more to the spec syntax to get that working. Do you have a preference for how "not " should look?

Another question would be whether you'd rather just have libpciaccess always built with the "system" compiler, and not with other special compilers. That might actually be easier to add. We could add a directive, like require_system_compiler() to the packages, in which case concretization would always choose the system compiler, and you wouldn't have to specify it at the command line. That, or you could use the recent stuff from #120 to set your preferred compiler for libpciaccess to gcc, and you wouldn't have to type it all the time...

@adamjstewart
Copy link
Member Author

In general, I think having a versatile when argument to depends_on would prove useful. Perhaps it could be modified to accept a list of conditions that must be met. It could still accept a string for backwards compatibility/simplicity. We could add an unless argument that handles the "not" part. For the libpciaccess situation, this would look something like:

depends_on('libpciaccess', unless=['=darwin', '%pgi'])

With this design, a user could specify an unlimited number of conditions that need to be met. They could also combine when and unless. The tricky part will be deciding whether we want to use "and" or "or" with these conditions. Maybe:

depends_on('libpciaccess', unless=['=darwin', '%pgi'])

could translate to "don't depend on libpciaccess if arch is darwin or compiler is pgi, and:

depends_on('libpciaccess', unless=[['=darwin', '%pgi']])

could translate to "don't depend on libpciaccess if arch is darwin and compiler is pgi. Note the use of double brackets. That way we could develop a sufficiently complicated conditional using nested lists. Something like [A, B, [C, D], E] would translate to "if A or B or (C and D) or E".

I'm not sure how I feel about the alternative of using the system compiler. It won't solve the problems with Darwin, so we would end up using both. It certainly sounds like the easiest solution; it just feels like we're cheating in a way. But then again, not depending on it at all requires us to use the pre-installed system installations, which probably weren't built with PGI. I would prefer to use the stuff from #120 than add a require_system_compiler() directive. Although I would want to add it to the Spack repo so that each user doesn't need to add that manually. This might end up being a better solution for this particular case, since we wouldn't have to apply it to every single package that depends on libpciaccess. I would still argue that my idea of using nested lists and when/unless arguments is useful for other situations though.

@tgamblin
Copy link
Member

I really like the unless idea, and using lists for or. You already have and semantics, though. Just put them in the same string: unless='=darwin%pgi', and that is consistent with how when works.

What I am not sure about is how unless is going to play with the constraint solving. Currently, the constraint solve is iterative and will never remove a dependency, so we're guaranteed it converges. If you add unless, I think we might need something way more sophisticated, because now during concretization, when can add deps and unless can remove them. I think I can keep that in check by disallowing unless with ^. I would need a way to recognize contradictions like this:

depends_on('libfoo', unless='^libbar')
depends_on('libbar', when='^libfoo')

I think what is needed is a more sophisticated constraint solver, and that will take time. The other avenue would be to disallow unless in conjunction with ^, and to enforce an ordering for conditional dependency evaluation. Right now we have to iterate because adding one new dependency means you need to reevaluate all when specs and see if it means you need to change something else. To get this right, you would need something to break loops or to detect them in the concretization process. So i have to think about it.

I'm game for at least adding [] to when as a way to do or. I think that would be handy. Lemme think about how to do unless, which is obviously the more useful one here.

@alalazo
Copy link
Member

alalazo commented Mar 15, 2016

@adamjstewart just fyi, for the time being you can use #299 to evaluate a predicate after when=

@becker33
Copy link
Member

@adamjstewart @alalazo PR #299 has been merged into the mainline, so that functionality is there if you choose to use it.

@adamjstewart
Copy link
Member Author

Now that I think about it, maybe unless isn't the best way to go. It wouldn't allow us to do something like "if (A and not B) or (B and not A)". All of these quick little hacks work, but I feel like they are obfuscating what we actually want. New proposal. Why not allow something like the following:

depends_on('libpciaccess', when=depends_on_libpciaccess)

def depends_on_libpciaccess(self, spec, version):
    if spec.satisfies('=darwin-x86_64') or spec.satisfies('%pgi')
        return False
    else:
        return True

This way we have complete control over exactly what we want, and it is much easier to comprehend.

@adamjstewart
Copy link
Member Author

One final thought I want to get out of my head. Let's suppose we have 2 packages, A and B, and 3 compilers, X, Y, and Z. A depends on B. B can be built with compilers X and Y, but not Z. So far, this is identical to the situation we have with libpciaccess. However, what if B is not already installed on the system and A cannot be built without it. The way that I would envision Spack handling this would be:

spack install A %X  # build A and B with X
spack install A %Y  # build A and B with Y
spack install A %Z  # build A with Z but B with X or Y

This is similar to the idea of setting a preferred compiler for B, except that it doesn't always build with X. For example, I want libpciaccess to be built with GCC (or whatever is the current default compiler) if and only if I try to build it with PGI.

Man, dependency resolution is confusing 0_o

@adamjstewart
Copy link
Member Author

I'm going to close this PR for now. It may still be wise to add some logic that will allow us to mark packages as not-buildable on certain platforms or with specific compilers. But for now, I am content with adding ^libpciaccess%gcc to every package I build with PGI that depends on libpciaccess.

@adamjstewart adamjstewart deleted the fixes/libpciaccess branch March 25, 2016 20:16
@adamjstewart adamjstewart mentioned this pull request Apr 21, 2016
matz-e added a commit to matz-e/spack that referenced this pull request Apr 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants