layout | title | categories | tags | date | description | ||
---|---|---|---|---|---|---|---|
post
|
Make & CMake 进阶
|
|
|
2019-01-10 14:22:22 -0800
|
开发中常用的cmake和make的tricks
|
引言
当下流行的IDE,将源代码生成可执行文件的过程都封装起来,对于开发着来说方便使用。 但是对于初学者来说,蒙蔽了源代码到可执行文件过程。源代码预处理,编译,打包,链接等步骤, 才能形成IDE中的一步到位的可执行文件target。而Makefile是直白的描述一个源代码如何被操作 才能成为target的一种文件格式。而CMake是一种可以通过配置的方式生成Makefile的脚本. 如果只是简单的开发一个.cpp进行测试,Makefile是首选。 本文中不对Makefile的基本语法进行介绍,要学习基本语法可以参看陈皓老师的Makefile中文教程进行学习。
Makefile
ifeq
和ifneq
之后要有个空格,否则不识别
ifeq ($(UNAME), linux)
$(info "")
else
$(warning "")
$(error $(HAVE_SSHSERVER))
endif
定义变量
HAVE_THE_VALUE :=
# 新定义一个变量 HAVE_THE_VALUE ?=
# 如果没有定义,则定义一个新变量 HAVE_THE_VALUE +=
# 往变量中append数据
这个地方有点像pascal,不要与shell中混淆了
变量赋值
后面一定不要有空格,回车之类的空白符号,否则可能会将你整疯了的。 就拿caffe中的Makefile.config中
USE_LEVELDB := 1
USE_LEVELDB := 1
这两行的区别在于,第二行赋值操作后面有一个空格。在Makefile中通过如下代码进行添加编译需要的宏。
ifeq ($(USE_LEVELDB), 1)
CXX_FLAGS += -DUSE_LEVELDB
endif
结果编译的时候打开的开关会与设想的不一样。
Makefile案例
#! Makefile
SRCS := PAPI_flops.c
OBJECTS := $(patsubst %.c, %.o, $(SRCS))
STATIC_LIB := /usr/local/lib/libpapi.a
INCLUDE_DIR := -I/usr/local/include
CC := gcc
all: PAPI_flops
PAPI_flops: $(OBJECTS)
$(CC) -O0 $< $(STATIC_LIB) -o $@
$(OBJECTS): $(SRCS)
$(CC) $(INCLUDE_DIR) -O0 -c $<
test:
echo "----Running the PAPI_flops-----"
@./PAPI_flops
clean:
rm -rf PAPI_flops
rm -rf *.o
makefile中调用.a库的编写
#!Makefile
CC = g++
TINYCV_DIR = /home/cwl/TinyCV
TINYCV_INCLUDE_DIR = $(TINYCV_DIR)/include
LIB_DIR = $(TINYCV_DIR)/build
CXX_FLAG = -O3 -std=c++11 -Wall -Werror -fPIC
all: main
main: main.o
$(CC) $< $(CXX_FLAG) -I$(TINYCV_INCLUDE_DIR) -L$(LIB_DIR) -ltinycv -o $@
main.o: main.cpp
$(CC) $(CXX_FLAG) -I$(TINYCV_INCLUDE_DIR) -c $<
clean:
rm -f *.o main
需要注意的是下面这句中$<
是指输入文件main.o,此处紧跟gcc
main: main.o
$(CC) $< $(CXX_FLAG) -I$(TINYCV_INCLUDE_DIR) -L$(LIB_DIR) -ltinycv -o $@
但是如果变为如下情形,就会出现后面中的错误
main: main.o
$(CC)