Работа с большими заголовочными файлами

Сначала немного предыстории:

Я использую Visual Studio 2017 - Профессиональное дополнение

Разработка собственного приложения для Android на C++

Я использовал стандартный шаблон. Итак, у меня есть чистая библиотека C++ (11), в которой находится весь мой код. И предварительно скомпилированный заголовок, определенный в основном проекте, который ссылается на мою библиотеку.

Что я делаю

Я работаю над кодом, который требует большого количества встроенных данных.

Я искал в Google хорошие способы сделать это, но большинство из них кажутся очень хлопотными, и почти всегда были комментарии, в которых говорилось, что нужно просто помещать данные непосредственно в файлы заголовков, поскольку это наиболее переносимый способ.

Итак, теперь у меня есть несколько файлов заголовков, которые в основном содержат статические массивы данных. ПРИМЕЧАНИЕ они не являются «константными», как если бы вы это сделали, тогда Visual Studio 2017 попытается отобразить данные, если вы переместите определение переменной. Так что просто статично.

Затем все файлы заголовков объединяются в один файл заголовка, и на него, наконец, ссылаются в стандартном файле cpp. эффективно делая данные приватными для этого класса.

Все работает нормально. НО время компиляции становится очень медленным. И если я смотрю окно вывода, я вижу, что он тратит 80% своего времени на файл cpp (даже если не было изменений в данных или коде)

Теперь это не лучшее, что может сделать компилятор. Я ожидал, что компилятор пропустит это, поскольку не было изменений, которые напрямую влияют на файл cpp.

Я также попытался переместить вещи в предварительно скомпилированный заголовок. Но из-за этого для создания файла pch.h каждый раз требуется много времени.

Так что я делаю не так?

Обновлять

Я дважды проверил, что файлы не были изменены. Если я нажму F6 (сборка), а затем снова нажму, он все равно восстановит большие файлы.

Я также попытался переработать статические данные, чтобы они были определены в файле cpp. И это все равно без разницы.

Для наглядности это пример:

.cpp файл:

#include "Some.h"

unsigned char _someData[] =
{
   0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00,
};

unsigned char* Some::GetSomeData(void)
{
   return _someData;
}

.h файл:

#pragma once

class Some
{
public:
static unsigned char* GetSomeData(void);
};

Очевидно, компилятор не должен перекомпилировать, если в коде не было изменений. Вот где вам следует искать. Сравните, например, временные метки исходного и объектного файлов. Во-вторых, зачем помещать данные в файл заголовка, который включен в один файл cpp. Почему бы просто не поместить данные в файл cpp? Это лучшая практика.

john 25.07.2018 09:31

Через некоторое время я дважды проверю метки времени. Данные находятся в файле .h, поскольку данные генерируются другим автономным процессом. Этот процесс может воссоздать файл .h, не уничтожая ничего другого. Если я хочу, чтобы данные находились непосредственно в моем файле cpp, тогда мой набор инструментов должен быть более сложным и «знать» больше о системе. Это не было бы хорошим дизайном.

Paul Spain 25.07.2018 09:37

Забыл сказать, что я бы предпочел решение, отличное от Android. То есть кое-что, что я могу сделать только в родном C++, чтобы его можно было портировать для работы на Apple.

Paul Spain 25.07.2018 09:54

Определите данные в файле cpp и функции получения и объявите этот метод получения в файле .h. Кстати, какой фреймворк вы используете, чтобы приложение работало на Android и IOS?

jaudo 25.07.2018 09:59

Я могу подтвердить, что ни один из файлов не меняется между сборками. Простое нажатие F6 (сборка) дважды подряд будет иметь один и тот же эффект каждый раз (долгая компиляция в файле cpp)

Paul Spain 25.07.2018 10:02

@jaudo Мне потребуется время, чтобы переработать мой инструмент, чтобы он создавал файлы cpp. но я попробую. Что касается фреймворка. Это стандартный нативный кроссплатформенный шаблон C++ в Visual Studio. это называется (Приложение OpenGLES (Android, iOS)). На данный момент 99,9% всего моего кода находится в общей части C++, и именно так я хотел бы сохранить его.

Paul Spain 25.07.2018 10:07

@jaudo, поэтому я переделал свой инструмент. теперь он создает файл .h, содержащий GetData (); и теперь у меня также есть cpp, который определяет данные получения. И я могу сказать, что это не имело никакого значения. Единственное изменение состоит в том, что теперь он показывает мне много файлов, создание которых в сумме занимает столько же времени. Я понятия не имею, почему файлы cpp собираются каждый раз.

Paul Spain 25.07.2018 10:40

Вы сказали, что ваш файл cpp был создан с помощью инструмента. Вы запускаете свой инструмент перед каждой сборкой C++? Вы уверены, что выполните команду «Построить», а не «Перестроить»?

jaudo 25.07.2018 11:37

> Теперь это не лучшее, что может сделать компилятор. Я ожидал, что компилятор пропустит это, поскольку не было изменений, которые напрямую влияют на файл cpp. Что ж, MSVC не лучший компилятор, когда дело касается этих вещей. Но это действительно лучшее, что он может. Вы не можете ожидать, что компилятор «пропускает» части заголовков, потому что они не влияют на реальный код. Это просто принятие желаемого за действительное, и это очень неправильно.

rubenvb 25.07.2018 11:40
«Я также пробовал переработать статические данные, чтобы они были определены в файле cpp. И это все равно не имеет значения». Это меня удивляет. Я бы так поступил (и делал это раньше).
Lightness Races in Orbit 25.07.2018 11:50

@LightnessRacesinOrbit Вы можете удивляться, как хотите, пока это правда.

Paul Spain 25.07.2018 21:35

@jaudo Мой инструмент - это совершенно отдельный проект на C#, я запускаю его вручную как отдельный процесс. Нет никакого способа, чтобы это могло помешать перекомпиляции C++.

Paul Spain 25.07.2018 21:43

@PaulSpain: Кажется, вы меня неправильно поняли. Я пытаюсь сказать, что вы почти наверняка что-то упустили, учитывая представленные доказательства. Конечно, вы можете проигнорировать мой совет; Вы же не пришли сюда в поисках второго мнения, верно? :)

Lightness Races in Orbit 26.07.2018 02:44

@LightnessRacesinOrbit вы совершенно правы .. Однако я уже знаю, что так быть не должно. отсюда и мой вопрос. Так получилось, что теперь я знаю, в чем была проблема. См. Комментарии к ответу SHR

Paul Spain 26.07.2018 02:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
14
183
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете рассмотреть возможность использования файлов данных (вне вашего кода), которые вы читаете при запуске программы. Это создаст некоторые накладные расходы (время чтения файла), но вы решите проблемы времени компиляции.

Я не верю, что это практично / возможно при разработке приложений для Android. Все данные должны находиться в файле APK. Я не смогу загрузить то, что было отправлено. Разве вы не знаете иначе?

Paul Spain 25.07.2018 09:27

Что насчет: 1) Файлы данных не отправляются 2) При первом запуске приложения загрузите файлы данных и сохраните их в хранилище.

jaudo 25.07.2018 09:30

В интересной возможности. Но это похоже на решение плана Б. Должно быть что-то не так, как я ожидаю, что компилятор будет работать. Но спасибо за хорошую идею! +1

Paul Spain 25.07.2018 09:40

Вы можете использовать ресурсы: developer.android.com/guide/topics/resources/…

jaudo 25.07.2018 09:42

Джаудо, мне придется внимательно изучить это, но похоже, что это не сработает в моем случае для нативной платформы C++ / кросс-платформы. (Забыл сказать, что это кроссплатформенный, но это то, что я имел в виду, когда сказал портативный)

Paul Spain 25.07.2018 09:52
Ответ принят как подходящий

Чтобы сэкономить время компиляции, попробуйте следующее:

  1. Убедитесь, что ваш проект не содержит недостающих файлов. Это вызывает повторную компиляцию, даже если никаких изменений нет).
  2. Не помещайте данные в заголовки, помещайте данные в файлы c \ cpp и используйте extern переменных данных в заголовках.
  3. Не включайте ненужные заголовки из другого заголовка. (любое изменение в заголовке приведет к перекомпиляции всего)
  4. Всегда предпочитайте использовать предварительное объявление в заголовках, когда это возможно (вместо включения).
  5. Обратите внимание на разницу между #include <file> и #include "file". если вы выберете неправильный метод включения (например, используйте <> для включения вашего файла или "" для включения системы), вы потратите больше времени на поиск файла.
  6. Упорядочивайте включаемые каталоги от наиболее распространенных к менее распространенным, это также может сэкономить время при поиске файла.

Если вы не хотите знать, почему проект или файл перекомпилировали или перекомпилировали, даже если изменений не было, вы можете сделать это следующим образом:

  1. Меню: инструменты -> параметры
  2. В открывшейся левой панели Параметры: Проект и решение-> Сборка и запуск:
  3. Затем на правой панели: измените подробность вывода сборки проекта MSBuild на «Диагностика».
  4. Построить проект
  5. Найдите в диагностических данных, почему он был перекомпилирован.

Удачи

Ваш первый номер 3 - самый важный. Конечно, причина повторяющейся перекомпиляции - это следующее, но исправление этого не решит проблему длительного времени компиляции.

rubenvb 25.07.2018 11:39

Хорошо, спасибо за подсказку! Наконец-то я понял. С помощью настройки диагностики все становится ясно. Код перестраивался из-за отсутствия файла. Таким образом, даже если нет никаких изменений, он все равно все перестроит. Как только я получил эту деталь, было легко найти и исправить проблему. выглядело так, будто у меня был какой-то странный файл заголовка, который не был правильно удален, но на самом деле не нужен и поэтому не тормозил сборку. Большое спасибо за ваше время и помощь.

Paul Spain 26.07.2018 02:51

Другие вопросы по теме