Makefile--由入门到放弃

 

入门:

最简单的makefile

目录结构如下:

# tree ./

./

├── 1unicode_test.c

├── a.test

├── comm

│   ├── cJSON.c

│   ├── cJSON.h

│   ├── Makefile

│   ├── unicode.c

│   ├── unicode.h

│   ├── url_code.c

│   └── url_code.h

├── include

│   ├── Makefile

│   ├── send_http.h

│   ├── ufile.h

│   └── uuser.h

├── Makefile

├── Makefile.bak

├── param.h

├── src

│   ├── Makefile

│   ├── send_http.c

│   ├── ufile.c

│   └── uuser.c

├── test.c

├── ucp.c

├── ucp.h

├── unicode_test.c

└── \351\205\215\347\275\256\346\211\223\345\214\205\347\216\257\345\242\203.txt

 

3 directories, 25 files

 

  1. makefile简单编写如下:

# cat Makefile

#gcc test.c  comm/cJSON.c src/uuser.c comm/cJSON.h include/uuser.h  -lcurl -lm

 

TARGET = a.test

CC = gcc

CCFLAG = -g

LIBP = -lcurl -lm

 

all:

$(CC) -o $(TARGET) test.c  \

comm/cJSON.c \

comm/cJSON.h \

comm/url_code.c  \

comm/url_code.h    \

comm/unicode.c \

comm/unicode.h \

src/uuser.c \

src/ufile.c  \

src/send_http.c  \

include/uuser.h \

include/ufile.h \

include/send_http.h  \

param.h \

$(LIBP)

 

.PHONY:clean

clean:

rm -f $(TARGET)

find ./* -name "*.gch"  |xargs rm -f

 

 

  1. 加入一些自动推导,简单的优化之后:

# cat Makefile

#gcc test.c  comm/cJSON.c src/uuser.c comm/cJSON.h include/uuser.h  -lcurl -lm

 

TARGET = a.out

CC = gcc

CCFLAG = -g

LIBP = -lcurl -lm

 

COMM_DIR=./comm

SRC_DIR=./src

INCL_DIR=./include

OBJ_DIR=./obj

 

objects = test.o $(COMM_DIR)/cJSON.o $(COMM_DIR)/url_code.o $(COMM_DIR)/unicode.o \

  $(SRC_DIR)/uuser.o $(SRC_DIR)/ufile.o $(SRC_DIR)/send_http.o

 

 

$(TARGET):$(objects)

mkdir -p obj

$(CC) -o $(TARGET) $(objects) $(LIBP)

 

 

test.o:param.h

cJSON.o:$(COMM_DIR)/cJSON.h

url_code.o:$(COMM_DIR)/url_code.h

unicode.o:$(COMM_DIR)/unicode.h

uuser.o:$(INCL_DIR)/uuser.h

ufile.o:$(INCL_DIR)/ufile.h

send_http.o:$(INCL_DIR)/send_http.h

 

 

#all:

# $(CC) -o $(TARGET) test.c  \

# comm/cJSON.c \

# comm/cJSON.h \

# comm/url_code.c  \

# comm/url_code.h    \

# comm/unicode.c \

# comm/unicode.h \

# src/uuser.c \

# src/ufile.c  \

# src/send_http.c  \

# include/uuser.h \

# include/ufile.h \

# include/send_http.h  \

# param.h \

# $(LIBP)

 

.PHONY:clean

clean:

rm -f $(TARGET)

find ./* -name "*.gch"  |xargs rm -f

find ./* -name "*.o"  |xargs rm -f

 

  1. 还是有很多的问题,如果文件数量很多的话,这样还是需要手动编写,会有很多大量的工作,所有再次进行优化

#gcc test.c  comm/cJSON.c src/uuser.c comm/cJSON.h include/uuser.h  -lcurl -lm

 

TARGET = a.out

CC = gcc

CCFLAG = -g

LIBP = -lcurl -lm

 

CUR_DIR=$(shell pwd)

COMM_DIR=./comm

SRC_DIR=./src

INCL_DIR=./include

OBJ_DIR=./obj

 

vpath %.c $(CUR_DIR):$(COMM_DIR):$(SRC_DIR)

 

objects = test.o cJSON.o url_code.o unicode.o \

  uuser.o ufile.o send_http.o

  

objectds = $(wildcard $(OBJ_DIR)/*.o)

 

$(TARGET):$(objects)

$(CC) -o $@ $(objectds)   $(LIBP)

@echo "..."

 

$(objects):%.o:%.c

$(CC)  -c $< -o $(OBJ_DIR)/$@

 

#mkdir -p obj

 

.PHONY:clean

clean:

rm -f $(TARGET)

find ./* -name "*.gch"  |xargs rm -f

find ./* -name "*.o"  |xargs rm -f

 

 

  1. 这一次的自动推导更加多了,但是上面的objects的.o还是手写的,要是改成自动的,则变为一个通用的makefile了,所以在此优化

#目录结构如下所i示

# tree \

. \

├── comm \

│   ├── cJSON.c \

│   ├── cJSON.h \

│   ├── Makefile \

│   ├── unicode.c \

│   ├── unicode.h \

│   ├── url_code.c \

│   └── url_code.h \

├── include \

│   ├── Makefile \

│   ├── send_http.h \

│   ├── ufile.h \

│   └── uuser.h \

├── Makefile \

├── Makefile.bak \

├── Makefile.bak1 \

├── Makefile.bak2 \

├── param.h \

├── src \

│   ├── Makefile \

│   ├── send_http.c \

│   ├── ufile.c\

│   └── uuser.c\

├── test\

│   ├── 1unicode_test.c\

│   ├── ucp.c\

│   ├── ucp.h\

│   └── unicode_test.c\

├── test.c\

└── \351\205\215\347\275\256\346\211\223\345\214\205\347\216\257\345\242\203.txt\

4 directories, 26 files\

 

 

TARGET = a.out

CC = gcc

CCFLAG = -g

LIBP = -lcurl -lm

 

CUR_DIR=$(shell pwd)

COMM_DIR=$(CUR_DIR)/comm

SRC_DIR=$(CUR_DIR)/src

INCL_DIR=$(CUR_DIR)/include

OBJ_DIR=$(CUR_DIR)/obj

TEST_DIR=$(CUR_DIR)/test

 

#设置环境变量,寻找编译的c文件在设置的环境变量中进行寻找

VPATH_SRC_DIR :=  $(CUR_DIR):$(COMM_DIR):$(SRC_DIR)

vpath %.c $(VPATH_SRC_DIR)

 

#这一条语句的作用是遍历CUR_DIR目录下,深度为3的文件夹,输出文件夹名字列表

#DIRS = $(shell find $(CUR_DIR) -maxdepth 3 -type d)

#这一条是直接指定使用的文件夹列表,不会多余的遍历,主要是除去test文件夹下的测试文件干扰项目

DIRS = $(CUR_DIR) $(COMM_DIR) $(SRC_DIR)

SOURCES = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))

#将所有遍历出来的.c文件,替换生成.o文件,供下面%.o:%.c使用

objects = $(patsubst %.c,%.o,$(notdir $(SOURCES)))

 

#all:

# @echo 1 $(DIRS)

# @echo 2 $(SOURCES)

# @echo 3 $(objects)

 

#获取OBJ_DIR目录下的带路经的.o文件列表,供链接的时候使用

objectds = $(wildcard $(OBJ_DIR)/*.o)

 

$(TARGET):$(objects)

$(CC) -o $@ $(objectds)   $(LIBP)

@echo "..."

 

#将所有.c文件编译生成.o文件,放在OBJ_DIR目录下

$(objects):%.o:%.c

# 如果OBJ_DIR目录不存在,则先创建该目录

@if [ ! -d $(OBJ_DIR) ];then mkdir -p $(OBJ_DIR);fi;

$(CC)  -c $< -o $(OBJ_DIR)/$@

 

 

.PHONY:clean

clean:

rm -f $(TARGET)

rm -fr $(OBJ_DIR)

find ./* -name "*.gch"  |xargs rm -f