< myhello.c >:
#include <stdio.h>
#include "test.h"
#include "abc.h"
void print(void);
int main()
{
abc();
printtest();
print();
return 0;
}
void print(void){
printf("hello world\n");
}
< abc.c >:
#include "abc.h"
void abc(void)
{
printf("\nit is in funciton abc");
}
< abc.h >:
#include <stdio.h>
void abc(void);
< test.c >:
#include <stdio.h>
void printtest(void)
{
printf("\nit is in test.c");
}
< test.h >:
#include <stdio.h>
void printtest(void);
简单来说,在myhello.c的main中,需要调用./abc.c的abc函数和./test.c的printtest函数,因而包含了他们的头文件abc.h test.h
重点来了,makefile可以怎么写(只是我的写法的参考)
#目标(要生成的文件名)
TARGET := myhello
#编译器的选择(在Linux中其实可以忽略,因为cc指向的本来就是gcc)
CC := gcc
#编译的参数
CFLAG := -Wall
#编译包含的头文件所在目录
INCLUDES := -I. -Iinclude/
#所有用到的源文件,注意:非当前目录的要+上详细地址(不是当前路径可以加)
SRCS = myhello.c ./common/abc.c test.c
#把源文件SRCS字符串的后缀.c改为.o
OBJS = $(SRCS:.c=.o)
#匹配所有的伪目标依赖,即执行目标myhello.o & ./common/abc.c & ./common/test/test.c
.PHONY:all
#all为伪目标
all:$(OBJS)
#当所有依赖目标都存在后,链接,即链接myhello.o & ./common/abc.c & ./commontest/test.c
$(CC) $(LDFLAG) -o $(TARGET) $^
#重定义隐藏规则,匹配上述目标:myhello.o & ./common/abc.c & ./common/test/test.c
%.o:%.c
#生成.o文件,注意,由于SRCS有个别包含详细地址的,生成的.o文件也是详细地址
$(CC) -c $(INCLUDES) $(CFLAG) $(CPPFLAG) $< -o $@
//清空除源文件外的所有生成文件
clean:
rm -rf $(basename $(TARGET)) $(SRCS:.c=.o)
不知道注意到了没,我通过-o指定地址,把生成的.o与源文件.c放在一起的,例如abc.o放在了abc.c的目录,但同时的,链接时也需要给出详细地址。
结论:
在gcc时,会自动解决头文件.h的依赖关系,只需要指明头文件的地址
在gcc链接时,才需要把所有的源文件.o列出了,否则出现引用了未定义的变量/函数