Support dynamic object loading on MS-Windows.

w32/include/dlfcn.h: New file.
 w32/compat/posixfcn.c: Include dlfcn.h.
 (dlopen, dlerror, dlsym) [MAKE_LOAD]: New functions, in support of
 dynamic loading.

 config.h.W32.template (MAKE_LOAD): Define.
 load.c (load_object) [HAVE_DOS_PATHS]: Support backslashes and
 drive letters in file names of dynamic objects.
This commit is contained in:
Eli Zaretskii 2013-04-29 19:26:06 +03:00
parent 9a7fe22b19
commit 19a69bafc0
5 changed files with 131 additions and 1 deletions

View File

@ -1,5 +1,16 @@
2013-04-29 Eli Zaretskii <eliz@gnu.org>
* w32/include/dlfcn.h: New file.
* w32/compat/posixfcn.c: Include dlfcn.h.
(dlopen, dlerror, dlsym) [MAKE_LOAD]: New functions, in support of
dynamic loading.
* config.h.W32.template (MAKE_LOAD): Define.
* load.c (load_object) [HAVE_DOS_PATHS]: Support backslashes and
drive letters in file names of dynamic objects.
* job.c (construct_command_argv_internal) [WINDOWS32]: Return
right after generating new_argv for one_shell case. This fixes
the Windows build for both Unixy shell and stock Windows shells.

View File

@ -366,6 +366,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
/* Define to 1 to enable job server support in GNU make. */
#define MAKE_JOBSERVER 1
/* Define to 1 to enable 'load' support in GNU make. */
#define MAKE_LOAD 1
/* Define to 1 to enable symbolic link timestamp checking. */
/* #undef MAKE_SYMLINKS */

20
load.c
View File

@ -49,7 +49,11 @@ load_object (const gmk_floc *flocp, int noerror,
void *dlp = NULL;
/* If the path has no "/", try the current directory first. */
if (! strchr (ldname, '/'))
if (! strchr (ldname, '/')
#ifdef HAVE_DOS_PATHS
&& ! strchr (ldname, '\\')
#endif
)
dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
/* If we haven't opened it yet, try the default search path. */
@ -134,6 +138,20 @@ load_file (const gmk_floc *flocp, const char **ldname, int noerror)
char *p = new;
fp = strrchr (*ldname, '/');
#ifdef HAVE_DOS_PATHS
if (fp)
{
const char *fp2 = strchr (fp, '\\');
if (fp2 > fp)
fp = fp2;
}
else
fp = strrchr (*ldname, '\\');
/* The (improbable) case of d:foo. */
if (fp && *fp && fp[1] == ':')
fp++;
#endif
if (!fp)
fp = *ldname;
else

View File

@ -21,6 +21,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <windows.h>
#include "dlfcn.h"
#include "makeint.h"
#include "job.h"
@ -256,3 +258,86 @@ same_stream (FILE *f1, FILE *f2)
}
#endif /* OUTPUT_SYNC */
#if MAKE_LOAD
/* Support for dynamic loading of objects. */
static DWORD last_err;
void *
dlopen (const char *file, int mode)
{
char dllfn[MAX_PATH], *p;
HANDLE dllhandle;
if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0)
{
errno = EINVAL;
last_err = ERROR_INVALID_PARAMETER;
return NULL;
}
if (!file)
dllhandle = GetModuleHandle (NULL);
else
{
/* MSDN says to be sure to use backslashes in the DLL file name. */
strcpy (dllfn, file);
for (p = dllfn; *p; p++)
if (*p == '/')
*p = '\\';
dllhandle = LoadLibrary (dllfn);
}
if (!dllhandle)
last_err = GetLastError ();
return dllhandle;
}
char *
dlerror (void)
{
static char errbuf[1024];
DWORD ret;
if (!last_err)
return NULL;
ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r'))
--ret;
errbuf[ret] = '\0';
if (!ret)
sprintf (errbuf, "Error code %lu", last_err);
last_err = 0;
return errbuf;
}
void *
dlsym (void *handle, const char *name)
{
FARPROC addr = NULL;
if (!handle || handle == INVALID_HANDLE_VALUE)
{
last_err = ERROR_INVALID_PARAMETER;
return NULL;
}
addr = GetProcAddress (handle, name);
if (!addr)
last_err = GetLastError ();
return (void *)addr;
}
#endif /* MAKE_LOAD */

13
w32/include/dlfcn.h Normal file
View File

@ -0,0 +1,13 @@
/* dlfcn.h replacement for MS-Windows build. */
#ifndef DLFCN_H
#define DLFCN_H
#define RTLD_LAZY 1
#define RTLD_NOW 2
#define RTLD_GLOBAL 4
extern void *dlopen (const char *, int);
extern void *dlsym (void *, const char *);
extern char *dlerror (void);
#endif /* DLFCN_H */