pkgsrc-Changes archive

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

CVS commit: pkgsrc/lang/ghc98



Module Name:    pkgsrc
Committed By:   pho
Date:           Wed Jan  8 10:17:27 UTC 2025

Modified Files:
        pkgsrc/lang/ghc98: Makefile bootstrap.mk buildlink3.mk
Added Files:
        pkgsrc/lang/ghc98/files: iconv-bridge.c inject-iconv-bridge.awk

Log Message:
lang/ghc98: A better workaround for the native vs. GNU iconv mixture problem

Instead of disallowing the existence of pkgsrc libiconv, we can have a
bridge between two implementations and use it during the build of the
stage-1 compiler. This way bootkits built with native iconv can co-exist
with GNU libiconv in ${BUILDLINK_DIR}/lib.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 pkgsrc/lang/ghc98/Makefile
cvs rdiff -u -r1.5 -r1.6 pkgsrc/lang/ghc98/bootstrap.mk
cvs rdiff -u -r1.3 -r1.4 pkgsrc/lang/ghc98/buildlink3.mk
cvs rdiff -u -r0 -r1.1 pkgsrc/lang/ghc98/files/iconv-bridge.c \
    pkgsrc/lang/ghc98/files/inject-iconv-bridge.awk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/lang/ghc98/Makefile
diff -u pkgsrc/lang/ghc98/Makefile:1.6 pkgsrc/lang/ghc98/Makefile:1.7
--- pkgsrc/lang/ghc98/Makefile:1.6      Tue Jul 30 11:38:42 2024
+++ pkgsrc/lang/ghc98/Makefile  Wed Jan  8 10:17:27 2025
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.6 2024/07/30 11:38:42 wiz Exp $
+# $NetBSD: Makefile,v 1.7 2025/01/08 10:17:27 pho Exp $
 # -----------------------------------------------------------------------------
 # Package metadata
 #
@@ -33,14 +33,6 @@ PKGSRC_OVERRIDE_MKPIE=       yes
 
 .include "options.mk"
 
-# The bootstrap kits are built with native iconv, and unfortunately ghc looks
-# in places it should not, so we have to do everything we can to avoid libiconv
-# being installed as it breaks the build due to iconv_*() vs libiconv_*().
-#
-.if ${OPSYS} == "Darwin"
-PREFER.iconv=  native
-.endif
-
 # -----------------------------------------------------------------------------
 # Distfiles
 #

Index: pkgsrc/lang/ghc98/bootstrap.mk
diff -u pkgsrc/lang/ghc98/bootstrap.mk:1.5 pkgsrc/lang/ghc98/bootstrap.mk:1.6
--- pkgsrc/lang/ghc98/bootstrap.mk:1.5  Thu Jun 20 12:49:39 2024
+++ pkgsrc/lang/ghc98/bootstrap.mk      Wed Jan  8 10:17:27 2025
@@ -1,4 +1,4 @@
-# $NetBSD: bootstrap.mk,v 1.5 2024/06/20 12:49:39 jperkin Exp $
+# $NetBSD: bootstrap.mk,v 1.6 2025/01/08 10:17:27 pho Exp $
 # -----------------------------------------------------------------------------
 # Select a bindist of bootstrapping compiler on a per-platform basis. See
 # ./files/BOOTSTRAP.md for details.
@@ -107,18 +107,13 @@ TOOLS_PLATFORM.cpp=       /usr/lib/cpp
 # Install a bootstrapping (stage-0) compiler directly into TOOLS_DIR so
 # that ./configure can find it.
 #
-USE_TOOLS+=    xzcat xz cpp patch # patch is for bootstrap.py
-
-# We must avoid gtar on Darwin because it ends up pulling in libiconv (see
-# Makefile for why that breaks things).  It's possible this is no longer
-# required anyway and has just been cargo-culted around since 2019.
-#
-.if ${OPSYS} == "Darwin"
-GHC_TAR=       ${TAR}
-.else
-USE_TOOLS+=    gtar
-GHC_TAR=       ${GTAR}
-.endif
+USE_TOOLS+=    xzcat xz cpp gtar patch
+# - patch is for bootstrap.py
+# - gtar isn't strictly necessary, but we need a tar(1) implementation
+#   supporting --use-compress-program (see
+#   patches/patch-hadrian_src_Rules_BinaryDist.hs). Since the option isn't
+#   guaranteed to be available everywhere, it's safer to explicitly pull in
+#   gtar.
 
 BOOT_ARCHIVE_TOP_DIR=  ${BOOT_ARCHIVE:C/\.tar\..z$//}
 pre-configure:
@@ -129,7 +124,7 @@ pre-configure:
        ${RUN}${MKDIR} ${WRKDIR}/bootkit-dist
        ${RUN}cd ${WRKDIR}/bootkit-dist && \
                ${XZCAT} ${DISTDIR}/${DIST_SUBDIR}/${BOOT_ARCHIVE} | \
-               ${GHC_TAR} -xf -
+               ${GTAR} -xf -
 
        @${PHASE_MSG} "Preparing bootstrapping compiler for ${PKGNAME}"
 # <kludge>
@@ -148,6 +143,21 @@ pre-configure:
                ${PKGSRC_SETENV} ${CONFIGURE_ENV} ${SH} ./configure \
                        --prefix=${TOOLS_DIR:Q} ${CONFIGURE_ARGS.boot} && \
                ${PKGSRC_SETENV} ${MAKE_ENV} ${MAKE_PROGRAM} install
+# <kludge>
+# A workaround for possible native iconv vs. GNU libiconv mismatch between
+# bootkits and the user's choice. See comments in ./files/iconv-bridge.c
+       ${RUN}${PKGSRC_SETENV} ${ALL_ENV} \
+               ${CC} -c ${FILESDIR}/iconv-bridge.c -o ${WRKDIR}/iconv-bridge-native.o -DNATIVE; \
+               ${CC} -c ${FILESDIR}/iconv-bridge.c -o ${WRKDIR}/iconv-bridge-gnu.o; \
+               ${AR} cr ${WRKDIR}/libiconv-bridge.a \
+                       ${WRKDIR}/iconv-bridge-native.o \
+                       ${WRKDIR}/iconv-bridge-gnu.o; \
+               ${RANLIB} ${WRKDIR}/libiconv-bridge.a
+       ${RUN}${AWK} -v WRKDIR=${WRKDIR} -f ${FILESDIR}/inject-iconv-bridge.awk \
+               < ${TOOLS_DIR}/bin/ghc > ${TOOLS_DIR}/bin/ghc.tmp
+       ${RUN}${MV} -f ${TOOLS_DIR}/bin/ghc.tmp ${TOOLS_DIR}/bin/ghc
+       ${RUN}${CHMOD} +x ${TOOLS_DIR}/bin/ghc
+# </kludge>
 
 
 # -----------------------------------------------------------------------------

Index: pkgsrc/lang/ghc98/buildlink3.mk
diff -u pkgsrc/lang/ghc98/buildlink3.mk:1.3 pkgsrc/lang/ghc98/buildlink3.mk:1.4
--- pkgsrc/lang/ghc98/buildlink3.mk:1.3 Sat Jun 22 12:16:40 2024
+++ pkgsrc/lang/ghc98/buildlink3.mk     Wed Jan  8 10:17:27 2025
@@ -1,4 +1,4 @@
-# $NetBSD: buildlink3.mk,v 1.3 2024/06/22 12:16:40 jperkin Exp $
+# $NetBSD: buildlink3.mk,v 1.4 2025/01/08 10:17:27 pho Exp $
 
 BUILDLINK_TREE+=       ghc
 
@@ -9,13 +9,7 @@ BUILDLINK_API_DEPENDS.ghc+=    ghc>=9.8.2
 BUILDLINK_ABI_DEPENDS.ghc+=    ghc>=9.8.2nb1
 BUILDLINK_PKGSRCDIR.ghc?=      ../../lang/ghc98
 
-.include "../../mk/bsd.fast.prefs.mk"
-
-# A regrettable hack.  See Makefile for background.
-.if ${OPSYS} != "Darwin"
 .include "../../converters/libiconv/buildlink3.mk"
-.endif
-
 .include "../../devel/libffi/buildlink3.mk"
 .include "../../devel/gmp/buildlink3.mk"
 .include "../../mk/curses.buildlink3.mk"

Added files:

Index: pkgsrc/lang/ghc98/files/iconv-bridge.c
diff -u /dev/null pkgsrc/lang/ghc98/files/iconv-bridge.c:1.1
--- /dev/null   Wed Jan  8 10:17:27 2025
+++ pkgsrc/lang/ghc98/files/iconv-bridge.c      Wed Jan  8 10:17:27 2025
@@ -0,0 +1,96 @@
+/* $NetBSD: iconv-bridge.c,v 1.1 2025/01/08 10:17:27 pho Exp $
+ *
+ * Our bootkits are built with native iconv, which means their
+ * libHSbase-*.a have references to native iconv symbols (iconv_open,
+ * iconv, ...). However, when PREFER.iconv is set to "pkgsrc", our
+ * infrastructure pulls in GNU libiconv in ${BUILDLINK_DIR}/lib. The
+ * stage-0 compiler (from bootkit) then attempts to link its libHSbase with
+ * GNU libiconv because the "base" library has metadata that instructs the
+ * compiler to link it with "-liconv"[*1], but this fails because they
+ * don't provide the same set of symbols[*2]. The same would happen when a
+ * bootkit is built with GNU libiconv but the user prefers native iconv.
+ *
+ * As a workaround we build a library containing symbols for both of them,
+ * and inject it into the command line of the stage-0 compiler to resolve
+ * missing symbols of the opposite side[*3]. We abuse the fact that
+ * <iconv.h> headers don't really affect ABI (aside from symbols names
+ * getting renamed) because the only type they define is iconv_t, which is
+ * just a pointer type. In theory implementations might provide iconv_t of
+ * different sizes and thus introducing ABI incompatibility, but in
+ * practice all of existing implementations define it as a pointer, so
+ * calling iconv() from libiconv() should be okay as long as we don't try
+ * to use two implementations at once.
+ *
+ * Note that this problem only affects the stage-0 compiler. The final
+ * product to be installed (stage-2) uses whatever implementation the user
+ * prefers, that is, this library is only used while building stage-1 but
+ * never used nor installed after that.
+ *
+ * [*1]: Only on platforms where native iconv is in a separate library but
+ *       not a part of libc. Darwin is one of such platforms, while NetBSD
+ *       is not.
+ *
+ * [*2]: jperkin@ reported this happened even if GNU libiconv was *not*
+ *       buildlinked. The mere existence of pkgsrc libiconv caused the same
+ *       issue. This is plausible, because GHC needs to record whatever
+ *       {C,CPP,LD}FLAGS used during build so that it can link user
+ *       programs with external libraries from pkgsrc, such as libffi and
+ *       libgmp. Though pho@ could not reproduce this exact failure mode.
+ *
+ * [*3]: -liconv-bridge must not appear before -lc, otherwise this breaks
+ *       platforms where native iconv is a part of libc, because dummy
+ *       definitions in the bridge gets preferred over the real ones.
+ */
+#include <sys/types.h>
+
+typedef void* iconv_t;
+
+/* Native iconv */
+iconv_t iconv_open(const char* tocode, const char* fromcode);
+int iconv_close(iconv_t cd);
+size_t iconv(iconv_t cd,
+             char** restrict src, size_t* restrict srcleft,
+             char** restrict dst, size_t* restrict dstleft);
+
+/* GNU iconv */
+iconv_t libiconv_open(const char* tocode, const char* fromcode);
+int libiconv_close(iconv_t cd);
+size_t libiconv(iconv_t cd,
+                char** restrict src, size_t* restrict srcleft,
+                char** restrict dst, size_t* restrict dstleft);
+
+/* These two variants cannot both be in the same module so we have to
+ * compile this file twice. Otherwise they will infinitely call each other
+ * and eventually segfault.
+ */
+#if NATIVE
+iconv_t iconv_open(const char* tocode, const char* fromcode) {
+    return libiconv_open(tocode, fromcode);
+}
+
+int iconv_close(iconv_t cd) {
+    return libiconv_close(cd);
+}
+
+size_t iconv(iconv_t cd,
+             char** restrict src, size_t* restrict srcleft,
+             char** restrict dst, size_t* restrict dstleft) {
+    return libiconv(cd, src, srcleft, dst, dstleft);
+}
+
+#else /* NATIVE */
+iconv_t libiconv_open(const char* tocode, const char* fromcode) {
+    return iconv_open(tocode, fromcode);
+}
+
+int libiconv_close(iconv_t cd) {
+    return iconv_close(cd);
+}
+
+size_t libiconv(iconv_t cd,
+                char** restrict src, size_t* restrict srcleft,
+                char** restrict dst, size_t* restrict dstleft) {
+    return iconv(cd, src, srcleft, dst, dstleft);
+}
+
+#endif /* NATIVE */
Index: pkgsrc/lang/ghc98/files/inject-iconv-bridge.awk
diff -u /dev/null pkgsrc/lang/ghc98/files/inject-iconv-bridge.awk:1.1
--- /dev/null   Wed Jan  8 10:17:27 2025
+++ pkgsrc/lang/ghc98/files/inject-iconv-bridge.awk     Wed Jan  8 10:17:27 2025
@@ -0,0 +1,22 @@
+# $NetBSD: inject-iconv-bridge.awk,v 1.1 2025/01/08 10:17:27 pho Exp $
+
+BEGIN {
+    replaced = 0;
+}
+
+/^exec / {
+    print $0 " -optl-lc -optl-L" WRKDIR " -optl-liconv-bridge";
+    replaced = 1;
+    next;
+}
+
+{
+    print $0;
+}
+
+END {
+    if (!replaced) {
+        print "[inject-iconv-bridge.awk] cannot find where to inject args" > "/dev/stderr";
+        exit 1;
+    }
+}



Home | Main Index | Thread Index | Old Index