Портабельный макрос для получения строки версии C++ компилятора и времени сборки приложения?

Понятно, что стандартного макроса не существует. Можно и самому наваять, но для этого нужно знать все compiler-specifc макросы (в общем-то не сложно их найти) и желательно возможность проверить их в работе.

Хочется, чтобы в исполняемый бинарник оказалась зашита версия компилятора в виде строки.

Также интересует такой же портабельный способ получить время сборки приложения, тут наверное посложнее, ведь нужно именно время линковки, а не компиляции. Как зашить эту информацию в бинарник?
  • Вопрос задан
  • 3002 просмотра
Решения вопроса 1
EXL
@EXL
Энтузиаст
Находим серьёзную кросс-платформенную программу с открытыми исходниками, я выбрал Qt Creator.

Заходим в диалог "About" и видим как раз то, что нам нужно:

wmUZzbo.png

Находим построение этого диалога в исходном коде - [src/plugins/coreplugin/versiondialog.cpp | 77].

Видим, что для получения даты и времени сборки использованы тривиальные предопредёленные макросы __DATE__ и __TIME__, которые гарантировано должны быть предопределены во всех компиляторах.

А вот для нахождения версии компилятора используется специальная функция ICore::buildCompatibilityString(). Проследуем по цепочке вызовов: [src/plugins/coreplugin/icore.cpp | 472].

В функции ICore::buildCompatibilityString() используется вызов статической функции compilerString() для получения информации о компиляторе и QSysInfo::WordSize для получения информации о битности порождаемого компилятором кода.

Функция compilerString() [src/plugins/coreplugin/icore.cpp | 440-458] выглядит так:

static QString compilerString()
{
#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
    QString isAppleString;
#if defined(__apple_build_version__) // Apple clang has other version numbers
    isAppleString = QLatin1String(" (Apple)");
#endif
    return QLatin1String("Clang " ) + QString::number(__clang_major__) + QLatin1Char('.')
            + QString::number(__clang_minor__) + isAppleString;
#elif defined(Q_CC_GNU)
    return QLatin1String("GCC " ) + QLatin1String(__VERSION__);
#elif defined(Q_CC_MSVC)
    if (_MSC_VER >= 1800) // 1800: MSVC 2013 (yearly release cycle)
        return QLatin1String("MSVC ") + QString::number(2008 + ((_MSC_VER / 100) - 13));
    if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ... (2-year release cycle)
        return QLatin1String("MSVC ") + QString::number(2008 + 2 * ((_MSC_VER / 100) - 15));
#endif
    return QLatin1String("<unknown compiler>");
}

Макросы Q_CC_CLANG, Q_CC_GNU и Q_CC_MSVC можно заменить на __clang__, __GNUC__ || __MINGW32__ и _MSC_VER соответственно. Вызовы QLatin1String() можно заменить обычным std::string, QString::number() - чем-нибудь типа sprintf, itoa, std::to_string (если используете c++11).

А QSysInfo::WordSize это простой:

enum Sizes {
        WordSize = (sizeof(void *)<<3)
};

Удачи!
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
risik
@risik
Программист
Ничего сложного нет. Если не смотреть на исходный текст, как на что-то данное свыше. Например, можно все сделать по аналогии вот с этим: stackoverflow.com/questions/151299/embedding-svn-r...
Ответ написан
donkaban
@donkaban
Умею рисовать тени
в elf2 и так пишется версия компилятора и платформы (включая GLIBC и GLIBCXX). gcc и clang на компоновке пишут в .comment, в чем легко убедиться -
readelf -p .comment t

Что там с некошерным PE - не знаю.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы