This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Changeset 9642 for ps


Ignore:
Timestamp:
06/20/11 22:06:51 (14 years ago)
Author:
Jan Wassenberg
Message:

add support for .dylib on OS X based on patch by Yves (thanks!)
c.f. http://www.wildfiregames.com/forum/index.php?showtopic=14173&pid=220828&st=0&#entry220828

Location:
ps/trunk/source
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/source/lib/sysdep/os/win/wposix/wdlfcn.cpp

    r9410 r9642  
    4747char* dlerror()
    4848{
    49     return 0;
     49    // the obvious implementation involves sys_StatusDescription, but we
     50    // don't want to return a pointer to a static array because that's not
     51    // thread-safe. we therefore check GetLastError directly.
     52    switch(GetLastError())
     53    {
     54    case ERROR_MOD_NOT_FOUND:
     55        return "module not found";
     56    case ERROR_PROC_NOT_FOUND:
     57        return "symbol not found";
     58    default:
     59        return "unknown";
     60    }
    5061}
    5162
  • ps/trunk/source/ps/DllLoader.cpp

    r8929 r9642  
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2011 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
     
    2626#include "ps/GameSetup/Config.h"
    2727
    28 void* const HANDLE_UNAVAILABLE = (void*)-1;
     28static void* const HANDLE_UNAVAILABLE = (void*)-1;
    2929
    3030// directory to search for libraries (optionally set by --libdir at build-time,
     
    4040// note: on Linux, lib is prepended to the SO file name
    4141#if OS_UNIX
    42 static const char* prefix = "lib";
     42static CStr prefix = "lib";
    4343#else
    44 static const char* prefix = "";
     44static CStr prefix = "";
    4545#endif
    46 // our SOs export binary-compatible interfaces across debug and release builds,
    47 // but for debugging/performance we prefer to use the same version as the app.
    48 // note: on Windows, the extension is replaced with .dll by dlopen.
     46
     47// we usually want to use the same debug/release build type as the
     48// main executable (the library should also be efficient in release builds and
     49// allow easy symbol access in debug builds). however, that version of the
     50// library might be missing, so we check for both.
     51// this works because the interface is binary-compatible.
    4952#ifndef NDEBUG
    50 static const char* primarySuffix = "_dbg.so";
    51 static const char* secondarySuffix = ".so";
     53static CStr suffixes[] = { "_dbg", "" };    // (order matters)
    5254#else
    53 static const char* primarySuffix = ".so";
    54 static const char* secondarySuffix = "_dbg.so";
     55static CStr suffixes[] = { "", "_dbg" };
    5556#endif
     57
     58// NB: our Windows dlopen() function changes the extension to .dll
     59static CStr extensions[] = {
     60    ".so",
     61#if OS_MACOSX
     62    ".dylib"    // supported by OS X dlopen
     63#endif
     64};
    5665
    5766// (This class is currently only used by 'Collada' and 'AtlasUI' which follow
     
    5968// to support other DLLs.)
    6069
    61 static CStr GenerateFilename(const CStr& name, const CStr& suffix)
     70static CStr GenerateFilename(const CStr& name, const CStr& suffix, const CStr& extension)
    6271{
    6372    CStr n;
    6473    if (!g_Libdir.empty())
    6574        n = g_Libdir + "/";
    66     n += prefix + name + suffix;
     75    n += prefix + name + suffix + extension;
    6776    return n;
    6877}
    6978
     79
     80
     81// @param name base name of the library (excluding prefix/suffix/extension)
     82// @param errors receives descriptions of any and all errors encountered
     83// @return valid handle or 0
     84static void* LoadAnyVariant(const CStr& name, std::stringstream& errors)
     85{
     86    for(size_t idxSuffix = 0; idxSuffix < ARRAY_SIZE(suffixes); idxSuffix++)
     87    {
     88        for(size_t idxExtension = 0; idxExtension < ARRAY_SIZE(extensions); idxExtension++)
     89        {
     90            CStr filename = GenerateFilename(name, suffixes[idxSuffix], extensions[idxExtension]);
     91
     92            // we don't really care when relocations take place, but one of
     93            // {RTLD_NOW, RTLD_LAZY} must be specified. go with the former because
     94            // it is safer and matches the Windows load behavior.
     95            const int flags = RTLD_LOCAL|RTLD_NOW;
     96            void* handle = dlopen(filename.c_str(), flags);
     97            if(handle)
     98                return handle;
     99            else
     100                errors << "dlopen(" << filename << ") failed: " << dlerror() << "; ";
     101        }
     102    }
     103
     104    return 0;   // none worked
     105}
     106
     107
    70108DllLoader::DllLoader(const char* name)
    71 : m_Name(name), m_Handle(0)
     109    : m_Name(name), m_Handle(0)
    72110{
    73111}
     
    92130        TIMER(L"LoadDLL");
    93131
    94         // we don't really care when relocations take place, but one of
    95         // {RTLD_NOW, RTLD_LAZY} must be passed. go with the former because
    96         // it is safer and matches the Windows load behavior.
    97         const int flags = RTLD_LOCAL|RTLD_NOW;
    98 
    99         CStr filename = GenerateFilename(m_Name, primarySuffix);
    100         m_Handle = dlopen(filename.c_str(), flags);
    101 
    102         char* primaryError = NULL;
    103 
    104         // open failed (mostly likely SO not found)
    105         if (! m_Handle)
     132        std::stringstream errors;
     133        m_Handle = LoadAnyVariant(m_Name, errors);
     134        if(!m_Handle)   // (only report errors if nothing worked)
    106135        {
    107             primaryError = dlerror();
    108             if (primaryError)
    109                 primaryError = strdup(primaryError); // don't get overwritten by next dlopen
    110 
    111             // Try to open the other debug/release version
    112             filename = GenerateFilename(m_Name, secondarySuffix);
    113             m_Handle = dlopen(filename.c_str(), flags);
    114         }
    115 
    116         // open still failed; report the first error
    117         if (! m_Handle)
    118         {
    119             if (primaryError)
    120                 LOGERROR(L"dlopen error: %hs", primaryError);
     136            LOGERROR(L"DllLoader: %hs", errors.str().c_str());
    121137            m_Handle = HANDLE_UNAVAILABLE;
    122138        }
    123 
    124         free(primaryError);
    125139    }
    126140
     
    130144void DllLoader::Unload()
    131145{
    132     if (! IsLoaded())
     146    if(!IsLoaded())
    133147        return;
    134148
     
    139153void DllLoader::LoadSymbolInternal(const char* name, void** fptr) const
    140154{
    141     if (! IsLoaded())
     155    if(!IsLoaded())
    142156    {
    143157        debug_warn(L"Loading symbol from invalid DLL");
     
    147161
    148162    *fptr = dlsym(m_Handle, name);
    149 
    150     if (*fptr == NULL)
     163    if(*fptr == NULL)
    151164        throw PSERROR_DllLoader_SymbolNotFound();
    152165}
  • ps/trunk/source/ps/DllLoader.h

    r7824 r9642  
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2011 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
Note: See TracChangeset for help on using the changeset viewer.