Shell 如何在Makefile中定义子例程

Shell 如何在Makefile中定义子例程,shell,makefile,bsdmake,Shell,Makefile,Bsdmake,我正在制作一个Makefile,它有一个使用M4生成文件的“收据”。它使用一些复杂的shell构造来计算必须传递给M4的宏值。如何组织代码以避免下面示例中显示的冗余声明 M4TOOL= m4 M4TOOL+= -D PACKAGE=$$(cd ${PROJECTBASEDIR} && ${MAKE} -V PACKAGE) M4TOOL+= -D VERSION=$$(cd ${PROJECTBASEDIR} && ${MAKE} -V VERSION) M4TO

我正在制作一个
Makefile
,它有一个使用M4生成文件的“收据”。它使用一些复杂的shell构造来计算必须传递给M4的宏值。如何组织代码以避免下面示例中显示的冗余声明

M4TOOL= m4
M4TOOL+= -D PACKAGE=$$(cd ${PROJECTBASEDIR} && ${MAKE} -V PACKAGE)
M4TOOL+= -D VERSION=$$(cd ${PROJECTBASEDIR} && ${MAKE} -V VERSION)
M4TOOL+= -D AUTHOR=$$(cd ${PROJECTBASEDIR} && ${MAKE} -V AUTHOR)
M4TOOL+= -D RDC960=$$(openssl rdc960 ${DISTFILE} | cut -d ' ' -f 2)
M4TOOL+= -D SHA256=$$(openssl sha256 ${DISTFILE} | cut -d ' ' -f 2)

Portfile: Portfile.m4
    ${M4TOOL} ${.ALLSRC} > ${.TARGET}

真的很多

您应该使用shell的
-c
选项定义伪命令,如下所示:

PROJECTVARIABLE=sh -c 'cd ${PROJECTBASEDIR} && ${MAKE} -V $$1' PROJECTVARIABLE
OPENSSLHASH=sh -c 'openssl $$1 $$2 | cut -d " " -f 2' OPENSSLHASH
M4TOOLS+= -D PACKAGE=$$(${PROJECTVARIABLE} PACKAGE)
M4TOOLS+= -D VERSION=$$(${PROJECTVARIABLE} VERSION)
M4TOOLS+= -D AUTHOR=$$(${PROJECTVARIABLE} AUTHOR)
M4TOOLS+= -D RMD160=$$(${OPENSSLHASH} rmd160 ${DISTFILE})
M4TOOLS+= -D SHA256=$$(${OPENSSLHASH} sha256 ${DISTFILE})
请注意使用
$
$
来使用
bsdmake
变量扩展或shell变量扩展。使用这些定义,您可以按如下方式重新组织代码:

PROJECTVARIABLE=sh -c 'cd ${PROJECTBASEDIR} && ${MAKE} -V $$1' PROJECTVARIABLE
OPENSSLHASH=sh -c 'openssl $$1 $$2 | cut -d " " -f 2' OPENSSLHASH
M4TOOLS+= -D PACKAGE=$$(${PROJECTVARIABLE} PACKAGE)
M4TOOLS+= -D VERSION=$$(${PROJECTVARIABLE} VERSION)
M4TOOLS+= -D AUTHOR=$$(${PROJECTVARIABLE} AUTHOR)
M4TOOLS+= -D RMD160=$$(${OPENSSLHASH} rmd160 ${DISTFILE})
M4TOOLS+= -D SHA256=$$(${OPENSSLHASH} sha256 ${DISTFILE})
结果可以说更易于阅读和维护。编写此类脚本时,请记住使用错误代码和stderr报告错误


PS:您可以在FreeBSD系统上查看
/usr/ports/Mk/bsd.port.Mk
中的
COPYTREE\u SHARE
宏。它很好地说明了这项技术。

你能更具体一点吗?您希望避免哪些冗余声明?即使您可以定义一个子例程,更大的问题是您仍然需要调用
make
3次。您可以将
-V
的多个用法分组,将其简化为一个,但您需要一些额外的shell来将其解析为
m4
的3个单独的
-d
选项。结合对
openssl
@AndrejAdamenko的两个调用,你做不了多少事情。我想减少
cd…&&${MAKE}-V
的冗余,并找到一种“更假”的方式来放置东西。@chepner我可以接受对
MAKE
的许多调用,我有更多的可读性/维护性问题。包含定义适当值的第二个makefile或将
m4
调用封装在真实脚本中可能更有效。