具有多个结果的 Makefile

Makefile with multiple outcomes

这是我第一次尝试编写makefile,因此还有很大的改进空间。我需要使用包 sedumi 和 intel compiler studio 在 mac 上为 matlab 生成几个 mex 函数。

这是生成文件

# define matlab dir
MDIR = /Applications/MATLAB_R2017b.app

# compiles mex files using g++
#CC = gcc

# compiler flags for g++
#CCFLAGS = -O3 -fpic

# to use the intel compiler instead, uncomment CC and CCFLAGS below:

# compiles mex file using the intel compiler
CC = icc

# compiler flags for intel compiler
CCFLAGS = -O3 -fPIC -D__amd64

# Figure out which platform we're on
UNAME = $(shell uname -s)

# Linux
ifeq ($(findstring Linux,${UNAME}), Linux)
    # define which files to be included
    CINCLUDE = -I$(MDIR)/extern/include -Ic++ -shared
    # define extension
    EXT = mexa64
endif

# Mac OS X
ifeq ($(findstring Darwin,${UNAME}), Darwin)
    # define which files to be included
    CINCLUDE = -L$(MDIR)/bin/maci64 -Ic++ -shared -lmx -lmex -lmat -lmwblas
    # define extension
    EXT = mexmaci64
    # CCFLAGS += -std=c++11 
endif

SRC:=$(wildcard *.c)

*.o: $(SRC)
    for i in $(SRC) ; do \
    $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $$i -o $${i%.c}.o; \
    done

OBJ0:=bwblkslv.o sdmauxFill.o sdmauxRdot.o
OBJ1:=choltmpsiz.o


all: 
    $(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ0) -o bwblkslv.$(EXT)
    $(CC) $(CCFLAGS) $(CINCLUDE) $(OBJ1) -o choltmpsiz.$(EXT)

# clean up
clean:
    rm -f *.o *.$(EXT)

事实上,Makefile 工作得很好。制作然后制作所有 return matlab 中所需的 mex 函数。

我有 OBJ0 到 OBJ37,虽然添加这些行可以解决问题,但我想知道是否有更简单的方法来实现相同的结果。

非常感谢。

埃德

PS。感谢 https://github.com/jtilly/mex 的作者提供部分 makefile。

有几个方面您可以改进:

  1. 使用make自动变量($@,$<,$^...)

  2. 由于 make pattern rule:

    ,为您的 C 编译使用更面向 make 的风格
    SRC := $(wildcard *.c)
    OBJ := $(patsubst %.c,%.o,$(SRC))
    
    %.o: %.c
        $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $@
    

    这比 shell 循环有几个优点。最重要的是当只有一个 C 文件更改时,只有一个编译是 运行。使用您的解决方案,所有 C 文件都会在只有一个更改时重新编译。此外,*.o 是扩展到现有目标文件的通配符。通常不是你想要的。请注意,在您的情况下,您还可以使用 static pattern rule:

    $(OBJ): %.o: %.c
        $(CC) $(CCFLAGS) -I$(MDIR)/extern/include -c -Ic++ $< -o $@
    

    看起来几乎相同,但将规则限制为指定的目标列表 $(OBJ)

  3. 使用宏和foreach-eval-call实例化链接器规则:

    .PHONY: all clean
    
    EXTS :=
    
    # $(1): variable name
    define MY_rule
    $(1)_EXT := $$(patsubst %.o,%.$$(EXT),$$(firstword $$($(1))))
    
    EXTS += $$($(1)_EXT)
    
    $$($(1)_EXT): $$($(1))
        $$(CC) $$(CCFLAGS) $$(CINCLUDE) $$^ -o $$@
    endef
    
    OBJVARS := OBJ0 OBJ1 ... OBJ37
    
    OBJ0 := bwblkslv.o sdmauxFill.o sdmauxRdot.o
    OBJ1 := choltmpsiz.o
    
    $(foreach v,$(OBJVARS),$(eval $(call MY_rule,$(v))))
    
    all: $(EXTS)
    
    clean:
        rm -f $(OBJ) $(EXTS)
    

    请注意 $$ 以转义 eval 添加的第一个扩展。例如,foreach 的第一次迭代实例化了以下规则:

    OBJ1_EXT := $(patsubst %.o,%.$(EXT),$(firstword $(OBJ1))
    
    EXTS += $(OBJ1_EXT)
    
    $(OBJ1_EXT): $(OBJ1)
        $(CC) $(CCFLAGS) $(CINCLUDE) $^ -o $@
    

    设计宏的一个简单方法是首先编写您想要的内容,例如 OBJ1 变量,将每个 $ 替换为 $$,最后替换 OBJ1 来自 $(1).