Eli Zaretskii wrote on 2026-02-22:
> Also, rpl_getopt_long that is known to 'main' is described as residing
> in the .exe:
> 
>   (gdb) info symbol rpl_getopt_internal
>   rpl_getopt_internal in section .text of 
> d:\gnu\texinfo-7.2.92-C\tta\C\.libs\ctexi2any.exe
> 
> However, if I step into getopt_internal, when it is called by 'main',
> I see something different:
> 
>   (gdb) info symbol rpl_getopt_internal
>   rpl_getopt_internal in section .text of 
> d:\gnu\texinfo-7.2.92-C\tta\C\.libs\libtexinfo-main-0.dll

Good progress! This means that we need to concentrate on
  - ctexi2any.exe
  - libtexinfo-main-0.dll

Which you already did in your followup message
https://lists.gnu.org/archive/html/bug-texinfo/2026-02/msg00104.html

> > Yes, rpl_optarg is intentionally meant to be different from the mingw
> > optarg.
> 
> Then I'm surprised to hear that Gettext needed to hack around that.
> I'd expect this to work with MinGW.

Every package that has the getopt[-gnu] module in a shared library and wants
Windows portability needs to make the DLL_VARIABLE dance.

This is because the definition of DLL_VARIABLE (__declspec(dllexport) vs.
__declspec(dllimport)) depends on whether the current compilation unit will
end up inside or outside that shared library. The boundaries of the shared
library are package-specific; they depend on which code is included via
  lib..._la_SOURCES += sourcecode.c

Find attached three patches. All three are needed for portability to
native Windows. Maybe more is needed; but I think with these three patches
you should be much closer to something that works.

0001 fixes the problem reported by Eli in
https://lists.gnu.org/archive/html/bug-texinfo/2026-02/msg00104.html

0002 fixes the problem reported by Gavin in
https://lists.gnu.org/archive/html/bug-texinfo/2026-02/msg00105.html

0003 fixes the problem that I explained in
https://lists.gnu.org/archive/html/bug-texinfo/2026-02/msg00102.html
It uses the same boilerplate code as GNU gettext for defining DLL_VARIABLE.
This solution is known to work with both mingw and MSVC. (Just in case
portability to MSVC would be desired sometime in the future.)

It works fine for me, but my mingw environment does not have PERL_EMBEDDED.
You'll need to test it in a mingw environment where PERL_EMBEDDED is true.

Bruno

>From db71bd4645f4cda7ff5ecde12c74ed12b091f933 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 27 Feb 2026 10:06:38 +0100
Subject: [PATCH 1/3] Portability to native Windows: Don't include libgnu.a in
 ctexi2any.

libgnu.la is a static library and is included in the libtexinfo-main
shared library. A second copy of it in the ctexi2any executable means
that on Windows there will be two copies of each variable (such as
'optarg'); this is undesired.

* tta/C/Makefile.am (ctexi2any_LDADD): Remove libgnu.la.
---
 tta/C/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tta/C/Makefile.am b/tta/C/Makefile.am
index 63c90cfd4e..b7aa6174dc 100644
--- a/tta/C/Makefile.am
+++ b/tta/C/Makefile.am
@@ -638,7 +638,7 @@ ctexi2any_SOURCES = \
 # Gnulib is directly needed on some platforms for getopt-gnu.
 # The Gnulib link variables are needed at least on Solaris and not added
 # by libtool.
-ctexi2any_LDADD = libtexinfo-main.la libtexinfoxs.la libtexinfo-convert.la libtexinfo.la $(top_builddir)/gnulib/lib/libgnu.la $(perl_conf_LIBS) $(EUIDACCESS_LIBGEN) $(LTLIBINTL) $(LTLIBICONV) $(LTLIBUNISTRING)
+ctexi2any_LDADD = libtexinfo-main.la libtexinfoxs.la libtexinfo-convert.la libtexinfo.la $(perl_conf_LIBS) $(EUIDACCESS_LIBGEN) $(LTLIBINTL) $(LTLIBICONV) $(LTLIBUNISTRING)
 
 # NOTE it is important to use perl_conf_CFLAGS here to match
 # with perl_conf_LDFLAGS used for linking, or in some platforms where
-- 
2.52.0

>From 67065db841d2960faff1b22a21b3c130a59af7e4 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 27 Feb 2026 10:12:54 +0100
Subject: [PATCH 2/3] Portability to native Windows: Configure libtool as
 needed.

Reported by Gavin Smith in
<https://lists.gnu.org/archive/html/bug-texinfo/2026-02/msg00105.html>.

* tta/configure.ac: Pass option win32-dll to LT_INIT.
---
 tta/configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tta/configure.ac b/tta/configure.ac
index a410f6e69d..467986d995 100644
--- a/tta/configure.ac
+++ b/tta/configure.ac
@@ -360,7 +360,7 @@ gl_INIT
 AM_GNU_GETTEXT_VERSION([0.26])
 AM_GNU_GETTEXT([external])
 
-LT_INIT([disable-static dlopen])
+LT_INIT([disable-static win32-dll dlopen])
 
 # for tests
 txi_ICONV_CONVERTS_EUC_CN
-- 
2.52.0

>From 8c4d97ebda828c8e985f304d51acbe46304de977 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 27 Feb 2026 10:26:22 +0100
Subject: [PATCH 3/3] Portability to native Windows: Deal with variables inside
 libtexinfo-main DLL.

* tta/gnulib-local/lib/getopt-core.h.diff: New file, from GNU gettext.
* tta/gnulib-local/modules/tta-misc: New file.
* tta/Makefile.am (EXTRA_DIST): Add them.
* tta/configure.ac (WOE32DLL): New conditional and C macro.
(DLL_VARIABLE): New C macro.
* tta/gnulib/m4/gnulib-cache.m4: Add gnulib-tool option --local-dir. Import
module tta-misc.
---
 tta/Makefile.am                         |  3 ++
 tta/configure.ac                        | 44 +++++++++++++++++++++++
 tta/gnulib-local/lib/getopt-core.h.diff | 46 +++++++++++++++++++++++++
 tta/gnulib-local/modules/tta-misc       | 17 +++++++++
 tta/gnulib/m4/gnulib-cache.m4           |  5 ++-
 5 files changed, 114 insertions(+), 1 deletion(-)
 create mode 100644 tta/gnulib-local/lib/getopt-core.h.diff
 create mode 100644 tta/gnulib-local/modules/tta-misc

diff --git a/tta/Makefile.am b/tta/Makefile.am
index def21d7314..d385089881 100644
--- a/tta/Makefile.am
+++ b/tta/Makefile.am
@@ -24,6 +24,9 @@ if BUILD_C_CODE
 SUBDIRS += gnulib/lib
 endif
 
+EXTRA_DIST += \
+  gnulib-local/lib/getopt-core.h.diff \
+  gnulib-local/modules/tta-misc
 EXTRA_DIST += gnulib/m4/gnulib-cache.m4
 
 ################### End Gnulib section #########################
diff --git a/tta/configure.ac b/tta/configure.ac
index 467986d995..73c6456d88 100644
--- a/tta/configure.ac
+++ b/tta/configure.ac
@@ -362,6 +362,50 @@ AM_GNU_GETTEXT([external])
 
 LT_INIT([disable-static win32-dll dlopen])
 
+dnl Compilation on native Windows and Cygwin needs special Makefile rules,
+dnl because
+dnl 1. when we install a shared library, we must arrange to export
+dnl    auxiliary pointer variables for every exported variable,
+dnl 2. when we install a shared library and a static library simultaneously,
+dnl    the include file specifies __declspec(dllimport) and therefore we
+dnl    must arrange to define the auxiliary pointer variables for the
+dnl    exported variables _also_ in the static library.
+if test "$enable_shared" = yes; then
+  case "$host_os" in
+    mingw* | windows* | cygwin*) is_woe32dll=yes ;;
+    *) is_woe32dll=no ;;
+  esac
+else
+  is_woe32dll=no
+fi
+AM_CONDITIONAL([WOE32DLL], [test $is_woe32dll = yes])
+if test $is_woe32dll = yes; then
+  AC_DEFINE([WOE32DLL], [1],
+    [Define when --enable-shared is used on Windows.])
+fi
+
+AH_BOTTOM([
+/* On Windows, variables that may be in a DLL must be marked specially.
+   The symbols marked with DLL_VARIABLE should be exported if and only if the
+   object file gets included in a DLL.  Libtool, on Windows platforms, defines
+   the C macro DLL_EXPORT (together with PIC) when compiling for a shared
+   library (called DLL under Windows) and does not define it when compiling
+   an object file meant to be linked statically into some executable.  */
+#if (defined _WIN32 || defined __CYGWIN__) && WOE32DLL
+# if IN_LIBGNU
+#  if defined DLL_EXPORT
+#   define DLL_VARIABLE __declspec (dllexport)
+#  else
+#   define DLL_VARIABLE
+#  endif
+# else
+#  define DLL_VARIABLE __declspec (dllimport)
+# endif
+#else
+# define DLL_VARIABLE
+#endif
+])
+
 # for tests
 txi_ICONV_CONVERTS_EUC_CN
 
diff --git a/tta/gnulib-local/lib/getopt-core.h.diff b/tta/gnulib-local/lib/getopt-core.h.diff
new file mode 100644
index 0000000000..5e385cf7d3
--- /dev/null
+++ b/tta/gnulib-local/lib/getopt-core.h.diff
@@ -0,0 +1,46 @@
+--- getopt-core.h.bak	2020-06-26 21:24:59.890340657 +0200
++++ getopt-core.h	2020-07-28 19:48:27.769014629 +0200
+@@ -20,6 +20,14 @@
+ #ifndef _GETOPT_CORE_H
+ #define _GETOPT_CORE_H 1
+ 
++/* Ensure that DLL_VARIABLE is defined.  Since on OSF/1 4.0 and Irix 6.5
++   <stdlib.h> includes <getopt.h>, and <config.h> is not a prerequisite for
++   using <stdlib.h>, this file can be included without a prior
++   "#include <config.h>".  */
++#if !defined DLL_VARIABLE && defined HAVE_CONFIG_H
++# include <config.h>
++#endif
++
+ /* This header should not be used directly; include getopt.h or
+    unistd.h instead.  Unlike most bits headers, it does not have
+    a protective #error, because the guard macro for getopt.h in
+@@ -33,7 +41,7 @@
+    Also, when 'ordering' is RETURN_IN_ORDER,
+    each non-option ARGV-element is returned here.  */
+ 
+-extern char *optarg;
++extern DLL_VARIABLE char *optarg;
+ 
+ /* Index in ARGV of the next element to be scanned.
+    This is used for communication to and from the caller
+@@ -47,16 +55,16 @@
+    Otherwise, 'optind' communicates from one call to the next
+    how much of ARGV has been scanned so far.  */
+ 
+-extern int optind;
++extern DLL_VARIABLE int optind;
+ 
+ /* Callers store zero here to inhibit the error message 'getopt' prints
+    for unrecognized options.  */
+ 
+-extern int opterr;
++extern DLL_VARIABLE int opterr;
+ 
+ /* Set to an option character which was unrecognized.  */
+ 
+-extern int optopt;
++extern DLL_VARIABLE int optopt;
+ 
+ /* Get definitions and prototypes for functions to process the
+    arguments in ARGV (ARGC of them, minus the program name) for
diff --git a/tta/gnulib-local/modules/tta-misc b/tta/gnulib-local/modules/tta-misc
new file mode 100644
index 0000000000..23058267a3
--- /dev/null
+++ b/tta/gnulib-local/modules/tta-misc
@@ -0,0 +1,17 @@
+Description:
+
+Files:
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+AM_CPPFLAGS += -DIN_LIBGNU
+
+Include:
+
+License:
+LGPLv2+
+
+Maintainer:
diff --git a/tta/gnulib/m4/gnulib-cache.m4 b/tta/gnulib/m4/gnulib-cache.m4
index 2c100ea1e2..7570af1684 100644
--- a/tta/gnulib/m4/gnulib-cache.m4
+++ b/tta/gnulib/m4/gnulib-cache.m4
@@ -28,6 +28,7 @@
 
 # Specification in the form of a command-line invocation:
 # gnulib-tool --import \
+#  --local-dir=gnulib-local \
 #  --lib=libgnu \
 #  --source-base=gnulib/lib \
 #  --m4-base=gnulib/m4 \
@@ -47,6 +48,7 @@
 #  setenv \
 #  strchrnul \
 #  strndup \
+#  tta-misc \
 #  uchar \
 #  unicase/u8-tolower \
 #  unicase/u8-toupper \
@@ -75,7 +77,7 @@
 #  vasprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
-gl_LOCAL_DIR([])
+gl_LOCAL_DIR([gnulib-local])
 gl_MODULES([
   euidaccess
   getline
@@ -87,6 +89,7 @@ gl_MODULES([
   setenv
   strchrnul
   strndup
+  tta-misc
   uchar
   unicase/u8-tolower
   unicase/u8-toupper
-- 
2.52.0

  • Re: ... Eli Zaretskii
    • ... Eli Zaretskii
      • ... pertusus
        • ... Eli Zaretskii
          • ... Eli Zaretskii
            • ... Bruno Haible via Bug reports for the GNU Texinfo documentation system
              • ... Eli Zaretskii
              • ... Eli Zaretskii
              • ... Gavin Smith
              • ... pertusus
              • ... Bruno Haible via Bug reports for the GNU Texinfo documentation system
              • ... pertusus
              • ... Bruno Haible via Bug reports for the GNU Texinfo documentation system
              • ... pertusus
            • ... pertusus
            • ... Gavin Smith
        • ... pertusus
          • ... Eli Zaretskii
            • ... Gavin Smith
              • ... pertusus
              • ... Eli Zaretskii

Reply via email to