对同一对象中的不同源文件使用不同的编译器或编译器标志
Using different compilers or compiler flags for different source files in the same object
我是 makefile 的新手,目前 运行 下面是代码附带的,我通过选项 FFLAGS_EXT1
、COMP_EXT1
和 file1.F90
和 file2.F90
:
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXT1 = -g -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5 -Dno_nans -I ../ # Stricter compiler flags
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
COMP_EXT1 = $(FC) $(FFLAGS_EXT1) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# compilation rules
.F90.$(OBJ_EXT):
# $(COMP)
$(COMP_EXT1)
.PHONY: all
all: \
program1.$(EXE_EXT) program2.$(EXE_EXT) ...
program1.$(EXE_EXT): \
$(addsuffix .$(OBJ_EXT),$(MAIN_MODULES)) \
$(addsuffix .$(OBJ_EXT),$(OUR_MODULES)) \
file1.$(OBJ_EXT) \
file2.$(OBJ_EXT)
$(LINK)
...
这使我能够使用 FFLAGS
或更严格的 FFLAGS_EXT1
编译所有源文件,具体取决于编译规则的选择。
我想得到的是:默认使用COMP
(除了定义的program1
之外还有其他程序,我不能破坏与之的兼容性)但使用COMP_EXT1
或分别针对 file1
和 file2
的 FFLAGS_EXT1
(遗留代码抛出了很多我想忽略的警告,只关注我的新东西 - 这是一个相当大的项目总数...)。
我知道,例如,this post,但我完全不知道如何在我的案例中实现它。
非常感谢任何帮助!
编辑:
感谢@Matt 的提示,我发现这个更改后的版本可以解决问题:
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXT1 = -g -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5 -Dno_nans -I ../ # Stricter compiler flags
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# compilation rules
.F90.$(OBJ_EXT):
$(COMP)
file1.$(OBJ_EXT):
$(FC) $(FFLAGS_EXT1) -c file1.F90 -o file1.$(OBJ_EXT)
file2.$(OBJ_EXT):
$(FC) $(FFLAGS_EXT1) -c file2.F90 -o file2.$(OBJ_EXT)
.PHONY: all
all: \
program1.$(EXE_EXT) program2.$(EXE_EXT) ...
program1.$(EXE_EXT): \
$(addsuffix .$(OBJ_EXT),$(MAIN_MODULES)) \
$(addsuffix .$(OBJ_EXT),$(OUR_MODULES)) \
file1.$(OBJ_EXT) \
file2.$(OBJ_EXT)
$(LINK)
...
但是在规则多、文件多的情况下,这就显得很麻烦了。简单地使用 $(COMP_EXT1)
之类的东西是行不通的,因为它因无输入文件错误而失败。
有没有办法缩短这个结构?
嗯,无论如何,这是一个风格问题。但让我们尝试一下:
# prefer simple variables over recursive ones...
FC := gfortran
FFLAGS := -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXTRA := -fbacktrace -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
# ...unless we *do* require deferred expansion
COMP = $(FC) $(FFLAGS) $(FFLAGS_$@) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
# this is a matter of choice but one-letter variables could be handy
O := o
X := x
# I assume both file1 and file2 are already mentioned here
MAIN_MODULES := $(a list of file names without extensions)
OUR_MODULES := $(another list of file names without extensions)
# use computed variables for maximum flexibility
FFLAGS_file1.$O := $(FFLAGS_EXTRA)
FFLAGS_file2.$O := $(FFLAGS_EXTRA)
.PHONY: all
all: program1.$X program2.$X ...
program1.$X: $(addsuffix .$O,$(MAIN_MODULES) $(OUR_MODULES))
$(LINK)
program2.$X: ...
$(LINK)
# it is recommended to use pattern rules instead of suffix rules
%.$O: %.F90
$(COMP)
...
也许您想走一条不同的路,即使用 gmtt 这是一个很好的库,可以在 GNUmake 中编程很多东西。它提供了一个 table 数据结构,旨在构建像您这样的配置任务:
include gmtt-master/gmtt.mk
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# Construct a gmtt table. The one caveat is that we must escape the space characters in the
# second column until we select entries from the table.
define COMPILE_FLAGS_TBL
2
file1.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
file2.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
endef
# Special flags: "select column 2 from COMPILE_FLAGS_TBL where first column is string-equal to the target"
# ...and recover the space characters afterwards:
FFLAGS_SPECIAL = $(call spc-unmask,$(call select,2,$(COMPILE_FLAGS_TBL),$$(call str-eq,$,$@)))
# compilation rules
.PHONY: all
all: foo.o bar.o file1.o file2.o
%.F90:
touch $@
%.o: %.F90
@echo flags: $(FFLAGS) $(FFLAGS_SPECIAL)
输出:
$ make
touch foo.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
touch bar.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
touch file1.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
touch file2.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
rm bar.F90 file1.F90 foo.F90 file2.F90
您可以使用 glob 来更灵活地选择文件:
include gmtt-master/gmtt-master/gmtt.mk
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
OBJ_EXT = o
# Construct a gmtt table. The one caveat is that we must escape the space characters in the
# second column until we select entries from the table.
define COMPILE_FLAGS_TBL
2
file1.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
file2.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
endef
define PATTERN_FLAGS_TBL
2
*_frobozz_[7-9].$(OBJ_EXT) $(call spc-mask,-ffrobozz)
X_frabazz_*.$(OBJ_EXT) $(call spc-mask,-ffrabazz -dwhatever)
endef
# Special flags: "select column 2 from COMPILE_FLAGS_TBL where first column is string-equal to the target"
# ...and recover the space characters afterwards:
FFLAGS_SPECIAL = $(call spc-unmask,$(call select,2,$(COMPILE_FLAGS_TBL),$$(call str-eq,$,$@)))
# Very special flags: "select column 2 from PATTERN_FLAGS_TBL where target matches glob in first column"
# ...and recover the space characters afterwards
FFLAGS_VERY_SPECIAL = $(call spc-unmask,$(call select,2,$(PATTERN_FLAGS_TBL),$$(call glob-match,$@,$)))
# compilation rules
.PHONY: all
all: foo.o bar.o file1.o file2.o A_frobozz_8.o A_frobozz_6.o X_frabazz_mike.o X_frabazz_mandy.o
%.F90:
@touch $@
%.o: %.F90
@echo $@ flags: $(FFLAGS) $(FFLAGS_SPECIAL) $(FFLAGS_VERY_SPECIAL)
输出:
$ make
foo.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
bar.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
file1.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
file2.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
A_frobozz_8.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrobozz
A_frobozz_6.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
X_frabazz_mike.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrabazz -dwhatever
X_frabazz_mandy.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrabazz -dwhatever
rm X_frabazz_mandy.F90 A_frobozz_8.F90 bar.F90 file1.F90 foo.F90 A_frobozz_6.F90 file2.F90 X_frabazz_mike.F90
我是 makefile 的新手,目前 运行 下面是代码附带的,我通过选项 FFLAGS_EXT1
、COMP_EXT1
和 file1.F90
和 file2.F90
:
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXT1 = -g -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5 -Dno_nans -I ../ # Stricter compiler flags
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
COMP_EXT1 = $(FC) $(FFLAGS_EXT1) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# compilation rules
.F90.$(OBJ_EXT):
# $(COMP)
$(COMP_EXT1)
.PHONY: all
all: \
program1.$(EXE_EXT) program2.$(EXE_EXT) ...
program1.$(EXE_EXT): \
$(addsuffix .$(OBJ_EXT),$(MAIN_MODULES)) \
$(addsuffix .$(OBJ_EXT),$(OUR_MODULES)) \
file1.$(OBJ_EXT) \
file2.$(OBJ_EXT)
$(LINK)
...
这使我能够使用 FFLAGS
或更严格的 FFLAGS_EXT1
编译所有源文件,具体取决于编译规则的选择。
我想得到的是:默认使用COMP
(除了定义的program1
之外还有其他程序,我不能破坏与之的兼容性)但使用COMP_EXT1
或分别针对 file1
和 file2
的 FFLAGS_EXT1
(遗留代码抛出了很多我想忽略的警告,只关注我的新东西 - 这是一个相当大的项目总数...)。
我知道,例如,this post,但我完全不知道如何在我的案例中实现它。
非常感谢任何帮助!
编辑: 感谢@Matt 的提示,我发现这个更改后的版本可以解决问题:
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXT1 = -g -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5 -Dno_nans -I ../ # Stricter compiler flags
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# compilation rules
.F90.$(OBJ_EXT):
$(COMP)
file1.$(OBJ_EXT):
$(FC) $(FFLAGS_EXT1) -c file1.F90 -o file1.$(OBJ_EXT)
file2.$(OBJ_EXT):
$(FC) $(FFLAGS_EXT1) -c file2.F90 -o file2.$(OBJ_EXT)
.PHONY: all
all: \
program1.$(EXE_EXT) program2.$(EXE_EXT) ...
program1.$(EXE_EXT): \
$(addsuffix .$(OBJ_EXT),$(MAIN_MODULES)) \
$(addsuffix .$(OBJ_EXT),$(OUR_MODULES)) \
file1.$(OBJ_EXT) \
file2.$(OBJ_EXT)
$(LINK)
...
但是在规则多、文件多的情况下,这就显得很麻烦了。简单地使用 $(COMP_EXT1)
之类的东西是行不通的,因为它因无输入文件错误而失败。
有没有办法缩短这个结构?
嗯,无论如何,这是一个风格问题。但让我们尝试一下:
# prefer simple variables over recursive ones...
FC := gfortran
FFLAGS := -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
FFLAGS_EXTRA := -fbacktrace -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
# ...unless we *do* require deferred expansion
COMP = $(FC) $(FFLAGS) $(FFLAGS_$@) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
# this is a matter of choice but one-letter variables could be handy
O := o
X := x
# I assume both file1 and file2 are already mentioned here
MAIN_MODULES := $(a list of file names without extensions)
OUR_MODULES := $(another list of file names without extensions)
# use computed variables for maximum flexibility
FFLAGS_file1.$O := $(FFLAGS_EXTRA)
FFLAGS_file2.$O := $(FFLAGS_EXTRA)
.PHONY: all
all: program1.$X program2.$X ...
program1.$X: $(addsuffix .$O,$(MAIN_MODULES) $(OUR_MODULES))
$(LINK)
program2.$X: ...
$(LINK)
# it is recommended to use pattern rules instead of suffix rules
%.$O: %.F90
$(COMP)
...
也许您想走一条不同的路,即使用 gmtt 这是一个很好的库,可以在 GNUmake 中编程很多东西。它提供了一个 table 数据结构,旨在构建像您这样的配置任务:
include gmtt-master/gmtt.mk
FC = gfortran
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
LDFLAGS =
OBJ_EXT = o
EXE_EXT = x
COMP = $(FC) $(FFLAGS) -c -o $@ $<
LINK = $(FC) $(LDFLAGS) -o $@ $^
MAIN_MODULES = $(a list of file names without extensions)
OUR_MODULES = $(another list of file names without extensions)
# FORTRAN settings
.SUFFIXES: .F90 .$(OBJ_EXT)
# Construct a gmtt table. The one caveat is that we must escape the space characters in the
# second column until we select entries from the table.
define COMPILE_FLAGS_TBL
2
file1.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
file2.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
endef
# Special flags: "select column 2 from COMPILE_FLAGS_TBL where first column is string-equal to the target"
# ...and recover the space characters afterwards:
FFLAGS_SPECIAL = $(call spc-unmask,$(call select,2,$(COMPILE_FLAGS_TBL),$$(call str-eq,$,$@)))
# compilation rules
.PHONY: all
all: foo.o bar.o file1.o file2.o
%.F90:
touch $@
%.o: %.F90
@echo flags: $(FFLAGS) $(FFLAGS_SPECIAL)
输出:
$ make
touch foo.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
touch bar.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
touch file1.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
touch file2.F90
flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
rm bar.F90 file1.F90 foo.F90 file2.F90
您可以使用 glob 来更灵活地选择文件:
include gmtt-master/gmtt-master/gmtt.mk
FFLAGS = -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
OBJ_EXT = o
# Construct a gmtt table. The one caveat is that we must escape the space characters in the
# second column until we select entries from the table.
define COMPILE_FLAGS_TBL
2
file1.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
file2.$(OBJ_EXT) $(call spc-mask,-fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5)
endef
define PATTERN_FLAGS_TBL
2
*_frobozz_[7-9].$(OBJ_EXT) $(call spc-mask,-ffrobozz)
X_frabazz_*.$(OBJ_EXT) $(call spc-mask,-ffrabazz -dwhatever)
endef
# Special flags: "select column 2 from COMPILE_FLAGS_TBL where first column is string-equal to the target"
# ...and recover the space characters afterwards:
FFLAGS_SPECIAL = $(call spc-unmask,$(call select,2,$(COMPILE_FLAGS_TBL),$$(call str-eq,$,$@)))
# Very special flags: "select column 2 from PATTERN_FLAGS_TBL where target matches glob in first column"
# ...and recover the space characters afterwards
FFLAGS_VERY_SPECIAL = $(call spc-unmask,$(call select,2,$(PATTERN_FLAGS_TBL),$$(call glob-match,$@,$)))
# compilation rules
.PHONY: all
all: foo.o bar.o file1.o file2.o A_frobozz_8.o A_frobozz_6.o X_frabazz_mike.o X_frabazz_mandy.o
%.F90:
@touch $@
%.o: %.F90
@echo $@ flags: $(FFLAGS) $(FFLAGS_SPECIAL) $(FFLAGS_VERY_SPECIAL)
输出:
$ make
foo.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
bar.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
file1.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
file2.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -fbacktrace -ffpe-trap=zero,invalid,overflow,underflow -fbounds-check -fcheck=all -Wconversion -std=gnu -O3 -fmax-errors=5
A_frobozz_8.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrobozz
A_frobozz_6.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../
X_frabazz_mike.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrabazz -dwhatever
X_frabazz_mandy.o flags: -g -ffpe-trap=zero,invalid,overflow,underflow -Dno_nans -I ../ -ffrabazz -dwhatever
rm X_frabazz_mandy.F90 A_frobozz_8.F90 bar.F90 file1.F90 foo.F90 A_frobozz_6.F90 file2.F90 X_frabazz_mike.F90