ARM-Linux Kernel Makefile $(TOPDIR)/Makefile VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 5 EXTRAVERSION =-rmk7-np2 버전정보를나타내는변수들 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) 버전을나타내는변수를합쳐서 KERNELRELEASE 라는변수를만들어냈다. 정확한버전명칭이다. ARCH := arm ARCH 변수는앞으로어떤 ARCH 하위폴더에있는소스를컴파일할것인가를결정한다. 의문 ) 위에서 : 가의미가무엇일까? : 빼도아무런문제없음이다. CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; else if [ -x /bin/bash ]; then echo /bin/bash; else echo sh; fi ; fi) 현재사용하고있는 shell 이무엇인지알아낸다. Shell 이라는명령을쓰면뒤에오는문자를 shell 에게보내서나온결과값을변수에저장하게한다. TOPDIR := $(shell /bin/pwd) 소스의최상위디렉토리를알아낸다. 이명령역시 shell 을통해결과값을저장한다. HPATH = $(TOPDIR)/include FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net 해더파일이있는곳을지정한다 HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 크로스컴파일링함에도불구하고호스트컴파일이필요할경우 ( 이런경우가있다 ) 사용할호스트컴파일러를지정한다. CROSS_COMPILE = arm-linux- 크로스컴파일할경우앞부분에들어갈단어지정
AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CPP = $(CC) E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump MAKEFILES = $(TOPDIR)/.config GENKSYMS = /sbin/genksyms DEPMOD = /sbin/depmod MODFLAGS = -DMODULE CFLAGS_KERNEL = PERL = perl make가가지고있는변수를상황에맞게셋팅 make 프로그램은위의변수들을내부적으로자동으로알아서사용한다 export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH CONFIG_SHELL TOPDIR HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS MODFLAGS PERL 여기서지정했던변수들을쉘변수로쓰일수있도록 export한다. 그러면하위 Makefile에위의변수들을재정의할필요가없게된다 All : do-it-all # # Make "config" the default target if there is no configuration file or # "depend" the target if there is no top-level dependency information # ifeq (.config,$(wildcard.config)) include.config ifeq (.depend,$(wildcard.depend)) include.depend do-it-all: Version vmlinux else
CONFIGURATION = depend do-it-all: depend else CONFIGURATION = config do-it-all: config make 또는 make all 을하게되면여기서부터시작하게된다. All : do-it-all 을요구한다 위구문해석.. if(.config 파일이있다면 ){ include.config //.config 파일을읽어서포함시킨다 if(.depend 파일이있다면 ){ include.depend //.depend 파일을읽어서포함시킨다 do-it-all: Version vmlinux //do-it-all 요구사항 Version vmlinux }else{ CONFIGURATION = depend do-it-all: depend ;depend 부터한다 } }else{ CONFIGURATION = config do-it-all: config ;config 부터한다. } # # INSTALL_PATH specifies where to place the updated kernel and system map # images. Uncomment if you want to place them anywhere other than root. # #export INSTALL_PATH=/boot 사용하지않아서주석처리가되었다 MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) export MODLIB 모듈이설치되는위치. 그리고나서 export 해서 shell 하위 Makefile 들도참조할수있게한다
# # standard CFLAGS # CPPFLAGS := -D KERNEL -I$(HPATH) CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing AFLAGS := -D ASSEMBLY $(CPPFLAGS) 특정컴파일시사용할프레그들지정 CPPFLAGS : preprocessor 처리할때쓰는프레그옵션지정 CFLAGS : 컴파일할때지정하는옵션 AFLAGS : 어셈블할때지정하는옵션 # # ROOT_DEV specifies the default root-device when making the image. # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case # the default of FLOPPY is used by 'build'. # This is i386 specific. # export ROOT_DEV = CURRENT ARM 에서는필요없는것이다. Only for i386 # # If you want to preset the SVGA mode, uncomment the next line and # set SVGA_MODE to whatever number you want. # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. # The number is the same as you would ordinarily press at bootup. # This is i386 specific. # export SVGA_MODE = -DSVGA_MODE=NORMAL_VGA ARM 에서는필요없는것이다. Only for i386 # # If you want the RAM disk device, define this to be the size in blocks. # This is i386 specific. # #export RAMDISK = -DRAMDISK=512 ARM 에서는필요없는것이다. Only for i386
CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o NETWORKS =net/network.o CORE_FILES 라고해서중요한오브젝트파일을지정해놓았다. NETWORKS 라고해서네트웍오트젝트를지정하고있다. LIBS =$(TOPDIR)/lib/lib.a SUBDIRS =kernel drivers mm fs net ipc lib LIBS 는라이브러리파일을지정 SUBDIRS 는컴파일이요구되는하위폴더를지정하고있다. 다른곳에서변수로자주쓰인다. DRIVERS-n := DRIVERS-y := DRIVERS-m := DRIVERS- := DRIVERS-n : 사용안함 DRIVERS-y : 커널에직접넣음 DRIVERS-m : 모듈로컴파일어떤 DEVERS가 y,n,m 인지를결정하는것은사용자이다. Make menuconfig 를통해서결정하면.config 파일에그정보가저장된다. 그러면여기 makefile 은.config 파일을참조한다. DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o DRIVERS-y += drivers/char/char.o drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/media/media.o DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o DRIVERS-$(CONFIG_DRM) += drivers/char/drm/drm.o DRIVERS-$(CONFIG_NUBUS) += drivers/nubus/nubus.a DRIVERS-$(CONFIG_ISDN) += drivers/isdn/isdn.a DRIVERS-$(CONFIG_NET_FC) += drivers/net/fc/fc.o DRIVERS-$(CONFIG_APPLETALK) += drivers/net/appletalk/appletalk.o DRIVERS-$(CONFIG_TR) += drivers/net/tokenring/tr.o DRIVERS-$(CONFIG_WAN) += drivers/net/wan/wan.o DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnetdrv.o DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o Ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_ PCD),) DRIVERS-y += drivers/cdrom/driver.o Endif DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o DRIVERS-$(CONFIG_PCMCIA_NETCARD) += drivers/net/pcmcia/pcmcia_net.o DRIVERS-$(CONFIG_PCMCIA_CHRDEV) += drivers/char/pcmcia/pcmcia_char.o DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus_all.o DRIVERS-$(CONFIG_ZORRO) += drivers/zorro/driver.o DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a DRIVERS-$(CONFIG_ALL_PPC) += drivers/macintosh/macintosh.o DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o DRIVERS-$(CONFIG_SGI_IP22) += drivers/sgi/sgi.a DRIVERS-$(CONFIG_VT) += drivers/video/video.o DRIVERS-$(CONFIG_PARIDE) += drivers/block/paride/paride.a DRIVERS-$(CONFIG_HAMRADIO) += drivers/net/hamradio/hamradio.o DRIVERS-$(CONFIG_TC) += drivers/tc/tc.a DRIVERS-$(CONFIG_USB) += drivers/usb/usbdrv.o DRIVERS-$(CONFIG_INPUT) += drivers/input/inputdrv.o DRIVERS-$(CONFIG_I2O) += drivers/i2o/i2o.o DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o $(CONFIG_####) 이라는변수는.config 안에저장되어있고, 그값은 y,n,m 중에하나이다. 만약사용자가 USB 를커널에직접넣는다고설정했을겨우,.config의파일에는 CONFIG_USB = y 라는변수로설정되어있게되고여기위에서는 DRIVERS-y += drivers/usb/usbdrv.o 로설정이되는것이다.
DRIVERS := $(DRIVERS-y) 커널에박기로결정한드라이버들은 DRIVERS 라는변수에다시저장한다 # files removed with 'make clean' CLEAN_FILES = kernel/ksyms.lst include/linux/compile.h vmlinux System.map.tmp* drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c drivers/char/conmakehash drivers/char/drm/*-mod.c drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist drivers/zorro/devlist.h drivers/zorro/gen-devlist drivers/sound/bin2hex drivers/sound/hex2hex drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} net/khttpd/make_times_h net/khttpd/times.h submenu* # directories removed with 'make clean' CLEAN_DIRS = Modules clean 에관련된변수들, 위에지정된변수들을 clean 명령을수행할때이용한다 # files removed with 'make mrproper' MRPROPER_FILES = include/linux/autoconf.h include/linux/version.h drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h drivers/net/hamradio/soundmodem/gentbl drivers/sound/*_boot.h drivers/sound/.*.boot drivers/sound/msndinit.c drivers/sound/msndperm.c drivers/sound/pndsperm.c drivers/sound/pndspini.c drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw
.version.config* config.in config.old scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp scripts/lxdialog/*.o scripts/lxdialog/lxdialog.menuconfig.log include/asm.hdepend scripts/mkdep scripts/split-include scripts/docproc $(TOPDIR)/include/linux/modversions.h # directories removed with 'make mrproper' MRPROPER_DIRS = include/config $(TOPDIR)/include/linux/modules mrproper 를했을때삭제가되는파일들과폴더들이다. mrproper 는완전히삭제, 처음처럼만들어주게된다 make clean 보다더강력하다. include arch/$(arch)/makefile 여기서 arch/arm/makefile 을 include 한다. export CPPFLAGS CFLAGS AFLAGS export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS 필요한 flag들하위 Makefile 들을위해 export 한다. Version: dummy @rm -f include/linux/compile.h Version 에대한구문, compile.h 파일을지우는것외엔특별히하는일이없다. @ 는화면에명령을보여주지말하는의미이다 dummy 는비어있다. boot: vmlinux @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(arch)/boot boot 는 arch/arm/boot 로폴더를이동거기에있는 Makefile 을실행한다.
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux $(NM) vmlinux grep -v ' (compiled ) (.o$$ ) ( [auw] ) (..ng$$ ) (LASH[RL]DI )' sort > System.map vmlinux 이이코드를수행해서나오는목표결과물이다. elf-executable 형식으로된실행파일이다요구사항인 $(CONFIGURATION) 는 config 와 depend를수행했다면비어있게된다그것들을먼저수행하지않았다면 $(CONFIGURATION) 는그것들을먼저수행하는단어가들어간다 init/main.o 와 init/version.o 를먼저생성하고 linuxsubdirs를수행한다. Linuxsubdirs 때문에 SUBDIRS 변수에정의된폴더를돌면서전부 Makefile을실행한다그리고나서 linking 작업을해서 vmlinux를만들어낸다마지막으로 nm 을통해서 System.map 을만든다. symlinks: rm -f include/asm ( cd include ; ln -sf asm-$(arch) asm) @if [! -d include/linux/modules ]; then mkdir include/linux/modules; fi include/asm 을적절한 arch의 include 폴더와연결시킨다. include/linux/modules 폴더가없다면생성한다. oldconfig: symlinks $(CONFIG_SHELL) scripts/configure -d arch/$(arch)/config.in configuration 할수있는메뉴중에하나, 정확한목적은모르겠지만, 잘안쓰인다. xconfig: symlinks $(MAKE) -C scripts kconfig. 사 wish -f scripts/kconfig.tk X-windows 기반의 configuration 메뉴설정
menuconfig: include/linux/version.h symlinks $(MAKE) -C scripts/lxdialog all $(CONFIG_SHELL) scripts/menuconfig arch/$(arch)/config.in 가장많이쓰이는 configuration 이다. Console 창에서메뉴형식으로설정을할수가있다. config: symlinks $(CONFIG_SHELL) scripts/configure arch/$(arch)/config.in 기본적인 configuration 설정방식, console 창에서하나씩 Y/N/M 을물어본다. include/config/marker: scripts/split-include include/linux/autoconf.h scripts/split-include include/linux/autoconf.h include/config @ touch include/config/marker 나중에조사해보자 ~ touch 를해서 MAKER 파일을만든다. 의미는없는것같다. 그냥 FLAG 같은걸로사용되는듯.. 위에작업들이잘수했되었다는의미로 linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS)) $(patsubst %,_dir_%, $(SUBDIRS)) : dummy include/linux/version.h include/config/marker $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@) SUBDIRS변수앞에 _dir_ 을붙여서새로운이름을하나씩만들어낸다. Patsubst는 $(patsubst PATTERN, REPLACEMENT, TEXT) 의형식으로 TEXT 에서 PATTERN 과일치하는부분을 REPLACEMENT로교체한다 SUBDIRS 변수에지정된폴더를이동하면서 Makefile 을실행한다 -C 뒤에붙는 patsubst 는 _dir_ 을뺀순수한디렉토리이름이다. $(TOPDIR)/include/linux/version.h: include/linux/version.h $(TOPDIR)/include/linux/compile.h: include/linux/compile.h version.h 나 compile.h 를사용할경우요구사항을먼저선행한다. 근데 $(TOPDIR)/include/linux/version.h: include/linux/version.h 이호출되는일이없다. 그냥바로다들 include/linux/version.h 을호출한다. 그래서이코드는별로쓸모가없다.
newversion: @if [! -f.version ]; then echo 1 >.version; else expr 0`cat.version` + 1 >.version; fi 버전을갱신한다. 여기서말하는버전이란이소스를지금까지몇번컴파일했는지는말한다. include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion @echo -n #define UTS_VERSION " #`cat.version` >.ver @if [ -n "$(CONFIG_SMP)" ] ; then echo -n " SMP" >>.ver; fi @if [ -f.name ]; then echo -n -`cat.name` >>.ver; fi @echo ' '`date`'"' >>.ver @echo #define LINUX_COMPILE_TIME "`date +%T` " >>.ver @echo #define LINUX_COMPILE_BY "`whoami` " >>.ver @echo #define LINUX_COMPILE_HOST "`hostname` " >>.ver @if [ -x /bin/dnsdomainname ]; then echo #define LINUX_COMPILE_DOMAIN "`dnsdomainname` "; elif [ -x /bin/domainname ]; then echo #define LINUX_COMPILE_DOMAIN "`domainname` "; else echo #define LINUX_COMPILE_DOMAIN ; fi >>.ver @echo #define LINUX_COMPILER "`$(CC) $(CFLAGS) -v 2>&1 tail -1` " >>.ver @mv -f.ver $@ 컴파일에관련된정보를직접만들어서 compile.h 라는파일에저장한다. 여기서컴파일한숫자를나타내는.version 파일의숫자를하나더증가시킨다. include/linux/version.h:./makefile @echo #define UTS_RELEASE "$(KERNELRELEASE) " >.ver @echo #define LINUX_VERSION_CODE `expr $(VERSION) * 65536 + $(PATCHLEVEL) * 256 + $(SUBLEVEL)` >>.ver @echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver @mv -f.ver $@ version.h 를생성한다. 그안에는 version 에관련된정보가 #define 되어있다.
init/version.o: init/version.c include/linux/compile.h include/config/marker $(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c init/version.c 를컴파일할때사용된다. Version.c 는 version.h 파일을 include 하고있다. 때문에 version.c 함수가잘작동하려면 version.h 파일을만든다음컴파일해야한다. init/main.o: init/main.c include/config/marker $(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $< main.c 를컴파일할때사용된다 fs lib mm ipc kernel drivers net: dummy $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@) fs lib mm ipc kernel drivers net 을만나면하위폴더도컴파일한다. 근데여기루틴은한번도수행을하지않는다. 그런데왜만들어놨는지모르겠다. TAGS: dummy etags `find include/asm-$(arch) -name '*.h'` find include -type d ( -name "asm-*" -o -name config ) -prune -o -name '*.h' -print xargs etags -a find $(SUBDIRS) init -name '*.c' xargs etags -a Vi 에디터나 emacs 를위한테그생성부분 # Exuberant ctags works better with -I tags: dummy CTAGSF=`ctags --version grep -i exuberant >/dev/null && echo "-I initdata, exitdata,export_symbol,export_symbol_novers"`; ctags $$CTAGSF `find include/asm-$(arch) -name '*.h'` && find include -type d ( -name "asm-*" -o -name config ) -prune -o -name '*.h' -print xargs ctags $$CTAGSF -a && find $(SUBDIRS) init -name '*.c' xargs ctags $$CTAGSF -a Vi 에디터나 emacs 를위한테그생성부분 ifdef CONFIG_MODULES ifdef CONFIG_MODVERSIONS MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h CONFIG_MODULES 는정의되어있고 CONFIG_MODVERSIONS 는정의되어있지않다. 그러므로 MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h 는설정되지않는다
.PHONY: modules modules: $(patsubst %, _mod_%, $(SUBDIRS)).PHONY: $(patsubst %, _mod_%, $(SUBDIRS)) $(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/marker $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules.phony 는정의된이름이 file 이아님을알려주고퍼포먼스를올려준다고한다..PHONY 라인을지워도작업수행에는문제가없다. 위에박스는 ifdef CONFIG_MODULES의범위안에설정된사항의연속이다. CONFIG_MODULES 가활성이라면 modules 라는항목이정의된다. 그러면 make modules 라는명령이가능하게된다. CONFIG_MODULES가비활성이라면위의구문들은 ifdef 문에의해설정이안된다. Make modules 를요청하면 $(patsubst %, _mod_%, $(SUBDIRS)) 를수행하게된다. $(SUBDIRS) 폴더들을돌면서 make modules 를수행하여모듈로설정한파일은다컴파일을한다. 각각의폴더의컴파일사항들은하위 Makefile 안에정의되어있다..PHONY: modules_install modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post Module_install의목적은컴파일이완료된모듈 (driver) 들을사용자가지정한디렉토리로이동하는것이다. 그작업을위해서 3가지의요구사항이정의되어있다. _modinst_, $(patsubst %, _modinst_%, $(SUBDIRS)), _modinst_post 가그것이다. 위 3가지가하는각각의일은아래라인에있다..PHONY: _modinst modinst_: @rm -rf $(MODLIB)/kernel @rm -f $(MODLIB)/build @mkdir -p $(MODLIB)/kernel @ln -s $(TOPDIR) $(MODLIB)/build 모듈을컴파일하기전에전에있던모듈들을다강제로삭제한다. 소프트링크도건다 ~
# If System.map exists, run depmod. This deliberately does not have a # dependency on System.map since that would run the dependency tree on # vmlinux. This depmod is only for convenience to give the initial # boot a modules.dep even before / is mounted read-write. However the # boot script depmod is the master version. ifeq "$(strip $(INSTALL_MOD_PATH))" "" depmod_opts := else depmod_opts := -b $(INSTALL_MOD_PATH) -r INSTALL_MOD_PATH 라는변수가비어있냐 / 아니냐를검사하는구문인데, 그결과에따라서 depmod_opts 라는변수를어떻게처리할것인가를결정한다. 하지만 depmod_opts 라는변수는아래박스안에서만쓰이는데주석처리가되어있어서결과적으로어디서도쓰이지않는다..PHONY: _modinst_post _modinst_post: _modinst_post_pcmcia # if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi System.map 을통해서의존성을만들어주는구문인데주석처리가되있다. # Backwards compatibilty symlinks for people still using old versions # of pcmcia-cs with hard coded pathnames on insmod. Remove # _modinst_post_pcmcia for kernel 2.4.1..PHONY: _modinst_post_pcmcia _modinst_post_pcmcia: cd $(MODLIB); mkdir -p pcmcia; find kernel -path '*/pcmcia/*' -name '*.o' xargs -i -r ln -sf../{} pcmcia pcmcia 이란다.. 그런가보다. 조사안했음.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS)) $(patsubst %, _modinst_%, $(SUBDIRS)) : $(MAKE) -C $(patsubst _modinst_%, %, $@) modules_install 하위폴더들을돌면서 module_install 을수행한다
# modules disabled... else modules modules_install: dummy @echo @echo "The present kernel configuration has modules disabled." @echo "Type 'make config' and enable loadable module support." @echo "Then build a kernel with module support enabled." @echo @exit 1 위의 else 전까지코드가 CONFIG_MODULES 라는변수가선언되어있으면다적용이되는코드이다. 그리고 CONFIG_MODULES 라는변수가선언이안되어있는데 make modoules, make modules_install 이라는명령이들어오면 ifdef 분기문에의해서 else 이후명령이수행되어 The present kernel configuration has modules disabled. Type 'make config' and enable loadable module support. Then build a kernel with module support enabled. 라는문구만나올뿐이다. clean: archclean find. ( -name '*.[oas]' -o -name core -o -name '.*.flags' ) -type f -print grep -v lxdialog/ xargs rm -f rm -f $(CLEAN_FILES) rm -rf $(CLEAN_DIRS) $(MAKE) -C Documentation/DocBook clean clean 이다. 요구사항인 archclean 은 arch/arm/makefile에있는것으로아키텍쳐에의존적인파일들을지우는역할을한다. Archclean은 $(TOPDIR)/arch/arm/Makefile 안에있다. mrproper: clean archmrproper find. ( -size 0 -o -name.depend ) -type f -print xargs rm -f rm -f $(MRPROPER_FILES) rm -rf $(MRPROPER_DIRS) $(MAKE) -C Documentation/DocBook mrproper distclean: mrproper rm -f core `find. ( -name '*.orig' -o -name '*.rej' -o -name '*~' -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' -o -name '.*.rej' -o -name '.SUMS' -o -size 0 ) -type f -print` TAGS tags
backup: mrproper cd.. && tar cf - linux/ gzip -9 > backup.gz sync sgmldocs: chmod 755 $(TOPDIR)/scripts/docgen chmod 755 $(TOPDIR)/scripts/gen-all-syms chmod 755 $(TOPDIR)/scripts/kernel-doc $(MAKE) -C $(TOPDIR)/Documentation/DocBook books psdocs: sgmldocs $(MAKE) -C Documentation/DocBook ps pdfdocs: sgmldocs $(MAKE) -C Documentation/DocBook pdf htmldocs: sgmldocs $(MAKE) -C Documentation/DocBook html sums: find. -type f -print sort xargs sum >.SUMS 위소스들은별로중요치않다 ~~ dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep -- init/*.c >.depend scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name *.h! -name modversions.h -print` >.hdepend $(MAKE) $(patsubst %,_sfdep_%,$(subdirs)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" Make dep을하면여기처리가된다. 요구사항으로 scripts/mkdep 이라는파일을생성한다. Arch/arm/Makefile 에있는 archdep 이라는곳에서 2개의폴더를소프트링크를건다. 그리고나서 Include/linux/version.h 을처리하면요구사항은끝이난다. Scripts/mkdep 이라는유틸을이용해서 init 폴더아래의모든 *.c 파일이 include 하고있는해더파일목록을작성한다음.depend 라는파일에저장한다. 그후에 make 명령을통해자기자신을또실행한다. 그때 _FASTDEP_ALL_SUB_DIRS 라는변수도넘겨준다. 위명령을처리한는부분은 Rules.make 에정의되어있다. Rules.make 파일은최상위 Makefile 외에도모든 Makefile들이같이쓰는공통된설정들을담고있으며, 모든 Makefile 들이 include 하고있다. 그 Rules.make 파일의부분에서다음과같이처리가수행된다.
ifdef _FASTDEP_ALL_SUB_DIRS $(patsubst %,_sfdep_%,$(_fastdep_all_sub_dirs)): $(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep 하위 make 들을돌면서 festdep 명령을내린다. fastdep 역시 rukes.make 파일에정의되어있다. fastdep에서실질적인.depend 생성을수행하고, 만약하위폴더가있다면하위폴더도.depend를할수있게해준다. ifdef CONFIG_MODVERSIONS $(MAKE) update-modverfile ifdef CONFIG_MODVERSIONS MODVERFILE := $(TOPDIR)/include/linux/modversions.h else MODVERFILE := export MODVERFILE 위의 CONFIG_MODVERSIONS 는정의되어있지않아서명령은수행되지않는다. depend dep: dep-files Make depend 가들어오면요구사항인 dep-files 를처리한다. 정작 depend 에서는하는일이없다. checkconfig: find * -name '*.[hcs]' -type f -print sort xargs $(PERL) -w scripts/checkconfig.pl checkhelp: find * -name [cc]onfig.in -print sort xargs $(PERL) -w scripts/checkhelp.pl checkincludes: find * -name '*.[hcs]' -type f -print sort xargs $(PERL) -w scripts/checkincludes.pl 파일을체크하는명령들인것같은데확인안해봤음
ifdef CONFIGURATION..$(CONFIGURATION): @echo @echo "You have a bad or nonexistent".$(configuration) ": running 'make" $(CONFIGURATION)"'" @echo $(MAKE) $(CONFIGURATION) @echo @echo "Successful. Try re-making (ignore the error that follows)" @echo exit 1 만약 CONFIGURATION 변수가존재하면위의화면을출력하고 make $(CONFIGURATION) 한후에 make를탈출하게된다. CONFIGURATION 변수가있을경우는.config 나.depend 파일이존재하지않을경우다. #dummy:..$(configuration) dummy: else dummy: Dummy 가하는일은아무것도없다. 왜만들어놨는지모르겠다. 사용자가원하는작업을추가시키고 싶을때이용하게하려는목적일수도있겠다. include Rules.make 여기서 Rules.make 파일을 include 하고있다 scripts/mkdep: scripts/mkdep.c $(HOSTCC) $(HOSTCFLAGS) -o scripts/mkdep scripts/mkdep.c scripts/split-include: scripts/split-include.c $(HOSTCC) $(HOSTCFLAGS) -o scripts/split-include scripts/split-include.c Mkdep 은해더파일을뽑아주는유틸이다.
Arch/arm/Makefile 은아키텍처에의존적인소스를컴파일할때사용된다. $(TOPDIR)/arch/arm/Makefile LINKFLAGS :=-p -X -T arch/arm/vmlinux.lds GZFLAGS :=-9 CFLAGS +=-fno-common -pipe 여기서쓰일추가적인 FLAG들이다. LINKFLAGS : 링킹을할때쓰일옵션이다 GZFLAGS : GUNZIP 으로압축할때쓰이는옵션이다 CFLAGS : 기존옵션에덧붙여지는옵션이다 ifneq ($(CONFIG_NO_FRAME_POINTER),y) CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) Endif 만약 CONFIG_NO_FRAME_POINTER 가 Y 가아니라면옵션을더추가한다..config를살펴보면 CONFIG_NO_FRAME_POINTER 는 not set 이므로위구문은추가가된다. ifeq ($(CONFIG_DEBUG_INFO),y) CFLAGS +=-g Endif Debug 모드가설정되어있다면 g FLAG를더추가한다 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) CC += -mbig-endian AS += -EB LD += -EB Endif 만약 ARM 을 Big-Endian 으로쓸것이라면, 그에해당하는 FLAGS를추가한다 # Select CPU dependent flags. Note that order of declaration is important; # the options further down the list override previous items. # apcs-y := apcs-$(config_cpu_26) :=-mcpu=arm3 -Os 무엇을의미하는옵션인지모르지만기본적으로설정하지않는다.
arch-y := arch-$(config_cpu_32v3) :=-march=armv3 arch-$(config_cpu_32v4) :=-march=armv4 arch-$(config_cpu_32v5) :=-march=armv5 Core Architecture 버전을설정한다. SA1110에서는 armv4 이다. tune-y := tune-$(config_cpu_arm610) :=-mtune=arm610 tune-$(config_cpu_arm710) :=-mtune=arm710 tune-$(config_cpu_arm720t) :=-mtune=arm7tdmi tune-$(config_cpu_arm920t) :=-mtune=arm9tdmi tune-$(config_cpu_sa110) :=-mtune=strongarm110 tune-$(config_cpu_sa1100) :=-mtune=strongarm1100 프로세서의종류를선택한다. 여기서는 CONFIG_CPU_SA1100 이다. CFLAGS += -mapcs-32 $(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float AFLAGS += -mapcs-32 $(apcs-y) $(arch-y) -mno-fpu 위에서설정한옵션을 FLAG에더욱추가한다. 위옵션들은아키텍처에의존적인플레그들이다. LIBGCC 분석불명 := $(shell $(CC) $(CFLAGS) print-libgcc-file-name) ifeq ($(CONFIG_ARCH_SA1100),y) ifeq ($(CONFIG_SA1111),y) # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory TEXTADDR = 0xc0208000 MACHINE = sa1100 Endif 프로세서에대한메모리영역을지정해주게된다. 다빼고여기서쓰는것만집어넣었다 CONFIG_ARCH_SA1100 은설정되어있고, CONFIG_SA1111은설정되어있지않다. LIBGCC := $(shell $(CC) $(CFLAGS) print-libgcc-file-name) 위에서설정한사항들을쉘변수로만든다 ifeq ($(origin INCDIR), undefined) INCDIR := $(MACHINE) Endif 위비교문에서어떤폴더를 include 폴더로쓸건지를정한다.
ifeq ($(origin DATAADDR), undefined) DATAADDR :=. Endif DATAADDR 이아직정의가안되어있다면여기서시킨다. 안해도됨. Ld-script 에정의되어있다. # If we have a machine-specific directory, then include it in the build. MACHDIR := arch/arm/mach-$(machine) 머신에따라 MACHDIR 이갈린다. 여기서는 mach-sa1100 이쓰인다 ifeq ($(MACHDIR),$(wildcard $(MACHDIR))) SUBDIRS += $(MACHDIR) CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES) Endif 만약설정한머신과그머신에해당하는폴더가존재하면그폴더를컴파일하도록변수에추가시킨다 HEAD := arch/arm/kernel/head-$(processor).o arch/arm/kernel/init_task.o SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe arch/arm/fastfpe CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) LIBS := arch/arm/lib/lib.a $(LIBS) $(LIBGCC) 변수들에아키텍처에관련된것들을더욱추가시킨다. ifeq ($(CONFIG_FPE_NWFPE),y) LIBS := arch/arm/nwfpe/math-emu.o $(LIBS) Endif CONFIG_FPE_NWFPE 가선택되었다면기존의 LIBS 변수에 math-emu.o를더추가한다. 부동소수점연산에관련이있는것같다. ifeq ($(CONFIG_FPE_FASTFPE),y) LIBS := arch/arm/fastfpe/fast-math-emu.o $(LIBS) Endif 이것은활성화되어있지않다. MAKEBOOT = $(MAKE) -C arch/$(arch)/boot MAKETOOLS = $(MAKE) -C arch/$(arch)/tools Boot 폴더와 tools 폴더를 Make 할때쓰일변수
# The following is a hack to get 'constants.h' up # to date before starting compilation $(patsubst %,_dir_%, $(SUBDIRS)): maketools $(patsubst %,_modsubdir_%,$(mod_dirs)): maketools 위의경우가생길경우 maketools 라는곳을처리하라는말이다. Maketools에가보면결국 $(MAKE) -C arch/$(arch)/tools all 이라는명령을처리하게된다. 그곳에존재하는파일들을컴파일한다. 여기를처리하는경우는다음과같은경우뿐이다. $(patsubst %,_dir_%, $(SUBDIRS)) 경우, make 할경우에들어오게되고 $(patsubst %,_modsubdir_%,$(mod_dirs)) 경우, make modules 할경우에들어온다 symlinks: archsymlinks archsymlinks: $(RM) include/asm-arm/arch include/asm-arm/proc (cd include/asm-arm; ln -sf arch-$(incdir) arch; ln -sf proc-$(processor) proc) 아키텍처에관련된링크를다시생성한다 vmlinux: arch/arm/vmlinux.lds Vmlinux 라는명령이들어오면처리하는구문이다. Vmlinux 라는명령은 $(TOPDIR)/Makefile 에도있고여기도있다. 두군데정의되어있는데둘다처리가된다. 여기에있는 vmlinux 가 $(TOPDIR)/Makefile 보다늦게처리가된다. arch/arm/vmlinux.lds: $(LDSCRIPT) dummy sed 's/textaddr/$(textaddr)/;s/dataaddr/$(dataaddr)/' $(LDSCRIPT) >$@ Sed 라는유틸이머하는유틸인지확인안해봤지만. 이부분은 vmlinux.lds 와관련이있다. arch/arm/kernel arch/arm/mm arch/arm/lib: dummy $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@) Make arch/arm/kernel 같이직접적으로코멘드를날리지않는이상여기는처리되는경우가없다. bzimage zimage zinstall Image bootpimage install %.swap: vmlinux @$(MAKEBOOT) $@ BzImage zimage zinstall Image 등등의코멘드를날리면여기서부터시작하게된다. 요구사항으로 vmlinux 를요구한다. 이것은 vmlinux 를만들기위해서모든폴더를돌면서소스를컴파일하라는명령이다. 때문에 make -> make zimage 하지않고 make zimage 를바로해도상관없다. 하지만 make zimage 를하기전에 make menuconfig 나 meke dep 은최소한 1번은필수다. @$(MAKEBOOT) $@ 를수행한다. 그러면 $(MAKE) -C arch/$(arch)/boot 구문이수행된다. Arch/arm/boot/makefile 이수행되는데인자값으로 $@ 이넘어가는것을확인할수있다.
이것은사용자가어떤이미지 (zimage, bzimage 등등..) 를선택했느냐에따라서 arch/arm/boot/makefile 이수행하는것이달라지게한다. 예를들어사용자가 make zimage 라는명령을쳤다면, make 프로그램은 arch/arm/boot/makefile 에게 zimage 라는값을같이넘겨줘서 arch/arm/boot/makefile 파일이 zimage 에관련된부분을처리하게한다. Arch/arm/boot/makefile 의처리부분은중요한부분으로유심히살펴봐야할것이다. CLEAN_FILES += arch/arm/vmlinux.lds Make clean 수행시 arch/arm/vmlinux.lds 를지우도록파일을추가시킨다. MRPROPER_FILES += include/asm-arm/arch include/asm-arm/proc include/asm-arm/constants.h* include/asm-arm/mach-types.h Make mrproper 수행시지우도록파일을추가시킨다. archmrproper: @/bin/true archclean: @$(MAKEBOOT) clean archdep: scripts/mkdep archsymlinks @$(MAKETOOLS) dep @$(MAKEBOOT) dep maketools: checkbin @$(MAKETOOLS) all 이것저것에관련된부분들. 자세히안살펴봄
# Ensure this is ld "2.9.4" or later NEW_LINKER := $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?) ifneq ($(NEW_LINKER),0) checkbin: @echo '*** ${VERSION}.${PATCHLEVEL} kernels no longer build correctly with old versions of binutils.' @echo '*** Please upgrade your binutils to 2.9.5.' @false else checkbin: @true # My testing targets (that short circuit a few dependencies) zimg:; @$(MAKEBOOT) zimage Img:; @$(MAKEBOOT) Image i:; @$(MAKEBOOT) install zi:; @$(MAKEBOOT) zinstall bp:; @$(MAKEBOOT) bootpimage # # Configuration targets. Use these to select a # configuration for your architecture %_config: @( CFG=$(@:_config=); if [ -f arch/arm/def-configs/$$cfg ]; then [ -f.config ] && $(MV).config.config.old; cp arch/arm/def-configs/$$cfg.config; echo "*** Default configuration for $$CFG installed"; echo "*** Next, you may run 'make oldconfig'"; else echo "$$CFG does not exist"; fi; )
$(TOPDIR)/arch/arm/boot/makefile 분석 SYSTEM =$(TOPDIR)/vmlinux SYSTEM 이라는변수를만들고 $(TOPDIR)/vmlinux 를지정한다. ifeq ($(CONFIG_ARCH_SA1100),y) ZTEXTADDR = 0xc0008000 ZRELADDR = 0xc0008000 ifeq ($(CONFIG_SA1100_VICTOR),y) ZTEXTADDR = 0x00002000 ZBSSADDR = 0xc0200000 ifeq ($(CONFIG_SA1100_SHERMAN),y) ZTEXTADDR = 0x00050000 ZBSSADDR = 0xc0200000 ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) ZTEXTADDR = 0xC0200000 ifeq ($(CONFIG_SA1100_YOPY),y) ZTEXTADDR = 0x00080000 ZBSSADDR = 0xc0200000 ifeq ($(CONFIG_SA1111),y) ZRELADDR = 0xc0208000 장치별로구분해서 ZTEXTADDR, ZRELADDR, ZBSSADDR등에적당한어드레스는저장한다. 이어드레스들은 arch/arm/boot/compressed/makefile 이참조하게된다. export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS 위에서지정한변수들을 export 한다. zimage: $(CONFIGURE) compressed/vmlinux $(OBJCOPY) -O binary -R.note -R.comment -S compressed/vmlinux $@ 다빼고 zimage 만보자. 다른것들도비슷비슷하다. 요구사항으로 $(CONFIGURE) 과 compressed/vmlinux 가있다. 여기서수행하는작업은 OBJCOPY를이용해서 binary 파일을얻어내는작업만하고직접적인작업들은 compressed 폴더의 makefile 안에서이루어지게된다.
compressed/vmlinux: $(TOPDIR)/vmlinux dep @$(MAKE) -C compressed vmlinux 요구사항인 $(TOPDIR)/vmlinux 는 vmlinux 파일이존재하면문제없고, dep 은조사결과비어있다. 명령은 compressed 폴더로이동해서 make vmlinux 를수행하도록한다. 그밖에부분은설명할필요가없어나중복되는설명이라생략했다. $(TOPDIR)/arch/arm/boot/compressed 분석 HEAD = head.o OBJS = misc.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_PROC) -msoft-float FONTC = $(TOPDIR)/drivers/video/font_acorn_8x8.c ZLDFLAGS = -p -X -T vmlinux.lds 여기 Makefile 에필요한변수들설정한다. ifeq ($(CONFIG_ARCH_SA1100),y) OBJS += head-sa1100.o setup-sa1100.o ifeq ($(CONFIG_SA1100_NANOENGINE),y) OBJS += hw-bse.o 아키텍처에관련된설정이다. Hyper-linux에서는 CONFIG_ARCH_SA1100은설정되어있고, CONFIG_SA1100_NANOENGINE 은설정되어있지않다. SEDFLAGS = s/text_start/$(ztextaddr)/;s/load_addr/$(zreladdr)/; Sed 유틸에관련된 FLAG 다. Sed 가머하는유틸이지? 조사해보자. ifneq ($(ZBSSADDR),) SEDFLAGS += s/bss_start/$(zbssaddr)/ Else SEDFLAGS += s/bss_start/align(4)/ Endif Ld-script 에관련된프레그인거같다. 조사요구됨
all: vmlinux Make all 이나 make vmlinux 나같은의미다. vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds $(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux Vmlinux 를처리하는구문. 요구사항으로 4가지가있다. 여기서만드는 vmlinux 는 $(TOPDIR)/vmlinux 와는다른이미지파일이다. 코멘드라인에서하는작업은 linking 이다. 요구사항을다처리하면나오는 piggy.o 파일과 $(head) 와 $(OBJS) 파일들을결합시켜서 vmlinux 라는파일을만들어낸다. 즉, 여기서만들어내는 vmlinux 는 $(TOPDIR)/vmlinux 앞에붙을코드인것이다. $(HEAD):$(HEAD:.o=.S) $(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S) 여기서는 head.s 라는파일을컴파일해서 head.o 를얻어낸다. piggy.o: $(SYSTEM) $(OBJCOPY) -O binary -R.note -R.comment -S $(SYSTEM) piggy gzip $(GZFLAGS) < piggy > piggy.gz $(LD) -r -o $@ -b binary piggy.gz rm -f piggy piggy.gz 요구사항중에있는 $(SYSTEM) 에있는값은 $(TOPDIR)/vmlinux 라는값이다. 첫번째커멘드라인을수행하면 $(TOPDIR)/vmlinux 를 Objcopy 유틸를이용바이너리형식 (piggy) 로바꾸어준다. 다음명령은 piggy파일을 gzip을이용해서압축해서 piggy.gz을얻어낸다. 다음명령은 linker 를이용해서압축된이미지 piggy.o 를바이너리형식파일 (piggy.o) 로변환한다. 마지막으로중간변환과정에쓰였던파일 piggy 와 piggy.gz 을삭제한다. font.o: $(FONTC) $(CC) $(CFLAGS) -Dstatic= -c -o $@ $(FONTC) Font 파일을컴파일한다. 이파일의목적은조사봐야하겠지만부팅시사용할폰트일까? vmlinux.lds: vmlinux.lds.in @sed "$(SEDFLAGS)" < vmlinux.lds.in > $@ Sed 유틸을이용해서 vmlinux.lds.in 파일을 vmlinux.lds 로만든다. 이과정에서무엇가는하는데.. 조사중
clean:; rm -f vmlinux core piggy* vmlinux.lds.phony: vmlinux.lds clean misc.o: misc.c $(TOPDIR)/include/asm/arch/uncompress.h $(TOPDIR)/lib/inflate.c %.o: %.S $(CC) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $< 그다지중요치않은설정들 이아래부터는 Makfile 을분석하는게아니라 Kernel Compile 순서를따라가보면서 Makefile 의 어떤부분들이실행되는지를알아보고, 그에따른 log 파일을보면서사실을확인해본다. Kernel Compile 의순서 # Make menuconfig # Make dep # Make zimage Make menuconfig 시퀀스 menuconfig: include/linux/version.h symlinks $(MAKE) -C scripts/lxdialog all $(CONFIG_SHELL) scripts/menuconfig arch/$(arch)/config.in 여기서부터시작한다. 요구사항 1 include/linux/version.h : version.h 를생성한다. Version.h 는커널버전정보를담고있는 version.h 라는파일을생성한다 요구사항2 symlinks : symlinks 는 2군데지정되어있다 $(TOPDIR)/Makefile 과 $(TOPDIR)/arch/arm/Makfile 에있다. 둘다수행한다. 로그파일을분석해보면 $(TOPDIR)/arch/arm/Makefile 에있는 symlinks 부터수행한다. 그곳에서하는일은, arch-sa1100 디렉토리를 arch 로소프트링크시키고 proc-armv 디렉토리를 proc 로소프트링크시킨다. 그후에 $(TOPDIR) 에있는 symlinks를수행한다. 그곳에서하는일은, asm-arm 폴더를 asm 에소프트링크시킨다. 요구사항을다끝냈으면아래의코멘드명령들을수행한다.
Scripts/lxdialog 로이동해서 make all 을수행한다. Lxdialog 에는텍스트환경에서메뉴환경을구축해주는소스가들어있다. Arch/arm/config.in 파일을토대로 scripts/menuconfig 스크립트를수행한다. Menuconfig 스크립트는 config.in 에정의되어있는메뉴구성을분석해서 Lxdialong 프로그램이화면을뿌리도록해준다. 그리고사용자가설정한데이터를.config 파일에기록까지해준다. Make menuconfig 로그분석 맨처음부분이 version.h 를만드는부분이지만 version.h 수행하는부분은 보여지지않도록숨겨져있다그래서아무것도보이지는다 rm -f include/asm-arm/arch include/asm-arm/proc (cd include/asm-arm; ln -sf arch-sa1100 arch; ln -sf proc-armv proc) 이부분이 $(TOPDIR)/arch/arm/Makefile 에있는 symlinks 를수행한부분 rm -f include/asm ( cd include ; ln -sf asm-arm asm) 이부분이 $(TOPDIR)/Makefile 에있는 symlinks 를수행한부분 make -C scripts/lxdialog all scripts/lxdialog 로이동해서 make all 을수행하라는명령을함 make[1]: Entering directory `/home/linux-hyper104/scripts/lxdialog' make 파일 lxdialong 로이동후명령수행 make[1]: Leaving directory `/home/linux-hyper104/scripts/lxdialog' 빠져나옴 /bin/bash scripts/menuconfig arch/arm/config.in 여기서 menuconfig 화면을보여주는명령실행 Using defaults found in.config Preparing scripts: functions, parsing...done. 완료
.config 파일분석.config 파일은 make config / menuconfig / xconfig 등을수행하면생성되는파일이다. 사용자가어떤것을컴파일할것인지를결정할건지를정보를담고있는파일이다. 여기서는하도록설정된파일은 Makefile 이참조하여컴파일을하게된다. 아래는 hyper-linux 에서기본설정된.config 파일이다. 임의로변경하지말라고써있다. # # Automatically generated make config: don't edit # CONFIG_ARM=y ARM으로설정되어있다. # CONFIG_EISA is not set # CONFIG_SBUS is not set # CONFIG_MCA is not set CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y # CONFIG_OBSOLETE is not set # # Loadable module support # CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y MODULE 을지원하도록했다. 이하생략 대부분이런식으로설정되어있다.
Make dep 분석 depend dep: dep-files Make dep 을하면처음시작하는부분이다. 요구사항으로 dep-files 만있을뿐명령은아무것도없다. 실질적인내용은 dep-files 에작성되어있는것이다. dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep -- init/*.c >.depend scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name *.h! -name modversions.h -print` >.hdepend $(MAKE) $(patsubst %,_sfdep_%,$(subdirs)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" ifdef CONFIG_MODVERSIONS $(MAKE) update-modverfile ifdef CONFIG_MODVERSIONS MODVERFILE := $(TOPDIR)/include/linux/modversions.h else MODVERFILE := Endif 첫번째요구사항 : scripts/mkdep scripts/mkdep: scripts/mkdep.c $(HOSTCC) $(HOSTCFLAGS) -o scripts/mkdep scripts/mkdep.c mkdep.c 파일을컴파일해서실행파일을얻어낸다. 두번째요구사항 : archdep archdep: scripts/mkdep archsymlinks @$(MAKETOOLS) dep @$(MAKEBOOT) dep archdep은 arch/arm/makefile 에들어있다. 아키텍처에의존적인 depend 를확인한다. 다음과같이코멘드라인을처리한다. arch/arm/tools/makefile dep 을수행한수, arch/arm/boot/makefile dep 을수행한다. 이명령은 @ 때문에화면에보이지않게된다. 세번째요구사항 : include/linux/version.h version.h 를생성해준다.
요구사항을다처리했으므로이제부터코멘드라인에정의된명령을수행해간다. scripts/mkdep -- init/*.c >.depend scripts/mkdep 유틸을이용해서 init 아래있는모든 *.c 파일의요구되는해더파일을.depend 로작성한다. scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name *.h! -name modversions.h -print` >.hdepend find 유틸을이용을적절히해서.hdepend 파일을생성 ( 좀있다함봐야겠다 ) $(MAKE) $(patsubst %,_sfdep_%,$(subdirs)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" 위명령은자기자신을다시호출한다. $(SUBDIRS) 변수앞에 _sfdep_ 을붙이고 _FASTDEP_ALL_SUB_DIRS 라는변수에 $(SUBDIRS) 를집어넣는다. 그러면 Rules.make 파일에있는명령이수행된다. ifdef _FASTDEP_ALL_SUB_DIRS $(patsubst %,_sfdep_%,$(_fastdep_all_sub_dirs)): $(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep _FASTDEP_ALL_SUB_DIRS 라는변수가선언되어있으므로명령은수행된다. 앞부분이 _sfdep_ 으로정의된이름의변수들에서 _sfdep_ 을빼고뒤에값만을취한다. 그러면그이름이바로 $(SUBDIR) 이되는것이다. 왜이렇게앞에접두사를붙이고다시빼는작업을하는지모르겠지만, linux kernel이자기자신을호출할때는꼭이렇게한다. 어쨌든코멘드라인에보는것처럼 SUBDIRS 를돌면서 make fastdep 를실행하도록하고있다. fastdep: dummy $(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- $(wildcard *.[chs]) >.depend ifdef ALL_SUB_DIRS $(MAKE) $(patsubst %,_sfdep_%,$(all_sub_dirs)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)" fastdep 에서는 mkdep 유틸을이용해서.depend 파일을생성한다. 그리고하위폴더가있다면계속파고들게한다.
Make dep log 분석 gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/mkdep scripts/mkdep.c 첫번째요구사항처리. Mkdep.c 파일을컴파일한다. rm -f include/asm-arm/arch include/asm-arm/proc (cd include/asm-arm; ln -sf arch-sa1100 arch; ln -sf proc-armv proc) 두번째요구사항처리과정중에하나이다. 아키텍처과관련된폴더를소프트링크시킨다. make[1]: 들어감 `/root/linux-hyper104/arch/arm/tools' 디렉토리 /root/linux-hyper104/scripts/mkdep getconstants.c sed s,getconstants.o,/root/linuxhyper104/include/asm-arm/constants.h, >.depend make all make[2]: 들어감 `/root/linux-hyper104/arch/arm/tools' 디렉토리 awk -f gen-mach-types mach-types > /root/linux-hyper104/include/asm-arm/mach-types.h arm-linux-gcc -D KERNEL -I/root/linux-hyper104/include -Wall -Wstrict-prototypes -O2 -fnostrict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 -mtune=strongarm1100 -mshortload-bytes -msoft-float -S -o - getconstants.c sed 's/^ (#define.* )[#$] (.* )/ 1 2/;/^#define/!d' cat constants-hdr - > /root/linux-hyper104/include/asm-arm/constants.h.tmp cmp /root/linux-hyper104/include/asm-arm/constants.h.tmp /root/linux-hyper104/include/asmarm/constants.h >/dev/null 2>&1 mv /root/linux-hyper104/include/asm-arm/constants.h.tmp /root/linux-hyper104/include/asm-arm/constants.h; rm -f /root/linux-hyper104/include/asmarm/constants.h.tmp make[2]: 나감 `/root/linux-hyper104/arch/arm/tools' 디렉토리 make[1]: 나감 `/root/linux-hyper104/arch/arm/tools' 디렉토리두번째요구사항처리과정중하나 arch/arm/tools 폴더에서 make dep 을수행하는과정이다. make[1]: 들어감 `/root/linux-hyper104/arch/arm/boot' 디렉토리 make[1]: Nothing to be done for `dep'. make[1]: 나감 `/root/linux-hyper104/arch/arm/boot' 디렉토리두번째요구사항처리과정중하나 arch/arm/boot 폴더에서 make dep 을수행하는과정이다. 세번째요구사항도처리할테지만, 숨겨서안보인다. 요구사항처리는끝났으므로이제부터는명령라인을처리한다. scripts/mkdep -- init/*.c >.depend 코멘드라인의첫번째명령이처리된다. init 폴더아래있는 *.c 파일들이 include 한해더파일들을.depend 로다정리한다.
scripts/mkdep -- `find /root/linux-hyper104/include/asm /root/linux-hyper104/include/linux /root/linux-hyper104/include/scsi /root/linux-hyper104/include/net -name SCCS -prune -o -follow - name *.h! -name modversions.h -print` >.hdepend 코멘드라인의두번째명령이다. 이건머하는걸까나.. make _sfdep_kernel _sfdep_drivers _sfdep_mm _sfdep_fs _sfdep_net _sfdep_ipc _sfdep_lib _sfdep_arch/arm/mach-sa1100 _sfdep_arch/arm/kernel _sfdep_arch/arm/mm _sfdep_arch/arm/lib _sfdep_arch/arm/nwfpe _sfdep_arch/arm/fastfpe _FASTDEP_ALL_SUB_DIRS="kernel drivers mm fs net ipc lib arch/arm/mach-sa1100 arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe arch/arm/fastfpe" 코멘드라인의세번째명령이다. 위명령을해석해서직접적인명령을수행하는구문은 Rules.make 파일에정의되어있다. _sfdep_### 로정의된폴더를이동하면서 make fastdep를수행하게된다. 만약 make fastdep 를해야할하위폴더들이존재한다면, 또한번자기자신을호출해서더파고든다. make[1]: 들어감 `/root/linux-hyper104' 디렉토리 위명령의처리가시작된것을알수있다. make -C kernel fastdep make[2]: 들어감 `/root/linux-hyper104/kernel' 디렉토리 위명령처리에의해가장첫번째로지정된폴더인 kernel 로이동한후 fastdep 을수행한다. /root/linux-hyper104/scripts/mkdep -D KERNEL -I/root/linux-hyper104/include -Wall -Wstrictprototypes -O2 -fno-strict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 - mtune=strongarm1100 -mshort-load-bytes -msoft-float -- acct.c capability.c context.c cpufreq.c dma.c exec_domain.c exit.c fork.c getch.c info.c itimer.c kmod.c ksyms.c module.c panic.c pm.c printk.c ptrace.c resource.c sched.c signal.c softirq.c sys.c sysctl.c time.c timer.c uid16.c user.c >.depend.depend 수행 make[2]: 나감 `/root/linux-hyper104/kernel' 디렉토리여기는하위폴더가없어서그냥위로올라간다. ( 이하생략 ) 이런식으로위에서정한폴더와그하위폴더를다뒤지면서.depend 파일을생성해낸다.
.depend 파일분석 acct.o: acct.c /root/linux-hyper104/include/linux/errno.h /root/linux-hyper104/include/linux/kernel.h $(wildcard /root/linux-hyper104/include/config/bsd/process/acct.h) /root/linux-hyper104/include/linux/mm.h /root/linux-hyper104/include/linux/slab.h /root/linux-hyper104/include/linux/acct.h /root/linux-hyper104/include/linux/smp_lock.h /root/linux-hyper104/include/linux/file.h /root/linux-hyper104/include/linux/tty.h /root/linux-hyper104/include/asm/uaccess.h capability.o: capability.c /root/linux-hyper104/include/linux/mm.h /root/linux-hyper104/include/asm/uaccess.h ( 이하생략 ) 특정 *.o 를 makefile이참조하려고하면위요구사항을체크하게될것이다. 위요구사항에는그.o가 include 하고있는모든.h 파일들이다. 만약해더파일이없다면 makefile 이에러를내면서작업을중단할것이다..depend 파일은.config 파일과다르게각각폴더에다존재한다.
Make 분석 make 만치면가장처음만나는명령을실행하게되는데그것이바로 all: do-it-all 이다. 그러므로 make 와 make all 은같은의미이다. 사용자가 make ( 또는 make all) 를치면 makefile 은몇가지검사를한다..config 파일이없다면 CONFIGURATION =.config 를저장하고, do-it-all 의요구사항으로 config 를집어넣는다..config 파일이있고,.depend 파일이없다면 CONFIGURATION =.depend 를저장한다. do-it-all 의요구사항으로 depend 를집어넣는다. 위의경우가아니라면 do-it-all 은요구사항이 Version 과 vmlinux 가된다. Version: dummy @rm -f include/linux/compile.h dummy 에는아무일도하지않는다. Version 에서는 rm f include/linux/compile.h 를삭제한다. vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux $(NM) vmlinux grep -v ' (compiled ) (.o$$ ) ( [auw] ) (..ng$$ ) (LASH[RL]DI )' sort > System.map 본격적인 Compile 부분이다. 첫번째요구사항 : $(CONFIGURATION) 만약.config 와.depend 파일이존재한다면 $(CONFIGURATION) 변수는비어있게된다..config 나.depend 중하나라도없다면그것을처리하는부분이선행된다. 두번째, 세번째요구사항 : init/main.o init/version.o main.c 와 version.c 파일을컴파일한다.
네번째요구사항 : linuxsubdirs linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS)) $(patsubst %, _dir_%, $(SUBDIRS)) : dummy include/linux/version.h include/config/marker $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@) $(patsubst %, _dir_%, $(SUBDIRS)) 는 $(TOPDIR)/Makefile 과 $(TOPDIR)/arch/arm/Makefile 두군데정의되어있다. 둘다처리가된다. 위에명령에의해서하위디렉토리를이동하면서 make 를하게된다. 여기까지해서요구사항을끝나게되고이제커멘드라인을수행하게되는데 vmlinux 를가지고있는곳이 $(TOPDIR)/Makefile 과 $(TOPDIR)/arch/arm/Makefile 두군데이다. 먼저수행되는 vmlinux 는 $(TOPDIR)/arch/arm/Makefile 에있는 vmlinux 이다. vmlinux: arch/arm/vmlinux.lds arch/arm/vmlinux.lds: $(LDSCRIPT) dummy sed 's/textaddr/$(textaddr)/;s/dataaddr/$(dataaddr)/' $(LDSCRIPT) >$@ 위명령을우선적으로수행하고나서 $(TOPDIR)/Makefile 의커멘드라인을수행하게된다. Sed 라는유틸을이용해서 vmlinux.lds 파일을어떻게한다. 자세한건더조사를 그리고나서다음커멘드를실행한다. $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux linking 을해서 vmlinux 실행파일을얻어낸다. --start-group 와 end-group 사이에들어가는파일들은아카이브로묶인파일들임을의미한다. $(NM) vmlinux grep -v ' (compiled ) (.o$$ ) ( [auw] ) (..ng$$ ) (LASH[RL]DI )' sort > System.map nm 을이용해서 System.map 파일을만들어낸다.
Make log 분석 arm-linux-gcc -D KERNEL -I/hyper104/kernel/linux/include -Wall -Wstrict-prototypes -O2 - fno-strict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 -mtune=strongarm1100 - mshort-load-bytes -msoft-float -c -o init/main.o init/main.c 가장처음에하는작업은 init/main.c 를컴파일하는것이다. arm-linux-gcc -D KERNEL -I/hyper104/kernel/linux/include -Wall -Wstrict-prototypes -O2 - fno-strict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 -mtune=strongarm1100 - mshort-load-bytes -msoft-float -DUTS_MACHINE='"arm"' -c -o init/version.o init/version.c 그다음 init/version.c 를컴파일한다. make[1]: 들어감 `/hyper104/kernel/linux/arch/arm/tools' 디렉토리 make[1]: Nothing to be done for `all'. make[1]: 나감 `/hyper104/kernel/linux/arch/arm/tools' 디렉토리 $(TOPDIR)/arch/arm/makefile 에정의된명령을수행했다. make CFLAGS="-D KERNEL -I/hyper104/kernel/linux/include -Wall -Wstrict-prototypes -O2 - fno-strict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 -mtune=strongarm1100 - mshort-load-bytes -msoft-float " -C kernel make[1]: 들어감 `/hyper104/kernel/linux/kernel' 디렉토리 make all_targets make[2]: 들어감 `/hyper104/kernel/linux/kernel' 디렉토리요구사항네번째 linuxsubdirs 에의해서하위디렉토리를돌면서컴파일을시작한다. arm-linux-gcc -D KERNEL -I/hyper104/kernel/linux/include -Wall -Wstrict-prototypes -O2 - fno-strict-aliasing -fno-common -pipe -mapcs-32 -march=armv4 -mtune=strongarm1100 - mshort-load-bytes -msoft-float -c -o fork.o fork.c ( 중간생략 ) kernel 밑에있는모든소스파일을컴파일한다. rm -f kernel.o kernel.o 파일을삭제한다. arm-linux-ld -r -o kernel.o sched.o fork.o exec_domain.o panic.o printk.o module.o exit.o itimer.o info.o time.o softirq.o resource.o sysctl.o acct.o capability.o ptrace.o timer.o user.o signal.o sys.o kmod.o context.o getch.o uid16.o ksyms.o kernel 아래있던컴파일된파일들을 ld 를이용해서 kernel.o 로통합한다.
( 중간생략 ) arm-linux-ld -p X -T arch/arm/vmlinux.lds arch/arm/kernel/head-armv.o arch/arm/kernel/init_task.o init/main.o init/version.o --start-group arch/arm/kernel/kernel.o arch/arm/mm/mm.o arch/arm/mach-sa1100/sa1100.o kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o drivers/char/char.o drivers/block/block.o drivers/misc/misc.o drivers/net/net.o drivers/media/media.o drivers/mtd/mtdlink.o drivers/video/video.o net/network.o arch/arm/nwfpe/math-emu.o arch/arm/lib/lib.a /hyper104/kernel/linux/lib/lib.a /usr/lib/gcclib/arm-linux/2.95.2/soft-float/libgcc.a --end-group -o vmlinux 컴파일된모든파일을 vmlinux 로 link 한다. arm-linux-nm vmlinux grep -v ' (compiled ) (.o$ ) ( [auw] ) (..ng$ ) (LASH[RL]DI )' sort > System.map system.map 파일을만든다. Make zimage 분석 bzimage zimage zinstall Image bootpimage install %.swap: vmlinux @$(MAKEBOOT) $@ $(TOPDIR)/arch/arm/makefile 부터시작한다. BzImage, zimage zinstall Image bootpimage install %.swap 옵션을붙이면전부여기로온다. 요구사항으로 vmlinux 를요구한다. Vmlinux 를수행하면 make 만친것과같은효과가난다. 그래서 make 를하지않고, make zimage만쳐도 make 까지자동으로된다. MAKEBOOT = $(MAKE) -C arch/$(arch)/boot 코멘드에있는명령은다음과같은명령이다. Arch/arm/boot 에있는작업을컴파일하게된다. 뒤에붙는 $@ 때문에 zimage 라는단어도같이넘어간다. zimage: $(CONFIGURE) compressed/vmlinux $(OBJCOPY) -O binary -R.note -R.comment -S compressed/vmlinux $@ Arch/arm/boot/Makefile 의 zimage 부분이다. 요구사항으로 $(CONFIGURE) 와 compressed/vmlinux를요구하고있다. $(CONFIGURE) 는어디에정의되어있는지확인할수없다. 정의되어있지않았을수도있다.
두번째요구사항인 compressed/vmlinux은처리내용은다음과같다. compressed/vmlinux: $(TOPDIR)/vmlinux dep @$(MAKE) -C compressed vmlinux 요구사항에있는내용은그다지특별한것이없고, 커멘드라인에내용을살펴보면 compressed 폴더로이동해서 make vmlinux를수행하도록한다. 두번째요구사항까지다완료했으면아래명령을수행한다. $(OBJCOPY) -O binary -R.note -R.comment -S compressed/vmlinux $@ 두번째요구사항을수행해서얻어낸파일인 compressed/vmlinux 를 binary 형태의 zimage 파일로바꾼다. 최종적으로완료된파일인것이다. 이렇게해서 zimage 를얻어낸후 kernel compile 은완료가된다.