首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个编译器的makefile

两个编译器的makefile
EN

Stack Overflow用户
提问于 2022-04-21 18:10:24
回答 1查看 59关注 0票数 0

我想为两个编译器制作一个makefile。我喜欢英特尔在其oneAPI中的例子,见下文。基本上,在每个目标规则下,它都有明确的编译规则。但我的makefile就像:

代码语言:javascript
复制
# compile old fortran files
$(BLD)/%.o: $(SRC)/%.for
    $(FC) -c $(FFLAGS) -o $@ $<
# compile new fortran files
$(BLD)/%.o: $(SRC)/%.f90
    $(FC) -c $(FFLAGS) -o $@ $<
# link everything
$(target): $(objects)
    $(FC) -o $@ $(FFLAGS) -I $(BLD) $^ $(LDFLAGS)

我看到一种方法是将$(FC)变量加上标志更改为目标中的适当值。英特尔的优势在于,它可以非常具体地改变额外的开关,所以如果对于gfortran,我有一行$(FC) -o $@ $(FFLAGS) -I $(BLD) $^ $(LDFLAGS),如果我需要它看起来像ifort的$(FC) -o $@ $(FFLAGS) -J $(BLD) $^ $(LDFLAGS),那么有什么方法可以在另一个规则中制定规则,比如:

代码语言:javascript
复制
GFORT_EXE = $(target).gfort
IFORT_EXE = $(target).ifort
#
gfort: $(GFORT_EXE)
ifort: $(IFORT_EXE)
$(GFORT_EXE):
    $(BLD)/%.o: $(SRC)/%.for
    $(FC) -c $(FFLAGS) -o $@ $<
    # compile new fortran files
    $(BLD)/%.o: $(SRC)/%.f90
    $(FC) -c $(FFLAGS) -o $@ $<
    # link everything
    $(FC) -o $@ $(FFLAGS) -I $(BLD) $^ $(LDFLAGS)

或者,如果我需要命令行在每个编译器的原则上看起来不同,那么什么才是最好的方法呢?

英特尔makefile

代码语言:javascript
复制
# Copyright Intel Corporation 2014
#
# To compile with the GNU* C/C++ compiler, creating an execution file with the
# extension ".gcc" for binary instrumentation, issue:
#
#   > make
#
# To compile with the Intel(R) C++ Compiler for Linux*, creating an execution
# file with the extension ".icc":
#
#   Source <path_to_compiler_bin>/compilervars.sh or iccvars.csh;
#
#   > make icc
#
# To compile with the Intel(R) C++ Compiler for Linux* with Intel(R) MKL library
# creating an executionfile with the extension ".mkl":
#
#   Source <path_to_compiler_bin>/compilervars.sh or iccvars.csh;
#
#   > make mkl
#
# To compile with the Intel(R) C++ Compiler for Linux to cross compile for the
# Intel(R) Xeon Phi(TM) coprocessor, creating an execution file with the
# extension ".mic":
#
#   Source <path_to_compiler_bin>/compilervars.sh intel64
#
#   > make mic
#
# To compile them all, use the source line from the Intel MIC architecture
# option above, then type:
#
#   > make all

SHELL = /bin/sh

PARAMODEL = -DUSE_THR   # Default parallelism using pthreads/Win threads
#PARAMODEL = -DUSE_OMP -fopenmp # Use OpenMP for multithreading

GCC     = gcc
ICC     = icc
CFLAGS  = -g -O3 -fno-asm
OPTFLAGS = -xSSE3 
# OPTFLAGS = -xHost -fno-alias
# add -DALIGNED to the multiply.c and matrix.c
LDFLAGS = -lpthread -lm

GCFLAGS = $(CFLAGS) $(PARAMODEL)
ICFLAGS = $(CFLAGS) $(PARAMODEL)-DICC -debug inline-debug-info #-vec-report3 -qopt-report -qopt-report-phase=vec
MKFLAGS = $(CFLAGS) -DUSE_MKL   -DICC -mkl -debug inline-debug-info


GCC_EXE = matrix.gcc
ICC_EXE = matrix.icc
MKL_EXE = matrix.mkl


srcdir = ../src

gcc: $(GCC_EXE)
icc: $(ICC_EXE)
mkl: $(MKL_EXE)
all: $(GCC_EXE) $(ICC_EXE) $(MKL_EXE)


OBJS = util.o thrmodel.o multiply.o matrix.o 


matrix.gcc: $(srcdir)/matrix.c $(srcdir)/multiply.c $(srcdir)/multiply.h $(srcdir)/util.c $(srcdir)/thrmodel.c
    $(GCC) $(GCFLAGS) -c $(srcdir)/util.c -D_LINUX
    $(GCC) $(GCFLAGS) -c $(srcdir)/thrmodel.c -D_LINUX
    $(GCC) $(GCFLAGS) -c $(srcdir)/multiply.c -D_LINUX
    $(GCC) $(GCFLAGS) -c $(srcdir)/matrix.c -D_LINUX
    $(GCC) $(GCFLAGS) -g $(OBJS) -o ../matrix $(LDFLAGS)


matrix.icc: $(srcdir)/matrix.c $(srcdir)/multiply.c $(srcdir)/multiply.h $(srcdir)/util.c $(srcdir)/thrmodel.c
    $(ICC) $(ICFLAGS) -c $(srcdir)/util.c -D_LINUX
    $(ICC) $(ICFLAGS) -c $(srcdir)/thrmodel.c -D_LINUX
    $(ICC) $(ICFLAGS) $(OPTFLAGS) -c $(srcdir)/multiply.c -D_LINUX
    $(ICC) $(ICFLAGS) $(OPTFLAGS) -c $(srcdir)/matrix.c -D_LINUX
    $(ICC) $(ICFLAGS) $(OBJS) -o ../matrix $(LDFLAGS)


matrix.mkl:     $(srcdir)/matrix.c $(srcdir)/multiply.c $(srcdir)/multiply.h $(srcdir)/util.c $(srcdir)/thrmodel.c
    $(ICC) $(MKFLAGS) -c $(srcdir)/util.c -D_LINUX
    $(ICC) $(MKFLAGS) -c $(srcdir)/thrmodel.c -D_LINUX
    $(ICC) $(MKFLAGS) $(OPTFLAGS) -c $(srcdir)/multiply.c -D_LINUX
    $(ICC) $(MKFLAGS) $(OPTFLAGS) -c $(srcdir)/matrix.c -D_LINUX
    $(ICC) $(MKFLAGS) $(OBJS) -o ../matrix $(LDFLAGS)

clean:
    @rm -rf $(OBJS) $(GCC_EXE) $(ICC_EXE) $(MKL_EXE)

# * Other names and brands may be claimed as the property of others.
EN

回答 1

Stack Overflow用户

发布于 2022-04-21 20:04:33

不,您不能在规则中重新定义规则(坦率地说,您可能不想这样做,因为这种方法有很多尖锐的地方,您肯定会被绊倒)。对于这种情况,我建议您执行两个单独的输出目录,并具有基于输出目录的规则,如下所示:

代码语言:javascript
复制
objects := ...
FC_gfort := ...
FC_ifort := ...

$(BLD)/gfort/%.o: $(SRC)/%.for
    $(FC_gfort) -c $(FFLAGS) -o $@ $<

$(BLD)/gfort/%.o: $(SRC)/%.f90
    $(FC_gfort) -c $(FFLAGS) -o $@ $<

$(BLD)/ifort/%.o: $(SRC)/%.for
    $(FC_ifort) -c $(FFLAGS) -o $@ $<

$(BLD)/ifort/%.o: $(SRC)/%.f90
    $(FC_gfort) -c $(FFLAGS) -o $@ $<

# link everything
$(target).gfort: $(BLD)/gfort/$(objects)
    $(FC_gfort) -o $@ $(FFLAGS) -J $(BLD)/gfort $^ $(LDFLAGS)

$(target).ifort: $(BLD)/ifort/$(objects)
    $(FC_ifort) -o $@ $(FFLAGS) -I $(BLD)/ifort $^ $(LDFLAGS)

现在,如果您有很多规则,并且重复使用,那么您可以使用一个定义和eval,这样就可以了:

代码语言:javascript
复制
LINK_FLAG_gfort:=-J
LINK_FLAG_ifort:=-I

define RULES_template =

$$(BLD)/$(1)/%.o: $$(SRC)/%.for
    $$(FC_$(1)) -c $$(FFLAGS) -o $$@ $$<

$$(BLD)/$(1)/%.o: $$(SRC)/%.f90
    $$(FC_$(1)) -c $$(FFLAGS) -o $$@ $$<

$$(target).$(1): $$(BLD)/$(1)/$$(objects)
    $$(FC_$(1)) -o $$@ $$(FFLAGS) $$(LINK_FLAG_$(1)) $$(BLD)/$(1) $^ $$(LDFLAGS)

endef

$(eval $(call RULES_template,ifort))
$(eval $(call RULES_template,gfort))

注意双$$在这里(但不是在$(1)前面.)

另外,我还提到了尖棒和你最初的想法,你推翻了规则--比如你建造了ifort,然后做了一个随后的gfort构建,中间没有干净。不会重建.o文件,因为时间戳将比源文件更新,但是链接器将运行并使用过时的工件。

希望这能有所帮助

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71959057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档