TopologySmooth 项目 Makefile 编译

TopologySmooth 项目 Makefile 编译

最近在阅读论文Topology-based Smoothing of 2D Scarlat Fields with $C^1$-Continuity 的c++源码的过程中, 遇到了编译Makefile的一些问题. 由于我之前的一些c++项目均是用cmake工具自动生成Makefile文件, 对具体的Makefile语法不是十分熟悉. 趁此机会, 简要学习一些Makefile语法. 主要参考了CSDN陈皓博客的《跟我一起写Makefile》系列.

Makefile

先直接贴出项目中Makefile文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
SOURCES = $(CXX_OBJECTS:%.o=%.cpp) $(C_OBJECTS:%.o=%.c) \
$(MAIN_OBJECT:%.o=%.cpp)
LIB_OBJECTS = $(CXX_OBJECTS) $(C_OBJECTS)
CXX_OBJECTS = monotonic_function_space.o minimath.o opt1d.o halfedge.o opt_height_field.o
C_OBJECTS =
## The main object is assumed to be a '.cpp' file.
MAIN_OBJECT = test.o

ARCH = $(shell uname)
include Makefile.$(ARCH)

TARGET = toposmooth2
LIBTARGET = lib$(TARGET).a
DYLIBTARGET = lib$(TARGET).$(DYLIB_SUFFIX)

CPPCOMPILER = g++
CCOMPILER = gcc

WARNINGFLAGS = -Wall -Wno-sign-compare -Woverloaded-virtual -fkeep-inline-functions

COMPILERFLAGS = -g -O2 $(WARNINGFLAGS) -finline-functions -ftree-vectorize -msse2


AR = /usr/bin/ar
ARFLAGS = -rus

## This comes from Makefile.$(ARCH)
#DYLIB_FLAGS = -shared
COMPILERFLAGS += -fPIC

MAKEDEPEND = $(CPPCOMPILER) -MM
DEPENDFILE = Makefile.depend

INCLUDEFLAGS = -Iext -Iext/eigen2
LINKTIMEFLAGS = -lm -Lext/tnc -ltnc

# clear out implicit rules
.SUFFIXES:

all: $(LIBTARGET) $(TARGET) $(DYLIBTARGET)

$(TARGET): $(MAIN_OBJECT) $(LIBTARGET)
$(CPPCOMPILER) -o $@ \
$(MAIN_OBJECT) \
$(LIBTARGET) \
$(INCLUDEFLAGS) $(LINKTIMEFLAGS) \
$(FRAMEWORKS)


library: $(LIBTARGET) $(DYLIBTARGET)

$(LIBTARGET): $(LIB_OBJECTS)
$(AR) $(ARFLAGS) $@ $(LIB_OBJECTS)

$(DYLIBTARGET): $(LIB_OBJECTS)
$(CPPCOMPILER) $(DYLIB_FLAGS) -o $@ $(LIB_OBJECTS) $(LINKTIMEFLAGS)

%.o: %.cpp
$(CPPCOMPILER) $(COMPILERFLAGS) $(INCLUDEFLAGS) -c $<

%.o: %.c
$(CCOMPILER) $(COMPILERFLAGS) $(INCLUDEFLAGS) -c $<

.PHONY : clean tidy
clean: tidy
rm -f $(TARGET)
rm -f $(LIBTARGET)
rm -f $(DYLIBTARGET)
rm -f $(DEPENDFILE)

tidy:
rm -f $(LIB_OBJECTS) $(MAIN_OBJECT)

relib:
rm -f $(TARGET)

depend:
$(MAKEDEPEND) $(INCLUDEFLAGS) $(SOURCES) > $(DEPENDFILE)

-include $(DEPENDFILE)

语法与说明

  1. Makefile最基本的规则如下
    1
    2
    3
    4
    target ... : prerequisites ...
    conmmand
    ...
    ...

如果依赖文件(prerequisites)的日期比目标文件(target)新, 则执行command命令.

  1. ARCH = $(shell uname) 变量在linux系统下为Linux.
  1. .PHONY : clean tidy 表示 clean, tidy是伪目标.
  1. include Makefile.$(ARCH) 表示引用Makefile.Linux 文件中的命令

    1
    2
    DYLIB_SUFFIX = so
    DYLIB_FLAGS = -shared
  2. gcc -I -L l区别 -Iext -Iext/eigen2 表示在ext文件夹与ext/eigen2文件夹中作为第一个寻找的头文件目录, 此外还有/usr/include, /usr/local/include. -Lext/tnc 表示作为第一个寻找库(动态)文件的目录, 此外还有/usr/lib, /usr/local/lib. -lm -Lext/tnc -ltnc 表示指定程序要链接的库, 数学库, 库名为m, 库文件名为libm.so.

  3. gcc 优化选项 -O1 -O2 -O3 -Os 优化级别从低到高. -g可执行程序包含调试信息.

  4. 利用伪目标的特性使用all生成多个可执行文件

    1
    all: $(LIBTARGET) $(TARGET) $(DYLIBTARGET)
  5. 生成多目标时, 采用自动化变量 $@ 表示目标集. $<表示所有依赖目标集.

  6. 静态模式更容易定义多目标规则.

    1
    2
    <targets ...>: <target-pattern>: <prereq-patterns ...>
    <commands>


1
2
%.o: %.cpp
$(CPPCOMPILER) $(COMPILERFLAGS) $(INCLUDEFLAGS) -c $<

  1. 自动生成依赖性.
    MAKEDEPEND = $(CPPCOMPILER) -MM
分享到