[PATCH] rust: Do not link with libdl and libpthread unconditionally

Arthur Cohen arthur.cohen@embecosm.com
Fri May 31 10:24:34 GMT 2024


Hi Richard,

On 4/30/24 09:55, Richard Biener wrote:
> On Fri, Apr 19, 2024 at 11:49 AM Arthur Cohen <arthur.cohen@embecosm.com> wrote:
>>
>> Hi everyone,
>>
>> This patch checks for the presence of dlopen and pthread_create in libc. If that is not the
>> case, we check for the existence of -ldl and -lpthread, as these libraries are required to
>> link the Rust runtime to our Rust frontend.
>>
>> If these libs are not present on the system, then we disable the Rust frontend.
>>
>> This was tested on x86_64, in an environment with a recent GLIBC and in a container with GLIBC
>> 2.27.
>>
>> Apologies for sending it in so late.
> 
> For example GCC_ENABLE_PLUGINS simply does
> 
>       # Check -ldl
>       saved_LIBS="$LIBS"
>       AC_SEARCH_LIBS([dlopen], [dl])
>       if test x"$ac_cv_search_dlopen" = x"-ldl"; then
>         pluginlibs="$pluginlibs -ldl"
>       fi
>       LIBS="$saved_LIBS"
> 
> which I guess would also work for pthread_create?  This would simplify
> the code a bit.

Thanks a lot for the review. I've udpated the patch's content in 
configure.ac per your suggestion. Tested similarly on x86_64 and in a 
container with libc 2.27

 From 00669b600a75743523c358ee41ab999b6e9fa0f6 Mon Sep 17 00:00:00 2001
From: Arthur Cohen <arthur.cohen@embecosm.com>
Date: Fri, 12 Apr 2024 13:52:18 +0200
Subject: [PATCH] rust: Do not link with libdl and libpthread unconditionally

ChangeLog:

	* Makefile.tpl: Add CRAB1_LIBS variable.
	* Makefile.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: Check if -ldl and -lpthread are needed, and if so, add
	them to CRAB1_LIBS.

gcc/rust/ChangeLog:

	* Make-lang.in: Remove overazealous LIBS = -ldl -lpthread line, link
	crab1 against CRAB1_LIBS.
---
  Makefile.in           |   3 +
  Makefile.tpl          |   3 +
  configure             | 154 ++++++++++++++++++++++++++++++++++++++++++
  configure.ac          |  41 +++++++++++
  gcc/rust/Make-lang.in |   6 +-
  5 files changed, 203 insertions(+), 4 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index edb0c8a9a42..1753fb6b862 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -197,6 +197,7 @@ HOST_EXPORTS = \
  	$(BASE_EXPORTS) \
  	CC="$(CC)"; export CC; \
  	ADA_CFLAGS="$(ADA_CFLAGS)"; export ADA_CFLAGS; \
+	CRAB1_LIBS="$(CRAB1_LIBS)"; export CRAB1_LIBS; \
  	CFLAGS="$(CFLAGS)"; export CFLAGS; \
  	CONFIG_SHELL="$(SHELL)"; export CONFIG_SHELL; \
  	CXX="$(CXX)"; export CXX; \
@@ -450,6 +451,8 @@ GOCFLAGS = $(CFLAGS)
  GDCFLAGS = @GDCFLAGS@
  GM2FLAGS = $(CFLAGS)

+CRAB1_LIBS = @CRAB1_LIBS@
+
  PKG_CONFIG_PATH = @PKG_CONFIG_PATH@

  GUILE = guile
diff --git a/Makefile.tpl b/Makefile.tpl
index adbcbdd1d57..4aeaad3c1a5 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -200,6 +200,7 @@ HOST_EXPORTS = \
  	$(BASE_EXPORTS) \
  	CC="$(CC)"; export CC; \
  	ADA_CFLAGS="$(ADA_CFLAGS)"; export ADA_CFLAGS; \
+	CRAB1_LIBS="$(CRAB1_LIBS)"; export CRAB1_LIBS; \
  	CFLAGS="$(CFLAGS)"; export CFLAGS; \
  	CONFIG_SHELL="$(SHELL)"; export CONFIG_SHELL; \
  	CXX="$(CXX)"; export CXX; \
@@ -453,6 +454,8 @@ GOCFLAGS = $(CFLAGS)
  GDCFLAGS = @GDCFLAGS@
  GM2FLAGS = $(CFLAGS)

+CRAB1_LIBS = @CRAB1_LIBS@
+
  PKG_CONFIG_PATH = @PKG_CONFIG_PATH@

  GUILE = guile
diff --git a/configure b/configure
index 02b435c1163..a9ea5258f0f 100755
--- a/configure
+++ b/configure
@@ -690,6 +690,7 @@ extra_host_zlib_configure_flags
  extra_host_libiberty_configure_flags
  stage1_languages
  host_libs_picflag
+CRAB1_LIBS
  PICFLAG
  host_shared
  gcc_host_pie
@@ -8826,6 +8827,139 @@ fi



+# Rust requires -ldl and -lpthread if you are using an old glibc that 
does not include them by
+# default, so we check for them here
+
+missing_rust_dynlibs=none
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library 
containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library 
containing pthread_create" >&5
+$as_echo_n "checking for library containing pthread_create... " >&6; }
+if ${ac_cv_search_pthread_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_pthread_create=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_pthread_create+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_pthread_create+:} false; then :
+
+else
+  ac_cv_search_pthread_create=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$ac_cv_search_pthread_create" >&5
+$as_echo "$ac_cv_search_pthread_create" >&6; }
+ac_res=$ac_cv_search_pthread_create
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+if test $ac_cv_search_dlopen = -ldl; then
+    CRAB1_LIBS="$CRAB1_LIBS -ldl"
+elif test $ac_cv_search_dlopen = no; then
+    missing_rust_dynlibs="libdl"
+fi
+
+if test $ac_cv_search_pthread_create = -lpthread; then
+    CRAB1_LIBS="$CRAB1_LIBS -lpthread"
+elif test $ac_cv_search_pthread_crate = no; then
+    missing_rust_dynlibs="$missing_rust_dynlibs, libpthread"
+fi
+
+CRAB1_LIBS="$CRAB1_LIBS"
+
+
  # If we are building PIC/PIE host executables, and we are building 
dependent
  # libs (e.g. GMP) in-tree those libs need to be configured to generate PIC
  # code.
@@ -9066,6 +9200,26 @@ $as_echo "$as_me: WARNING: GDC is required to 
build $language" >&2;}
              ;;
          esac

+        # Disable Rust if we are missing some required C libraries for 
the Rust runtime.
+        case ${add_this_lang}:${language}:${missing_rust_dynlibs} in
+          *:rust:none)
+            # Nothing to do - we're not missing any C libraries
+            ;;
+          yes:rust:*)
+            as_fn_error $? "some C libraries are required to build 
$language: $missing_rust_dynlibs" "$LINENO" 5
+            add_this_lang=unsupported
+            ;;
+          all:rust:*)
+            { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: some C 
libraries are required to build $language: $missing_rust_dynlibs" >&5
+$as_echo "$as_me: WARNING: some C libraries are required to build 
$language: $missing_rust_dynlibs" >&2;}
+            add_this_lang=unsupported
+            ;;
+          *:rust:*)
+            # Silently disable.
+            add_this_lang=unsupported
+            ;;
+        esac
+
          # Disable jit if -enable-host-shared not specified
          # but not if building for Mingw. All code in Windows
          # is position independent code (PIC).
diff --git a/configure.ac b/configure.ac
index 1a19c07a27b..adb738ac346 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2036,6 +2036,28 @@ fi

  AC_SUBST(PICFLAG)

+# Rust requires -ldl and -lpthread if you are using an old glibc that 
does not include them by
+# default, so we check for them here
+
+missing_rust_dynlibs=none
+
+AC_SEARCH_LIBS([dlopen], [dl])
+AC_SEARCH_LIBS([pthread_create], [pthread])
+
+if test $ac_cv_search_dlopen = -ldl; then
+    CRAB1_LIBS="$CRAB1_LIBS -ldl"
+elif test $ac_cv_search_dlopen = no; then
+    missing_rust_dynlibs="libdl"
+fi
+
+if test $ac_cv_search_pthread_create = -lpthread; then
+    CRAB1_LIBS="$CRAB1_LIBS -lpthread"
+elif test $ac_cv_search_pthread_crate = no; then
+    missing_rust_dynlibs="$missing_rust_dynlibs, libpthread"
+fi
+
+AC_SUBST(CRAB1_LIBS, "$CRAB1_LIBS")
+
  # If we are building PIC/PIE host executables, and we are building 
dependent
  # libs (e.g. GMP) in-tree those libs need to be configured to generate PIC
  # code.
@@ -2273,6 +2295,25 @@ if test -d ${srcdir}/gcc; then
              ;;
          esac

+        # Disable Rust if we are missing some required C libraries for 
the Rust runtime.
+        case ${add_this_lang}:${language}:${missing_rust_dynlibs} in
+          *:rust:none)
+            # Nothing to do - we're not missing any C libraries
+            ;;
+          yes:rust:*)
+            AC_MSG_ERROR([some C libraries are required to build 
$language: $missing_rust_dynlibs])
+            add_this_lang=unsupported
+            ;;
+          all:rust:*)
+            AC_MSG_WARN([some C libraries are required to build 
$language: $missing_rust_dynlibs])
+            add_this_lang=unsupported
+            ;;
+          *:rust:*)
+            # Silently disable.
+            add_this_lang=unsupported
+            ;;
+        esac
+
          # Disable jit if -enable-host-shared not specified
          # but not if building for Mingw. All code in Windows
          # is position independent code (PIC).
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index dd94c9b5eab..edcf2ee4c7b 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -54,8 +54,6 @@ GCCRS_D_OBJS = \
     rust/rustspec.o \
     $(END)

-LIBS += -ldl -lpthread
-
  gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a 
$(LIBDEPS)
  	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
  	  $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
@@ -234,7 +232,7 @@ crab1$(exeext): $(RUST_ALL_OBJS) attribs.o 
$(BACKEND) $(LIBDEPS) $(LIBPROC_MACRO
  	@$(call LINK_PROGRESS,$(INDEX.rust),start)
  	+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
  	      $(RUST_ALL_OBJS) attribs.o $(BACKEND) \
-	      $(LIBS) $(LIBPROC_MACRO_INTERNAL) $(LIBFORMAT_PARSER) 
$(LIBFFI_POLONIUS) \
+	      $(LIBS) $(CRAB1_LIBS) $(LIBPROC_MACRO_INTERNAL) 
$(LIBFORMAT_PARSER) $(LIBFFI_POLONIUS) \
   		  $(BACKENDLIBS)
  	@$(call LINK_PROGRESS,$(INDEX.rust),end)

@@ -496,4 +494,4 @@ rust/libffi_polonius.a: \
  	rust/checks/errors/borrowck/ffi-polonius/Cargo.toml \
  	$(wildcard $(srcdir)/rust/checks/errors/borrowck/ffi-polonius/src/*)
  	cargo build --manifest-path 
$(srcdir)/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml --release 
--target-dir rust/ffi-polonius
-	cp rust/ffi-polonius/release/libffi_polonius.a rust/libffi_polonius.a
\ No newline at end of file
+	cp rust/ffi-polonius/release/libffi_polonius.a rust/libffi_polonius.a
-- 
2.42.0



More information about the Gcc-rust mailing list