如何在 Makefile 中使用 notdir、通配符和 patsubst?

How to use notdir, wildcard and patsubst in a Makefile?

我有以下生成文件:

#.SUFFIXES:
#.SUFFIXES: .F90 .cuf .o

ROOT = /home/ccevallos/finalMIT

SRCDIR := $(ROOT)/external/lib_eigesolve

#F90SRC = $(notdir $(wildcard $(SRCDIR)/*.F90))
#F90OBJS = $(patsubst %.F90,%.o,$(F90SRC))
F90OBJS = eigsolve_vars.o toolbox.o zhegst_gpu.o zhemv_gpu.o zhetd2_gpu.o zhetrd_gpu.o zheevd_gpu.o zhegvdx_gpu.o \
          dsygst_gpu.o dsymv_gpu.o dsytd2_gpu.o dsytrd_gpu.o dsyevd_gpu.o dsygvdx_gpu.o
#CUFSRC = $(notdir $(wildcard $(SRCDIR)/*.cuf))
#CUFOBJS = $(patsubst %.cuf,%.o,$(CUFSRC))
CUFOBJS = cusolverDn_m.o

FLAGS = -O3 -mp -pgf90libs -Mcuda=cc60,cuda9.1,ptxinfo -Mlarge_arrays
FLAGS2 = -O3 -mp -pgf90libs -Mcuda=cc60,cuda9.1,ptxinfo,maxregcount:64 -Mlarge_arrays
FLAGS3 = -O3 -mp -pgf90libs -Mcuda=cc60,cuda9.1,ptxinfo,nordc,maxregcount:255  -Mlarge_arrays

.PHONY: all
all: lib_eigsolve.a

zhetd2_gpu.o : zhetd2_gpu.F90
    pgf90 -c ${FLAGS2} ${OPTFLAGS} $*.F90 -o $*.o 
zhemv_gpu.o : zhemv_gpu.F90
    pgf90 -c ${FLAGS3} ${OPTFLAGS} $*.F90 -o $*.o
dsytd2_gpu.o : dsytd2_gpu.F90
    pgf90 -c ${FLAGS2} ${OPTFLAGS} $*.F90 -o $*.o
dsymv_gpu.o : dsymv_gpu.F90
    pgf90 -c ${FLAGS3} ${OPTFLAGS} $*.F90 -o $*.o
cusolverDn_m.o: cusolverDn_m.cuf
    pgf90 -c ${FLAGS}  ${OPTFLAGS} $*.cuf -o $*.o
%.o: %.F90
    pgf90 -c ${FLAGS}  ${OPTFLAGS} $*.F90 -o $*.o

lib_eigsolve.a: $(F90OBJS) $(CUFOBJS)
    ar rcs $@ $^


PHONY: clean
clean:
    rm -f lib_eigsolve.a *.mod *.o

这个 makefile 编译得非常好,但是我基本上想用 # 取消对行的注释以使其更简单,但是当我这样做时只

ar rcs lib_eigsolve.a 

出现在终端,没有创建目标文件,因此lib_eigsolve.a是空的... 为什么不编译目标文件?

P.S。您可以在此处找到经过一些修改的 Makefile https://github.com/NVIDIA/Eigensolver_gpu

确保 $(SRCDIR) 没有空格:

SRCDIR := $(strip ${SRCDIR})
ifneq (1,$(words ${SRCDIR}))
  $(error Not without further fiddling, friend)
endif

在通配符表达式中指定路径看起来很奇怪。当你直接在srcdir(make -C lib_eigsolve)中执行make时,你应该写

F90SRC = $(notdir $(wildcard *.F90))

srcdir = .
F90SRC = $(notdir $(wildcard ${srcdir}/*.F90))

当您想保留树外构建的选项时。

您在 $(SRCDIR) 中有一个简单的拼写错误:Eigensolver_gpu 中的源目录称为 lib_eigsolve 而不是 lib_eigesolve

$ cd ~workarea/playground
$ git clone https://github.com/NVIDIA/Eigensolver_gpu.git
$ ls Eigensolver_gpu/
lib_eigsolve  LICENSE  README.md  test_driver

然后我通过复制并粘贴您问题中的相关行来创建一个虚拟 makefile:

ROOT   := $(HOME)/workarea/playground/Eigensolver_gpu
ifndef FIXED
    SRCDIR := $(ROOT)/lib_eigesolve
else
    SRCDIR := $(ROOT)/lib_eigsolve
endif

F90SRC = $(notdir $(wildcard $(SRCDIR)/*.F90))
$(info F90SRC '$(F90SRC)')
F90OBJS = $(patsubst %.F90,%.o,$(F90SRC))
$(info F90OBJS '$(F90OBJS)')

CUFSRC = $(notdir $(wildcard $(SRCDIR)/*.cuf))
$(info CUFSRC '$(CUFSRC)')
CUFOBJS = $(patsubst %.cuf,%.o,$(CUFSRC))
$(info CUFOBJS '$(CUFOBJS)')

lib_eigsolve.a: $(F90OBJS) $(CUFOBJS)
    echo ar rcs $@ $^

测试运行:

$ make
F90SRC ''
F90OBJS ''
CUFSRC ''
CUFOBJS ''
echo ar rcs lib_eigsolve.a 
ar rcs lib_eigsolve.a

$ make FIXED=1
F90SRC 'dsyevd_gpu.F90 ... zhemv_gpu.F90'
F90OBJS 'dsyevd_gpu.o ... zhemv_gpu.o'
CUFSRC 'cusolverDn_m.cuf'
CUFOBJS 'cusolverDn_m.o'
make: *** No rule to make target 'dsyevd_gpu.o', needed by 'lib_eigsolve.a'.  Stop.