带你10分钟学会编写makefile文件

  1. Makefile是什么?
    简单的说,Makefile/makefile就是项目管理器。如果你了解过linux内核的话。你对Makefile就不陌生,因为linux内核源码非常庞大,想要编译内核源码就不得不使用make。

  2. Makefile的五个规则。
    

    显示规则:生成目标文件所依赖的所有文件写进Makefile。
    隐晦规则:make具有自动推导的功能,有时我们可以不用把目标依赖写进Makefile。
    变量:Makefile文件允许使用变量,所有变量都是字符串,和shell脚本类似。
    注释:在c语言中使用//注释,而在Makefile中使用#(和shell一样)。
    文件指示:如果你想要编译的文件不在同一个目录下。就要包含进来(make -I(dir) -f(file))

  3. 在linux下如何编写一个简单Makefile文件?
    首先创建一个Makefile文件:
    peng@ubuntu:~/Desktop/interviewer/list$ vim Makefile

	test.out:file1.o file2.o main.o             #生成test需要的目标文件
		gcc file1.o file2.o main.o -o test   #注意tab
	file1.o:file1.c                                        #目标 依赖
		gcc	-c file1.c -o file1.o
	file2.o:file2.c
		gcc -c file2.c  -o file2.o
	main.o:main.c
		gcc -c main.c  -o main.o       
	clean:
		rm *.o test.out                              #执行make clean时删除编译所有目标文件和可执行文件                            
  1. make编译过的工程,如果源码没有更新。不会再次编译,其实这个也可以理解,编译内核需要几个小时,如果每次修改都要编译几个小时,不是我们所期望的,所以make靠时间戳来判断是否已经编译过。如果没有更新则不会再次编译。如果你想不更新也编译可以加这样的一条语句:
 	PHONY:      #伪目标,不更新也编译      
  1. 如何写一个实用的Makefile文件?
	 1 OBJ = test                                                     //变量的使用                                 
	 2 
	 3 ALLC = $(wildcard *.c)                                 //此目录下所有.c
	 4 
	 5 ALLO = $(patsubst %.c,%.o,$(ALLC))         //匹配每一个.c 
	 6  
	 7 all:$(ALLO)                   
	 8     gcc $(ALLO) -o $(OBJ).out                      //编译               
	 9 
	10 clean:
	11     rm *.out *.o                                             //makefile 支持shell命令

  1. 初探linux内核源码
    peng@ubuntu:~/Desktop/linux-3.14/arch/x86/syscalls$ vim Makefile
	out := $(obj)/../include/generated/asm
	uapi := $(obj)/../include/generated/uapi/asm
	
	# Create output directory if not already present
	_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') \
		  $(shell [ -d '$(uapi)' ] || mkdir -p '$(uapi)')
	
	syscall32 := $(srctree)/$(src)/syscall_32.tbl
	syscall64 := $(srctree)/$(src)/syscall_64.tbl
	
	syshdr := $(srctree)/$(src)/syscallhdr.sh
	systbl := $(srctree)/$(src)/syscalltbl.sh
	
	quiet_cmd_syshdr = SYSHDR  $@
	      cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
			   '$(syshdr_abi_$(basetarget))' \
			   '$(syshdr_pfx_$(basetarget))' \
			   '$(syshdr_offset_$(basetarget))'
	quiet_cmd_systbl = SYSTBL  $@
	      cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@
	
	syshdr_abi_unistd_32 := i386
	$(uapi)/unistd_32.h: $(syscall32) $(syshdr)
		$(call if_changed,syshdr)
	
	syshdr_abi_unistd_32_ia32 := i386
	syshdr_pfx_unistd_32_ia32 := ia32_
	$(out)/unistd_32_ia32.h: $(syscall32) $(syshdr)
		$(call if_changed,syshdr)
	
	syshdr_abi_unistd_x32 := common,x32
	syshdr_offset_unistd_x32 := __X32_SYSCALL_BIT
	$(uapi)/unistd_x32.h: $(syscall64) $(syshdr)
		$(call if_changed,syshdr)
	
	syshdr_abi_unistd_64 := common,64
	$(uapi)/unistd_64.h: $(syscall64) $(syshdr)
		$(call if_changed,syshdr)
	
	syshdr_abi_unistd_64_x32 := x32
	syshdr_pfx_unistd_64_x32 := x32_
	$(out)/unistd_64_x32.h: $(syscall64) $(syshdr)
		$(call if_changed,syshdr)
	
	$(out)/syscalls_32.h: $(syscall32) $(systbl)
		$(call if_changed,systbl)
	$(out)/syscalls_64.h: $(syscall64) $(systbl)
		$(call if_changed,systbl)
	
	uapisyshdr-y			+= unistd_32.h unistd_64.h unistd_x32.h
	syshdr-y			+= syscalls_32.h
	syshdr-$(CONFIG_X86_64)		+= unistd_32_ia32.h unistd_64_x32.h
	syshdr-$(CONFIG_X86_64)		+= syscalls_64.h
	
	targets	+= $(uapisyshdr-y) $(syshdr-y)
	
	all: $(addprefix $(uapi)/,$(uapisyshdr-y))
	all: $(addprefix $(out)/,$(syshdr-y))

通过这个例子,你就知道makefile有多么强大,就连我们最熟悉的linux内核源码都是通过它编译的。当然,看完这篇文件之后你只是了解一下什么是makefile,如果你想要深入的话需要买一本有linux c环境高级编程一样厚的书仔细品味,希望大家能多多支持。。。

你可能感兴趣的:(linux)