diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index deb063e..c49b6fc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,6 +31,9 @@ jobs: sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 1 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 1 + - name: Generate version information + run: ./scripts/generate-version.sh + - name: Build run: bazel build //src:all //src/quipper:all diff --git a/scripts/build-deb.sh b/scripts/build-deb.sh index ba81264..4cb4ec4 100755 --- a/scripts/build-deb.sh +++ b/scripts/build-deb.sh @@ -5,6 +5,10 @@ VERSION=$1 # e.g. "v1.2.3" OUTDIR="$PWD/artifacts" mkdir -p "$OUTDIR" +# Generate version information +echo "Generating version information..." +./scripts/generate-version.sh + # Build the project with Bazel (with static linking for better compatibility) echo "Building perf_to_profile with Bazel..." bazel build \ diff --git a/scripts/generate-version.sh b/scripts/generate-version.sh new file mode 100755 index 0000000..a5ba78a --- /dev/null +++ b/scripts/generate-version.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Script to generate version information for perf_to_profile +# Usage: ./scripts/generate-version.sh [output_file] + +OUTPUT_FILE="${1:-src/version.h}" + +# Try to get version from git +if git rev-parse --git-dir > /dev/null 2>&1; then + # Get the latest tag + if GIT_TAG=$(git describe --tags --exact-match 2>/dev/null); then + # We're on a tagged commit + VERSION="$GIT_TAG" + elif GIT_TAG=$(git describe --tags --abbrev=0 2>/dev/null); then + # Get commit count since last tag and short hash + COMMIT_COUNT=$(git rev-list --count "${GIT_TAG}..HEAD") + SHORT_HASH=$(git rev-parse --short HEAD) + VERSION="${GIT_TAG}-${COMMIT_COUNT}-g${SHORT_HASH}" + else + # No tags found, use commit hash + SHORT_HASH=$(git rev-parse --short HEAD) + VERSION="git-${SHORT_HASH}" + fi + + # Add dirty suffix if working directory is not clean + if ! git diff-index --quiet HEAD --; then + VERSION="${VERSION}-dirty" + fi +else + # Not a git repository, use default + VERSION="development" +fi + +echo "Generating version: $VERSION" + +# Create the version header file +cat > "$OUTPUT_FILE" << EOF +/* + * Copyright (c) 2024, Google Inc. + * All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef PERFTOOLS_VERSION_H_ +#define PERFTOOLS_VERSION_H_ + +// Version information for perf_to_profile +// Generated automatically by scripts/generate-version.sh + +#define PERF_TO_PROFILE_VERSION "$VERSION" + +#endif // PERFTOOLS_VERSION_H_ +EOF + +echo "Version header generated: $OUTPUT_FILE" diff --git a/src/BUILD b/src/BUILD index d47cbb2..912c988 100644 --- a/src/BUILD +++ b/src/BUILD @@ -131,7 +131,10 @@ cc_test( cc_library( name = "perf_to_profile_lib", srcs = ["perf_to_profile_lib.cc"], - hdrs = ["perf_to_profile_lib.h"], + hdrs = [ + "perf_to_profile_lib.h", + "version.h", + ], deps = [ ":perf_data_converter", "//src/quipper:base", diff --git a/src/perf_to_profile_lib.cc b/src/perf_to_profile_lib.cc index 49e982d..28b9e09 100644 --- a/src/perf_to_profile_lib.cc +++ b/src/perf_to_profile_lib.cc @@ -9,6 +9,9 @@ #include #include +#include + +#include "src/version.h" bool FileExists(const std::string& path) { struct stat file_stat; @@ -57,6 +60,11 @@ void PrintUsage() { << "profile."; LOG(INFO) << "If the -j option is given, allow unaligned MMAP events " << "required by perf data from VMs with JITs."; + LOG(INFO) << "Use --version to print version information."; +} + +void PrintVersion() { + LOG(INFO) << "perf_to_profile version " << PERF_TO_PROFILE_VERSION; } bool ParseArguments(int argc, const char* argv[], std::string* input, @@ -66,9 +74,17 @@ bool ParseArguments(int argc, const char* argv[], std::string* input, *output = ""; *overwrite_output = false; *allow_unaligned_jit_mappings = false; + + // Define long options + static struct option long_options[] = { + {"version", no_argument, 0, 'v'}, + {0, 0, 0, 0} + }; + int opt; - while ((opt = getopt(argc, const_cast(argv), ":jfi:o:")) != - -1) { + int option_index = 0; + while ((opt = getopt_long(argc, const_cast(argv), ":jfi:o:", + long_options, &option_index)) != -1) { switch (opt) { case 'i': *input = optarg; @@ -82,6 +98,10 @@ bool ParseArguments(int argc, const char* argv[], std::string* input, case 'j': *allow_unaligned_jit_mappings = true; break; + case 'v': // --version + PrintVersion(); + exit(EXIT_SUCCESS); + break; case ':': LOG(ERROR) << "Must provide arguments for flags -i and -o"; return false; diff --git a/src/perf_to_profile_lib.h b/src/perf_to_profile_lib.h index d26f371..4bfeba3 100644 --- a/src/perf_to_profile_lib.h +++ b/src/perf_to_profile_lib.h @@ -43,4 +43,7 @@ bool ParseArguments(int argc, const char* argv[], std::string* input, // Prints the usage of the tool. void PrintUsage(); +// Prints the version of the tool. +void PrintVersion(); + #endif // PERFTOOLS_PERF_TO_PROFILE_LIB_H_ diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..271fa89 --- /dev/null +++ b/src/version.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024, Google Inc. + * All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef PERFTOOLS_VERSION_H_ +#define PERFTOOLS_VERSION_H_ + +// Version information for perf_to_profile +// Generated automatically by scripts/generate-version.sh + +#define PERF_TO_PROFILE_VERSION "v0.0.5-7-g9ae6d28-dirty" + +#endif // PERFTOOLS_VERSION_H_