How to write loop in a Makefile?

后端 未结 12 2243
天命终不由人
天命终不由人 2020-11-27 09:38

I want to execute the following commands:

./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on

How to write this thing as a loop in a

相关标签:
12条回答
  • 2020-11-27 10:14

    A simple, shell/platform-independent, pure macro solution is ...

    # GNU make (`gmake`) compatible; ref: <https://www.gnu.org/software/make/manual>
    define EOL
    
    $()
    endef
    %sequence = $(if $(word ${1},${2}),$(wordlist 1,${1},${2}),$(call %sequence,${1},${2} $(words _ ${2})))
    
    .PHONY: target
    target:
        $(foreach i,$(call %sequence,10),./a.out ${i}${EOL})
    
    0 讨论(0)
  • 2020-11-27 10:14

    Dynamically assign variables in the loop

    The promblem with the for number in 1 2 3 4 ; do \ ...-solution is, that no variables can be assigned within the loop. $(eval VAR=...) can only be used, if the content of the assignment is known at the beginning of the target execution. If the assignment depends on the loop-variable, VAR will be empty.

    To circumvent this issue, one can use the target functionality to model a loop. The following example takes the n-th file from SRC / OBJ and processes them together. Using this construction you can even use $(eval ...) to process the loop variable, as demonstrated with VAR3.

    makefile

    SRC = f1.c f2.cpp f3.cpp
    OBJ = f1.o f2.o f3.o
    
    SRC2 = $(addsuffix _,$(SRC))
    JOIN = $(join $(SRC2),$(OBJ))
    
    PHONY: all
    all : info loop
    
    loop : $(JOIN)
    
    $(JOIN) :
        @# LOOP - CONTENT
        @echo "TARGET: $@"
        $(eval VAR1=$(word 1,$(subst _, ,$@)))
        @echo "VAR1: "$(VAR1)
        $(eval VAR2=$(word 2,$(subst _, ,$@)))
        @echo "VAR2: "$(VAR2)
        $(eval VAR3=$(subst .o,.x,$(VAR2)))
        @echo "You can even substitute you loop variable VAR3: "$(VAR3)
        #g++ -o $(VAR2) $(VAR1)
        @echo
    
    PHONY: info
    info:
        @printf "\n"
        @echo "JOIN: "$(JOIN)
        @printf "\n"
    

    output

    $ make
    
    JOIN: f1.c_f1.o f2.cpp_f2.o f3.cpp_f3.o
    
    TARGET: f1.c_f1.o
    VAR1: f1.c
    VAR2: f1.o
    You can even substitute you loop variable VAR3: f1.x
    #g++ -o f1.o f1.c
    
    TARGET: f2.cpp_f2.o
    VAR1: f2.cpp
    VAR2: f2.o
    You can even substitute you loop variable VAR3: f2.x
    #g++ -o f2.o f2.cpp
    
    TARGET: f3.cpp_f3.o
    VAR1: f3.cpp
    VAR2: f3.o
    You can even substitute you loop variable VAR3: f3.x
    #g++ -o f3.o f3.cpp
    
    0 讨论(0)
  • 2020-11-27 10:16
    #I have a bunch of files that follow the naming convention
    #soxfile1  soxfile1.o  soxfile1.sh   soxfile1.ini soxfile1.txt soxfile1.err
    #soxfile2  soxfile2.o   soxfile2.sh  soxfile2.ini soxfile2.txt soxfile2.err
    #sox...        ....        .....         ....         ....        ....
    #in the makefile, only select the soxfile1.. soxfile2... to install dir
    #My GNU makefile solution follows:
    tgt=/usr/local/bin/          #need to use sudo
    tgt2=/backup/myapplication/  #regular backup 
    
    install:
            for var in $$(ls -f sox* | grep -v '\.' ) ; \
            do \
                    sudo  cp -f $$var ${TGT} ;     \
                          cp -f  $$var ${TGT2} ;  \
            done
    
    
    #The ls command selects all the soxfile* including the *.something
    #The grep command rejects names with a dot in it, leaving  
    #My desired executable files in a list. 
    
    0 讨论(0)
  • 2020-11-27 10:17

    You can use set -e as a prefix for the for-loop. Example:

    all:
        set -e; for a in 1 2 3; do /bin/false; echo $$a; done
    

    make will exit immediately with an exit code <> 0.

    0 讨论(0)
  • 2020-11-27 10:20

    Maybe you can use:

    xxx:
        for i in `seq 1 4`; do ./a.out $$i; done;
    
    0 讨论(0)
  • 2020-11-27 10:27

    For cross-platform support, make the command separator (for executing multiple commands on the same line) configurable.

    If you're using MinGW on a Windows platform for example, the command separator is &:

    NUMBERS = 1 2 3 4
    CMDSEP = &
    doit:
        $(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
    

    This executes the concatenated commands in one line:

    ./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
    

    As mentioned elsewhere, on a *nix platform use CMDSEP = ;.

    0 讨论(0)
提交回复
热议问题