Запустите команду в make-файле и выведите STDERR / STDOUT на терминал и в текстовый файл. - PullRequest
0 голосов
/ 27 января 2020

Во-первых, я использую GNU Make 4.3 на Windows 10. Ранее я пробовал GNU Make 4.2.1, которая дала мне те же результаты, что и 4.3.

В любом случае, у меня очень простой make-файл, который делает (или, по крайней мере, намеревается сделать) не что иное, как простую команду и выводит вывод этой команды (как stderr, так и stdout) на терминал и в текстовый файл.

$(info $$(MAKECMDGOALS) is "$(MAKECMDGOALS)". $$(SHELL) is \
"$(SHELL)". $$(MAKESHELL) is "$(MAKESHELL)". $$(COMSPEC) is "$(COMSPEC)". $$(OS) is "$(OS)".)

TEE := C:\tools\UnixTools\usr\local\wbin\tee.exe

LOG_FILE := C:\Temp\loggy__.txt

.PHONY : meep

all : meep

meep :
    $(info Making meep.)
    $(info Running command {dir 2>&1 | $(TEE) $(LOG_FILE)}.)
    $(shell dir 2>&1 | $(TEE) $(LOG_FILE))

Последняя строка - та, которая доставляет мне неприятности. Происходят две вещи, которые противоречат моим ожиданиям:

  1. В то время как вызов $(shell ...) выводит вывод команды dir как в мой текстовый файл, так и на терминал, вывод на терминале странно отформатирован. Там, где обычно dir печатает один элемент на строку, здесь я получаю весь вывод в одну строку, поэтому кажется, что GNU Make (или что-то еще) каким-то образом удаляет символы новой строки из вывода, прежде чем он будет показан в терминале окно.

  2. Кроме того, я получаю сообщение об ошибке The system cannot find the file specified. (и, как обычно, Windows не достаточно хорош, чтобы сказать мне, какой файл он не может найти ). Запуск echo %errorlevel% в той же оболочке CMD, в которой я запускал GNU Make, подтверждает, что вызов Make ошибся (состояние выхода равно 2).

Довольно странно, если я запускаю команду dir 2>&1 | C:\tools\UnixTools\usr\local\wbin\tee.exe C:\Temp\loggy__.txt прямо в окне CMD, все работает точно так, как и следовало ожидать, без каких-либо ошибок, поэтому я думаю, что с функцией GNU Make $(shell ...) что-то не так, или я использую ее неправильно. Кто-нибудь замечает что-то глупое в том, как я пытаюсь использовать функцию $(shell ...)?

Я просто добавил --debug = a в мой вызов make, чтобы получить дополнительные выходные данные отладки, и я нашел следующее в output:

Creating temporary batch file C:\Users\mkemp\AppData\Local\Temp\make23400-1.bat
Batch file contents:
    @echo off
    dir 2>&1 | C:\tools\UnixTools\usr\local\wbin\tee.exe C:\Temp\loggy__.txt
CreateProcess(C:\Users\mkemp\AppData\Local\Temp\make23400-1.bat,C:\Users\mkemp\AppData\Local\Temp\make23400-1.bat,...)
Main thread handle = 00000000000000B4
Cleaning up temporary batch file C:\Users\mkemp\AppData\Local\Temp\make23400-1.bat
Creating temporary batch file C:\Users\mkemp\AppData\Local\Temp\make23400-2.bat
Batch file contents:
    @echo off
    Volume in drive C is Windows  Volume Serial Number is 045A-E422   Directory of C:\tools\UnixTools\usr\local\wbin (... the rest of the output) 
CreateProcess(C:\Users\mkemp\AppData\Local\Temp\make23400-2.bat,C:\Users\mkemp\AppData\Local\Temp\make23400-2.bat,...)

Таким образом, похоже, что функция $(shell ...) GNU Make каким-то образом интерпретирует вывод, произведенный вызовом dir, как дополнительную команду, которую нужно выполнить, что, конечно, бессмысленно.

1 Ответ

2 голосов
/ 27 января 2020

Использование $(shell) - это нонсенс здесь. make действует точно так, как вы указали.

Правильное решение - не добавлять вызов функции $(shell ...) там, где это не имеет смысла.

meep :
    $(info Making meep.)
    $(info Running command {dir 2>&1 | $(TEE) $(LOG_FILE)}.)
    dir 2>&1 | $(TEE) $(LOG_FILE)
...