【问题标题】:How to get the exit status and the output of a $(shell command) before make 4.2?如何在 make 4.2 之前获取退出状态和 $(shell 命令) 的输出?
【发布时间】:2019-09-14 07:47:30
【问题描述】:

make version 4.2 {2016} 上添加了变量.SHELLSTATUS。但我的大多数 linux 都使用 make 版本4.1。如何在旧版 make 上获取 make $(shell ...) 命令的退出状态和输出结果?

使用 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 ...) 之外使用。我在 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. Returning value from called function in a shell script
  3. How to get exit status of a shell command used in GNU Makefile?
  4. How to make GNU Make fail if a shell command assigned to a variable failed?
  5. Shell status codes in make
  6. Create zip archive with multiple files
  7. Zip Multiple files with multiple result in Python
  8. python/zip: How to eliminate absolute path in zip archive if absolute paths for files are provided?
  9. How to send input on stdin to a python script defined inside a Makefile?

【问题讨论】:

  • 从源代码构建和安装更新的make 是否可行?
  • 没有。重点是为最终用户提供轻松的解决方案。管理创建一个临时文件更实用,因为除了要求它们运行sudo apt install make之外不需要任何更改。

标签: shell makefile return return-value


【解决方案1】:

我完全不明白您为什么要尝试使用$(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 脚本可能会很棘手(但我认为这不是必需的)。

【讨论】:

    【解决方案2】:

    我设法通过创建一个文件来做到这一点:

    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
    

    还有更好的选择吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      • 2011-06-21
      • 2013-04-25
      • 1970-01-01
      • 2013-03-01
      • 1970-01-01
      • 2010-12-28
      相关资源
      最近更新 更多