From 242a075e3256fc7f369f0e5f93fd2ae91c255774 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Tue, 8 Jul 2014 21:45:47 +0200 Subject: emulator/opengl: refactor shared library handling. + Add a unit test. Change-Id: I27c993d1dc819e5bd89fc1e9ae266e11e6ef9a76 --- emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp | 2 +- emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h | 4 +- .../opengl/host/libs/GLESv2_dec/GL2Decoder.cpp | 2 +- emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h | 5 +- .../opengl/host/libs/Translator/EGL/EglImp.cpp | 4 +- .../host/libs/Translator/GLcommon/GLDispatch.cpp | 8 +- .../host/libs/libOpenglRender/EGLDispatch.cpp | 5 +- .../host/libs/libOpenglRender/GL2Dispatch.cpp | 7 +- .../host/libs/libOpenglRender/GLDispatch.cpp | 7 +- emulator/opengl/shared/OpenglOsUtils/Android.mk | 2 +- .../opengl/shared/OpenglOsUtils/osDynLibrary.cpp | 79 ------------ .../opengl/shared/OpenglOsUtils/osDynLibrary.h | 71 ----------- emulator/opengl/shared/emugl/common/Android.mk | 21 ++- .../opengl/shared/emugl/common/shared_library.cpp | 105 +++++++++++++++ .../opengl/shared/emugl/common/shared_library.h | 85 +++++++++++++ .../emugl/common/shared_library_unittest.cpp | 141 +++++++++++++++++++++ .../emugl/common/testing/test_shared_library.cpp | 22 ++++ 17 files changed, 396 insertions(+), 174 deletions(-) delete mode 100644 emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp delete mode 100644 emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h create mode 100644 emulator/opengl/shared/emugl/common/shared_library.cpp create mode 100644 emulator/opengl/shared/emugl/common/shared_library.h create mode 100644 emulator/opengl/shared/emugl/common/shared_library_unittest.cpp create mode 100644 emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp index 3c5bd70..7aa6ede 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp +++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp @@ -47,7 +47,7 @@ int GLDecoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData) libname = getenv(GLES_LIBNAME_VAR); } - m_glesDso = osUtils::dynLibrary::open(libname); + m_glesDso = emugl::SharedLibrary::open(libname); if (m_glesDso == NULL) { fprintf(stderr, "Couldn't find %s \n", GLES_LIBNAME); return -1; diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h index 14ca222..0d26090 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h +++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h @@ -19,7 +19,7 @@ #include "gl_dec.h" #include "FixedBuffer.h" #include "GLDecoderContextData.h" -#include +#include "emugl/common/shared_library.h" #define GLES_LIBNAME_VAR "ANDROID_GLESv1_LIB" #define GLES_LIBNAME "libGLES_CM.so" @@ -65,7 +65,7 @@ private: static void * s_getProc(const char *name, void *userData); GLDecoderContextData *m_contextData; - osUtils::dynLibrary* m_glesDso; + emugl::SharedLibrary* m_glesDso; }; #endif diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp index ccf2f06..2ef306e 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp +++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp @@ -60,7 +60,7 @@ int GL2Decoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData) libname = getenv(GLES2_LIBNAME_VAR); } - m_GL2library = osUtils::dynLibrary::open(libname); + m_GL2library = emugl::SharedLibrary::open(libname); if (m_GL2library == NULL) { fprintf(stderr, "%s: Couldn't find %s \n", __FUNCTION__, libname); return -1; diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h index dcf2c07..8910da9 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h +++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h @@ -21,9 +21,8 @@ #define GLES2_LIBNAME "libGLESv2.so" #include "gl2_dec.h" -#include "osDynLibrary.h" #include "GLDecoderContextData.h" - +#include "emugl/common/shared_library.h" class GL2Decoder : public gl2_decoder_context_t { @@ -35,7 +34,7 @@ public: void setContextData(GLDecoderContextData *contextData) { m_contextData = contextData; } private: GLDecoderContextData *m_contextData; - osUtils::dynLibrary * m_GL2library; + emugl::SharedLibrary* m_GL2library; static void *s_getProc(const char *name, void *userData); static void gl2_APIENTRY s_glGetCompressedTextureFormats(void *self, int count, GLint *formats); diff --git a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp index 06dcf67..30d358f 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp @@ -24,7 +24,7 @@ #include #include "ThreadInfo.h" #include -#include +#include "emugl/common/shared_library.h" #include "EglWindowSurface.h" #include "EglPbufferSurface.h" @@ -175,7 +175,7 @@ EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { #define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces" static __translator_getGLESIfaceFunc loadIfaces(const char* libName){ - osUtils::dynLibrary* libGLES = osUtils::dynLibrary::open(libName); + emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open(libName); if(!libGLES) return NULL; __translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME); diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp index 7b217fd..5da7247 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include "emugl/common/shared_library.h" #ifdef __linux__ #include @@ -31,13 +31,13 @@ typedef void (*GL_FUNC_PTR)(); static GL_FUNC_PTR getGLFuncAddress(const char *funcName) { GL_FUNC_PTR ret = NULL; #ifdef __linux__ - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("libGL.so"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("libGL"); ret = (GL_FUNC_PTR)glXGetProcAddress((const GLubyte*)funcName); #elif defined(WIN32) - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("opengl32"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("opengl32"); ret = (GL_FUNC_PTR)wglGetProcAddress(funcName); #elif defined(__APPLE__) - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL"); #endif if(!ret && libGL){ ret = libGL->findSymbol(funcName); diff --git a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp index 3cf5dbc..7d514e8 100644 --- a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp @@ -16,7 +16,8 @@ #include "EGLDispatch.h" #include #include -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" EGLDispatch s_egl; @@ -28,7 +29,7 @@ bool init_egl_dispatch() const char *libName = getenv("ANDROID_EGL_LIB"); if (!libName) libName = DEFAULT_EGL_LIB; - osUtils::dynLibrary *lib = osUtils::dynLibrary::open(libName); + emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName); if (!lib) { printf("Failed to open %s\n", libName); return NULL; diff --git a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp index cda205f..8c51a4e 100644 --- a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp @@ -17,12 +17,13 @@ #include "GL2Dispatch.h" #include #include -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" gl2_decoder_context_t s_gl2; int s_gl2_enabled; -static osUtils::dynLibrary *s_gles2_lib = NULL; +static emugl::SharedLibrary *s_gles2_lib = NULL; #define DEFAULT_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator") @@ -38,7 +39,7 @@ bool init_gl2_dispatch() // // Load the GLES library // - s_gles2_lib = osUtils::dynLibrary::open(libName); + s_gles2_lib = emugl::SharedLibrary::open(libName); if (!s_gles2_lib) return false; // diff --git a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp index 089512a..c127dc3 100644 --- a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp @@ -16,11 +16,12 @@ #include "GLDispatch.h" #include #include -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" GLDispatch s_gl; -static osUtils::dynLibrary *s_gles_lib = NULL; +static emugl::SharedLibrary *s_gles_lib = NULL; // // This function is called only once during initialiation before @@ -34,7 +35,7 @@ bool init_gl_dispatch() const char *libName = getenv("ANDROID_GLESv1_LIB"); if (!libName) libName = DEFAULT_GLES_CM_LIB; - s_gles_lib = osUtils::dynLibrary::open(libName); + s_gles_lib = emugl::SharedLibrary::open(libName); if (!s_gles_lib) return false; s_gl.glAlphaFunc = (glAlphaFunc_t) s_gles_lib->findSymbol("glAlphaFunc"); diff --git a/emulator/opengl/shared/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk index f9673fc..42b57dd 100644 --- a/emulator/opengl/shared/OpenglOsUtils/Android.mk +++ b/emulator/opengl/shared/OpenglOsUtils/Android.mk @@ -8,7 +8,7 @@ LOCAL_PATH := $(call my-dir) ### Host library ############################################## -host_common_SRC_FILES := osDynLibrary.cpp +host_common_SRC_FILES := host_common_LDLIBS := host_common_INCLUDES := $(LOCAL_PATH) diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp deleted file mode 100644 index e8e6ab7..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osDynLibrary.h" - -#ifndef _WIN32 -#include -#endif -#include - -namespace osUtils { - -dynLibrary *dynLibrary::open(const char *p_libName) -{ - dynLibrary *lib = new dynLibrary(); - if (!lib) { - return NULL; - } - -#ifdef _WIN32 - lib->m_lib = LoadLibrary(p_libName); -#else // !WIN32 - lib->m_lib = dlopen(p_libName, RTLD_NOW); -#endif - - if (lib->m_lib == NULL) { - printf("Failed to load %s\n", p_libName); -#ifndef _WIN32 - printf("error %s\n", dlerror()); //only on linux -#endif - delete lib; - return NULL; - } - - return lib; -} - -dynLibrary::dynLibrary() : - m_lib(NULL) -{ -} - -dynLibrary::~dynLibrary() -{ - if (NULL != m_lib) { -#ifdef _WIN32 - FreeLibrary(m_lib); -#else // !WIN32 - dlclose(m_lib); -#endif - } -} - -dynFuncPtr dynLibrary::findSymbol(const char *p_symName) -{ - if (NULL == m_lib) { - return NULL; - } - -#ifdef _WIN32 - return (dynFuncPtr) GetProcAddress(m_lib, p_symName); -#else // !WIN32 - return (dynFuncPtr) dlsym(m_lib, p_symName); -#endif -} - -} // of namespace osUtils diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h deleted file mode 100644 index c83fbf3..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef _OSUTILS_DYN_LIBRARY_H -#define _OSUTILS_DYN_LIBRARY_H - -#ifdef _WIN32 -#include -#endif - -namespace osUtils { - -typedef void (*dynFuncPtr)(void); - -class dynLibrary -{ -public: - static dynLibrary *open(const char *p_libName); - ~dynLibrary(); - - dynFuncPtr findSymbol(const char *p_symName); - -private: - dynLibrary(); - -private: -#ifdef _WIN32 - HMODULE m_lib; -#else - void *m_lib; -#endif -}; - -} // of namespace osUtils - - - -// Macro to compose emugl shared library name under various OS and bitness -// eg. -// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo.so" - -#ifdef _WIN32 -# define DLL_EXTENSION "" // _WIN32 LoadLibrary only accept name w/o .dll extension -#elif defined(__APPLE__) -# define DLL_EXTENSION ".dylib" -#else -# define DLL_EXTENSION ".so" -#endif - -#if defined(__x86_64__) -# define EMUGL_LIBNAME(name) "lib64" name DLL_EXTENSION -#elif defined(__i386__) -# define EMUGL_LIBNAME(name) "lib" name DLL_EXTENSION -#else -/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ -#endif - - -#endif diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk index 58dd6da..e75f887 100644 --- a/emulator/opengl/shared/emugl/common/Android.mk +++ b/emulator/opengl/shared/emugl/common/Android.mk @@ -9,16 +9,22 @@ commonSources := \ id_to_object_map.cpp \ lazy_instance.cpp \ pod_vector.cpp \ + shared_library.cpp \ smart_ptr.cpp \ sockets.cpp \ thread_store.cpp \ host_commonSources := $(commonSources) +host_commonLdLibs := -lstdc++ +ifneq (windows,$(HOST_OS)) + host_commonLdLibs += -ldl +endif + $(call emugl-begin-host-static-library,libemugl_common) LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) -$(call emugl-export,LDLIBS,-lstdc++) +$(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) ifdef EMUGL_BUILD_64BITS @@ -26,7 +32,7 @@ ifdef EMUGL_BUILD_64BITS LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-export,CFLAGS,-m64 -fPIC) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) - $(call emugl-export,LDLIBS,-lstdc++) + $(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) endif @@ -38,6 +44,7 @@ host_commonSources := \ lazy_instance_unittest.cpp \ pod_vector_unittest.cpp \ mutex_unittest.cpp \ + shared_library_unittest.cpp \ smart_ptr_unittest.cpp \ thread_store_unittest.cpp \ @@ -52,3 +59,13 @@ ifdef EMUGL_BUILD_64BITS $(call emugl-import,lib64emugl_common lib64emugl_gtest) $(call emugl-end-module) endif + +$(call emugl-begin-host-shared-library,libemugl_test_shared_library) +LOCAL_SRC_FILES := testing/test_shared_library.cpp +$(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64emugl_test_shared_library) + LOCAL_SRC_FILES := testing/test_shared_library.cpp + $(call emugl-end-module) +endif diff --git a/emulator/opengl/shared/emugl/common/shared_library.cpp b/emulator/opengl/shared/emugl/common/shared_library.cpp new file mode 100644 index 0000000..db1c75c --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library.cpp @@ -0,0 +1,105 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/shared_library.h" + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#endif + +namespace emugl { + +#ifdef _WIN32 + +// static +SharedLibrary* SharedLibrary::open(const char* libraryName) { + HMODULE lib = LoadLibrary(libraryName); + return lib ? new SharedLibrary(lib) : NULL; +} + +SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} + +SharedLibrary::~SharedLibrary() { + if (mLib) { + FreeLibrary(mLib); + } +} + +SharedLibrary::FunctionPtr SharedLibrary::findSymbol( + const char* symbolName) { + if (!mLib || !symbolName) { + return NULL; + } + return reinterpret_cast( + GetProcAddress(mLib, symbolName)); +} + +#else // !_WIN32 + +// static +SharedLibrary* SharedLibrary::open(const char* libraryName) { + const char* libPath = libraryName; + char* path = NULL; + + const char* libBaseName = strrchr(libraryName, '/'); + if (!libBaseName) { + libBaseName = libraryName; + } + + if (!strchr(libBaseName, '.')) { + // There is no extension in this library name, so append one. +#ifdef __APPLE__ + static const char kDllExtension[] = ".dylib"; +#else + static const char kDllExtension[] = ".so"; +#endif + size_t pathLen = strlen(libraryName) + sizeof(kDllExtension); + path = static_cast(malloc(pathLen)); + snprintf(path, pathLen, "%s%s", libraryName, kDllExtension); + libPath = path; + } + + void* lib = dlopen(libPath, RTLD_NOW); + + if (path) { + free(path); + } + + return lib ? new SharedLibrary(lib) : NULL; +} + +SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} + +SharedLibrary::~SharedLibrary() { + if (mLib) { + dlclose(mLib); + } +} + +SharedLibrary::FunctionPtr SharedLibrary::findSymbol( + const char* symbolName) { + if (!mLib || !symbolName) { + return NULL; + } + return reinterpret_cast(dlsym(mLib, symbolName)); +} + +#endif // !_WIN32 + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/shared_library.h b/emulator/opengl/shared/emugl/common/shared_library.h new file mode 100644 index 0000000..38d25bd --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library.h @@ -0,0 +1,85 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef EMUGL_COMMON_SHARED_LIBRARY_H +#define EMUGL_COMMON_SHARED_LIBRARY_H + +#ifdef _WIN32 +#include +#endif + +namespace emugl { + +// A class used to open a platform-specific shared library, and probe +// it for symbols. Usage is the following: +// +// // Open the library. +// SharedLibrary* library = SharedLibrary::open("libFoo"); +// if (!library) { +// ... could not find / open library! +// } +// +// //Probe for function symbol. +// FunctionPtr my_func = library->findSymbol("my_func"); +// +// // Closes library/ +// delete library; +// +class SharedLibrary { +public: + // Open a given library. |libraryName| can be either a full library + // path, or a simple name without an extension. On success, returns + // a new SharedLibrary instance that must be deleted by the caller. + static SharedLibrary* open(const char* libraryName); + + // Closes an existing SharedLibrary instance. + ~SharedLibrary(); + + // Generic function pointer type, for values returned by the + // findSymbol() method. + typedef void (*FunctionPtr)(void); + + // Probe a given SharedLibrary instance to find a symbol named + // |symbolName| in it. Return its address as a FunctionPtr, or + // NULL if the symbol is not found. + FunctionPtr findSymbol(const char* symbolName); + +private: +#ifdef _WIN32 + typedef HMODULE HandleType; +#else + typedef void* HandleType; +#endif + + // Constructor intentionally hidden. + SharedLibrary(HandleType); + + HandleType mLib; +}; + +// Macro to compose emugl shared library name under various OS and bitness +// eg. +// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo" + +#if defined(__x86_64__) +# define EMUGL_LIBNAME(name) "lib64" name +#elif defined(__i386__) +# define EMUGL_LIBNAME(name) "lib" name +#else +/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ +#endif + +} // namespace emugl + +#endif // EMUGL_COMMON_SHARED_LIBRARY_H diff --git a/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp new file mode 100644 index 0000000..cec4c73 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp @@ -0,0 +1,141 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/shared_library.h" + +#include + +#include + +#include +#include + +// Hack to get the current executable's full path. +namespace testing { +namespace internal { + +extern std::string g_executable_path; + +} // namespace internal +} // namespace testing + +namespace emugl { + +namespace { + +// Return the name/path of the test shared library to load. +// Note that this doesn't include a platform-specific extension. +// This assumes that the test shared library is under the lib/ sub-directory +// of the current executable's path! +std::string GetTestLibraryName() { + static const char kSubDir[] = "lib/"; +#ifdef __x86_64__ + static const char kLibraryPrefix[] = "lib64"; +#else + static const char kLibraryPrefix[] = "lib"; +#endif + static const char kTestLibrarySuffix[] = "emugl_test_shared_library"; + + const char* exec_path = testing::internal::g_executable_path.c_str(); + +#ifdef _WIN32 + const char* p = strrchr(exec_path, '/'); + const char* p2 = strrchr(exec_path, '\\'); + if (p2) { + if (!p || p2 > p) { + p = p2; + } + } +#else + const char* p = strrchr(exec_path, '/'); +#endif + + std::string path; + + if (!p) { + path = "./"; + } else { + path = std::string(exec_path, p - exec_path + 1U); + } + path += kSubDir; + path += kLibraryPrefix; + path += kTestLibrarySuffix; + printf("Library path: %s\n", path.c_str()); + return path; +} + +class SharedLibraryTest : public testing::Test { +public: + SharedLibraryTest() { + // Locate the shared library + mLibraryPath = GetTestLibraryName(); + } + + ~SharedLibraryTest() {} + + const char* library_path() const { return mLibraryPath.c_str(); } + +private: + std::string mLibraryPath; +}; + +class ScopedSharedLibrary { +public: + explicit ScopedSharedLibrary(SharedLibrary* lib) : mLib(lib) {} + ~ScopedSharedLibrary() { + delete mLib; + } + SharedLibrary* get() const { return mLib; } + + SharedLibrary* operator->() { return mLib; } + +private: + SharedLibrary* mLib; +}; + +} // namespace + +TEST_F(SharedLibraryTest, Open) { + ScopedSharedLibrary lib(SharedLibrary::open(library_path())); + EXPECT_TRUE(lib.get()); +} + +TEST_F(SharedLibraryTest, OpenWithExtension) { + std::string path = library_path(); +#ifdef _WIN32 + path += ".dll"; +#elif defined(__APPLE__) + path += ".dylib"; +#else + path += ".so"; +#endif + ScopedSharedLibrary lib(SharedLibrary::open(path.c_str())); + EXPECT_TRUE(lib.get()); +} + +TEST_F(SharedLibraryTest, FindSymbol) { + ScopedSharedLibrary lib(SharedLibrary::open(library_path())); + EXPECT_TRUE(lib.get()); + + if (lib.get()) { + typedef int (*FooFunction)(void); + + FooFunction foo_func = reinterpret_cast( + lib->findSymbol("foo_function")); + EXPECT_TRUE(foo_func); + EXPECT_EQ(42, (*foo_func)()); + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp new file mode 100644 index 0000000..598a963 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source file must be compiled into a simple shared library which +// will be used by shared_library_unittest.cpp to verify that the +// emugl::SharedLibrary class works properly. + + +extern "C" int foo_function(void) { + return 42; +} -- cgit v1.1