Makefile에 bash 스크립트를 정확하게 작성하는 방법은 무엇입니까?

Makefile에 bash 스크립트를 정확하게 작성하는 방법은 무엇입니까?

나는 bash 스크립트를 작성하는 것을 좋아하지만 여러 도구를 준비하면 프로젝트의 루트 디렉토리가 많은 쉘 스크립트로 채워질 것입니다. 이것이 바로 Makefile을 사용하는 것을 선호하는 이유입니다.

Makefile은 괜찮습니다. 그러나 나는 일반 bash 스크립트처럼 makefile을 만들고 싶습니다.

예를 들어:

생각해보니 나는 다음과 같은 내용으로 bash 스크립트를 빠르게 작성했습니다.

#!/bin/bash
echo "hello"
cd ~
do-some-work.sh my-parameter

을 사용하여 이 스크립트를 실행할 수 있습니다 $ ./my-important-task.sh.

이 스크립트를 makefile로 옮기려면 다음을 수행해야 합니다.

SHELL := /bin/bash 

my-important-task: 
    echo "hello" ;\
    cd ~ ;\
    do-some-work.sh my-parameter

하지만 나는 다음을 원합니다:

my-important-task: 
    [[copy and paste the my-important-task.sh file]]

이것을 달성할 수 있는 방법이 있나요?

답변1

정말로 "Makefiles에 bash 스크립트를 정확하게 작성"하려면 간접적으로 수행해야 합니다. 대상 줄 뒤에 스크립트를 붙여넣기만 하면 해결할 수 없는 두 가지 문제에 직면하게 됩니다. 즉, 명령줄을 탭으로 들여쓰기해야 하고 달러 기호를 이스케이프해야 합니다.

GNU make(BSD make, Solaris make 등과 반대)를 사용하는 경우 다음을 사용하여 스크립트를 변수로 정의할 수 있습니다.여러 줄 정의 구문, 그런 다음 사용value기능확장을 우회하고 변수의 원래 값을 사용합니다.

또한,skwllsp의 설명에 따르면, 각 대상에 대한 명령 목록을 GNU make에서 한 줄씩 실행하는 대신 단일 쉘 스크립트로 실행하도록 make에게 지시해야 합니다..ONESHELL목표 정의.

define my_important_task =
# script goes here
endef

my-important-task: ; $(value my_important_task)

.ONESHELL:

답변2

https://www.gnu.org/software/make/manual/html_node/One-Shell.html

.ONESHELL 특수 대상이 makefile의 어느 위치에나 나타나는 경우 각 대상에 대한 모든 레시피 행은 셸의 단일 호출에 제공됩니다.

여전히 각 줄의 시작 부분에 탭 문자를 넣어야 하고 모든 달러 기호를 두 배로 늘려야 합니다(즉, 스크립트의 모든 곳에서 이를 교체해야 합니다) $.$$

답변3

최상위 프로젝트 디렉토리가 수십 개의 스크립트로 가득 차 있다는 것이 문제인 경우 확실한 해결책은 scripts이를 배치할 하위 디렉토리(예: )를 생성하는 것입니다.

이를 실행 ./scripts/scriptname하거나 PATH에 스크립트 디렉터리를 추가하세요.

여전히 Makefile을 사용하여 실행하려면 ./scripts/scriptname해당 대상에 대해 실행되는 Makefile 항목을 생성하면 됩니다. 예를 들어

my-important-task: 
    ./scripts/my-important-task.sh my-parameter

참고: ./scripts의 스크립트가 동일한 디렉터리에 있는 다른 스크립트를 호출하는 경우 스크립트의 전체 경로를 지정하거나 PATH에 스크립트 디렉터리를 포함해야 합니다.

답변4

그런데... Bash만 사용할 수는 없습니다.

실제로 원하는 스크립트 언어로 make target 레시피를 작성할 수 있습니다.

Python을 사용한 예제 스니펫:

...
SHELL != sh -c "command -v python"
.SHELLFLAGS := -c
.ONESHELL:

# et voilà : the recipe can now be written in pure python :-)
all: foo    
    # use some make variables
    print "# target name is '$@', depends on '$^'"

    import os
    print os.listdir ("..")

foo:
    # use some make variables
    print "# target name is '$@', depends on '$^'"

    import sys
    print 'python version is %s.%s.%s' % (sys.version_info[0], sys.version_info[1], sys.version_info[2])
...

다양한 언어로 된 예를 확인하세요:https://github.com/lgersman/make-recipes-in- Different-scripting-언어-demo

관련 정보