2016-12-07 2 views
4

У меня есть Makefile, где одна цель зависит от нескольких файлов - каждая из которых должна обрабатываться отдельно (без предоставления промежуточных выходных файлов). Мой конкретный сценарий более сложный:Как подать несколько файлов на фоновый процесс с помощью Makefile

У меня есть источник C, из которого я хотел бы извлечь определения перечислений. Есть несколько морщин, которые я не могу изменить:

  1. Компилятор не GCC - это настраиваемый компилятор от Cosmic Software.
  2. В дополнение к компилятору я могу запустить анализатор (давайте назовем его parser.exe) сам по себе, и у него есть опция (-e) для вывода предварительно обработанного источника на STDOUT.
  3. make на самом деле является проприетарной версией, которая поставляется с программным пакетом PTC Integrity. Он не поддерживает циклы - если я хочу использовать циклы, мне придется делать пакетные скрипты Windows.
  4. Это все работает на Windows,

Я написал утилиту (с помощью C# и ANTLR), давайте назовем его ExtractEnums.exe, который извлекает перечислений (и вычисляет выражения) от источника С тех пор, как источник был предварительно обработан. Предварительно обработанный источник в целом весит чуть более 30 МБ. Вместо того, чтобы писать предварительно обработанный источник на диск с помощью анализатора Cosmic, я решил связать его с ExtractEnums.exe. Поскольку мне нужно вызвать синтаксический анализатор для каждого исходного файла, мне нужно использовать именованный канал, а не только оператор pipe (|). В Windows названные каналы не получают реальных имен файлов, поэтому вы увидите ExtractEnums.exe -client для записи в трубу и фоновый процесс ExtractEnums.exe -server, который читается из трубы в приведенном ниже примере.

############################################################################ 
# Dummy files - these will never exist 
# 
D_FILES = $(SRCS:.c=.dummy)      # All dummy files 

server : 
    cmd /c start /B ExtractEnums.exe -server > temp.pipe 

%.dummy : %.c server 
    cmd /c parser.exe $(DEFINES_AND_OPTS) -e $^ | cmd /c ExtractEnums.exe -client 

# Extract enums from all the preprocessed source: 
%.enums : $(D_FILES) 
    cmd /c echo ;;exit;; | cmd /c ExtractEnums.exe -client 
    cmd /c move temp.pipe [email protected] 

Это все работает, если я звоню make product_name.enums. SRCS - это список всех исходных файлов. ;;exit;; - это специальная строка, которую я отправляю на адрес ExtractEnums.exe -server, чтобы сообщить об этом для выхода. Вот проблема:

Чтобы перебрать все источники и передать их в препроцессор, я составил список .dummy файлов, которые никогда не будут существовать. Поскольку они никогда не существуют, цели всегда устарели. Это означает, что вызов make product_name.enums всегда будет запускать все источники через препроцессор, даже если источники не изменились.

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

+2

Ваше описание проблемы 2 неясно. Получатель (запущенный по правилу 'server') направляет вывод в' product_name.pipe', а правило '% .enums' переименовывает этот файл в другое. В чем проблема? – Beta

+1

Вы можете уменьшить все до одной цели '% .enums', используя периодические циклы, когда вы укажете в своем вопросе. Любая причина не делать этого? – perencia

+0

@ Бета - Наверное, ты прав. product_name.pipe - это всего лишь временный файл. Я отредактирую свой вопрос, чтобы было ясно, что это временный файл и удалить элемент # 1. – watkipet

ответ

0

Я столкнулся с этим старым вопросом при решении подобной проблемы. Просто переверните файлы «dummy» в реальные (пустые), чтобы отслеживать последний раз, когда вы обрабатывали исходный файл. В следующем I группы их в подкаталоге (dummies) таким образом, чтобы они не мешали слишком много с исходным деревом:

D_DIR = dummies 
D_FILES = $(patsubst %.c,$(D_DIR)/%.dummy,$(SRCS)) # All dummy files 

$(D_DIR)/%.dummy : %.c 
    [ -f server ] || { cmd /c start /B ExtractEnums.exe -server > temp.pipe && touch server; } 
    cmd /c parser.exe $(DEFINES_AND_OPTS) -e $^ | cmd /c ExtractEnums.exe -client 
    mkdir -p $(dir [email protected]) # create dummy's directory if it does not exist 
    touch [email protected]   # create dummy 

# Extract enums from all the preprocessed source: 
%.enums : $(D_FILES) 
    cmd /c echo ;;exit;; | cmd /c ExtractEnums.exe -client 
    rm -f server 
    cmd /c move temp.pipe [email protected] 

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

Смежные вопросы