【uclinux的Makefile分析】
1、make menuconfig
在uclinux根目录中的Makefile文件中找到:
menuconfig: config.in #依赖config.in文件
$(MAKE)-C $(SCRIPTSDIR)/lxdialog all
@HELP_FILE=config/Configure.help\
$(CONFIG_SHELL) $(SCRIPTSDIR)/Menuconfig config.in
@if[ ! -f .config ]; then \
echo;\
echo"You have not saved your config, please re-run make config"; \
echo;\
exit1; \
fi
@config/setconfigdefaults
@ifegrep "^CONFIG_DEFAULTS_KERNEL=y" .config > /dev/null; then \
$(MAKE)linux_menuconfig; \
fi
@ifegrep "^CONFIG_DEFAULTS_MODULES=y" .config > /dev/null; then \
$(MAKE)modules_menuconfig; \
fi
@ifegrep "^CONFIG_DEFAULTS_VENDOR=y" .config > /dev/null; then \
$(MAKE)config_menuconfig; \
fi
@config/setconfigfinal
注释:make menuconfig的目的是将config.in配置选项生成对应的变量参数存放在.config和config.xxx(如:config.arch)文件中。 在Makefile中包含了include .config和config.arch(被链接到了) |
在进行make是执行Makefile中的:
all: subdirsromfs modules modules_install image
……
subdirs: linux //依赖linux
fordir in $(DIRS) ; do [ ! -d $$dir ] || $(MAKEARCH_KERNEL) -C $$dir || exit 1 ;done
……
在linux-2.4.x/Makefile中:
include arch/$(ARCH)/Makefile
……
ifndef CONFIG_UCLINUX
LINUX=vmlinux
else
LINUX=linux // LINUX为一个变量$(LINUX)
endif
……
$(LINUX): include/linux/version.h $(CONFIGURATION) init/main.oinit/version.o init/do_mounts.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.oinit/version.o init/do_mounts.o \
--start-group\
$(CORE_FILES)\
$(DRIVERS)\
$(NETWORKS)\
$(LIBS)\
--end-group\
-o$(LINUX)
$(NM)$(LINUX) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw]\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
……
CROSS_COMPILE = arm-elf-
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 = -gdwarf-2
在arch/$(ARCH)/Makefile中:
LINKFLAGS :=-p -X -T arch/armnommu/vmlinux.lds
HEAD :=arch/armnommu/kernel/head-$(PROCESSOR).o
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0xC0008000
endif
$(LD) $(LINKFLAGS) $(HEAD) init/main.o 替换为: arm-elf-ld -p -X -T arch/armnommu/vmlinux.lds arch/armnommu/kernel/head- armv.o init/main.o\ init/version.o init/do_mounts.o \ …… 由上面分析得出下面3个文件: arch/armnommu/vmlinux.lds arch/armnommu/kernel/head- armv.s //内核源代码入口文件 init/main.c |
【注意】
boot: $(LINUX)
@$(MAKE)CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" LINUX="$(LINUX)" -Carch/$(ARCH)/boot
这个指令是为linux内核加上一个boot头部,进入arch/$(ARCH)/boot目录进行编译。
在/arch/armnommu/boot/compressed/Makefile中:
all: $(LINUX)
$(LINUX): $(HEAD)$(OBJS) piggy.o $(LINUX).lds
$(LD)$(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o -o$(LINUX)
……
ZLDFLAGS = -p -X -T $(LINUX).lds
HEAD = head.o //对应该目录下的head.S
OBJS = misc.o //对应该目录下的misc.c
……
$(LINUX).lds: vmlinux.lds.in
@sed"$(SEDFLAGS)" < vmlinux.lds.in > $@
……
//可以看出vmlinux.lds又vmlinux.lds.in生成,但在该目录没有vmlinux.lds产生,说明该命令没有被执行,所以uclinux内核没有加上boot引导头部。
在打印信息中:
Image Name: uClinux_test_cqy
Image Type: ARM Linux Kernel Image (gzip compressed)
Data Size: 226491 Bytes = 221 kB = 0 MB
Load Address: c0008000
Entry Point: c0008000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK //这是u-boot解压内核并非linux内核自解压程序处理
Starting kernel ...
……
对于linux内核自解压程序执行应该打印为:
ulg decompress_kernel(ulgoutput_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
int arch_id)
{
……
makecrc();
puts("UncompressingLinux...");
gunzip();
puts(" done,booting the kernel.\n");
……
}
u-boot解压程序打印:
int do_bootm (cmd_tbl_t*cmdtp, int flag, int argc, char *argv[])
{
……
case IH_COMP_GZIP:
printf (" Uncompressing %s ... ", name); //name=Kernel Image
if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,
(uchar*)data, (int *)&len) != 0) {
puts ("GUNZIP ERROR - must RESET board torecover\n");
SHOW_BOOT_PROGRESS (-6);
do_reset (cmdtp, flag, argc, argv);
}
break;
……
}