fujingdcn |
2009-01-21 18:38 |
PSPSDK例子中所带的makfile
如果你已经看了PSPSDK环境搭建,相信可以搭建好PSP的开发环境并编译运行了第一个Hello World程序。只需要到SDK的例子目录中,执行一下make命令就生成了可供PSP运行的EBOOT.PBP。为了更多的了解EBOOT.PBP的创建过程,需要去看看Makefile文件都干了些什么,首先你需要知道一点makefile的基本知识。
打开Makefile文件。
TARGET = template OBJS = main.o
INCDIR = CFLAGS = -O2 -G0 -Wall CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS)
LIBDIR = LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP PSP_EBOOT_TITLE = Hello World
PSPSDK=$(shell psp-config --pspsdk-path) include $(PSPSDK)/lib/build.mak 这个Makefile在include之前都是对变量的定义,可以理解为C里面的宏定义。include也相当于C中的include,在执行make的时候,会把$(PSPSDK)/lib/build.mak这个文件引入。
打开$(PSPSDK)/lib/build.mak。$(PSPSDK)为/usr/local/pspdev/psp/sdk。
# PSP Software Development Kit - http://www.pspdev.org # ----------------------------------------------------------------------- # Licensed under the BSD license, see LICENSE in PSPSDK root for details. # # build.mak - Base makefile for projects using PSPSDK. # # Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org> # Copyright (c) 2005 James Forshaw <tyranid@gmail.com> # Copyright (c) 2005 John Kelley <ps2dev@kelley.ca> # # $Id: build.mak 2333 2007-10-31 19:37:40Z tyranid $
# Note: The PSPSDK make variable must be defined before this file is included. 这几行是以#号开始的,都是注释。
ifeq ($(PSPSDK),) $(error $$(PSPSDK) is undefined. Use "PSPSDK := $$(shell psp-config --pspsdk-path)" in your Makefile) endif 这是判断$(PSPSDK)是否和空值相等,相等则输出错误信息。
CC = psp-gcc CXX = psp-g++ AS = psp-gcc LD = psp-gcc AR = psp-ar RANLIB = psp-ranlib STRIP = psp-strip MKSFO = mksfo PACK_PBP = pack-pbp FIXUP = psp-fixup-imports 一些变量的赋值,这里都是些命令。
# Add in PSPSDK includes and libraries. INCDIR := $(INCDIR) . $(PSPSDK)/include LIBDIR := $(LIBDIR) . $(PSPSDK)/lib
CFLAGS := $(addprefix -I,$(INCDIR)) $(CFLAGS) CXXFLAGS := $(CFLAGS) $(CXXFLAGS) ASFLAGS := $(CFLAGS) $(ASFLAGS) 这里有一个地方需要解释,addprefix -I,$(INCDIR)是把$(INCDIR)的参数列表的每一项都加上-I,-I是指到-I指定的目录查找头文件。
ifeq ($(PSP_LARGE_MEMORY),1) MKSFO = mksfoex -d MEMSIZE=1 endif mksfo,mksfoex都是生成固定格式的文件并把你设置的程序显示名称导入这个文件的工具。
ifeq ($(PSP_FW_VERSION),) PSP_FW_VERSION=150 endif
CFLAGS += -D_PSP_FW_VERSION=$(PSP_FW_VERSION) CXXFLAGS += -D_PSP_FW_VERSION=$(PSP_FW_VERSION) 对固件版本的设置。
ifeq ($(BUILD_PRX),1) LDFLAGS := $(addprefix -L,$(LIBDIR)) -specs=$(PSPSDK)/lib/prxspecs -Wl,-q,-T$(PSPSDK)/lib/linkfile.prx $(LDFLAGS) EXTRA_CLEAN += $(TARGET).elf # Setup default exports if needed ifdef PRX_EXPORTS EXPORT_OBJ=$(patsubst %.exp,%.o,$(PRX_EXPORTS)) EXTRA_CLEAN += $(EXPORT_OBJ) else EXPORT_OBJ=$(PSPSDK)/lib/prxexports.o endif else LDFLAGS := $(addprefix -L,$(LIBDIR)) $(LDFLAGS) endif -L是指到指定的目录查找库文件。 这个地方有必要解释一下,生成EBOOT.PBP的过程是这样的,首先是把源文件编译成目标文件,然后链接成ELF文件,修正ELF文件,用psp-strip生成新的ELF文件或者用psp-prxgen生成PRX文件(这两种格式的文件都是可执行文件),最后EBOOT.PBP文件是由8个部分组成的,开始的部分是由mksfo生成的SFO文件,第7个部分是PRX或者ELF,其他的是程序在XMB上显示的图片、短片这些东西。PSP运行程序时读取EBOOT.PBP,然后释放ELF或者PRX模块,3.10以后的OE对这两种格式的文件都能执行。这里如果你把BUILD_PRX设置为1,那会影响链接过程中引用的库,编译过程也会对这个变量进行检查,最后可执行模块的格式也就为PRX了。
# Library selection. By default we link with Newlib's libc. Allow the # user to link with PSPSDK's libc if USE_PSPSDK_LIBC is set to 1.
ifeq ($(USE_KERNEL_LIBC),1) # Use the PSP's kernel libc PSPSDK_LIBC_LIB = CFLAGS := -I$(PSPSDK)/include/libc $(CFLAGS) else ifeq ($(USE_PSPSDK_LIBC),1) # Use the pspsdk libc PSPSDK_LIBC_LIB = -lpsplibc CFLAGS := -I$(PSPSDK)/include/libc $(CFLAGS) else # Use newlib (urgh) PSPSDK_LIBC_LIB = -lc endif endif 从注释中可以看到这是决定是否用PSPSDK自带的库进行链接。
# Link with following default libraries. Other libraries should be specified in the $(LIBS) variable. # TODO: This library list needs to be generated at configure time. # ifeq ($(USE_KERNEL_LIBS),1) PSPSDK_LIBS = -lpspdebug -lpspdisplay_driver -lpspctrl_driver -lpspsdk LIBS := $(LIBS) $(PSPSDK_LIBS) $(PSPSDK_LIBC_LIB) -lpspkernel else ifeq ($(USE_USER_LIBS),1) PSPSDK_LIBS = -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk LIBS := $(LIBS) $(PSPSDK_LIBS) $(PSPSDK_LIBC_LIB) -lpspnet \ -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility \ -lpspuser else PSPSDK_LIBS = -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk LIBS := $(LIBS) $(PSPSDK_LIBS) $(PSPSDK_LIBC_LIB) -lpspnet \ -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility \ -lpspuser -lpspkernel endif endif
ifndef PSP_EBOOT_SFO PSP_EBOOT_SFO = PARAM.SFO endif
ifndef PSP_EBOOT_ICON PSP_EBOOT_ICON = NULL endif
ifndef PSP_EBOOT_ICON1 PSP_EBOOT_ICON1 = NULL endif
ifndef PSP_EBOOT_UNKPNG PSP_EBOOT_UNKPNG = NULL endif
ifndef PSP_EBOOT_PIC1 PSP_EBOOT_PIC1 = NULL endif
ifndef PSP_EBOOT_SND0 PSP_EBOOT_SND0 = NULL endif
ifndef PSP_EBOOT_PSAR PSP_EBOOT_PSAR = NULL endif
ifndef PSP_EBOOT PSP_EBOOT = EBOOT.PBP endif 指定链接所使用的库,和指定EBOOT.PBP中的各个部分。
ifeq ($(BUILD_PRX),1) ifneq ($(TARGET_LIB),) $(error TARGET_LIB should not be defined when building a prx) else FINAL_TARGET = $(TARGET).prx endif else ifneq ($(TARGET_LIB),) FINAL_TARGET = $(TARGET_LIB) else FINAL_TARGET = $(TARGET).elf endif endif 指定生成的可执行文件的格式。
好了,应该说上面这些都是根据用户的设置进行预处理,下面开始make了~
all: $(EXTRA_TARGETS) $(FINAL_TARGET) 默认的make入口,指定最终生成的目标,EBOOT.PBP,template.elf或者template.prx。
kxploit: $(TARGET).elf $(PSP_EBOOT_SFO) mkdir -p "$(TARGET)" $(STRIP) $(TARGET).elf -o $(TARGET)/$(PSP_EBOOT) mkdir -p "$(TARGET)%" $(PACK_PBP) "$(TARGET)%/$(PSP_EBOOT)" $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ $(PSP_EBOOT_SND0) NULL $(PSP_EBOOT_PSAR)
SCEkxploit: $(TARGET).elf $(PSP_EBOOT_SFO) mkdir -p "__SCE__$(TARGET)" $(STRIP) $(TARGET).elf -o __SCE__$(TARGET)/$(PSP_EBOOT) mkdir -p "%__SCE__$(TARGET)" $(PACK_PBP) "%__SCE__$(TARGET)/$(PSP_EBOOT)" $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ $(PSP_EBOOT_SND0) NULL $(PSP_EBOOT_PSAR) 这两个入口在现在的OE中已经没有必要使用了。
$(TARGET).elf: $(OBJS) $(EXPORT_OBJ) $(LINK.c) $^ $(LIBS) -o $@ $(FIXUP) $@
$(TARGET_LIB): $(OBJS) $(AR) cru $@ $(OBJS) $(RANLIB) $@
$(PSP_EBOOT_SFO): $(MKSFO) '$(PSP_EBOOT_TITLE)' $@
ifeq ($(BUILD_PRX),1) $(PSP_EBOOT): $(TARGET).prx $(PSP_EBOOT_SFO) $(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ $(PSP_EBOOT_SND0) $(TARGET).prx $(PSP_EBOOT_PSAR) else $(PSP_EBOOT): $(TARGET).elf $(PSP_EBOOT_SFO) $(STRIP) $(TARGET).elf -o $(TARGET)_strip.elf $(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ $(PSP_EBOOT_SND0) $(TARGET)_strip.elf $(PSP_EBOOT_PSAR) -rm -f $(TARGET)_strip.elf endif
%.prx: %.elf psp-prxgen $< $@
%.c: %.exp psp-build-exports -b $< > $@ 依赖关系的描述,命令的执行。 CFLAGS和LDFLAGS在这条命令$(LINK.c) $^ $(LIBS) -o $@中被自动引入,分别指定头文件和库文件的搜索目录和其他相关参数。该命令其实是两条指令的组合,包括了编译和链接。$^表示依赖的文件集合,$@表示目标的文件集合,$<表示依赖文件中第一个目标的名字。
clean: -rm -f $(FINAL_TARGET) $(EXTRA_CLEAN) $(OBJS) $(PSP_EBOOT_SFO) $(PSP_EBOOT) $(EXTRA_TARGETS) 指定clean入口,rm前面加了一个减号的意思是,即使某些文件除了问题,也不用理会,继续执行。
rebuild: clean all
到这里make的过程就算介绍完毕了。如果你能够参照例子自带的Makefile自己重新写一个,尽管不如自带的灵活,但是对EBOOT.PBP构建流程会有多点了解。如果你对Makefile不熟悉,我就不熟悉的,但是看完这个Makefile也使我学到了很多。好了,祝各位编程愉快。如果你对本文有任何的建议或者意见都希望能告诉我,先谢谢了。
(附件)我的Makefile。 CC = psp-gcc PSPSDK = /usr/local/pspdev/psp/sdk CFLAGS = -I. -I$(PSPSDK)/include -O2 -G0 -Wall -D_PSP_FW_VERSION=150 LIBS = -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet \ -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel LDFLAGS := -L$(PSPSDK)/lib
EBOOT.PBP: tmp_strip.elf tmp.SFO pack-pbp EBOOT.PBP tmp.SFO NULL NULL NULL NULL NULL tmp_strip.elf NULL tmp_strip.elf: tmp.elf psp-strip tmp.elf -o tmp_strip.elf tmp.elf: main.o $(LINK.c) main.o $(LIBS) -o tmp.elf psp-fixup-imports tmp.elf
tmp.SFO: mksfo 'TITLE' tmp.SFO
clean: -rm -f *.SFO *.o *.elf *.PBP
欢迎转载,并注明出处。
|
|