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 <dmitry.bushev@intel.com>
This commit is contained in:
DmitryBushev 2021-03-11 20:22:38 +03:00 committed by Compute-Runtime-Automation
parent 4dda709b41
commit 9e18416098
10 changed files with 271 additions and 15 deletions

View File

@ -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 */

View File

@ -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<const char *>(*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<const char *>(*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",

View File

@ -246,6 +246,18 @@ TEST_F(MultiCommandTests, GivenOutputFileListFlagWhenBuildingMultiCommandThenSuc
deleteOutFileList();
delete pMultiCommand;
}
TEST_F(OfflineCompilerTests, GivenArgsWhenQueryIsCalledThenSuccessIsReturned) {
std::vector<std::string> 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<std::string> argv = {
"ocloc",

View File

@ -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

View File

@ -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;

View File

@ -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<std::
return pOffCompiler;
}
int OfflineCompiler::query(size_t numArgs, const std::vector<std::string> &allArgs, OclocArgHelper *helper) {
int retVal = OUT_OF_HOST_MEMORY;
std::unique_ptr<OfflineCompiler> 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<CIF::Builtins::BufferLatest, CIF::RAII::ReleaseHelper<CIF::Builtins::BufferLatest>> fclOptions;
std::unique_ptr<CIF::Builtins::BufferLatest, CIF::RAII::ReleaseHelper<CIF::Builtins::BufferLatest>> fclInternalOptions;
@ -360,7 +377,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector<std::string> &
size_t sourceFromFileSize = 0;
this->pBuildInfo = std::make_unique<buildInfo>();
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<std::string> &
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<std::string> &argv) {
int retVal = SUCCESS;
bool compile32 = false;
@ -598,7 +629,7 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector<std::str
for (uint32_t argIndex = 1; argIndex < numArgs; argIndex++) {
const auto &currArg = argv[argIndex];
const bool hasMoreArgs = (argIndex + 1 < numArgs);
if ("compile" == currArg) {
if ("compile" == currArg || "query" == currArg) {
//skip it
} else if (("-file" == currArg) && hasMoreArgs) {
inputFile = argv[argIndex + 1];
@ -653,6 +684,10 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vector<std::str
} else if (("-revision_id" == currArg) && hasMoreArgs) {
revisionId = std::stoi(argv[argIndex + 1]);
argIndex++;
} else if ("NEO_REVISION" == currArg && queryInvoke && !hasMoreArgs) {
queryOption = QUERY_NEO_REVISION;
} else if ("OCL_DRIVER_VERSION" == currArg && queryInvoke && !hasMoreArgs) {
queryOption = QUERY_OCL_DRIVER_VERSION;
} else {
argHelper->printf("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::vector<std::str
}
if (retVal == SUCCESS) {
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;
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;
}
}
}

View File

@ -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<std::string> &allArgs, bool dumpFiles, int &retVal, OclocArgHelper *helper);
static int query(size_t numArgs, const std::vector<std::string> &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<std::string> &allArgs, bool dumpFiles);
int parseCommandLine(size_t numArgs, const std::vector<std::string> &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<uint8_t> elfBinary;
char *genBinary = nullptr;

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "driver_version.h"
#include <string>
#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

View File

@ -0,0 +1,14 @@
/*
* Copyright (C) 2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <string>
namespace NEO {
extern std::string getRevision();
extern std::string getOclDriverVersion();
} // namespace NEO

View File

@ -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)