summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-04-29 19:26:06 +0300
committerEli Zaretskii <eliz@gnu.org>2013-04-29 19:26:06 +0300
commit19a69bafc0913f13e334b5f56d95c693fab29023 (patch)
treeb3f1d061b1a72d5f7e74a60831d85362f41fafe1
parent9a7fe22b197770271a2235062fe52cb1c71a3d9e (diff)
downloadmake-19a69bafc0913f13e334b5f56d95c693fab29023.tar.gz
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.
-rw-r--r--ChangeLog11
-rw-r--r--config.h.W32.template3
-rw-r--r--load.c20
-rw-r--r--w32/compat/posixfcn.c85
-rw-r--r--w32/include/dlfcn.h13
5 files changed, 131 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index e297795..6badda8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/config.h.W32.template b/config.h.W32.template
index 8818a76..8d59a13 100644
--- a/config.h.W32.template
+++ b/config.h.W32.template
@@ -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 */
diff --git a/load.c b/load.c
index 95529c2..9a83829 100644
--- a/load.c
+++ b/load.c
@@ -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
diff --git a/w32/compat/posixfcn.c b/w32/compat/posixfcn.c
index 90534d0..cafc864 100644
--- a/w32/compat/posixfcn.c
+++ b/w32/compat/posixfcn.c
@@ -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 */
+
diff --git a/w32/include/dlfcn.h b/w32/include/dlfcn.h
new file mode 100644
index 0000000..c95fee2
--- /dev/null
+++ b/w32/include/dlfcn.h
@@ -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 */