Add CHANGES file with high level software history

Add a high level version number for SPIRV-Tools, beginning
with v2016.0-dev.  The README describes the format of the
version number.

The high level version number is extracted from the CHANGES
file.  That works around:
 - stale-bait for when we don't add tags to the repository
 - our inability to add tags to the repository

Option --version causes spirv-as, spirv-dis, and spirv-val to
show the high level version number.

Add spvSoftwareVersionString to return the C-string for
the high level version number.

Add spvSoftwareVersionDetailsString() so that clients can get
more information if they want to.
Also allows us to clean up the uses in the tool executables files,
so now only one file includes build-version.inc.

Move the update-build-version logic to the only
CMakeLists file that needs it.

The update build version script takes a new argument
to name the output file.
This commit is contained in:
David Neto 2016-04-21 20:50:11 -04:00
parent 776029fb71
commit 9166854ac9
13 changed files with 243 additions and 36 deletions

19
CHANGES Normal file
View File

@ -0,0 +1,19 @@
Revision history for SPIRV-Tools
v2016.0-dev 2016-04-22
- Adds v<year>.<index> versioning, with "-dev" indicating
work in progress. The intent is to more easly report
and summarize functionality when SPIRV-Tools is incorporated
in downstream projects.
- Summary of functionality (See the README.md for more):
- Supports SPIR-V 1.1 Rev 1
- Supports SPIR-V 1.0 Rev 5
- Supports GLSL std450 extended instructions 1.0 Rev 3
- Supports OpenCL extended instructions 1.0 Rev 2
- Assembler, disassembler are complete
- Supports floating point widths of 16, 32, 64 bits
- Supports integer widths up to 64 bits
- Validator is incomplete
- Supported on Linux, OSX, Android, Windows

View File

@ -133,11 +133,6 @@ endif()
find_host_package(PythonInterp)
add_custom_target(spirv-tools-build-version
${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/utils/update_build_version.py
${spirv-tools_SOURCE_DIR}
COMMENT "Update build-version.inc in the Spirv-tools build directory (if necessary).")
# Defaults to OFF if the user didn't set it.
option(SPIRV_SKIP_EXECUTABLES

View File

@ -18,6 +18,23 @@ SPIR-V is defined by the Khronos Group Inc.
See the [SPIR-V Registry][spirv-registry] for the SPIR-V specification,
headers, and XML registry.
## Verisoning SPIRV-Tools
See [`CHANGES`](CHANGES) for a high level summary of recent changes, by version.
SPIRV-Tools project version numbers are of the form `v`*year*`.`*index* and with
an optional `-dev` suffix to indicate work in progress. For exampe, the
following versions are ordered from oldest to newest:
* `v2016.0`
* `v2016.1-dev`
* `v2016.1`
* `v2016.2-dev`
* `v2016.2`
Use the `--version` option on each command line tool to see the software
version. An API call reports the software version as a C-style string.
## Supported features
### Assembler, binary parser, and disassembler

View File

@ -329,6 +329,16 @@ typedef spv_context_t* spv_context;
// Platform API
// Returns the SPIRV-Tools software version as a null-terminated string.
// The contents of the underlying storage is valid for the remainder of
// the process.
const char* spvSoftwareVersionString();
// Returns a null-terminated string containing the name of the project,
// the software version string, and commit details.
// The contents of the underlying storage is valid for the remainder of
// the process.
const char* spvSoftwareVersionDetailsString();
// Certain target environments impose additional restrictions on SPIR-V, so it's
// often necessary to specify which one applies. SPV_ENV_UNIVERSAL means
// environment-agnostic SPIR-V.

View File

@ -102,6 +102,24 @@ set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
PROPERTIES OBJECT_DEPENDS "${EXTINST_CPP_DEPENDS}")
set(SPIRV_TOOLS_BUILD_VERSION_INC
${spirv-tools_BINARY_DIR}/build-version.inc)
set(SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR
${spirv-tools_SOURCE_DIR}/utils/update_build_version.py)
set(SPIRV_TOOLS_CHANGES_FILE
${spirv-tools_SOURCE_DIR}/CHANGES)
add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC}
COMMAND ${PYTHON_EXECUTABLE}
${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
${spirv-tools_SOURCE_DIR} ${SPIRV_TOOLS_BUILD_VERSION_INC}
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
${SPIRV_TOOLS_CHANGES_FILE}
COMMENT "Update build-version.inc in the SPIRV-Tools build directory (if necessary).")
# Convenience target for standalone generation of the build-version.inc file.
# This is not required for any dependence chain.
add_custom_target(spirv-tools-build-version
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC})
set(SPIRV_SOURCES
${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h
${spirv-tools_SOURCE_DIR}/include/spirv/spirv.h
@ -135,6 +153,7 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
${CMAKE_CURRENT_SOURCE_DIR}/print.cpp
${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_target_env.cpp
${CMAKE_CURRENT_SOURCE_DIR}/table.cpp
@ -148,6 +167,22 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/validate_ssa.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_types.cpp)
# The software_version.cpp file includes build-version.inc.
# Rebuild the software_version.cpp object file if it is older than
# build-version.inc or whenever build-version.inc itself is out of
# date. In the latter case, rebuild build-version.inc first.
# CMake is not smart enough to detect this dependency automatically.
# Without this, the dependency detection system for #included files
# does not kick in on a clean build for the following reason: The
# build will fail early because it doesn't know how to build the
# missing source file build-version.inc. That occurs before the
# preprocessor is run on software_version.cpp to detect the
# #include dependency.
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
PROPERTIES OBJECT_DEPENDS "${SPIRV_TOOLS_BUILD_VERSION_INC}")
add_library(${SPIRV_TOOLS} ${SPIRV_SOURCES})
spvtools_default_compile_options(${SPIRV_TOOLS})
target_include_directories(${SPIRV_TOOLS}

View File

@ -0,0 +1,43 @@
// Copyright (c) 2015-2016 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
// https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
#include "spirv-tools/libspirv.h"
namespace {
const char* kBuildVersions[] = {
#include "build-version.inc"
};
} // anonymous namespace
const char* spvSoftwareVersionString() {
return kBuildVersions[0];
}
const char* spvSoftwareVersionDetailsString() {
return kBuildVersions[1];
}

View File

@ -59,6 +59,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
${CMAKE_CURRENT_SOURCE_DIR}/OperandCapabilities.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Operand.cpp
${CMAKE_CURRENT_SOURCE_DIR}/OperandPattern.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SoftwareVersion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TextAdvance.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TextDestroy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TextLiteral.cpp

77
test/SoftwareVersion.cpp Normal file
View File

@ -0,0 +1,77 @@
// Copyright (c) 2015-2016 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
// https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
#include "UnitSPIRV.h"
#include <sstream>
#include "gmock/gmock.h"
using ::testing::AnyOf;
using ::testing::Eq;
using ::testing::Ge;
using ::testing::StartsWith;
namespace {
void CheckFormOfHighLevelVersion(const std::string& version) {
std::istringstream s(version);
char v = 'x';
int year = -1;
char period = 'x';
int index = -1;
s >> v >> year >> period >> index;
EXPECT_THAT(v, Eq('v'));
EXPECT_THAT(year, Ge(2016));
EXPECT_THAT(period, Eq('.'));
EXPECT_THAT(index, Ge(0));
EXPECT_TRUE(s.good() || s.eof());
std::string rest;
s >> rest;
EXPECT_THAT(rest, AnyOf("", "-dev"));
}
TEST(SoftwareVersion, ShortIsCorrectForm) {
SCOPED_TRACE("short form");
CheckFormOfHighLevelVersion(spvSoftwareVersionString());
}
TEST(SoftwareVersion, DetailedIsCorrectForm) {
const std::string detailed_version(spvSoftwareVersionDetailsString());
EXPECT_THAT(detailed_version, StartsWith("SPIRV-Tools v"));
// Parse the high level version.
const std::string from_v =
detailed_version.substr(detailed_version.find_first_of('v'));
const size_t first_space_after_v_or_npos = from_v.find_first_of(' ');
SCOPED_TRACE(detailed_version);
CheckFormOfHighLevelVersion(from_v.substr(0, first_space_after_v_or_npos));
// We don't actually care about what comes after the version number.
}
} // anonymous namespace

View File

@ -31,19 +31,16 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
spvtools_default_compile_options(spirv-as)
target_link_libraries(spirv-as PRIVATE ${SPIRV_TOOLS})
target_include_directories(spirv-as PRIVATE ${spirv-tools_BINARY_DIR})
add_dependencies(${SPIRV_TOOLS} spirv-tools-build-version)
add_executable(spirv-dis ${CMAKE_CURRENT_SOURCE_DIR}/dis/dis.cpp)
spvtools_default_compile_options(spirv-dis)
target_link_libraries(spirv-dis PRIVATE ${SPIRV_TOOLS})
target_include_directories(spirv-dis PRIVATE ${spirv-tools_BINARY_DIR})
add_dependencies(${SPIRV_TOOLS} spirv-tools-build-version)
add_executable(spirv-val ${CMAKE_CURRENT_SOURCE_DIR}/val/val.cpp)
spvtools_default_compile_options(spirv-val)
target_link_libraries(spirv-val PRIVATE ${SPIRV_TOOLS})
target_include_directories(spirv-val PRIVATE ${spirv-tools_BINARY_DIR})
add_dependencies(${SPIRV_TOOLS} spirv-tools-build-version)
install(TARGETS ${SPIRV_INSTALL_TARGETS}
RUNTIME DESTINATION bin

View File

@ -52,10 +52,6 @@ Options:
argv0, argv0);
}
const char kBuildVersion[] =
#include "build-version.inc"
;
int main(int argc, char** argv) {
const char* inFile = nullptr;
const char* outFile = nullptr;
@ -87,7 +83,7 @@ int main(int argc, char** argv) {
case '-': {
// Long options
if (0 == strcmp(argv[argi], "--version")) {
printf("%s\n", kBuildVersion);
printf("%s\n", spvSoftwareVersionDetailsString());
printf("Target: %s\n",
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1));
return 0;

View File

@ -59,10 +59,6 @@ Options:
argv0, argv0);
}
const char kBuildVersion[] =
#include "build-version.inc"
;
int main(int argc, char** argv) {
const char* inFile = nullptr;
const char* outFile = nullptr;
@ -100,7 +96,7 @@ int main(int argc, char** argv) {
print_usage(argv[0]);
return 0;
} else if (0 == strcmp(argv[argi], "--version")) {
printf("%s\n", kBuildVersion);
printf("%s\n", spvSoftwareVersionDetailsString());
printf("Target: %s\n",
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1));
return 0;

View File

@ -50,10 +50,6 @@ Options:
argv0, argv0);
}
const char kBuildVersion[] =
#include "build-version.inc"
;
int main(int argc, char** argv) {
const char* inFile = nullptr;
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_1;
@ -62,7 +58,7 @@ int main(int argc, char** argv) {
const char* cur_arg = argv[argi];
if ('-' == cur_arg[0]) {
if (0 == strcmp(cur_arg, "--version")) {
printf("%s\n", kBuildVersion);
printf("%s\n", spvSoftwareVersionDetailsString());
printf("Targets:\n %s\n %s\n",
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1),
spvTargetEnvDescription(SPV_ENV_VULKAN_1_0));

View File

@ -14,24 +14,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Updates build-version.inc in the current directory, unless the update is
# identical to the existing content.
# Updates an output file with version info unless the new content is the same
# as the existing content.
#
# Args: <spirv-tools_dir>
# Args: <spirv-tools_dir> <output-file>
#
# For each directory, there will be a line in build-version.inc containing that
# directory's "git describe" output enclosed in double quotes and appropriately
# escaped.
# The output file will contain a line of text consisting of two C source syntax
# string literals separated by a comma:
# - The software version deduced from the CHANGES file in the given directory.
# - A longer string with the project name, the software version number, and
# git commit information for the directory. The commit information
# is the output of "git describe" if that succeeds, or "git rev-parse HEAD"
# if that succeeds, or otherwise a message containing the phrase "unknown hash".
# The string contents are escaped as necessary.
from __future__ import print_function
import datetime
import os.path
import re
import subprocess
import sys
OUTFILE = 'build-version.inc'
def command_output(cmd, dir):
"""Runs a command in a directory and returns its standard output stream.
@ -50,6 +54,23 @@ def command_output(cmd, dir):
return stdout
def deduceSoftwareVersion(dir):
"""Returns a software version number parsed from the CHANGES file
in the given dir.
The CHANGES file describes most recent versions first.
"""
pattern = re.compile('(v\d+\.\d+(-dev)) \d\d\d\d-\d\d-\d\d$')
changes_file = os.path.join(dir, 'CHANGES')
with open(changes_file) as f:
for line in f.readlines():
match = pattern.match(line)
if match:
return match.group(1)
raise Exception('No version number found in {}'.format(changes_file))
def describe(dir):
"""Returns a string describing the current Git HEAD version as descriptively
as possible.
@ -72,15 +93,19 @@ def describe(dir):
def main():
if len(sys.argv) != 2:
print('usage: {0} <spirv-tools_dir>'.format(sys.argv[0]))
if len(sys.argv) != 3:
print('usage: {0} <spirv-tools_dir> <output-file>'.format(sys.argv[0]))
sys.exit(1)
new_content = '"spirv-tools {}\\n"\n'.format(
output_file = sys.argv[2]
software_version = deduceSoftwareVersion(sys.argv[1])
new_content = '"{}", "SPIRV-Tools {} {}"\n'.format(
software_version, software_version,
describe(sys.argv[1]).replace('"', '\\"'))
if os.path.isfile(OUTFILE) and new_content == open(OUTFILE, 'r').read():
if os.path.isfile(output_file) and new_content == open(output_file, 'r').read():
sys.exit(0)
open(OUTFILE, 'w').write(new_content)
open(output_file, 'w').write(new_content)
if __name__ == '__main__':
main()