diff options
-rwxr-xr-x | android-configure.sh | 112 | ||||
-rw-r--r-- | android/main-emulator.c | 128 |
2 files changed, 239 insertions, 1 deletions
diff --git a/android-configure.sh b/android-configure.sh index 7f8c79b..6d25d20 100755 --- a/android-configure.sh +++ b/android-configure.sh @@ -26,6 +26,11 @@ OPTION_DEBUG=no OPTION_STATIC=no OPTION_MINGW=no +GLES_INCLUDE= +GLES_LIBS= +GLES_SUPPORT=no +GLES_PROBE=yes + HOST_CC=${CC:-gcc} OPTION_CC= @@ -67,6 +72,14 @@ for opt do ;; --arch=*) TARGET_ARCH=$optarg ;; + --gles-include=*) GLES_INCLUDE=$optarg + GLES_SUPPORT=yes + ;; + --gles-libs=*) GLES_LIBS=$optarg + GLES_SUPPORT=yes + ;; + --no-gles) GLES_PROBE=no + ;; *) echo "unknown option '$opt', use --help" exit 1 @@ -96,6 +109,9 @@ EOF echo " --static build a completely static executable" echo " --verbose verbose configuration" echo " --debug build debug version of the emulator" + echo " --gles-include=PATH specify path to GLES emulation headers" + echo " --gles-libs=PATH specify path to GLES emulation host libraries" + echo " --no-gles disable GLES emulation support" echo "" exit 1 fi @@ -124,10 +140,22 @@ if [ "$OPTION_TRY_64" != "yes" ] ; then force_32bit_binaries fi +case $OS in + linux-*) + TARGET_DLL_SUFFIX=.so + ;; + darwin-*) + TARGET_DLL_SUFFIX=.dylib + ;; + windows*) + TARGET_DLL_SUFFIX=.dll +esac + TARGET_OS=$OS -if [ "$OPTION_MINGW" == "yes" ] ; then +if [ "$OPTION_MINGW" = "yes" ] ; then enable_linux_mingw TARGET_OS=windows + TARGET_DLL_SUFFIX=.dll else enable_cygwin fi @@ -146,6 +174,14 @@ if [ "$OPTION_NO_PREBUILTS" = "yes" ] ; then IN_ANDROID_BUILD=no fi +# This is the list of static and shared host libraries we need to link +# against in order to support OpenGLES emulation properly. Note that in +# the case of a standalone build, we will find these libraries inside the +# platform build tree and copy them into objs/lib/ automatically, unless +# you use --gles-libs to point explicitely to a different directory. +# +GLES_SHARED_LIBRARIES="libOpenglRender libGLES_CM_translator libGLES_V2_translator libEGL_translator" + if [ "$IN_ANDROID_BUILD" = "yes" ] ; then locate_android_prebuilt @@ -169,6 +205,9 @@ if [ "$IN_ANDROID_BUILD" = "yes" ] ; then # finally ensure that our new binary is copied to the 'out' # subdirectory as 'emulator' HOST_BIN=$(get_android_abs_build_var HOST_OUT_EXECUTABLES) + if [ "$TARGET_OS" = "windows" ]; then + HOST_BIN=$(echo $HOST_BIN | sed "s%$OS/bin%windows/bin%") + fi if [ -n "$HOST_BIN" ] ; then OPTION_TARGETS="$OPTION_TARGETS $HOST_BIN/emulator$EXE" log "Targets : TARGETS=$OPTION_TARGETS" @@ -182,8 +221,70 @@ if [ "$IN_ANDROID_BUILD" = "yes" ] ; then else log "Tools : Could not locate $TOOLS_PROPS !?" fi + + # Try to find the GLES emulation headers and libraries automatically + if [ "$GLES_PROBE" = "yes" ]; then + GLES_SUPPORT=yes + if [ -z "$GLES_INCLUDE" ]; then + log "GLES : Probing for headers" + GLES_INCLUDE=$ANDROID_TOP/development/tools/emulator/opengl/host/include + if [ -d "$GLES_INCLUDE" ]; then + log "GLES : Headers in $GLES_INCLUDE" + else + echo "Warning: Could not find OpenGLES emulation include dir: $GLES_INCLUDE" + echo "Disabling GLES emulation from this build!" + GLES_SUPPORT=no + fi + fi + if [ -z "$GLES_LIBS" ]; then + log "GLES : Probing for host libraries" + GLES_LIBS=$(dirname "$HOST_BIN")/lib + if [ -d "$GLES_LIBS" ]; then + echo "GLES : Libs in $GLES_LIBS" + else + echo "Warning: Could nof find OpenGLES emulation libraries in: $GLES_LIBS" + echo "Disabling GLES emulation from this build!" + GLES_SUPPORT=no + fi + fi + fi fi # IN_ANDROID_BUILD = no +if [ "$GLES_SUPPORT" = "yes" ]; then + if [ -z "$GLES_INCLUDE" -o -z "$GLES_LIBS" ]; then + echo "ERROR: You must use both --gles-include and --gles-libs at the same time!" + echo " Or use --no-gles to disable its support from this build." + exit 1 + fi + + GLES_HEADER=$GLES_INCLUDE/libOpenglRender/render_api.h + if [ ! -f "$GLES_HEADER" ]; then + echo "ERROR: Missing OpenGLES emulation header file: $GLES_HEADER" + echo "Please fix this by using --gles-include to point to the right directory!" + exit 1 + fi + + mkdir -p objs/lib + + for lib in $GLES_SHARED_LIBRARIES; do + GLES_LIB=$GLES_LIBS/${lib}$TARGET_DLL_SUFFIX + if [ ! -f "$GLES_LIB" ]; then + echo "ERROR: Missing OpenGLES emulation host library: $GLES_LIB" + echo "Please fix this by using --gles-libs to point to the right directory!" + if [ "$IN_ANDROID_BUILD" = "true" ]; then + echo "You might also be missing the library because you forgot to rebuild the whole platform!" + fi + exit 1 + fi + cp $GLES_LIB objs/lib + if [ $? != 0 ]; then + echo "ERROR: Could not find required OpenGLES emulation library: $GLES_LIB" + exit 1 + else + log "GLES : Copying $GLES_LIB" + fi + done +fi # we can build the emulator with Cygwin, so enable it enable_cygwin @@ -440,6 +541,11 @@ if [ "$OPTION_MINGW" = "yes" ] ; then echo "HOST_OS := windows" >> $config_mk fi +if [ "$GLES_INCLUDE" -a "$GLES_LIBS" ]; then + echo "QEMU_OPENGLES_INCLUDE := $GLES_INCLUDE" >> $config_mk + echo "QEMU_OPENGLES_LIBS := $GLES_LIBS" >> $config_mk +fi + # Build the config-host.h file # config_h=objs/config-host.h @@ -543,6 +649,10 @@ fi echo "#define CONFIG_ANDROID 1" >> $config_h +if [ "$GLES_INCLUDE" -a "$GLES_LIBS" ]; then + echo "#define CONFIG_ANDROID_OPENGLES 1" >> $config_h +fi + log "Generate : $config_h" echo "Ready to go. Type 'make' to build emulator" diff --git a/android/main-emulator.c b/android/main-emulator.c index 39e5e1e..3252053 100644 --- a/android/main-emulator.c +++ b/android/main-emulator.c @@ -41,8 +41,21 @@ int android_verbose; # define D(...) do{}while(0) #endif +/* The extension used by dynamic libraries on the host platform */ +#ifdef _WIN32 +# define DLL_EXTENSION ".dll" +#elif defined(__APPLE__) +# define DLL_EXTENSION ".dylib" +#else +# define DLL_EXTENSION ".so" +#endif + +#define GLES_EMULATION_LIB "libOpenglRender" DLL_EXTENSION + /* Forward declarations */ static char* getTargetEmulatorPath(const char* progName, const char* avdArch); +static char* getSharedLibraryPath(const char* progName, const char* libName); +static void prependSharedLibraryPath(const char* prefix); #ifdef _WIN32 static char* quotePath(const char* path); @@ -138,6 +151,20 @@ int main(int argc, char** argv) } #endif + /* We need to find the location of the GLES emulation shared libraries + * and modify either LD_LIBRARY_PATH or PATH accordingly + */ + { + char* sharedLibPath = getSharedLibraryPath(emulatorPath, GLES_EMULATION_LIB); + + if (sharedLibPath != NULL) { + D("Found OpenGLES emulation libraries in %s\n", sharedLibPath); + prependSharedLibraryPath(sharedLibPath); + } else { + D("Could not find OpenGLES emulation host libraries!\n"); + } + } + /* Launch it with the same set of options ! */ safe_execv(emulatorPath, argv); @@ -196,6 +223,107 @@ getTargetEmulatorPath(const char* progName, const char* avdArch) return NULL; } +/* return 1 iff <path>/<filename> exists */ +static int +probePathForFile(const char* path, const char* filename) +{ + char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); + p = bufprint(temp, end, "%s/%s", path, filename); + D("Probing for: %s\n", temp); + return (p < end && path_exists(temp)); +} + +/* Find the directory containing a given shared library required by the + * emulator (for GLES emulation). We will probe several directories + * that correspond to various use-cases. + * + * Caller must free() result string. NULL if not found. + */ + +static char* +getSharedLibraryPath(const char* progName, const char* libName) +{ + char* progDir; + char* result = NULL; + char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp); + + /* Get program's directory name */ + path_split(progName, &progDir, NULL); + + /* First, try to probe the program's directory itself, this corresponds + * to the standalone build with ./android-configure.sh where the script + * will copy the host shared library under external/qemu/objs where + * the binaries are located. + */ + if (probePathForFile(progDir, libName)) { + return progDir; + } + + /* Try under $progDir/lib/, this should correspond to the SDK installation + * where the binary is under tools/, and the libraries under tools/lib/ + */ + { + p = bufprint(temp, end, "%s/lib", progDir); + if (p < end && probePathForFile(temp, libName)) { + result = strdup(temp); + goto EXIT; + } + } + + /* try in $progDir/../lib, this corresponds to the platform build + * where the emulator binary is under out/host/<system>/lib and + * the libraries are under out/host/<system>/lib + */ + { + char* parentDir = path_parent(progDir, 1); + + if (parentDir == NULL) { + parentDir = strdup("."); + } + p = bufprint(temp, end, "%s/lib", parentDir); + free(parentDir); + if (p < end && probePathForFile(temp, libName)) { + result = strdup(temp); + goto EXIT; + } + } + + /* Nothing found! */ +EXIT: + free(progDir); + return result; +} + +/* Prepend the path in 'prefix' to either LD_LIBRARY_PATH or PATH to + * ensure that the shared libraries inside the path will be available + * through dlopen() to the emulator program being launched. + */ +static void +prependSharedLibraryPath(const char* prefix) +{ + char temp[2048], *p=temp, *end=p+sizeof(temp); +#ifdef _WIN32 + const char* path = getenv("PATH"); + if (path == NULL || path[0] == '\0') { + p = bufprint(temp, end, "PATH=%s", prefix); + } else { + p = bufprint(temp, end, "PATH=%s;%s", prefix); + } + /* Ignore overflow, this will push some paths out of the variable, but + * so be it. */ + D("Setting %s\n", temp); + putenv(temp); +#else + const char* path = getenv("LD_LIBRARY_PATH"); + if (path != NULL && path[0] != '\0') { + p = bufprint(temp, end, "%s:%s", prefix, path); + prefix = temp; + } + setenv("LD_LIBRARY_PATH",prefix,1); + D("Setting LD_LIBRARY_PATH=%s\n", prefix); +#endif +} + #ifdef _WIN32 static char* quotePath(const char* path) |