OBS Code Reading: ウインドウタイトルのバージョン情報の仕様

はじめに

これは、OBSのウインドウのタイトルがどのように決められているのか突き止めるまでのメモです。

OBSのタイトル部分

今回使用したバージョンはこちらです。

https://github.com/obsproject/obs-studio/tree/e8dc70d0eef4503378d6ac300e680215eb5c9379

結論

開発版のOBSは、ビルド対象のOBSの作業ツリーで

git describe --always --tags --dirty=-modified

を実行した結果がウインドウのタイトルとして使用される。

このコマンドを実行すると、具体的には、このような結果が得られる。

$ git describe --always --tags --dirty=-modified
28.0.0-8-gbfa2053b0-modified

読み方は

  • 作業ディレクトリのツリーは、直近の「28.0.0」というタグから数えて8番目にあたる位置
  • 「bfa2053b0」(先頭の「g」は除く)が直前のコミットのハッシュ値
  • 修正あり

つまり、タイトルを見れば、ビルドされたOBSのバージョンを正確に知ることができる。

調査

OBS 28.0.0がリリースされた時付近に、このバージョン番号変更のコミットがあるのを覚えていました。 github.com

/*
 * Increment if major breaking API changes
 */
#define LIBOBS_API_MAJOR_VER 28

LIBOBS_API_MAJOR_VER の値がタイトルに使われているのでは?という予想の元、LIBOBS_API_MAJOR_VER で検索してみます。 そうすると、以下の関数が見つかりました。コードの内容的に、ここでウインドウタイトルのバージョン情報が作られているのは確実です。

string OBSApp::GetVersionString() const
{
    stringstream ver;

#ifdef HAVE_OBSCONFIG_H
    ver << OBS_VERSION;
#else
    ver << LIBOBS_API_MAJOR_VER << "." << LIBOBS_API_MINOR_VER << "."
        << LIBOBS_API_PATCH_VER;

#endif
    ver << " (";

#ifdef _WIN32
    if (sizeof(void *) == 8)
        ver << "64-bit, ";
    else
        ver << "32-bit, ";

    ver << "windows)";
#elif __APPLE__
    ver << "mac)";
#elif __OpenBSD__
    ver << "openbsd)";
#elif __FreeBSD__
    ver << "freebsd)";
#else /* assume linux for the time being */
    ver << "linux)";
#endif

    return ver.str();
}

Visual Studio上では HAVE_OBSCONFIG_H の分岐が有効になっています。 つまり、開発中は先ほど検索したLIBOBS_API_MAJOR_VERは参照されません。

OBS_VERSION で検索します。 すると、以下のcmake/Modules/VersionConfig.cmakeで値が決定されていることが分かりました。

# Set full and canonical OBS version from current git tag or manual override
if(NOT DEFINED OBS_VERSION_OVERRIDE)
  if(NOT DEFINED RELEASE_CANDIDATE
     AND NOT DEFINED BETA
     AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
    execute_process(
      COMMAND git describe --always --tags --dirty=-modified
      OUTPUT_VARIABLE _OBS_VERSION
      WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
      RESULT_VARIABLE _OBS_VERSION_RESULT
      OUTPUT_STRIP_TRAILING_WHITESPACE)

    if(_OBS_VERSION_RESULT EQUAL 0)
      if(${_OBS_VERSION} MATCHES "rc[0-9]+$")
        set(RELEASE_CANDIDATE ${_OBS_VERSION})
      elseif(${_OBS_VERSION} MATCHES "beta[0-9]+$")
        set(BETA ${_OBS_VERSION})
      else()
        string(REPLACE "-" "." _CANONICAL_SPLIT ${_OBS_VERSION})
        string(REPLACE "." ";" _CANONICAL_SPLIT ${_CANONICAL_SPLIT})
        list(GET _CANONICAL_SPLIT 0 1 2 _OBS_VERSION_CANONICAL)
        string(REPLACE "." ";" _OBS_VERSION ${_OBS_VERSION})
      endif()
    endif()
  endif()

git describe --always --tags --dirty=-modified の値が使われているようです。

実際に実行してみると

$ git describe --always --tags --dirty=-modified
28.0.0-8-gbfa2053b0-modified

のような結果が得られました。ウインドウのタイトルのバージョン情報と一致しています。

このコマンドは、以下のように解釈できます。

  • 作業ディレクトリのツリーは、直近の「28.0.0」というタグから数えて8番目にあたる位置
  • 「bfa2053b0」(先頭の「g」は除く)が直前のコミットのハッシュ値
  • 修正あり

以下の libobs/obsconfig.h.in をテンプレートとして入力し、バージョン情報を置換してobsconfig.hを生成します。

#pragma once

#ifndef ON
#define ON 1
#endif

#ifndef OFF
#define OFF 0
#endif

#define OBS_VERSION "@OBS_VERSION@"
#define OBS_VERSION_CANONICAL "@OBS_VERSION_CANONICAL@"
#define OBS_DATA_PATH "@OBS_DATA_PATH@"
#define OBS_INSTALL_PREFIX "@OBS_INSTALL_PREFIX@"
#define OBS_PLUGIN_DESTINATION "@OBS_PLUGIN_DESTINATION@"
#define OBS_QT_VERSION @_QT_VERSION@
[...]

さらにビルドディレクトリまで検索範囲を広げると、生成されたobsconfig.hが見つかりました。

$ cd obs-build
$ grep -rn OBS_VERSION .
[...]
./config/obsconfig.h:12:#define OBS_VERSION "28.0.0-8-gbfa2053b0-modified"
[...]

これで、ウインドウのタイトルが決められるまでの過程を追うことができました。