makefile 中的 eval 列表

Lists on eval inside a makefile

我需要一些宏在目标上进行评估,但我无法让 OBJECT_FILE 由 $^ 显然地进行评估。这是我的生成文件:

#___________________________________build tools_________________________________

MKDIR    := mkdir
RM       := rm
CP       := cp
CD       := cd
COMPILER := gfortran

GENERAL_FLAGS       := -fno-automatic -static -I/usr/include -fimplicit-none
TESTING_DEBUG_FLAGS := -Og -g -fbounds-check -fbacktrace -pedantic -Wextra \
                   -Wall ${GENERAL_FLAGS}
RELEASE_FLAGS       := ${GENERAL_FLAGS} -Ofast

#______________________________macros de diretórios_____________________________

SRC_DIR     := src
BUILD_DIR   := build
RELEASE_DIR := release
DEBUG_DIR   := debug
TEST_DIR    := test
DIST_DIR    := dist

PROGRAM := ${DIST_DIR}/SimulArroz

#______________________________regras de compilação_____________________________

tests:   | TEST_PATHS ${PROGRAM}

TEST_PATHS:
    $(eval FLAGS        = ${TESTING_DEBUG_FLAGS})
    $(eval OBJECT_DIR   = ${BUILD_DIR}/${TEST_DIR})
    $(eval OBJECT_FILES = ${OBJECT_DIR}/Data.o ${OBJECT_DIR}/Model.o \
              ${OBJECT_DIR}/Control.o ${OBJECT_DIR}/Farmings.o \
              ${OBJECT_DIR}/Test_data.o ${OBJECT_DIR}/Test_main.o \
              ${OBJECT_DIR}/Test_subroutines.o)
    ${MKDIR} -p ${DIST_DIR}
    ${MKDIR} -p ${OBJECT_DIR}

clean :
    ${RM} -fr ${BUILD_DIR}
    ${RM} -fr ${DIST_DIR}
    ${RM} -f seed.mod

run :
    ${CD} ${DIST_DIR} ; ./${PROGRAM}

${PROGRAM}: ${OBJECT_FILES}
    ${COMPILER} ${FLAGS} -o $@ $^

${OBJECT_DIR}/%.o: ${SRC_DIR}/%.f90
    ${MKDIR} -p ${OBJECT_DIR}
    ${COMPILER} ${FLAGS} -c -o $@ $<

我得到的结果是:

gfortran -Og -g -fbounds-check -fbacktrace -pedantic -Wextra -Wall -fno-automatic -static -I/usr/include -fimplicit-none -o dist/SimulArroz 
gfortran: fatal error: no input files; unwilling to write output files
compilation terminated.
makefile:90: recipe for target 'dist/SimulArroz' failed
make: *** [dist/SimulArroz] Error 1

更新:

我按照评论中的指示尝试了 secondary expansion,但最终在我的情况下它给出了相同的结果,这是我尝试过的更改:

tests: FLAGS        := ${TESTING_DEBUG_FLAGS}
tests: OBJECT_DIR   := ${BUILD_DIR}/${TEST_DIR}
tests: OBJECT_FILES := ${TEST_OBJ_DIR}/Data.o ${TEST_OBJ_DIR}/Model.o \
              ${TEST_OBJ_DIR}/Control.o ${TEST_OBJ_DIR}/Farmings.o \
              ${TEST_OBJ_DIR}/Test_data.o ${TEST_OBJ_DIR}/Test_main.o \
              ${TEST_OBJ_DIR}/Test_subroutines.o

.SECONDEXPANSION:
tests: $$(PROGRAM)

${PROGRAM}: ${OBJECT_FILES}
    ${MKDIR} -p ${DIST_DIR}
    ${COMPILER} ${FLAGS} -o $@ $^

${OBJECT_DIR}/%.o: ${SRC_DIR}/%.f90
    ${MKDIR} -p ${OBJECT_DIR}
    ${COMPILER} ${FLAGS} -c -o $@ $<

好的,我进一步调查了它,正如问题评论中指出的那样,可以使用 second expansion 解决我的问题,我也使用 text function 解决了它。由于没有人给出答案,我把它放在这里:

#___________________________________build tools_________________________________

MKDIR    := mkdir -p
RM       := rm
CP       := cp
CD       := cd
COMPILER := gfortran

# flags do compilador

GENERAL_FLAGS       := -fno-automatic -static -I/usr/include -fimplicit-none
TESTING_DEBUG_FLAGS := -Og -g -fbounds-check -fbacktrace -pedantic -Wextra \
                       -Wall ${GENERAL_FLAGS}
RELEASE_FLAGS       := ${GENERAL_FLAGS} -Ofast

#______________________________macros de diretórios_____________________________

SRC_DIR     := src
BUILD_DIR   := build
RELEASE_DIR := release
DEBUG_DIR   := debug
TEST_DIR    := test
DIST_DIR    := dist

test_FILES  := Data.o Model.o Control.o Farmings.o Test_Data.o Test_Main.o \
               Test_Subroutines.o 

#______________________________regras de compilação_____________________________

.PHONY: test clean run

test: FLAGS       := ${TESTING_DEBUG_FLAGS} -o
test: OBJ_DIR     := ${BUILD_DIR}/${TEST_DIR}
test: PROGRAM_DIR := ${DIST_DIR}/${TEST_DIR}
test: PROGRAM     := ${PROGRAM_DIR}/SimulArroz

.SECONDEXPANSION:
test: $${$$@_FILES}
      ${MKDIR} ${PROGRAM_DIR}
      ${COMPILER} ${FLAGS} ${PROGRAM} $($@_FILES:%o=${OBJ_DIR}/%o)

%.o: ${SRC_DIR}/%.f90
    ${MKDIR} ${OBJ_DIR}
    ${COMPILER} -c ${FLAGS} ${OBJ_DIR}/$@ $<

clean :
    ${RM} -fr ${BUILD_DIR}
    ${RM} -fr ${DIST_DIR}
    ${RM} -f seed.mod

run :
    ${CD} ${DIST_DIR} ; ./${PROGRAM}

但是...我仍然不明白为什么我不能只获得这样的目标:

${OBJ_DIR}/%.o: ${SRC_DIR}/%.f90
   ${MKDIR} ${OBJ_DIR}
   ${COMPILER} -c ${FLAGS} $@ $<

因为 ${OBJ_DIR} 如果在目标中使用则不会扩展。如果有人能解释一下在这种情况下发生了什么,我将不胜感激。

我也要感谢我在评论中收到的建议。