Обработка stdafx.h в кросс-платформенном коде
У меня есть программа на Visual С++, которая использует предварительно скомпилированные заголовки (stdafx.h
). Теперь мы переносим приложение в Linux с помощью gcc 4.x.
Вопрос заключается в том, как обрабатывать предварительно скомпилированный заголовок в обеих средах.
Я googled, но не могу прийти к выводу.
Очевидно, я хочу оставить stdafx.h
в Visual Studio, так как база кода довольно большая, а предварительно скомпилированные заголовки увеличивают время компиляции.
Но вопрос в том, что делать в Linux. Вот что я нашел:
- Оставьте
stdafx.h
как есть. gcc компилирует код значительно быстрее, чем VС++ (или это только моя машина Linux сильнее...:)), поэтому я, возможно, доволен этой опцией.
-
Используйте подход здесь - сделайте stdafx.h
похожим (установите USE_PRECOMPILED_HEADER
только для VS):
#ifdef USE_PRECOMPILED_HEADER
... my stuff
#endif
-
Используйте подход здесь - скомпилируйте VС++ с /FI
до неявно include stdafx.h
в каждом файле cpp. Поэтому в VS ваш код можно легко переключать, чтобы компилироваться без предварительно скомпилированных заголовков, и код не должен изменяться.
Мне лично не нравятся зависимости, а беспорядок stdafx.h
подталкивает большую базу кода. Поэтому вариант привлекателен для меня - на Linux у вас нет stdafx.h
, но при этом можно включить только предварительно скомпилированные заголовки на VS только /FI
.
- В компиляции Linux
stdafx.h
только как предварительно скомпилированный заголовок (mimic Visual Studio)
Ваше мнение? Существуют ли другие подходы к решению проблемы?
Ответы
Ответ 1
Лучше всего использовать предварительно скомпилированные заголовки для быстрой компиляции.
Вы также можете использовать предварительно скомпилированные заголовки в gcc. См. здесь.
Скомпилированный предварительно скомпилированный заголовок будет иметь расширение, добавленное как .gch
вместо .pch
.
Так, например, если вы предварительно компилируете stdafx.h, у вас будет предварительно скомпилированный заголовок, который будет автоматически искать вызванный stdafx.h.gch
в любое время, когда вы включаете stdafx.h
Пример:
stdafx.h:
#include <string>
#include <stdio.h>
a.cpp:
#include "stdafx.h"
int main(int argc, char**argv)
{
std::string s = "Hi";
return 0;
}
Затем скомпилируйте как:
> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out
Ваша компиляция будет работать, даже если вы удалите stdafx.h после шага 1.
Ответ 2
Я использовал вариант 3 в прошлый раз мне нужно было сделать то же самое. Мой проект был довольно маленьким, но это работало чудесно.
Ответ 3
Я либо поеду на вариант 4, либо на вариант 2. Я экспериментировал с прекомпилированными заголовками как на разных версиях VS, так и на GCC на Linux (сообщения в блогах об этом здесь и здесь). По моему опыту, VS намного более чувствителен к длине включенных путей, количеству каталогов в пути включения и количеству файлов include, чем g++. Когда я измерил время сборки правильно упорядоченных предварительно скомпилированных заголовков, это существенно изменило бы время компиляции под VS, тогда как g++ в значительной степени не впечатлило это.
Собственно, на основании вышеизложенного, что я делал в последний раз, когда я работал над проектом, когда это было необходимо, чтобы обуздать время компиляции, было прекомпилировать эквивалент stdafx.h под Windows, где это имело смысл и просто использовало его как обычный файл под Linux.
Ответ 4
Очень простое решение.
Добавьте фиктивную запись файла для "stdafx.h" в среду Linux.
Ответ 5
Это просто, действительно:
Project- > Настройки проекта (Alt + F7)
Параметры проекта-Диалог:
С++ → Категория: Предварительно скомпилированные заголовки → Предварительно скомпилированные заголовки с переключателями → отключить
Ответ 6
Так как stdafx.h
по умолчанию все компоненты, относящиеся к Windows, я поместил пустой stdafx.h
на другую платформу. Таким образом, ваш исходный код остается идентичным при эффективном отключении stdafx
от Linux без необходимости удаления всех строк #include "stdafx.h"
из вашего кода.
Ответ 7
Я бы использовал только вариант 1 в большой команде разработчиков.
Варианты 2, 3 и 4 часто останавливают производительность других членов вашей команды, поэтому вы можете сэкономить несколько минут в день во время компиляции.
Вот почему:
Предположим, что половина ваших разработчиков использует VS и половину использования gcc.
Время от времени какой-то разработчик VS забудет включить заголовок в .cpp файл.
Он не заметит, потому что stdafx.h неявно включает его. Таким образом, он подталкивает свои изменения в контроле версий, а затем несколько других членов команды gcc получат ошибки компилятора.
Таким образом, за каждые 5 минут в день вы получаете, используя предварительно скомпилированные заголовки, 5 других людей тратят время, исправляя недостающие заголовки.
Если вы не используете один и тот же код для всех своих компиляторов, вы будете сталкиваться с такими проблемами каждый день. Если вы заставляете разработчиков VS проверять компиляцию на gcc перед тем, как нажимать изменения, вы отбросите все свои выгоды от использования предварительно скомпилированных заголовков.
Вариант 4 звучит привлекательно, но что, если вы хотите использовать другой компилятор в какой-то момент? Вариант 4 работает только в том случае, если вы используете только VS и gcc.
Обратите внимание, что опция 1 может сделать компиляцию gcc несколько секунд. Хотя это может быть и не заметно.
Ответ 8
Если вы используете CMake в своем проекте, то есть модули, которые автоматизируют его для вас, очень удобно, например, см. cmake-precompiled-header здесь. Чтобы использовать его, просто включите модуль и вызовите:
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( ${target} ${header} FORCEINCLUDE SOURCE_CXX ${source} )
Другой модуль под названием Cotire создает предварительно скомпилированный файл заголовка (нет необходимости вручную писать StdAfx.h) и ускоряет сборку другими способами - см. здесь.
Ответ 9
Я сделал как вариант 2 (#ifdef), так и вариант 4 (PCH для gcc) для кросс-платформенного кода без проблем.
Я нахожу, что gcc компилируется намного быстрее, чем VS, поэтому предварительно скомпилированные заголовки, как правило, не так важны, если вы не ссылаетесь на какой-то огромный файл заголовка.