From 9e18416098e0c0bdf005748318f612ead6949c70 Mon Sep 17 00:00:00 2001 From: DmitryBushev Date: Thu, 11 Mar 2021 20:22:38 +0300 Subject: [PATCH] Add interface to extract versioning info Appened ocloc interface with new 'query' feature. Using this feature now one can extract HEAD hash and version of neo. Signed-off-by: Bushev, Dmitry --- driver_version.h.in | 3 +- .../offline_compiler/ocloc_api_tests.cpp | 121 ++++++++++++++++++ .../offline_compiler_tests.cpp | 12 ++ shared/offline_compiler/source/CMakeLists.txt | 2 + shared/offline_compiler/source/ocloc_api.cpp | 2 + .../source/offline_compiler.cpp | 70 ++++++++-- .../source/offline_compiler.h | 9 ++ .../source/utilities/get_git_version_info.cpp | 41 ++++++ .../source/utilities/get_git_version_info.h | 14 ++ version.cmake | 12 ++ 10 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 shared/offline_compiler/source/utilities/get_git_version_info.cpp create mode 100644 shared/offline_compiler/source/utilities/get_git_version_info.h diff --git a/driver_version.h.in b/driver_version.h.in index 25e6263db5..ececba299e 100644 --- a/driver_version.h.in +++ b/driver_version.h.in @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -9,5 +9,6 @@ #define DRIVER_VERSION_H #cmakedefine NEO_OCL_DRIVER_VERSION ${NEO_OCL_DRIVER_VERSION} +#cmakedefine NEO_REVISION "${NEO_REVISION}" #endif /* DRIVER_VERSION_H */ diff --git a/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp b/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp index d3221b8079..d545a4a688 100644 --- a/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/ocloc_api_tests.cpp @@ -7,6 +7,7 @@ #include "shared/offline_compiler/source/ocloc_api.h" #include "shared/offline_compiler/source/offline_compiler.h" +#include "shared/offline_compiler/source/utilities/get_git_version_info.h" #include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/ocl_elf.h" @@ -44,6 +45,126 @@ TEST(OclocApiTests, WhenGoodArgsAreGivenThenSuccessIsReturned) { EXPECT_EQ(std::string::npos, output.find("Command was: ocloc -file test_files/copybuffer.cl -device "s + argv[4])); } +TEST(OclocApiTests, WhenValidQueryArgumentWithoutQueryInvokeIsGivenThenErrorMessageIsProduced) { + const char *argv[] = { + "ocloc", + "compile", + "NEO_REVISION"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + uint32_t numOutputs; + uint64_t *lenOutputs; + uint8_t **dataOutputs; + char **nameOutputs; + testing::internal::CaptureStdout(); + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE); + EXPECT_NE(std::string::npos, output.find("Invalid option (arg 2): NEO_REVISION")); +} + +TEST(OclocApiTests, WhenValidQueryArgumentWithExtraArgumentIsGivenThenErrorMessageIsProduced) { + const char *argv[] = { + "ocloc", + "query", + "NEO_REVISION", + "extra"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + uint32_t numOutputs; + uint64_t *lenOutputs; + uint8_t **dataOutputs; + char **nameOutputs; + testing::internal::CaptureStdout(); + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE); + EXPECT_NE(std::string::npos, output.find("Invalid option (arg 2): NEO_REVISION")); +} + +TEST(OclocApiTests, WhenRightArgumentsToQueryOptionAreGivenThenSuccessIsReturned) { + const char *argv[] = { + "ocloc", + "query", + "NEO_REVISION"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + uint32_t numOutputs; + uint64_t *lenOutputs; + uint8_t **dataOutputs; + char **nameOutputs; + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS); + EXPECT_EQ(numOutputs, 2u); + EXPECT_STREQ(*nameOutputs, "NEO_REVISION"); + const char *revision = reinterpret_cast(*dataOutputs); + EXPECT_STREQ(revision, NEO::getRevision().c_str()); + + oclocFreeOutput(&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + + const char *argv1[] = { + "ocloc", + "query", + "OCL_DRIVER_VERSION"}; + + retVal = oclocInvoke(argc, argv1, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::SUCCESS); + EXPECT_EQ(numOutputs, 2u); + EXPECT_STREQ(*nameOutputs, "OCL_DRIVER_VERSION"); + const char *driverVersion = reinterpret_cast(*dataOutputs); + EXPECT_STREQ(driverVersion, NEO::getOclDriverVersion().c_str()); + + oclocFreeOutput(&numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); +} + +TEST(OclocApiTests, WhenQueryCommandPassedWithWrongArgumentThenErrorMessageIsProduced) { + const char *argv[] = { + "ocloc", + "query", + "wrong"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + uint32_t numOutputs; + uint64_t *lenOutputs; + uint8_t **dataOutputs; + char **nameOutputs; + testing::internal::CaptureStdout(); + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE); + EXPECT_NE(std::string::npos, output.find("Invalid option (arg 2): wrong")); +} + +TEST(OclocApiTests, WhenQueryCommandPassedWithoutArgumentsThenErrorMessageIsProduced) { + const char *argv[] = { + "ocloc", + "query"}; + unsigned int argc = sizeof(argv) / sizeof(const char *); + uint32_t numOutputs; + uint64_t *lenOutputs; + uint8_t **dataOutputs; + char **nameOutputs; + testing::internal::CaptureStdout(); + int retVal = oclocInvoke(argc, argv, + 0, nullptr, nullptr, nullptr, + 0, nullptr, nullptr, nullptr, + &numOutputs, &dataOutputs, &lenOutputs, &nameOutputs); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(retVal, NEO::OfflineCompiler::ErrorCode::INVALID_COMMAND_LINE); + EXPECT_NE(std::string::npos, output.find("Error: no options for query provided.")); +} + TEST(OclocApiTests, WhenGoodFamilyNameIsProvidedThenSuccessIsReturned) { const char *argv[] = { "ocloc", diff --git a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp index 74c447c6f7..dd0e84e202 100644 --- a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp @@ -246,6 +246,18 @@ TEST_F(MultiCommandTests, GivenOutputFileListFlagWhenBuildingMultiCommandThenSuc deleteOutFileList(); delete pMultiCommand; } + +TEST_F(OfflineCompilerTests, GivenArgsWhenQueryIsCalledThenSuccessIsReturned) { + std::vector argv = { + "ocloc", + "query", + "NEO_REVISION"}; + + int retVal = OfflineCompiler::query(argv.size(), argv, oclocArgHelperWithoutInput.get()); + + EXPECT_EQ(OfflineCompiler::ErrorCode::SUCCESS, retVal); +} + TEST_F(OfflineCompilerTests, GivenArgsWhenOfflineCompilerIsCreatedThenSuccessIsReturned) { std::vector argv = { "ocloc", diff --git a/shared/offline_compiler/source/CMakeLists.txt b/shared/offline_compiler/source/CMakeLists.txt index 0311c3e821..6252ed4a01 100644 --- a/shared/offline_compiler/source/CMakeLists.txt +++ b/shared/offline_compiler/source/CMakeLists.txt @@ -59,6 +59,8 @@ set(CLOC_LIB_SRCS_LIB ${OCLOC_DIRECTORY}/source/offline_compiler.h ${OCLOC_DIRECTORY}/source/offline_compiler_helper.cpp ${OCLOC_DIRECTORY}/source/offline_compiler_options.cpp + ${OCLOC_DIRECTORY}/source/utilities/get_git_version_info.h + ${OCLOC_DIRECTORY}/source/utilities/get_git_version_info.cpp ${NEO_SOURCE_DIR}/shared/source/device_binary_format/device_binary_format_zebin.cpp ${NEO_SOURCE_DIR}/shared/source/device_binary_format/zebin_decoder.cpp ${NEO_SOURCE_DIR}/shared/source/device_binary_format/yaml/yaml_parser.cpp diff --git a/shared/offline_compiler/source/ocloc_api.cpp b/shared/offline_compiler/source/ocloc_api.cpp index b99586234a..ca86fb6d20 100644 --- a/shared/offline_compiler/source/ocloc_api.cpp +++ b/shared/offline_compiler/source/ocloc_api.cpp @@ -106,6 +106,8 @@ int oclocInvoke(unsigned int numArgs, const char *argv[], return buildFatBinary(allArgs, helper.get()); } else if (numArgs > 1 && ConstStringRef("validate") == allArgs[1]) { return NEO::Ocloc::validate(allArgs, helper.get()); + } else if (numArgs > 1 && ConstStringRef("query") == allArgs[1]) { + return OfflineCompiler::query(numArgs, allArgs, helper.get()); } else { int retVal = OfflineCompiler::ErrorCode::SUCCESS; diff --git a/shared/offline_compiler/source/offline_compiler.cpp b/shared/offline_compiler/source/offline_compiler.cpp index 5904864279..cda86a3022 100644 --- a/shared/offline_compiler/source/offline_compiler.cpp +++ b/shared/offline_compiler/source/offline_compiler.cpp @@ -7,6 +7,7 @@ #include "offline_compiler.h" +#include "shared/offline_compiler/source/utilities/get_git_version_info.h" #include "shared/source/compiler_interface/intermediate_representations.h" #include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/device_binary_format/device_binary_formats.h" @@ -104,6 +105,22 @@ OfflineCompiler *OfflineCompiler::create(size_t numArgs, const std::vector &allArgs, OclocArgHelper *helper) { + int retVal = OUT_OF_HOST_MEMORY; + std::unique_ptr pOffCompiler{new OfflineCompiler()}; + + pOffCompiler->queryInvoke = true; + pOffCompiler->argHelper = helper; + retVal = pOffCompiler->initialize(numArgs, allArgs, true); + + if (retVal != SUCCESS) + return retVal; + + retVal = pOffCompiler->performQuery(); + + return retVal; +} + struct OfflineCompiler::buildInfo { std::unique_ptr> fclOptions; std::unique_ptr> fclInternalOptions; @@ -360,7 +377,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & size_t sourceFromFileSize = 0; this->pBuildInfo = std::make_unique(); retVal = parseCommandLine(numArgs, allArgs); - if (retVal != SUCCESS) { + if (retVal != SUCCESS || queryInvoke) { return retVal; } @@ -585,6 +602,20 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & return retVal; } +int OfflineCompiler::performQuery() { + int retVal = SUCCESS; + + if (queryOption == QUERY_NEO_REVISION) { + auto revision = NEO::getRevision(); + argHelper->saveOutput("NEO_REVISION", revision.c_str(), revision.size() + 1); + } else { + auto driverVersion = NEO::getOclDriverVersion(); + argHelper->saveOutput("OCL_DRIVER_VERSION", driverVersion.c_str(), driverVersion.size() + 1); + } + + return retVal; +} + int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector &argv) { int retVal = SUCCESS; bool compile32 = false; @@ -598,7 +629,7 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vectorprintf("Invalid option (arg %d): %s\n", argIndex, argv[argIndex].c_str()); retVal = INVALID_COMMAND_LINE; @@ -661,18 +696,25 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vectorprintf("Error: Cannot compile for 32-bit and 64-bit, please choose one.\n"); - retVal = INVALID_COMMAND_LINE; - } else if (inputFile.empty()) { - argHelper->printf("Error: Input file name missing.\n"); - retVal = INVALID_COMMAND_LINE; - } else if (deviceName.empty() && (false == onlySpirV)) { - argHelper->printf("Error: Device name missing.\n"); - retVal = INVALID_COMMAND_LINE; - } else if (!argHelper->fileExists(inputFile)) { - argHelper->printf("Error: Input file %s missing.\n", inputFile.c_str()); - retVal = INVALID_FILE; + if (queryInvoke) { + if (queryOption == QUERY_LAST) { + argHelper->printf("Error: no options for query provided.\n"); + retVal = INVALID_COMMAND_LINE; + } + } else { + if (compile32 && compile64) { + argHelper->printf("Error: Cannot compile for 32-bit and 64-bit, please choose one.\n"); + retVal = INVALID_COMMAND_LINE; + } else if (inputFile.empty()) { + argHelper->printf("Error: Input file name missing.\n"); + retVal = INVALID_COMMAND_LINE; + } else if (deviceName.empty() && (false == onlySpirV)) { + argHelper->printf("Error: Device name missing.\n"); + retVal = INVALID_COMMAND_LINE; + } else if (!argHelper->fileExists(inputFile)) { + argHelper->printf("Error: Input file %s missing.\n", inputFile.c_str()); + retVal = INVALID_FILE; + } } } diff --git a/shared/offline_compiler/source/offline_compiler.h b/shared/offline_compiler/source/offline_compiler.h index 7bc55f299b..60149896f8 100644 --- a/shared/offline_compiler/source/offline_compiler.h +++ b/shared/offline_compiler/source/offline_compiler.h @@ -43,8 +43,14 @@ class OfflineCompiler { INVALID_FILE = -5151, PRINT_USAGE = -5152, }; + enum QueryOption { + QUERY_OCL_DRIVER_VERSION = 0, + QUERY_NEO_REVISION = 1, + QUERY_LAST, + }; static OfflineCompiler *create(size_t numArgs, const std::vector &allArgs, bool dumpFiles, int &retVal, OclocArgHelper *helper); + static int query(size_t numArgs, const std::vector &allArgs, OclocArgHelper *helper); int build(); std::string &getBuildLog(); void printUsage(); @@ -81,6 +87,7 @@ class OfflineCompiler { std::string getStringWithinDelimiters(const std::string &src); int initialize(size_t numArgs, const std::vector &allArgs, bool dumpFiles); int parseCommandLine(size_t numArgs, const std::vector &allArgs); + int performQuery(); void setStatelessToStatefullBufferOffsetFlag(); void resolveExtraSettings(); void parseDebugSettings(); @@ -124,6 +131,8 @@ class OfflineCompiler { bool inputFileSpirV = false; bool outputNoSuffix = false; bool forceStatelessToStatefulOptimization = false; + bool queryInvoke = false; + int queryOption = QUERY_LAST; std::vector elfBinary; char *genBinary = nullptr; diff --git a/shared/offline_compiler/source/utilities/get_git_version_info.cpp b/shared/offline_compiler/source/utilities/get_git_version_info.cpp new file mode 100644 index 0000000000..e59de98eb6 --- /dev/null +++ b/shared/offline_compiler/source/utilities/get_git_version_info.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "driver_version.h" + +#include + +#ifdef QTR +#undef QTR +#endif + +#ifdef TOSTR +#undef TOSTR +#endif + +#define QTR(a) #a +#define TOSTR(b) QTR(b) + +namespace NEO { + +std::string getRevision() { +#ifdef NEO_REVISION + return NEO_REVISION; +#else + return ""; +#endif +} + +std::string getOclDriverVersion() { +#ifdef NEO_OCL_DRIVER_VERSION + return TOSTR(NEO_OCL_DRIVER_VERSION); +#else + return ""; +#endif +} + +} // namespace NEO diff --git a/shared/offline_compiler/source/utilities/get_git_version_info.h b/shared/offline_compiler/source/utilities/get_git_version_info.h new file mode 100644 index 0000000000..db813d87bd --- /dev/null +++ b/shared/offline_compiler/source/utilities/get_git_version_info.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include + +namespace NEO { +extern std::string getRevision(); +extern std::string getOclDriverVersion(); +} // namespace NEO diff --git a/version.cmake b/version.cmake index 5c92b1b0a6..2d3b736088 100644 --- a/version.cmake +++ b/version.cmake @@ -66,6 +66,18 @@ else() set(NEO_OCL_DRIVER_VERSION "${NEO_OCL_VERSION_MAJOR}.${NEO_OCL_VERSION_MINOR}.${NEO_VERSION_BUILD}") endif() +find_program(GIT NAMES git) +if(NOT "${GIT}" STREQUAL "GIT-NOTFOUND") + if(IS_DIRECTORY ${NEO_SOURCE_DIR}/.git) + set(GIT_arg --git-dir=${NEO_SOURCE_DIR}/.git rev-parse HEAD) + execute_process( + COMMAND ${GIT} ${GIT_arg} + OUTPUT_VARIABLE NEO_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() +endif() + # Level-Zero package version set(NEO_L0_VERSION_MAJOR 1) set(NEO_L0_VERSION_MINOR 1)