This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[libgfortran] Patch to handle statically linked libgfortran


:ADDPATCH testsuite:

Attached patch fixes a bug (PR libfortran/22298) where the libgfortran constructor function wasn't linked in when libgfortran was statically linked. The patch itself is straightforward and well commented, and it could go under the "obvious rule".

I added a test for the testsuite, conditionnal on a new effective target. Could someone OK this part?

Thanks,
FX
2005-10-30  Francois-Xavier Coudert  <coudert@clipper.ens.fr>

	PR libfortran/22298
	* runtime/main.c (stupid_function_name_for_static_linking): New
	function.
	* runtime/error.c (internal_error): Call
	stupid_function_name_for_static_linking.
	* libgfortran.h: Add prototype for
	stupid_function_name_for_static_linking.


2005-10-30  Francois-Xavier Coudert  <coudert@clipper.ens.fr>

	PR libfortran/22298
	* gcc/testsuite/lib/target-supports.exp
	(check_effective_target_static_libgfortran): New
	static_libgfortran effective target.
	* gcc/testsuite/gfortran.dg/static_linking_1.f: New test.
	* gcc/testsuite/gfortran.dg/static_linking_1.c: New file.
Index: libgfortran/runtime/main.c
===================================================================
--- libgfortran/runtime/main.c	(revision 105991)
+++ libgfortran/runtime/main.c	(working copy)
@@ -35,6 +35,14 @@
 
 #include "libgfortran.h"
 
+/* Stupid function to be sure the constructor is always linked in, even
+   in the case of static linking.  See PR libfortran/22298 for details.  */
+void
+stupid_function_name_for_static_linking (void)
+{
+  return;
+}
+
 /* This is the offset (in bytes) required to cast from logical(8)* to
    logical(4)*. and still get the same result.  Will be 0 for little-endian
    machines and 4 for big-endian machines.  */
Index: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c	(revision 105991)
+++ libgfortran/runtime/error.c	(working copy)
@@ -353,6 +353,13 @@
   recursion_check ();
   show_locus ();
   st_printf ("Internal Error: %s\n", message);
+
+  /* This function call is here to get the main.o object file included
+     when linking statically. This works because error.o is supposed to
+     be always linked in (and the function call is in internal_error
+     because hopefully it doesn't happen too often).  */
+  stupid_function_name_for_static_linking();
+
   sys_exit (3);
 }
 
Index: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h	(revision 105991)
+++ libgfortran/libgfortran.h	(working copy)
@@ -434,6 +434,9 @@
 
 /* main.c */
 
+extern void stupid_function_name_for_static_linking (void);
+internal_proto(stupid_function_name_for_static_linking);
+
 extern void library_start (void);
 internal_proto(library_start);
 
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 105991)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -522,6 +522,59 @@
     return $et_fortran_large_int_saved
 }
 
+# Return 1 if we can statically link libgfortran, 0 otherwise.
+#
+# When the target name changes, replace the cached result.
+
+proc check_effective_target_static_libgfortran { } {
+    global et_static_libgfortran
+    global et_static_libgfortran_target_name
+    global tool
+
+    if { ![info exists et_static_libgfortran_target_name] } {
+	set et_static_libgfortran_target_name ""
+    }
+
+    # If the target has changed since we set the cached value, clear it.
+    set current_target [current_target_name]
+    if { $current_target != $et_static_libgfortran_target_name } {
+	verbose "check_effective_target_static_libgfortran: `$et_static_libgfortran_target_name' `$current_target'" 2
+	set et_static_libgfortran_target_name $current_target
+	if [info exists et_static_libgfortran_saved] {
+	    verbose "check_effective_target_static_libgfortran: removing cached result" 2
+	    unset et_static_libgfortran_saved
+	}
+    }
+
+    if [info exists et_static_libgfortran_saved] {
+	verbose "check_effective_target_static_libgfortran returning saved $et_static_libgfortran_saved" 2
+    } else {
+	set et_static_libgfortran_saved 0
+
+	# Set up, compile, and execute a test program using large integer
+	# kinds.  Include the current process ID in the file names to
+	# prevent conflicts with invocations for multiple testsuites.
+	set src static[pid].f
+        set exe static[pid].x
+
+	set f [open $src "w"]
+	puts $f "      print *, 'test'"
+	puts $f "      end"
+	close $f
+
+	verbose "check_effective_target_static_libgfortran compiling testfile $src" 2
+	set lines [${tool}_target_compile $src $exe executable ""]
+	file delete $src
+
+	if [string match "" $lines] then {
+	    # No error message, compilation succeeded.
+	    set et_static_libgfortran_saved 1
+	}
+    }
+
+    return $et_static_libgfortran_saved
+}
+
 # Return 1 if the target supports executing AltiVec instructions, 0
 # otherwise.  Cache the result.
 
Index: gcc/testsuite/gfortran.dg/static_linking_1.c
===================================================================
--- gcc/testsuite/gfortran.dg/static_linking_1.c	(revision 0)
+++ gcc/testsuite/gfortran.dg/static_linking_1.c	(revision 0)
@@ -0,0 +1,6 @@
+extern void f_(void);
+int main (void)
+{
+  f_();
+  return 0;
+}
Index: gcc/testsuite/gfortran.dg/static_linking_1.f
===================================================================
--- gcc/testsuite/gfortran.dg/static_linking_1.f	(revision 0)
+++ gcc/testsuite/gfortran.dg/static_linking_1.f	(revision 0)
@@ -0,0 +1,11 @@
+! { dg-require-effective-target static_libgfortran }
+! { dg-do run }
+! { dg-additional-sources static_linking_1.c }
+! { dg-options "-static" }
+!
+! This testcase checks that statically linking libgfortran with C main()
+! really calls the constructor function
+! PR libfortran/22298
+      subroutine f
+        print *, "subroutine output"
+      end

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]