2010-07-24 14:04:04 +00:00
|
|
|
Index: source/ps/DllLoader.cpp
|
|
|
|
===================================================================
|
2010-07-24 15:53:25 +00:00
|
|
|
--- source/ps/DllLoader.cpp (revision 7732)
|
|
|
|
+++ source/ps/DllLoader.cpp (revision 7795)
|
|
|
|
@@ -1,4 +1,4 @@
|
|
|
|
-/* Copyright (C) 2009 Wildfire Games.
|
|
|
|
+/* Copyright (C) 2010 Wildfire Games.
|
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
@@ -19,19 +19,25 @@
|
|
|
|
|
|
|
|
#include "DllLoader.h"
|
|
|
|
|
|
|
|
+#include "lib/timer.h"
|
|
|
|
#include "lib/posix/posix_dlfcn.h"
|
|
|
|
#include "ps/CStr.h"
|
|
|
|
#include "ps/CLogger.h"
|
|
|
|
+#include "ps/GameSetup/Config.h"
|
|
|
|
|
2010-07-24 14:04:04 +00:00
|
|
|
void* const HANDLE_UNAVAILABLE = (void*)-1;
|
|
|
|
|
2010-07-24 15:53:25 +00:00
|
|
|
+// directory to search for libraries (optionally set by --libdir at build-time,
|
|
|
|
+// optionally overridden by -libdir at run-time in the test executable);
|
|
|
|
+// if we don't have an explicit libdir then the linker will look in DT_RUNPATH
|
|
|
|
+// (which we set to $ORIGIN) to find it in the executable's directory
|
|
|
|
+#ifdef INSTALLED_LIBDIR
|
|
|
|
+static CStr g_Libdir = STRINGIZE(INSTALLED_LIBDIR);
|
|
|
|
+#else
|
|
|
|
+static CStr g_Libdir = "";
|
|
|
|
+#endif
|
2010-07-24 14:04:04 +00:00
|
|
|
|
|
|
|
-// TODO Use path_util instead, get the actual path to the ps_dbg exe and append
|
|
|
|
-// the library name.
|
|
|
|
-
|
2010-07-24 15:53:25 +00:00
|
|
|
-// note: on Linux, lib is prepended to the SO file name;
|
|
|
|
-// we don't use a path with '/' so the linker will look in DT_RUNPATH
|
|
|
|
-// (which we set to $ORIGIN) to find it in the executable's directory
|
|
|
|
+// note: on Linux, lib is prepended to the SO file name
|
2010-07-24 14:04:04 +00:00
|
|
|
#if OS_UNIX
|
2010-07-24 15:53:25 +00:00
|
|
|
static const char* prefix = "lib";
|
|
|
|
#else
|
|
|
|
@@ -41,15 +47,26 @@
|
2010-07-24 14:04:04 +00:00
|
|
|
// but for debugging/performance we prefer to use the same version as the app.
|
|
|
|
// note: on Windows, the extension is replaced with .dll by dlopen.
|
|
|
|
#ifndef NDEBUG
|
|
|
|
-static const char* suffix = "_dbg.so";
|
|
|
|
+static const char* primarySuffix = "_dbg.so";
|
|
|
|
+static const char* secondarySuffix = ".so";
|
|
|
|
#else
|
|
|
|
-static const char* suffix = ".so";
|
|
|
|
+static const char* primarySuffix = ".so";
|
|
|
|
+static const char* secondarySuffix = "_dbg.so";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// (This class is currently only used by 'Collada' and 'AtlasUI' which follow
|
2010-07-24 15:53:25 +00:00
|
|
|
// the naming/location convention above - it'll need to be changed if we want
|
|
|
|
// to support other DLLs.)
|
2010-07-24 14:04:04 +00:00
|
|
|
|
2010-07-24 15:53:25 +00:00
|
|
|
+static CStr GenerateFilename(const CStr& name, const CStr& suffix)
|
|
|
|
+{
|
|
|
|
+ CStr n;
|
|
|
|
+ if (!g_Libdir.empty())
|
|
|
|
+ n = g_Libdir + "/";
|
|
|
|
+ n += prefix + name + suffix;
|
|
|
|
+ return n;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
DllLoader::DllLoader(const char* name)
|
|
|
|
: m_Name(name), m_Handle(0)
|
|
|
|
{
|
|
|
|
@@ -72,23 +89,39 @@
|
|
|
|
// postcondition: m_Handle valid or == HANDLE_UNAVAILABLE.
|
|
|
|
if (m_Handle == 0)
|
|
|
|
{
|
2010-07-24 14:04:04 +00:00
|
|
|
- CStr filename = CStr(prefix) + m_Name + suffix;
|
2010-07-24 15:53:25 +00:00
|
|
|
+ TIMER(L"LoadDLL");
|
|
|
|
|
2010-07-24 14:04:04 +00:00
|
|
|
// we don't really care when relocations take place, but one of
|
|
|
|
// {RTLD_NOW, RTLD_LAZY} must be passed. go with the former because
|
|
|
|
// it is safer and matches the Windows load behavior.
|
|
|
|
const int flags = RTLD_LOCAL|RTLD_NOW;
|
|
|
|
|
2010-07-24 15:53:25 +00:00
|
|
|
+ CStr filename = GenerateFilename(m_Name, primarySuffix);
|
2010-07-24 14:04:04 +00:00
|
|
|
m_Handle = dlopen(filename, flags);
|
|
|
|
|
|
|
|
+ char* primaryError = NULL;
|
|
|
|
+
|
|
|
|
// open failed (mostly likely SO not found)
|
|
|
|
if (! m_Handle)
|
|
|
|
{
|
|
|
|
- const char* error = dlerror();
|
|
|
|
- if (error)
|
|
|
|
- LOG(CLogger::Error, L"", L"dlopen error: %hs", error);
|
|
|
|
+ primaryError = dlerror();
|
|
|
|
+ if (primaryError)
|
|
|
|
+ primaryError = strdup(primaryError); // don't get overwritten by next dlopen
|
|
|
|
+
|
|
|
|
+ // Try to open the other debug/release version
|
2010-07-24 15:53:25 +00:00
|
|
|
+ filename = GenerateFilename(m_Name, secondarySuffix);
|
2010-07-24 14:04:04 +00:00
|
|
|
+ m_Handle = dlopen(filename, flags);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // open still failed; report the first error
|
|
|
|
+ if (! m_Handle)
|
|
|
|
+ {
|
|
|
|
+ if (primaryError)
|
|
|
|
+ LOGERROR(L"dlopen error: %hs", primaryError);
|
|
|
|
m_Handle = HANDLE_UNAVAILABLE;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ free(primaryError);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (m_Handle != HANDLE_UNAVAILABLE);
|
2010-07-24 15:53:25 +00:00
|
|
|
@@ -117,3 +150,8 @@
|
|
|
|
if (*fptr == NULL)
|
|
|
|
throw PSERROR_DllLoader_SymbolNotFound();
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+void DllLoader::OverrideLibdir(const CStr& libdir)
|
|
|
|
+{
|
|
|
|
+ g_Libdir = libdir;
|
|
|
|
+}
|