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
endifmksfo,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欢迎转载,并注明出处。
[ 此帖被fujingdcn在2009-01-21 18:43重新编辑 ]