--- /dev/null
+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
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
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
// 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.
${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
${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
${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}
--- /dev/null
+// 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];
+}
${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
--- /dev/null
+// 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
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
argv0, argv0);
}
-const char kBuildVersion[] =
-#include "build-version.inc"
- ;
-
int main(int argc, char** argv) {
const char* inFile = nullptr;
const char* outFile = nullptr;
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;
argv0, argv0);
}
-const char kBuildVersion[] =
-#include "build-version.inc"
- ;
-
int main(int argc, char** argv) {
const char* inFile = nullptr;
const char* outFile = nullptr;
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;
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;
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));
# 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.
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.
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()