bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

execute, spawn-pipe: Support DLL dependencies of Windows executables


From: Bruno Haible
Subject: execute, spawn-pipe: Support DLL dependencies of Windows executables
Date: Tue, 22 Oct 2024 22:15:52 +0200

Michele Locati noticed that executing programs on Windows has an additional
complexity that does not exist on Unix: On Unix, programs have their runtime
path embedded in the executable ('-rpath' option). On Windows, this is not
the case; instead, DLLs used by the executable are looked up [1]
  - in the directory where the executable sits,
  - in $PATH,
  - in the current directory (this is irrelevant here).

As a consequence, GNU programs on Windows don't install DLLs in $(libdir),
but in $(bindir), so that executables installed in $(bindir) will find them.

But there is a problem when a program (installed in $(bindir)) invokes a
program installed in $(pkglibexecdir). Namely, it will not find its DLLs,
if $(bindir) does not happen to be in the $PATH.

What workarounds exist?

  - A package could install all its executables in $(bindir), none in
    $(pkglibexecdir).
    Problem: Executables from $(pkglibexecdir) are not meant to be public
    (i.e. visible to the user).

  - A package could install the DLLs both in $(bindir) and $(pkglibexecdir).
    Problem: Waste of disk space.

  - A package could avoid invoking helper executables and instead incorporate
    the helper code in its own executable or libraries.
    Problem: A particular platform would dictate the architecture of the
    entire package.

  - While invoking a program installed in $(pkglibexecdir), $(bindir) gets
    added to $PATH.
    This is the best solution.
    Note that it cannot be implemented by invoking "env PATH=.... program ...",
    because there is no 'env' program on native Windows.
    Note also that we cannot require the caller to do a
      setenv ("PATH", value, 1);
    call, because setenv() is not multithread-safe and also because it would
    be an ad-hoc "solution".

So, the PATH modifications must be done in the Gnulib modules 'execute'
and 'spawn-pipe'. (The posix_spawn and posix_spawnp functions don't need
modifications, since they already accept an 'envp' parameter which can
contain a definition of PATH.)

This patch implements that.

[1] 
https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order


2024-10-22  Bruno Haible  <bruno@clisp.org>

        execute, spawn-pipe: Support DLL dependencies of Windows executables.
        Reported by Michele Locati <michele@locati.it>.
        * lib/windows-path.h: New file.
        * lib/windows-path.c: New file.
        * lib/windows-spawn.h (compose_envblock): Add new_PATH parameter.
        (spawnpvech): Add dll_dirs parameter. Call extended_PATH.
        * lib/windows-spawn.c: Include windows-path.h.
        (compose_envblock): Add new_PATH parameter.
        * modules/windows-spawn (Description): Now applies to Cygwin as well.
        (Files): Add lib/windows-path.h, lib/windows-path.c.
        (configure.ac): Define GL_COND_OBJ_WINDOWS_PATH.
        (Makefile.am): Conditionally compile windows-path.c.
        (Include): Add windows-path.h.
        * lib/spawni.c (__spawni): Update compose_envblock call.
        * lib/execute.h (execute): Add dll_dirs parameter.
        * lib/execute.c: Include windows-path.h.
        (execute): Add dll_dirs parameter. Pass it down to spawnpvech. Call
        extended_environ.
        * lib/spawn-pipe.h (create_pipe_out, create_pipe_in, create_pipe_bidi):
        Add dll_dirs parameter.
        * lib/spawn-pipe.c: Include windows-path.h.
        (create_pipe): Add dll_dirs parameter. Pass it down to spawnpvech. Call
        extended_environ.
        (create_pipe_bidi, create_pipe_in, create_pipe_out): Add dll_dirs
        parameter.
        * lib/javaexec.c (execute_java_class): Update execute invocations.
        * lib/cygpath.c (execute_and_read_line): Update create_pipe_in
        invocation.
        * lib/javaversion.c (execute_and_read_line): Likewise.
        * lib/csharpcomp.c (compile_csharp_using_mono,
        compile_csharp_using_dotnet, compile_csharp_using_sscli): Update
        execute, create_pipe_in invocations.
        * lib/csharpexec.c (execute_csharp_using_mono,
        execute_csharp_using_dotnet, execute_csharp_using_sscli): Likewise.
        * lib/javacomp.c (compile_using_envjavac, compile_using_javac,
        execute_and_read_line, is_javac_present): Likewise.
        * lib/pipe-filter-gi.c (pipe_filter_gi_create): Update create_pipe_bidi
        invocation.
        * lib/pipe-filter-ii.c (pipe_filter_ii_execute): Likewise.
        * tests/test-execute-main.c (main): Update execute invocations.
        * tests/test-execute-script.c (main): Likewise.
        * tests/test-spawn-pipe-main.c (main): Update create_pipe_bidi
        invocation.
        * tests/test-spawn-pipe-script.c (main): Update create_pipe_in
        invocations.
        * NEWS: Mention the changes.

Attachment: 0001-execute-spawn-pipe-Support-DLL-dependencies-of-Windo.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]