Explorar o código

[mini] Use C++ linker iff building C++ that needs the C++ runtime (#12266)

* [mini] Use C++ linker iff building C++ that needs the C++ runtime

(This has nothing to do with --enable-cxx.  This is about our LLVM .cpp files).

Explicitly set the linker for libmini.  The issue is that the automatic
linker selection (See
https://www.gnu.org/software/automake/manual/html_node/How-the-Linker-is-Chosen.html)
looks at all the _SOURCES for a target, even those that are only
conditionally added, even if the condition is false.  So because we sometimes
build mini-llvm-cpp.cpp we always get the c++ linker.  But that's not what we
want.

The goal is:
 - if there's any C++ code included into mono (either the shared lib or a
   program) that needs the C++ runtime library, ensure that we link using the C++
   linker.  This was already true, we just need to make sure it stays true.
 - if mono is built in such a way that it has no C++ code in it (that needs the
   C++ runtime library), ensure that we link with the C linker and without
   including the C++ runtime library.
   This will address issues like https://github.com/mono/mono/issues/12060

We do this in two steps:

1. We split out all the c++ source code to libmini-cxx.la and include that into
   libmini.la.

   That's enough to force C++ linking if libmini-cxx.la has any code in it.  If
   there's no C++ code (right now that means there's no --enable-llvm or
   --enable-llvm-runtime), we don't add libmini-cxx.la and all the C source in
   libmini links in the normal manner.

2. We have a hack where we sometimes include libmono.a (the static library)
   into the mono executable.  In that case, we could forget about the C++
   linker (which leads to build failures because llvm uses all the C++ runtime
   library stuff that we forgot to link in).

   So we use the "nodist_EXTRA_..._SOURCES=dummy.cpp` hack to make it look like
   the mono executable has C++ source, which in turn forces the use of the C++
   linker.

   The conditional logic here has to match exactly what we do for deciding
   whether to add libmini-cxx.la into libmini.la.  If we do, then force the use
   the C++ linker here.

   It may seem like another option is to use something like
   `mono_boehm_LINK=$(CXXLINK)` to set a target-specific linker.  But this is
   bad, actually, because in that case we will drop the `..._LDFLAGS` and other
   linker flags unless we're very diligent to include all of them.  The
   `nodist_EXTRA_..._SOURCES` hack is more resilient because automake will
   ensure that all the flags are kept.

* [llvm,wasm] Don't add -lstdc++ in llvm_config.mk

Leave it to the linker.

This is needed when building wasm cross compilers for windows which pass
-static-libstdc++ to configure.  As a result we would get duplicate symbols by
linking against a static libstdc++.a and also the export stubs of libstdc++.dll

In mini, link monow using the C++ linker same as with mono by using the nodist_EXTRA_..._SOURCES
trick.

In wasm, pass -static-libstdc++ to CXXFLAGS, not LDFLAGS.  c++ linking picks up
CXXFLAGS anyway, and -static-libstdc++ has no effect on the C linker and it
doesn't affect explicit -lstdc++ flags anyway.
Aleksey Kliger (λgeek) %!s(int64=7) %!d(string=hai) anos
pai
achega
988f4a2147
Modificáronse 3 ficheiros con 55 adicións e 7 borrados
  1. 2 2
      llvm/build_llvm_config.sh
  2. 50 2
      mono/mini/Makefile.am.in
  3. 3 3
      sdks/builds/wasm.mk

+ 2 - 2
llvm/build_llvm_config.sh

@@ -139,10 +139,10 @@ fi
 
 if [[ $llvm_config_cflags = *"stdlib=libc++"* ]]; then
 	llvm_libc_c="-stdlib=libc++"
-	llvm_libc_link="-lc++"
+	# llvm_libc_link="-lc++"
 else
 	llvm_libc_c=""
-	llvm_libc_link="-lstdc++"
+	# llvm_libc_link="-lstdc++"
 fi
 
 if [[ $llvm_host_win32 = 1 ]]; then

+ 50 - 2
mono/mini/Makefile.am.in

@@ -260,6 +260,30 @@ mono_sgen_LDADD = \
 
 mono_sgen_LDFLAGS = $(static_flags) $(monobinldflags) $(monobin_platform_ldflags) 
 
+
+if STATIC_MONO
+# Force the C++ linker if we linked mono against libmono.a and if we know that
+# libmono.a has C++ code in it.
+#
+# The conditional logic here has to match exactly what we do for deciding
+# whether to add libmini-cxx.la into libmini.la.  If we do, then force the use
+# of the C++ linker here.
+#
+# Have to use the nodist_EXTRA_..._SOURCES hack because if we set
+#  ..._LINK=$(CXXLINK) directly, it will not use the ..._LDFLAGS and other
+#  linker flags and so we would end up with linker errors because we wouldn't pick up
+#  monobin_platform_ldflags, for example.
+if ENABLE_LLVM
+nodist_EXTRA_mono_boehm_SOURCES = dummy.cpp
+nodist_EXTRA_mono_sgen_SOURCES = dummy.cpp
+else
+if ENABLE_LLVM_RUNTIME
+nodist_EXTRA_mono_boehm_SOURCES = dummy.cpp
+nodist_EXTRA_mono_sgen_SOURCES = dummy.cpp
+endif
+endif
+endif
+
 if BITCODE
 libmonoldflags += -no-undefined
 endif
@@ -290,10 +314,12 @@ if SUPPORT_BOEHM
 monow_LDADD = $(mono_boehm_LDADD)
 monow_LDFLAGS = $(mono_boehm_LDFLAGS) -mwindows
 monow_SOURCES = $(mono_boehm_SOURCES)
+nodist_EXTRA_monow_SOURCES = $(nodist_EXTRA_mono_boehm_SOURCES)
 else
 monow_LDADD = $(mono_sgen_LDADD)
 monow_LDFLAGS = $(mono_sgen_LDFLAGS) -mwindows
 monow_SOURCES = $(mono_sgen_SOURCES)
+nodist_EXTRA_monow_SOURCES = $(nodist_EXTRA_mono_sgen_SOURCES)
 endif
 endif
 
@@ -386,10 +412,12 @@ if ENABLE_LLVM
 if LOADED_LLVM
 llvm_sources = \
 	mini-llvm-loaded.c
+llvm_cxx_sources =
 else
 llvm_sources = \
 	mini-llvm.c		\
-	mini-llvm-loaded.c \
+	mini-llvm-loaded.c
+llvm_cxx_sources = \
 	mini-llvm-cpp.cpp \
 	llvm-jit.cpp
 endif
@@ -704,8 +732,28 @@ endif
 # This library is shared between mono and mono-sgen, since the code in mini/ doesn't contain
 # compile time dependencies on boehm/sgen.
 #
-libmini_la_SOURCES = $(common_sources) $(llvm_sources) $(llvm_runtime_sources) $(arch_sources) $(os_sources)
+libmini_la_SOURCES = $(common_sources) $(llvm_sources) $(arch_sources) $(os_sources)
 libmini_la_CFLAGS = $(AM_CFLAGS) @CXX_ADD_CFLAGS@
+if ENABLE_LLVM
+libmini_la_LIBADD = libmini-cxx.la
+noinst_LTLIBRARIES += libmini-cxx.la
+else
+if ENABLE_LLVM_RUNTIME
+libmini_la_LIBADD = libmini-cxx.la
+noinst_LTLIBRARIES += libmini-cxx.la
+endif
+endif
+
+# Split out the C++ sources so that if they're not used, libmini will be linked
+# with the C linker.  The issue is that the automatic linker selection (See
+# https://www.gnu.org/software/automake/manual/html_node/How-the-Linker-is-Chosen.html)
+# looks at all the _SOURCES for a target, even those that are only
+# conditionally added, even if the condition is false.  So because we sometimes
+# build mini-llvm-cpp.cpp we always get the c++ linker.  But that's not what we
+# want.
+libmini_cxx_la_SOURCES = $(llvm_cxx_sources) $(llvm_runtime_sources)
+libmini_cxx_la_CFLAGS = $(AM_CFLAGS) @CXX_ADD_CFLAGS@
+
 
 libmonoboehm_2_0_la_SOURCES =
 libmonoboehm_2_0_la_CFLAGS = $(mono_boehm_CFLAGS) @CXX_ADD_CFLAGS@

+ 3 - 3
sdks/builds/wasm.mk

@@ -150,12 +150,12 @@ _wasm-$(1)_CFLAGS= \
 _wasm-$(1)_CXXFLAGS= \
 	$$(if $$(RELEASE),,-DDEBUG_CROSS) \
 	-static \
-	-static-libgcc
+	-static-libgcc \
+	-static-libstdc++
 
 _wasm-$(1)_LDFLAGS= \
 	-static \
-	-static-libgcc \
-	-static-libstdc++
+	-static-libgcc
 
 _wasm-$(1)_CONFIGURE_FLAGS= \
 	--disable-boehm \