一步一步写一个简单通用的makefile(二)
这一篇源代码沿用上一篇的源代码hellomake.c hellofunc.c hellofunc.h makefile
但是代码内容和结构有变化,如下:
.
├── include
│ └── hellofunc.h
├── makefile
└── src
├── hellofunc.c
└── hellomake.c
hellomake.c 代码:
#include"../include/hellofunc.h" #include<stdio.h> void myPrintHelloMake(void) { printf("Hello makefiles!\n"); return; }
hellofunc.c代码:
#include"../include/hellofunc.h" #include<stdio.h> void myPrintHelloMake(void) { printf("Hello makefiles!\n"); return; }
hellofunc.h代码:
/*
example include file
*/
void myPrintHelloMake(void);
makefile 文件代码:
#Hellomake #Magnum, 2014-10-19 # 指令编译器和选项 CC=gcc CFLAGS=-Wall LIBS=-lm IncludeDir = -I./hellofunc/ LinkDir = -L OBJ_DIR = ./obj BIN_DIR = ./bin PROJECT_TOP_DIR=.#$(shell pwd) #$(shell cd ../; pwd) PROJECT_BIN_DIR=./bin PROJECT_SRC_DIR=./src PROJECT_LIB_DIR=./lib PROJECT_OBJ_DIR=./objs MKDIR := mkdir -p # 目标文件 TARGET=$(BIN_DIR)/hellomake src=$(wildcard ./src/*.c) dir= $(notdir $(src)) PROJECT_OBJ= $(patsubst %.c,%.o,$(dir) ) PROJECT_ALL_OBJS= $(addprefix ./objs/, $(PROJECT_OBJ)) $(TARGET): $(PROJECT_ALL_OBJS) $(CC) -o $@ $^ $(LIBS) .PHONY : clean clean: -rm -rf $(TARGET) $(PROJECT_ALL_OBJS) ./objs/%.o:./src/%.c @if test ! -d $(PROJECT_OBJ_DIR) ; \ then \ mkdir $(PROJECT_OBJ_DIR) ; \ fi @if test ! -d $(PROJECT_BIN_DIR) ; \ then \ mkdir $(PROJECT_BIN_DIR) ; \ fi $(CC) $(CFLAGS) -o $@ -c $<
makefile执行命令的部分记得改为tab而不是空格,否则会报错。
执行make,结果如下:
. ├── bin │ └── hellomake ├── include │ └── hellofunc.h ├── makefile ├── objs │ ├── hellofunc.o │ └── hellomake.o └── src ├── hellofunc.c └── hellomake.c 4 directories, 7 files
这里面课执行文件放在拉bin文件夹中,而中间.o文件全部放在objs文件夹内。
执行命令"./bin/hellomake"得到:
Hello makefiles! Value:2.708050
可以发现hellomake.c 和 hellofunc.c 在引入头文件的地方有变化,其他内容还是和之前的一样。
也可以这样修改:
hellomake.c:
//#include "../include/hellofunc.h" #include<hellofunc.h> #include<stdio.h> #include<math.h> int main() { // call a function in another file myPrintHelloMake(); double value =15; printf("Value:%f\n",log(value)); return(0); }
hellofunc.c:
//#include"../include/hellofunc.h" #include<hellofunc.h> #include<stdio.h> void myPrintHelloMake(void) { printf("Hello makefiles!\n"); return; }
makefile:
#Hellomake #Magnum, 2014-10-19 # 指令编译器和选项 CC=gcc CFLAGS=-Wall LIBS=-lm IncludeDir = -I./include/ LinkDir = -L OBJ_DIR = ./obj BIN_DIR = ./bin PROJECT_TOP_DIR=.#$(shell pwd) #$(shell cd ../; pwd) PROJECT_BIN_DIR=./bin PROJECT_SRC_DIR=./src PROJECT_LIB_DIR=./lib PROJECT_OBJ_DIR=./objs MKDIR := mkdir -p # 目标文件 TARGET=$(BIN_DIR)/hellomake src=$(wildcard ./src/*.c) dir= $(notdir $(src)) PROJECT_OBJ= $(patsubst %.c,%.o,$(dir) ) PROJECT_ALL_OBJS= $(addprefix ./objs/, $(PROJECT_OBJ)) $(TARGET): $(PROJECT_ALL_OBJS) $(CC) -o $@ $^ $(LIBS) .PHONY : clean clean: -rm -rf $(TARGET) $(PROJECT_ALL_OBJS) ./objs/%.o:./src/%.c @if test ! -d $(PROJECT_OBJ_DIR) ; \ then \ mkdir $(PROJECT_OBJ_DIR) ; \ fi @if test ! -d $(PROJECT_BIN_DIR) ; \ then \ mkdir $(PROJECT_BIN_DIR) ; \ fi $(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)
进一步优化makefile:
#Hellomake
#Magnum, 2014-10-19
# 指令编译器和选项
CC=gcc
CFLAGS=-Wall
LIBS=-lm
IncludeDir = -I./include/
LinkDir = -L
OBJ_DIR = ./obj
BIN_DIR = ./bin
PROJECT_TOP_DIR=$(shell pwd)#$(shell cd ../; pwd)
PROJECT_BIN_DIR=./bin
PROJECT_SRC_DIR=./src
PROJECT_LIB_DIR=./lib
PROJECT_OBJ_DIR=./objs
MKDIR := mkdir -p
# 目标文件
TARGET=$(BIN_DIR)/hellomake
src=$(wildcard $(PROJECT_SRC_DIR)/*.c)
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.c,%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ))
all: chdir $(TARGET)
$(TARGET): $(PROJECT_ALL_OBJS)
$(CC) -o $@ $^ $(LIBS)
chdir:
@if test ! -d $(PROJECT_OBJ_DIR) ; \
then \
mkdir $(PROJECT_OBJ_DIR) ; \
fi
@if test ! -d $(PROJECT_BIN_DIR) ; \
then \
mkdir $(PROJECT_BIN_DIR) ; \
fi
.PHONY : clean
clean:
-rm -rf $(TARGET) $(PROJECT_ALL_OBJS)
./objs/%.o:./src/%.c
$(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)
执行make也能得到正确的结果, "-I"指定啦编译的时候系统搜索头文件的系统路径首先是"-I"后面的路径,然后才是/usr/include 之类的。
提示: makefile文件结束后请删除不必要的空格,很可能你google 超久最后就是由于这些多余的空格引起的。
关于下面这部分代码不懂的,可以百度,网上有很多详细的解释:
src=$(wildcard ./src/*.c)
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.c,%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix ./objs/, $(PROJECT_OBJ))