Подтвердить что ты не робот

Как я могу автоматически генерировать/обновлять файлы заголовков из файлов cpp без использования среды IDE?

Я использую VIM для разработки на С++ уже довольно много лет, и я не хочу обсуждать вопрос о том, использовать ли IDE или мощный текстовый редактор для разработки программного обеспечения. До сих пор я участвовал в основном с библиотекой шаблонов только для заголовка, где все либо является шаблоном, либо объявлено встроенным, поэтому файлы .cpp не играют важной роли.

В последнее время я больше вовлечен в "традиционную" разработку на С++, столкнувшись с старой проблемой синхронизации заголовка/без заголовка. Мне интересно, есть ли какие-либо средства командной строки, которые могут быть использованы в make-target или интегрированы в VIM для обработки этого задания, то есть обновлять заголовочные файлы на основе файлов .cpp. В основном, объявления классов/структур или (шаблонные и встроенные) реализации должны игнорировать файлы заголовков int, в то время как объявления функций следует добавлять, удалять или обновлять на основе файла .cpp.

Я знаю инструмент lzz, однако для этого требуется, чтобы вы действительно кодировали дополнительный, третий формат файла, который затем предварительно обрабатывается на .h/. cpp до фактической компиляции.

Есть ли что-нибудь, что может сделать эту работу? Как другие разработчики, не связанные с IDE, справляются с этой проблемой?

4b9b3361

Ответ 1

Как мне самому очень интересно узнать ответы на ваш первый вопрос, к сожалению, я не могу дать вам хороший совет здесь.

По крайней мере, вы получите ответ на свой второй вопрос: это несколько полуавтоматический способ, который я использую для ручного добавления отсутствующих или настройки измененных объявлений из файлов заголовков синхронизации.

используйте компилятор с включенными предупреждениями (!), чтобы указать отсутствующие/измененные объявления:

Отрегулируйте объявления

После изменения сигнатуры определения функции gcc выдаст ошибку, подобную следующей:

  • error: conflicting types for ‘....’
    note: previous declaration of ‘....’ was here

Фиксация этого относительно проста, поскольку в сообщении об ошибке уже указаны ссылка на определение и соответствующее объявление.

Поскольку я являюсь пользователем emacs, я не могу сказать вам, как это делается в vi, но я уверен, что есть и простой способ автоматического перехода к этим местам. Все, что нужно сделать, это:

  • перейти к местоположению, скопировать строку

  • переместитесь в локальное место, замените старую строку на копию и добавьте завершающий ;

Отсутствующие объявления

Если с другой стороны была добавлена ​​новая функция без добавления ее прототипа в соответствующий заголовочный файл gcc, он будет бросать что-то вроде:

  • warning: implicit declaration of function ...

Исправлено это таблицей тегов. Опять же, я не знаю точно, как это обрабатывается в vi, но я уверен, что есть способ быстро перейти к определению функции, заданному его именем, в предупреждении компилятора.

Рабочий процесс выглядит следующим образом:

  • перейти к функции.... определение, копировать строку

  • перейдите в файл заголовка, вставьте строку и добавьте завершающий ;

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

Сломанный пример

Чтобы продемонстрировать свое приложение на примере здесь, программа minmal, которая нуждается в исправлениях:

/* main.c */
#include "add.h"

int main (int argc, char *argv[]) {
  int a=0, b=0;

  add (a, b);
  sub (a, b);

  return 0;
}

Обе функции add и sub определены в add.c, показанной ниже:

/* add.c */
#include "add.h"

int add (int a, int b) {
  return a + b;
}

int sub (int a, int b) {
  return a - b;
}

Преступник add.h показывает как несоответствие подписи функции add, так и отсутствующее объявление функции sub:

/* add.h */
long add (long a, long b);

Попытка компиляции приведет к:

gcc -Wall main.c add.c
main.c: In function ‘main’:
main.c:7: warning: implicit declaration of function ‘sub’
add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here

Фиксация примера

Отсутствующие объявления

Первая проблема:

  • main.c:7: warning: implicit declaration of function ‘sub’

Это связано с тем, что в add.h

отсутствует объявление sub

Поиск правильной подписи:

  • C-x ` (следующая ошибка) переместится к месту ошибки
  • M-. (gtags-find-tag) предложит искать тег
  • RET перейдет к определению sub, поскольку символ в точке является значением по умолчанию
  • M-z { (zap-to- char) C-y (yank), чтобы скопировать подпись

Здесь все шаги можно было бы выполнить автоматически с помощью макроса клавиатуры, поскольку никакое вмешательство не требовалось. Следующая часть должна быть сделана вручную:

  • откройте "правильный" заголовочный файл
  • и перейдите к месту, где должно быть введено объявление

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

Наконец, последний шаг - вставить скопированную подпись:

  • C-y M-y вставить скопированную подпись
  • DEL ; заменить { на ;

Настройка объявлений

Далее должно быть исправлено несоответствие между объявлением и определением add.

add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here

Чтобы скопировать новую подпись из определения:

  • C-x ` (следующая ошибка) переместится в местоположение определения
  • M-z { (zap-to- char) C-y (yank), чтобы скопировать подпись

Чтобы заменить объявление:

  • C-x ` (следующая ошибка) переместится в местоположение объявления
  • M-z ; (zap-to- char) для удаления старого объявления
  • C-y M-y теперь вставьте скопированную подпись
  • DEL ; заменить { на ;

И снова

Так как были добавлены два буфера:

  • M-2 M-x burry-buffer должен вернуться в буфер, который был посещен до

Резюме

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

Ручное размещение "правильных" объявлений в заголовке по-прежнему является основным подходом, который я принимаю.

Как изложение API до его реализации, возможно, это не худшая идея IMHO, эта стратегия не должна быть слишком плохим выбором.

Ответ 2

В системах типа UNIX обычно IDE не обрабатывают эту работу (по моему опыту). Инструмент построения (который обычно не поставляется с IDE, например Eclipse, Emacs и т.д.) Будет выполнять эту работу.

В современных системах лучший способ справиться с этим - позволить компилятору сделать это: в конце концов, компилятор знает лучше всего. GCC и большинство других компиляторов UNIX/POSIX имеют параметры, которые будут вызывать объявления зависимостей make-style во время компиляции исходного файла. Вы просто устраиваете это в своем make файле, затем включаете выходные файлы в свой файл makefile, и все это работает очень хорошо.

См., например: http://make.mad-scientist.net/autodep.html

Затем проверьте параметры GCC, такие как -MMD -MP (это опции препроцессора).