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

Project version number in CMake/pkg-config is still 1.5.5 even though headers seem newer #334

Open
smcv opened this issue Mar 31, 2023 · 8 comments

Comments

@smcv
Copy link

smcv commented Mar 31, 2023

The headers <spirv/unified1/spirv.h> identifies itself as SPV_VERSION 0x10600 and SPV_REVISION 1, which seems to mean human-facing version number 1.6.1 (or at least that's how the Debian packaging labels it), but the CMakeLists.txt still has

project(SPIRV-Headers LANGUAGES CXX VERSION 1.5.5)

and therefore the pkg-config metadata generated from cmake/SPIRV-Headers.pc.in also identifies this project as version 1.5.5.

This makes it more difficult for a dependent project to check that it is going to be compiled against a sufficiently new set of SPIRV headers.

@johnkslang
Copy link
Member

I don't think the SPIR-V version should come from CMake files. Maybe the CMake version should migrate to be the version of the build? Is it normal for the build system to decide the version of the content of what it is building?

@smcv
Copy link
Author

smcv commented Apr 5, 2023

The important thing from my point of view is that if I build and install this project, and run pkg-config --modversion SPIRV-Headers (or equivalently, read ${libdir}/pkgconfig/SPIRV-Headers.pc in the installed tree), I should get some version number that the project's maintainers consider to be meaningful, so that I can use that version number in the build system of a dependent project to answer the question: is the installed version of SPIRV-Headers sufficient for a feature I'm interested in, or is it too old? If that's achieved, then I don't mind exactly how.

One way to achieve that result would be to change the version number passed to CMake build's project() from 1.5.5 to whatever it should be (perhaps 1.6.1 for the current version?), either as part of the procedure for updating to a new version or revision of the SPIR-V specification, or as part of the procedure for releasing a new tagged "SDK" version of SPIRV-Headers. This is how a lot of projects do this, and for projects with reasonably infrequent releases, it has the advantage of being very simple.

Another way to achieve that result (if CMake allows for it, I've lost track of which build systems do and don't allow dynamically-computed version numbers) would be to make the CMake build system parse whatever other location you consider to be the single source of truth, and use that to define its idea of the project version number, instead of it being a hard-coded string in CMakeLists.txt.

A third way to achieve that result would be to make the CMake build system parse whatever you consider to be the single source of truth, use that to define some other CMake variable that is not CMake's idea of the "project version", and substitute that variable into cmake/SPIRV-Headers.pc.in instead of using @CMAKE_PROJECT_VERSION@. If you do this, the value of the CMAKE_PROJECT_VERSION would become mostly irrelevant (unless it's used in other places in the project, I only looked at the .pc).

Is it normal for the build system to decide the version of the content of what it is building?

I'm not sure I understand. What else would be responsible for knowing what is the version number of the overall project that is being built, if not the project's build system?

@smcv
Copy link
Author

smcv commented Apr 5, 2023

If there are two version numbers that are meant to be aligned, and there's a technical reason why there can't be a single source of truth, the next best thing would be to have an automated test that asserts that the two ideas of the version number match up, so that versions where they don't match up correctly don't get released.

@johnkslang
Copy link
Member

Maybe this version number should be removed, or more likely more clearly saying it's the version of something else, and more clearly be in its own number space, independent of the SPIR-V content. (If there's supposed to be an exact match, I think it should go away, so that fragility doesn't exist, e.g., if you need to know the SPIR-V version, look in the SPIR-V content. However, I can see the need for a version number that changes at the frequency of what the build system is building, not exactly matching the SPIR-V version.)

Perhaps we should really be using the tags to know what's going on.

@smcv
Copy link
Author

smcv commented Apr 5, 2023

Another way to achieve that result (if CMake allows for it, I've lost track of which build systems do and don't allow dynamically-computed version numbers) would be to make the CMake build system parse whatever other location you consider to be the single source of truth, and use that to define its idea of the project version number

It looks like this is implementable, and https://github.com/KhronosGroup/Vulkan-Headers/blob/main/CMakeLists.txt sets its CMake-level version number from the version number in include/vulkan/vulkan_core.h.

if you need to know the SPIR-V version, look in the SPIR-V content

This project is called SPIRV-Headers, so I would have expected that it's a set of header files describing SPIR-V, and its build-system-visible version number represents the version of the SPIR-V headers that it contains and installs. Is that not true?

(I was asked to package a project that depends on these headers but I have no particular knowledge of SPIR-V, so perhaps I'm missing something important.)

If you're writing a build system for a dependent project and you want to say (pseudocode)

if system copy of SPIRV-Headers >= 1.6.1:
    use it
else:
    use a vendored copy

or

if system copy of SPIRV-Headers >= 1.6.1:
    use it
else:
    fail "your copy of SPIRV-Headers is too old, get a newer one"

then the build system metadata (the .pc file, or equivalent) is the natural place to look for that information.

@johnkslang
Copy link
Member

and its build-system-visible version number represents the version of the SPIR-V headers that it contains and installs. Is that not true?

Probably not exactly true in the way you want, and maybe that's why I wish this number hadn't been introduced. But, if it is introduced, those who want it should probably maintain it to actually have the semantic meaning they are looking for in it.

I can see that if we define SPIR-V header versioning to be what this particular form of packaging wants, and push it upstream into the core project, that it might appear to work for those who want this form of packaging. And maybe we should just do that to make this discussion stop. I'd hesitate for a few reasons:

  • Is there really only one view in the world of how packaging should work, and it's this one? Like, we shouldn't just be providing the core components here, with tags and versions defined by this project, and then having packagers create the dependencies they want by layering their own views on top? As if it's not okay if someone makes a manual decision, say commit 0xZZZZZZ of SPIR-V gets plugged into packaging scheme A wrapped as version Y, as per the definitions of how packaging scheme A works and the semantics of Y needed by scheme A? Which would be accompanied by testing within scheme A that it all the components worked together correctly as needed by scheme A?
  • Can the version number inside SPIR-V even reflect what people want it to? It's not getting bumped for every reservation of enumerants that change the headers, right? Does having the build just dumbly reuse something spelled "version" actually solve the intended problems people using scheme A are hoping something spelled "version" solves, or just give the appearance they were solved? Would there then be follow-on bug reports coming, like because the SPIR-V version didn't behave according to the definition of scheme A, that SPIR-V has a bug?

Maybe that's mostly too philosophical, but I do specifically worry that what is being done with other mechanisms (commit numbers, tags, maybe other git/github mechanisms) is being expected to be done by the version number, and that there actually is a human-level semantic mismatch around the word "version" between different parties.

Maybe we need to make the big change here, to conform to a specific view of packaging, it's just that wasn't the original intent. Original intent was there could be multiple parties making SDKs, many packagers doing things differently for many different kinds of environments, and the core projects would simply say exactly what they were (not necessarily condensable into a single number), while the packagers and SDK makers would take that raw information from all the components to make coherent packages.

@jeremy-lunarg
Copy link
Contributor

having packagers create the dependencies they want by layering their own views on top?

That's basically what LunarG does. Our package version is derived from the version of the Vulkan header we choose to target. During an SDK release cycle, there is a large effort by many people to identify release candidates (identified either by their commit ID or branch name depending on the repository). As part of the release cycle we also tag the repositories with an SDK version. Other members of the community can use these tags for their release in their own packaging schemes if they see fit.

That said, I have a few questions.

  1. Should there even be a project version declared in the CMake configuration? I don't have strong opinion here, but I do think it's reasonable (and maybe even expected in modern cmake) for a project to declare a version. Also worth noting that write_basic_package_version_file implicitly uses CMAKE_PROJECT_VERSION as well.
  2. What does the version mean? It's clear in spirv.h, but it's a bit trickier in SPIRV-Headers. SPIRV-Headers is a "library." It contains more than just spirv.h. It's sort of unfortunate that it's named SPIRV-Headers because it's natural to assume it will have the same version that is identified in spirv.h. However, SPIRV-Headers is its own thing and should maybe have it's own semantic version. Maybe.
  3. What breaks if SPIRV-Headers has the same version as spirv.h? Maybe not much? I dunno. A quick glance atgit log CMakeLists.txt indicates that several people have already made this innocent assumption before. One problem I see is that there is no way to message (via the semantic version) that a fix has been made in SPIRV-Headers and is ready for repackaging because it is married to the version in spirv.h. But how often will that happen?

@johnkslang
Copy link
Member

Thanks @jeremy-lunarg. I think the tags are a vital point, and if we haven't already said so, I recommend looking for the most recent tag to get the right contents to package.

We discussed internally, and are not opposed to having some number that increments each time there is a change, to make it easier for downstream consumers to package, provided it's a robust (non-manual) process. If downstream only grabs tagged content, we'd only have to increment once per tag. Alternatively, we could increment once per commit, or once per change that's relevant downstream (i.e., every token reservation).

Anyone have ideas or input on how to accomplish this, technically? Especially, accomplish it automatically? Just something that keeps bumping a version number for each change? Thanks!

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

No branches or pull requests

3 participants