具有多个结果的 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。
有几个方面您可以改进:
使用make自动变量($@
,$<
,$^
...)
- ,为您的 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)
。
使用宏和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)
.
这是我第一次尝试编写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。
有几个方面您可以改进:
使用make自动变量(
$@
,$<
,$^
...)- ,为您的 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)
。 使用宏和
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)
.