Major improvements to spack create#2707
Conversation
| version_lines = "\n".join([ | ||
| " version('{0}', {1}'{2}')".format( | ||
| v, ' ' * (max_len - len(str(v))), h) for v, h in version_hashes | ||
| ]) |
There was a problem hiding this comment.
Previously, spack checksum tau would result in:
version('2.26', '2af91f02ad26d5bf0954146c56a8cdfa')
version('2.25.2', 'f5e542d41eb4a7daa6241e5472f49fd7')
version('2.25.1.1', 'f2baae27c5c024937566f33339826d7c')
version('2.25.1', 'b9783f9bbe2862254bfdd208735241b6')
version('2.25', '46cd48fa3f3c4ce0197017b3158a2b43')
while
$ spack create --force https://www.cs.uoregon.edu/research/tau/tau_releases/tau-2.25.tar.gz
would result in:
version('2.26' , '2af91f02ad26d5bf0954146c56a8cdfa')
version('2.25.2' , 'f5e542d41eb4a7daa6241e5472f49fd7')
version('2.25.1.1', 'f2baae27c5c024937566f33339826d7c')
version('2.25.1' , 'b9783f9bbe2862254bfdd208735241b6')
version('2.25' , '46cd48fa3f3c4ce0197017b3158a2b43')
The latter isn't even PEP 8 compliant, and would raise problems during the flake8 tests. Now, both result in:
version('2.26', '2af91f02ad26d5bf0954146c56a8cdfa')
version('2.25.2', 'f5e542d41eb4a7daa6241e5472f49fd7')
version('2.25.1.1', 'f2baae27c5c024937566f33339826d7c')
version('2.25.1', 'b9783f9bbe2862254bfdd208735241b6')
version('2.25', '46cd48fa3f3c4ce0197017b3158a2b43')
| # Make sure the user provided a package and not a URL | ||
| if not valid_fully_qualified_module_name(args.package): | ||
| tty.die("`spack checksum` accepts package names, not URLs. " | ||
| "Use `spack md5 <url>` instead.") |
There was a problem hiding this comment.
I accidentally do this all the time.
There was a problem hiding this comment.
If you know what the user wants, why not just do it instead of quitting with an error message? Do we need spack md5 at all, or can its functionality be folded into spack checksum?
There was a problem hiding this comment.
Does it make sense to rename spack checksum? We will not always use md5, and it would be nice if spack checksum gave you whatever the current recommended checksum of a file/url was. Should spack checksum be called spack find-new-versions or spack-spider-versions or something?
There was a problem hiding this comment.
You mean rename spack md5 or rename spack checksum? I don't have any particular preference. Let's leave that for another PR.
There was a problem hiding this comment.
I mean:
spack checksum->spack find-new-versionsor some better name.spack md5->spack checksum(and it might spit out asha256)
Another PR sounds good.
There was a problem hiding this comment.
Yeah, there's a lot of overlap between spack versions/checksum/md5. We can work on that during the switch to sha256 or whatever we decide on.
| format = " version(%%-%ds, '%%s')" % (max_len + 2) | ||
| return '\n'.join( | ||
| format % ("'%s'" % v, h) for v, h in self.version_hash_tuples | ||
| ) |
There was a problem hiding this comment.
This is now done in spack checksum. No need to duplicate the effort.
| '-f', '--force', action='store_true', dest='force', | ||
| help="Overwrite any existing package file with the same name.") | ||
|
|
||
| setup_parser.subparser = subparser |
There was a problem hiding this comment.
I don't think this line is necessary? I don't see it in any other cmd.
lib/spack/spack/cmd/create.py
Outdated
| '-N', '--namespace', | ||
| help="Specify a namespace for the package. Must be the namespace of " | ||
| "a repository registered with Spack.") | ||
| help="namespace for the package") |
There was a problem hiding this comment.
Can someone test --repo and --namespace for me? I don't use either, so I can't really test whether or not the behavior has changed.
|
|
||
| sorted_versions = sorted(versions.keys(), reverse=True) | ||
| sorted_urls = [versions[v] for v in sorted_versions] | ||
| return sorted_versions[:archives_to_fetch], sorted_urls[:archives_to_fetch] |
There was a problem hiding this comment.
This is all duplicated in spack checksum, so I un-duplicated it.
lib/spack/spack/cmd/create.py
Outdated
| # Determine the build system based on the files contained | ||
| # in the archive. | ||
| build_system = 'unknown' | ||
| build_system = 'default' |
There was a problem hiding this comment.
Thoughts on unknown vs. default?
There was a problem hiding this comment.
How about 'generic' for the regular old Package?
There was a problem hiding this comment.
So the name is only presented to the user in 2 scenarios. One, as a help option for spack create --template, and two, when it prints out "This package looks like it uses the {0} build system". I think --template generic makes more sense, but I also think the generic build system doesn't make much sense. I could reword it of course.
There was a problem hiding this comment.
I like the idea of just special casing the method to something like "couldn't detect a build system -- using generic package", since that gives the user more information anyway.
citibeth
left a comment
There was a problem hiding this comment.
- I would suggest a grammar of
spack create [options] <package>, since that is consistent with other Spack commands. The demo you shared would then become:
$ spack create
# create an example package
$ spack create foobar
# create a package called foobar
$ spack create --template cmake
# create an example CMake package
$ spack create --force --template python numpy
$ spack create --force --template python py-numpy
# create a python package, both commands create the same package
$ spack create --template autotools <url>
# convenient when the tarball doesn't contain a configure script and autoreconf needs to be run
- Where was the code deduplicated, and where is it now?
| # Make sure the user provided a package and not a URL | ||
| if not valid_fully_qualified_module_name(args.package): | ||
| tty.die("`spack checksum` accepts package names, not URLs. " | ||
| "Use `spack md5 <url>` instead.") |
There was a problem hiding this comment.
If you know what the user wants, why not just do it instead of quitting with an error message? Do we need spack md5 at all, or can its functionality be folded into spack checksum?
lib/spack/spack/cmd/create.py
Outdated
| 'scons': SconsGuess, | ||
| 'bazel': BazelGuess, | ||
| 'python': PythonGuess, | ||
| 'R': RGuess, |
lib/spack/spack/__init__.py
Outdated
|
|
||
| # User's editor from the environment | ||
| editor = Executable(os.environ.get("EDITOR", "vi")) | ||
| editor = Executable(os.environ.get("EDITOR", "vim")) |
There was a problem hiding this comment.
vi is not present on newer distributions like Fedora, and when both are present, vi generally enables legacy mode. How common are distributions that only come with vi?
There was a problem hiding this comment.
I don't know. But maybe some embedded or stripped down ones (e.g. for containers)? What about:
if "EDITOR" in os.environ:
editor = Executable(os.environ.get("EDITOR"))
else:
editor = which('vim')
if not editor:
editor = Executable('vi')I'm an emacs user -- I just picked vi as the default because it's more likely to be installed, so I guess we should do best effort here.
There was a problem hiding this comment.
Let me back out this change and make it in a different PR, just to keep things simple.
lib/spack/spack/cmd/edit.py
Outdated
| subparser.add_argument( | ||
| '-f', '--force', dest='force', action='store_true', | ||
| help="Open a new file in $EDITOR even if package doesn't exist.") | ||
| help='deprecated, use `spack create` instead') |
There was a problem hiding this comment.
Is this deprecated enough for now? Honestly, I would be fine with ripping it out completely in this PR, but I can wait.
There was a problem hiding this comment.
I think taking it out is fine if the docs reflect it.
|
I think this is good to go now. We should merge #2475 before this though. I'll rebase on that after it's merged. Let me know if there are any other places in the documentation or code that reference |
That's the plan. But in a separate PR, as that change was more controversial and I don't want it to hold up these changes.
Here and here. It is in |
5dee821 to
6d8a824
Compare
|
@tgamblin Can you look this over at some point? I have a |
|
Ping @tgamblin |
|
Ping ping @tgamblin |
There was a problem hiding this comment.
@adamjstewart: mostly minor questions/comments. This looks really good to me. See below.
Comments/questions:
- Now that the build system guessers are getting complex, does it make sense to make a subpackage for the different kinds, like
build_systems,cmd, etc.? - We'll need to figure out whether to merge this or #2780 first.
| 5.0.0 https://gmplib.org/download/gmp/gmp-5.0.0.tar.bz2 | ||
|
|
||
| Include how many checksums in the package file? (default is 5, q to abort) | ||
| How many would you like to checksum? (default is 1, q to abort) |
There was a problem hiding this comment.
Oh good! I keep thinking to change this to 1.
|
|
||
| # FIXME: Add dependencies if this package requires them. | ||
| # depends_on("foo") | ||
| # FIXME: Add dependencies if required. |
There was a problem hiding this comment.
Can we add a note here for autotools packages, that most autotools packages will not need m4, autoconf, automake, libtool, etc.? I think it was confusing for at least one person. Also does m4 need to be here? It's brought in transitively through the other three.
There was a problem hiding this comment.
Not sure about the m4 question. One thing I was considering doing was to create 2 separate build system guessers, one for Autotools with a configure script and one for Autotools without. I presume there are pretty tell-tale filenames that should make it obvious that the package uses Autotools even if it doesn't have a configure script?
Autotools without configure would automatically create an empty autoreconf method and add those 3-4 deps. Autotools with configure wouldn't add those deps, so no one would get confused.
If you can give me a list of tell-tale filenames that would indicate a package uses Autotools without a configure script, I can do this.
There was a problem hiding this comment.
I'm kind of tempted to say we should just not bother at that point. I think it'll be confusing to have two autotools packages, and the existing one already has an autoreconf phase. Also, I think it's complicated to do this generically. Some packages use automake but not autoconf, some do it the other way around, and some may or may not use libtool. The particular dependencies you want are going to depend on that stuff, so I don't think it's unreasonable to require the packager to straighten this stuff out for packages that don't ship with a proper configure script.
I think we should be mindful of making the common case easy and the special cases possible. This accomplishes that very well, and we go a step further by automating a number of important build systems. I think helping people beyond that is outside the scope of what we should have to maintain in Spack.
There was a problem hiding this comment.
I didn't mean creating a second AutotoolsPackage, just a second AutotoolsPackageTemplate. Both would subclass AutotoolsPackage, but one would have additional dependencies and an additional method to override in the body. BuildSystemGuesser would choose between the two based on whether or not a configure script is present.
But if we don't want to do that, I think I'll just remove these dependencies. I agree that it is confusing. Also, the only way we can detect that it uses the Autotools build system is if there is a configure script, and if there is a configure script, we definitely won't need these.
| # depends_on('autoconf', type='build') | ||
| # depends_on('automake', type='build') | ||
| # depends_on('libtool', type='build') | ||
| # depends_on('foo') |
There was a problem hiding this comment.
maybe separate this from the autotools-related build deps and add a comment to the template saying to add library/other dependencies here?
| make("install") | ||
| def configure_args(self): | ||
| # FIXME: Add arguments other than --prefix | ||
| # FIXME: If not needed delete the function |
| and installed before this one. See :ref:`dependencies`. | ||
|
|
||
| #. Get the ``install()`` method working. | ||
| #. Get the installation working. |
There was a problem hiding this comment.
I can remove this particular line from my changes and we can discuss it in #2780.
There was a problem hiding this comment.
I think it will be good at some point to review the documentation as a whole, maybe before the next major release. The information is there, but rearranging it to make the important bits more prominent or rewording parts to make the style more homogeneous across sections may be worth it.
lib/spack/spack/__init__.py
Outdated
|
|
||
| # User's editor from the environment | ||
| editor = Executable(os.environ.get("EDITOR", "vi")) | ||
| editor = Executable(os.environ.get("EDITOR", "vim")) |
There was a problem hiding this comment.
I don't know. But maybe some embedded or stripped down ones (e.g. for containers)? What about:
if "EDITOR" in os.environ:
editor = Executable(os.environ.get("EDITOR"))
else:
editor = which('vim')
if not editor:
editor = Executable('vi')I'm an emacs user -- I just picked vi as the default because it's more likely to be installed, so I guess we should do best effort here.
| # Make sure the user provided a package and not a URL | ||
| if not valid_fully_qualified_module_name(args.package): | ||
| tty.die("`spack checksum` accepts package names, not URLs. " | ||
| "Use `spack md5 <url>` instead.") |
There was a problem hiding this comment.
Does it make sense to rename spack checksum? We will not always use md5, and it would be nice if spack checksum gave you whatever the current recommended checksum of a file/url was. Should spack checksum be called spack find-new-versions or spack-spider-versions or something?
lib/spack/spack/cmd/create.py
Outdated
| # Determine the build system based on the files contained | ||
| # in the archive. | ||
| build_system = 'unknown' | ||
| build_system = 'default' |
There was a problem hiding this comment.
How about 'generic' for the regular old Package?
lib/spack/spack/cmd/edit.py
Outdated
| subparser.add_argument( | ||
| '-f', '--force', dest='force', action='store_true', | ||
| help="Open a new file in $EDITOR even if package doesn't exist.") | ||
| help='deprecated, use `spack create` instead') |
There was a problem hiding this comment.
I think taking it out is fine if the docs reflect it.
I think it would make sense to move a lot of this logic to
I actually think our PRs don't overlap that much. My changes to the Packaging Guide mostly affect the beginning, where we introduce |
|
@tgamblin I believe this is ready for a second review now. |
|
@adamjstewart: some stuff is still missing but we can add it later. |
|
Thanks for getting this into 0.10! Let me know what is still missing and I'll add it to a new PR. |
This is a first stab at fulfilling #1108.
spack createpreviously required a URL. If one was not present, or could not be parsed or fetched, it was useless. This resulted in many users being forced to usespack edit -for manually copy packages by hand. I wanted to draw a line between the two commands.spack createis used to create new packages,spack editis used to edit existing packages. In order to removespack edit -f, I needed to allowspack createto work even if a URL does not exist.The following commands demonstrate the new abilities of
spack create:I noticed a lot of duplicated code between
spack createandspack checksum. For example, all of the logic that searches for available versions, displays them and asks the user how many they would like to checksum, and formats the output versions was duplicated. I un-duplicated them.spack createandspack checksum--templateflag tospack createspack createto work even if a URL is not specifiedspack createspack edit --forceWe can change the UI from
spack create --name <name> <url>tospack create --url <url> <name>in another PR, as that seemed like a more controversial change.