Как получить статус выхода и вывод команды $ (команда shell) перед тем, как сделать 4.2? - PullRequest
1 голос
/ 25 апреля 2019

На сделать версию 4.2 {2016} была добавлена ​​переменная .SHELLSTATUS. Но мой самый linux использует make version 4.1. Как я могу получить статус выхода и результаты вывода команды make $ (shell ...) в старых версиях make?

С make 4.2 я могу сделать это:

newmake:
    printf '%s\n' "$(shell command && \
        ( printf 'Successfully created the zip file!\n'; exit 0 ) || \
        ( printf 'Error: Could not create the zip file!\n'; exit 1 ) )"
    printf 'Exit status: '%s'\n' "${.SHELLSTATUS}"

Который работает правильно:

printf '%s\n' "Successfully created the zip file!"
Successfully created the zip file!
printf 'Exit status: '%s'\n' "0"
Exit status: 0

Но, если я использую make 4.1 или старше, переменная .SHELLSTATUS отсутствует. Затем я пытаюсь определить свою собственную переменную .SHELLSTATUS следующим образом:

oldmake:
    printf '%s\n' "$(shell command && \
        ( printf 'Successfully created the zip file!\n'; $(eval exit_status := 0) echo ${exit_status} > /dev/null ) || \
        ( printf 'Error: Could not create the zip file!\n'; $(eval exit_status := 1) echo ${exit_status} > /dev/null ) )"
    printf 'Exit status: '%s'\n' "${exit_status}"

Но он работает неправильно:

printf '%s\n' "Successfully created the zip file!"
Successfully created the zip file!
printf 'Exit status: '%s'\n' "1"
Exit status: 1

Как видите, правильное сообщение было напечатано, но статус выхода должен быть 0, а не 1.

Примечание

Сообщения Successfully created the zip file! и Error: Could not create the zip file! являются исключительно иллюстративными и не могут использоваться за пределами $(shell ...). Что у меня внутри оболочки, так это полнофункциональный Python скрипт, который выводит свои результаты на экран:

define NEWLINE


endef

define RELEASE_CODE
from __future__ import print_function
import os
import zipfile

version = "${version}"
if not version:
    print( "Error: You need pass the release version. For example: make release version=1.1", end="@NEWNEWLINE@" )
    exit(1)

CURRENT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
print( "Packing files on %s" % CURRENT_DIRECTORY, end="@NEWNEWLINE@" )

file_names = []
initial_file_names = [
    "Makefile",
    "build.bat",
    "fc-portuges.def",
    os.path.join("setup", "makefile.mk"),
    os.path.join("setup", "scripts", "timer_calculator.sh"),
]

for direcory_name, dirs, files in os.walk(CURRENT_DIRECTORY):

    if ".git" in direcory_name:
        continue

    for filename in files:
        filepath = os.path.join( direcory_name, filename )

        if ".git" in filepath or not ( filepath.endswith( ".tex" )
                or filepath.endswith( ".bib" )
                or filepath.endswith( ".pdf" ) ):
            continue

        file_names.append( filepath )

for filename in initial_file_names:
    filepath = os.path.join( CURRENT_DIRECTORY, filename )
    file_names.append( filepath )

zipfilepath = os.path.join( CURRENT_DIRECTORY, version + ".zip" )
zipfileobject = zipfile.ZipFile(zipfilepath, mode="w")
zipfilepathreduced = os.path.dirname( os.path.dirname( zipfilepath ) )

try:
    for filename in file_names:
        relative_filename = filename.replace( zipfilepathreduced, "" )
        print( relative_filename, end="@NEWNEWLINE@" )
        zipfileobject.write( filename, relative_filename, compress_type=zipfile.ZIP_DEFLATED )

except Exception as error:
    print( "", end="@NEWNEWLINE@" )
    print( "An error occurred: %s" % error, end="@NEWNEWLINE@" )
    exit(1)

finally:
    zipfileobject.close()

print( "", end="@NEWNEWLINE@" )
print( "Successfully created the release version on:@NEWNEWLINE@  %s!" % zipfilepath , end="" )
endef

all:
    printf '%s\n' "$(shell echo \
        '$(subst ${NEWLINE},@NEWLINE@,${RELEASE_CODE})' | \
        sed 's/@NEWLINE@/\n/g' | python - && \
        printf 'Successfully created the zip file!\n' || \
        printf 'Error: Could not create the zip file!\n' )" | sed 's/@NEWNEWLINE@/\n/g'

Теперь он работает правильно, но мне не хватает кода выхода Python, который можно исправить с помощью этого .SHELLSTATUS:

all:
    printf '%s\n' "$(shell echo \
        '$(subst ${NEWLINE},@NEWLINE@,${RELEASE_CODE})' | \
        sed 's/@NEWLINE@/\n/g' | python - && \
        ( printf 'Successfully created the zip file!\n'; exit 0 ) || \
        ( printf 'Error: Could not create the zip file!\n'; exit 1 ) )" | sed 's/@NEWNEWLINE@/\n/g'
    exit "${.SHELLSTATUS}"

Но это работает только для версии make 4.2 или новее.

Связанный:

  1. https://askubuntu.com/questions/93499/assign-standard-exit-status-to-a-makefile-variable
  2. Возвращение значения из вызываемой функции в сценарии оболочки
  3. Как получить статус завершения команды оболочки, используемой в Makefile GNU?
  4. Как заставить GNU сделать сбой, если команда оболочки, назначенная переменной, не удалась?
  5. Коды состояния оболочки в марке
  6. Создать zip-архив с несколькими файлами
  7. Zip Несколько файлов с несколькими результатами в Python
  8. python / zip: Как исключить абсолютный путь в zip-архиве, если указаны абсолютные пути для файлов?
  9. Как отправить входные данные на стандартный ввод скрипту Python, определенному в Makefile?

Ответы [ 2 ]

2 голосов
/ 25 апреля 2019

Я просто не могу понять, почему вы вообще пытаетесь использовать $(shell ...). Это слишком сложно и бессмысленно. Единственный эффект $(shell ...) заключается в том, что он расширяется до запуска любого рецепта. Но вы никогда не пытаетесь использовать это. Напротив, выглядит вполне естественным перемещение сценария непосредственно в рецепт.

Например, рассмотрим это:

unused = """
ifeq (true,false)
"""

# some python stuff
print("Hello world")
exit(1)

unused = """
endif

# here comes make stuff
.ONESHELL:
.PHONY: all
all:
    @/usr/bin/python $(lastword $(MAKEFILE_LIST))
    ec=$$?
    echo "script exitcode is $$ec"
    exit $$ec

#"""

Может быть, даже лучшее решение - просто сделать python настраиваемым SHELL для одного правила. Хотя, в этом случае может быть сложно смешивать скрипты на python и shell в одном правиле (но я не думаю, что это действительно важно).

0 голосов
/ 25 апреля 2019

Мне удалось сделать это, создав файл:

fixedmake:
    printf '%s\n' "$(shell command && \
        printf 'Successfully created the zip file!\n' || \
        ( printf 'Error: Could not create the zip file!\n'; \
            printf 'error\n' > /tmp/has_errors ) )"

    if [ -e /tmp/has_errors ]; \
        then printf 'Exit with errror\n'; \
        rm /tmp/has_errors; \
    else \
        printf 'Exit with success\n'; \
    fi;

->

printf '%s\n' "Successfully created the zip file!"
Successfully created the zip file!
if [ -e /tmp/has_errors ]; \
        then printf 'Exit with errror\n'; \
        rm /tmp/has_errors; \
else \
        printf 'Exit with success\n'; \
fi;
Exit with success

Любая лучшая альтернатива?

...