安卓游戏开发:编译、链接脚本与开发环境搭建
立即解锁
发布时间: 2025-08-26 00:32:31 阅读量: 6 订阅数: 10 


Android游戏开发:从零开始构建经典射击游戏
### 安卓游戏开发:编译、链接脚本与开发环境搭建
在安卓游戏开发中,从x86平台迁移到ARM平台进行代码编译时,会面临诸多挑战。为了使这个过程尽可能顺利,我们需要了解传统的Linux编译过程、定制编译和链接脚本,以及如何搭建开发环境。
#### 1. 工具链与定制脚本概述
工具链与GNU GCC工具链类似,唯一明显的区别是所有命令都以`arm-none-linux-gnueabi`为前缀。有了工具链后,还需要一组自定义脚本来调用前面的命令,主要包括`agcc`和`ald`两个脚本。
#### 2. 传统Linux编译过程
在传统的x86 Linux编译过程中,开发者使用一组C/C++程序和一个Makefile来构建最终的可执行文件。Makefile的基本骨架如下:
```makefile
# Makefile Skeleton
# Object files
OBJS = file1.o file2.o....
# Header files
INC = -Ifolder1 –Ifolder2 ...
# Libraries and paths (used when linking)
LIB = -lc -lm -Lpath1 -Lpath2 ...
# Main target
all: $(OBJS)
@echo Linking..
gcc -o myapp $(OBJ) $(LIB)
# Compile C files
%o:%.c
@echo Compiling $<...
gcc -c $< $(INC)
```
在这个Makefile中,`OBJS`、`INC`和`LIB`是变量,`all`和`%o`是目标。变量的值由等号分隔,目标的依赖项由冒号分隔。要编译应用程序,只需在命令行输入`$ make`,这将触发主目标`all`的执行。
然而,这种传统的编译方式在Android设备上无法正常工作,原因主要有两点:
- GCC生成的是x86架构的二进制文件,无法在ARM处理器上运行。
- 使用工具链自带的标准头文件进行编译可能会导致链接时出现符号缺失等问题。例如,在为ARM编译3D游戏Doom的文件时,会出现`sysv_signal`函数隐式声明的错误。
#### 3. 安卓编译脚本(agcc)
为了解决上述问题,我们可以使用`agcc`脚本。以下是`agcc`脚本的代码:
```bash
#!/bin/bash
#############################################
# Android Compilation helper script
# Uses the CodeSourcery G++ Toolchain for ARM
#############################################
#############################################
# Root folder where files are installed
# Update this to match your system
#############################################
HOME=/home/user
# JVM location. Set to your location
JAVA_HOME=/usr/lib/jvm/java-6-sun
# Device system image
SYS_ROOT=$HOME/tmp/android/system
# Android source code
SYS_DEV=$HOME/mydroid
# Code Sourcery Toolchain location
TOOLCHAIN_ROOT=$HOME/Desktop/android/arm-2008q3
#############################################
# Include locations
# No need to change this
#############################################
BASE=$SYS_DEV/frameworks/base
# C - Runtime
LIBC=$SYS_DEV/bionic/libc
# Math library
LIBM=${SYS_DEV}/bionic/libm
# Location of some required GCC compiler libraries
TC=${SYS_DEV}/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/lib/gcc/arm-eabi/4.3.1
# Kernel headers
KERNEL=${SYS_DEV}/kernel
# GNU GZIP
LIBZ=${SYS_DEV}/external/zlib
# XML Expat parser
EXPAT=${SYS_DEV}/external/expat/lib
# Includes
AND_INC="-I$JAVA_HOME/include"
AND_INC+=" -I${JAVA_HOME}/include/linux"
AND_INC+=" -I${LIBC}/include "
AND_INC+=" -I${LIBC}/arch-arm/include"
AND_INC+=" -I${LIBC}/kernel/arch-arm/include "
AND_INC+=" -I${LIBM}/include"
AND_INC+=" -I${BASE}/include"
AND_INC+=" -I${TC}/include"
AND_INC+=" -I${KERNEL}/include"
AND_INC+=" -I${KERNEL}/arch/arm/include -I${KERNEL}/arch/arm/mach-ebsa110/include"
AND_INC+=" -I${SYS_DEV}/system/core/include"
AND_INC+=" -I${LIBZ}"
AND_INC+=" -I${EXPAT}"
#############################################
# Toolchain compiler command
#############################################
CROSS=arm-none-linux-gnueabi-
GCC=${CROSS}gcc
# Uncomment for debugging
# echo ${GCC} -nostdinc $AND_INC $@
# Go!
${GCC} -nostdinc ${AND_INC} "$@"
```
`agcc`脚本定义了一系列变量,可根据自己的系统进行调整:
- `HOME`:所有软件组件的根目录。
- `JAVA_HOME`:Java SDK的位置。
- `SYS_ROOT`:设备系统库的位置。
- `SYS_DEV`:Android源代码的位置。
- `TOOLCHAIN_ROOT`:CodeSourcery工具链的安装位置。
脚本还定义了编译步骤中使用的基本库的位置,如C运行时库、数学库、内核头文件等。最后,通过`${GCC} -nostdinc ${AND_INC} "$@"`调用工具链的gcc命令,其中`-nostdinc`参数告诉编译器不使用工具链自带的标准头文件,而是使用Android源代码提供的头文件。
#### 4. 安卓链接脚本(ald)
除了编译,还需要将生成的目标文件链接到设备系统库,这就需要使用`ald`脚本。以下是`ald`脚本的代码:
```bash
#!/bin/bash
#############################################
# Android Linker helper script
# Set these values to match your system
#############################################
HOME=/home/user
JAVA_HOME=/usr/lib/jvm/java-6-sun
# System image location
SYS_ROOT=$HOME/tmp/android/system
# Toolchain location
TOOLCHAIN_ROOT=$HOME/Desktop/android/arm-2008q3
# Android Toolchain libgcc.a
LIBGCC=${SYS_DEV}/prebuilt/darwin-x86/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/libgcc.a
# CodeSourcery libgcc.a
#LIBGCC=${TOOLCHAIN_ROOT}/lib/gcc/arm-none-linux-gnueabi/4.3.2/libgcc.a
# Linker libraries: C runtime, Math, and extra symbols
LIBRARIES="-lc -lm ${LIBGCC}"
# Library locations
LIB_PATHS="-rpath /system/lib \
-rpath ${SYS_ROOT}/lib \
-L${SYS_ROOT}/lib \
-L${JAVA_HOME}/jre/lib/i386 -L."
# Linker flags
LD_FLAGS="--dynamic-linker=/system/bin/linker -nostdlib"
#############################################
# Linker command
#############################################
CROSS=arm-none-linux-gnueabi-
GCC=${CROSS}ld
# Uncomment for debugging
#echo "${GCC} $LD_FLAGS $LIB_PATHS $@ $LIBRARIES"
# Go!
${GCC} $LD_FLAGS $LIB_PATHS $@ $LIBRARIES
```
`ald`脚本定义的变量与`agcc`脚本类似,同时还包含一些额外的链接变量:
- `LIBRARIES`:定义了最终二进制文件应链接的基本库,包括C运行时库、数学库和`libgcc.a`。
- `LIB_PATHS`:告诉链接器在文件系统中查找库的位置,同时设置运行时共享库的搜索路径。
- `LD_FLAGS`:定义链接器标志,`--dynamic-linker=/system/bin/linker`设置动态链接器,`-nostdlib`告诉链接器不使用工具链定义的标准库,而是使用用户在链接时定义的库。
#### 5. 测试脚本
将`agcc`和`ald`脚本保存到`$HOME/bin`目录后,可以使用以下命令进行测试:
```bash
user@ubuntu:~$ agcc --version
user@ubuntu:~$ ald --version
```
需要注意的是,不要使用Windows的记事本或写字板编辑脚本,否则可能会插入无效字符,导致脚本运行出现奇怪的结果。
#### 6. 开发环境搭建
现在可以开始搭建开发环境,使用Eclipse 3.5(Galileo)和最新的Android SDK(1.6):
1. 启动Eclipse Galileo,选择`Help ➤ Check for Updates`。
2. 在`Available Software`窗口中,点击`Add`按钮安装新软件。
3. 在`Add Site`对话框中,输入`Android`作为名称,`https://dl-ssl.google.com/android/eclipse`作为位置。
4. 从`Available Software`窗口中,选择刚添加的Android站点。如果列表中未显示该名称,点击`Available Software Sites preferences`链接,然后点击`Add`将其插入列表。
5. 勾选`Developer Tools`复选框,然后点击`Next`。
6. 按照安装向导的说明操作,接受许可协议,完成安装。安装结束后,工作台将要求重启。
7. 工作台重启后,选择`Window ➤ Preferences`打开工作台首选项窗口,选择左侧导航树中的`Android`选项,在`Preferences`部分设置SDK的位置,确保所有构建目标都显示出来,然后点击`Apply`。
8. 点击`OK`,然后打开`New Project`向导,确保Android插件已成功安装。如果安装成功,应该会看到一个创建Android项目的文件夹。
#### 7. 关于安卓原生开发工具包(NDK)
随着SDK 1.5版本的发布,Google推出了新工具——原生开发工具包(NDK),可从[这里](http://developer.android.com/sdk/ndk/1.5_r1/index.html)获取。它是SDK的配套工具,用于构建代码的原生部分,提供了一组系统头文件,如:
- `libc`(C库)头文件
- `libm`(数学库)头文件
- JNI接口头文件
通过以上步骤,你可以在ARM平台上顺利进行安卓游戏开发,解决传统编译方式在Android设备上遇到的问题。同时,了解和使用NDK可以进一步提升开发效率和性能。
### 安卓游戏开发:编译、链接脚本与开发环境搭建
#### 8. 脚本变量详细解析
为了更好地理解和使用`agcc`和`ald`脚本,下面对其中的变量进行详细解析。
| 脚本 | 变量 | 描述 |
| --- | --- | --- |
| `agcc` | `HOME` | 所有软件组件的根目录,其他变量可能会依赖此目录 |
| | `JAVA_HOME` | Java SDK的位置,用于混合Java和C代码的开发 |
| | `SYS_ROOT` | 设备系统库的位置,从设备中提取的系统镜像 |
| | `SYS_DEV` | Android源代码的位置,可从中获取头文件和共享库 |
| | `TOOLCHAIN_ROOT` | CodeSourcery工具链的安装位置 |
| | `AND_INC` | 编译时所需的头文件路径,通过一系列`-I`参数指定 |
| `ald` | `LIBRARIES` | 最终二进制文件应链接的基本库,包括C运行时库、数学库和`libgcc.a` |
| | `LIB_PATHS` | 告诉链接器在文件系统中查找库的位置,同时设置运行时共享库的搜索路径 |
| | `LD_FLAGS` | 链接器标志,设置动态链接器和不使用工具链的标准库 |
#### 9. 脚本工作流程分析
下面通过mermaid流程图来展示`agcc`和`ald`脚本的工作流程。
```mermaid
graph TD;
A[开始] --> B[设置环境变量];
B --> C{脚本类型};
C -- agcc --> D[定义头文件路径AND_INC];
D --> E[调用arm-none-linux-gnueabi-gcc编译];
C -- ald --> F[定义链接库LIBRARIES和路径LIB_PATHS];
F --> G[设置链接器标志LD_FLAGS];
G --> H[调用arm-none-linux-gnueabi-ld链接];
E --> I[结束];
H --> I;
```
从流程图可以看出,`agcc`脚本主要负责编译,通过设置头文件路径并调用`arm-none-linux-gnueabi-gcc`进行编译;`ald`脚本主要负责链接,定义链接库、路径和标志后,调用`arm-none-linux-gnueabi-ld`进行链接。
#### 10. 常见问题及解决方法
在使用上述脚本和搭建开发环境过程中,可能会遇到一些常见问题,以下是一些解决方法:
| 问题 | 解决方法 |
| --- | --- |
| 编译时出现符号缺失错误 | 检查`agcc`脚本中的头文件路径是否正确,确保使用的是Android源代码提供的头文件 |
| 链接时提示找不到库 | 检查`ald`脚本中的`LIB_PATHS`变量,确保链接器能够找到所需的库 |
| Eclipse安装Android插件失败 | 检查网络连接,确保能够访问`https://dl-ssl.google.com/android/eclipse`;或者尝试手动添加该站点 |
#### 11. 开发实战示例
为了更好地理解整个开发过程,下面给出一个简单的开发实战示例。假设我们有一个简单的C程序`main.c`:
```c
#include <stdio.h>
int main() {
printf("Hello, Android Gaming!\n");
return 0;
}
```
1. **编译**:
使用`agcc`脚本进行编译:
```bash
agcc -o main.o -c main.c
```
2. **链接**:
使用`ald`脚本进行链接:
```bash
ald -o main main.o
```
3. **运行**:
将生成的`main`二进制文件推送到Android设备上运行:
```bash
adb push main /data/local/tmp/
adb shell chmod +x /data/local/tmp/main
adb shell /data/local/tmp/main
```
#### 12. 总结
通过本文的介绍,我们了解了从x86平台迁移到ARM平台进行安卓游戏开发时,如何使用定制的编译和链接脚本解决传统编译方式的问题。同时,详细介绍了开发环境的搭建步骤和测试方法,以及常见问题的解决方法。最后,通过一个简单的实战示例,展示了整个开发过程。希望这些内容能够帮助你顺利开展安卓游戏开发工作。
0
0
复制全文
相关推荐










