]> Cypherpunks.ru repositories - gostls13.git/commitdiff
misc/cgo/fortran: convert to Go test
authorAustin Clements <austin@google.com>
Fri, 14 Oct 2022 13:51:52 +0000 (09:51 -0400)
committerAustin Clements <austin@google.com>
Mon, 17 Oct 2022 15:15:37 +0000 (15:15 +0000)
Currently, the entry-point to this test is a Bash script that smoke
tests the FORTRAN compiler and then runs a FORTRAN-containing Go test.
This CL rearranges things so a pure Go Go test smoke tests the FORTRAN
compiler and then runs a non-test FORTRAN-containing Go binary.

While we're here, we fix a discrepancy when the host is GOARCH=amd64,
but the target is GOARCH=386. Previously, we would pick the wrong
libgfortran path because we didn't account for the cross-compilation,
causing the link to fail. Except for some reason this was ignored and
the test nevertheless "passed". In the new test we're a little more
strict, so this build failure will cause the test to fail, so we add a
little logic to account for cross-compilation with the host toolchain.

For #37486.

Change-Id: Ie6f70066885d6fbb4e1b5a2b1e13b85dee5b359b
Reviewed-on: https://go-review.googlesource.com/c/go/+/443069
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Austin Clements <austin@google.com>

misc/cgo/fortran/fortran_test.go
misc/cgo/fortran/test.bash [deleted file]
misc/cgo/fortran/testdata/testprog/answer.f90 [moved from misc/cgo/fortran/answer.f90 with 100% similarity]
misc/cgo/fortran/testdata/testprog/fortran.go [moved from misc/cgo/fortran/fortran.go with 58% similarity]
src/cmd/dist/test.go

index d0cb9f22463007730abdb458084e176bc353b50f..4604a4dce3e02799764378b3474d22c798d00091 100644 (file)
@@ -1,13 +1,81 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2022 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package fortran
 
-import "testing"
+import (
+       "fmt"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "testing"
+)
 
 func TestFortran(t *testing.T) {
-       if a := TheAnswer(); a != 42 {
-               t.Errorf("Unexpected result for The Answer. Got: %d Want: 42", a)
+       // Find the FORTRAN compiler.
+       fc := os.Getenv("FC")
+       if fc == "" {
+               fc, _ = exec.LookPath("gfortran")
+       }
+       if fc == "" {
+               t.Skip("fortran compiler not found (try setting $FC)")
+       }
+
+       var fcExtra []string
+       if strings.Contains(fc, "gfortran") {
+               // TODO: This duplicates but also diverges from logic from cmd/go
+               // itself. For example, cmd/go merely adds -lgfortran without the extra
+               // library path work. If this is what's necessary to run gfortran, we
+               // should reconcile the logic here and in cmd/go.. Maybe this should
+               // become a cmd/go script test to share that logic.
+
+               // Add -m32 if we're targeting 386, in case this is a cross-compile.
+               if runtime.GOARCH == "386" {
+                       fcExtra = append(fcExtra, "-m32")
+               }
+
+               // Find libgfortran. If the FORTRAN compiler isn't bundled
+               // with the C linker, this may be in a path the C linker can't
+               // find on its own. (See #14544)
+               libExt := "so"
+               switch runtime.GOOS {
+               case "darwin":
+                       libExt = "dylib"
+               case "aix":
+                       libExt = "a"
+               }
+               libPath, err := exec.Command(fc, append([]string{"-print-file-name=libgfortran." + libExt}, fcExtra...)...).CombinedOutput()
+               if err != nil {
+                       t.Errorf("error invoking %s: %s", fc, err)
+               }
+               libDir := filepath.Dir(string(libPath))
+               cgoLDFlags := os.Getenv("CGO_LDFLAGS")
+               cgoLDFlags += " -L " + libDir
+               if runtime.GOOS != "aix" {
+                       cgoLDFlags += " -Wl,-rpath," + libDir
+               }
+               t.Logf("CGO_LDFLAGS=%s", cgoLDFlags)
+               os.Setenv("CGO_LDFLAGS", cgoLDFlags)
+
+       }
+
+       // Do a test build that doesn't involve Go FORTRAN support.
+       fcArgs := append([]string{"helloworld/helloworld.f90", "-o", "/dev/null"}, fcExtra...)
+       t.Logf("%s %s", fc, fcArgs)
+       if err := exec.Command(fc, fcArgs...).Run(); err != nil {
+               t.Skipf("skipping Fortran test: could not build helloworld.f90 with %s: %s", fc, err)
+       }
+
+       // Finally, run the actual test.
+       t.Log("go", "run", "./testdata/testprog")
+       out, err := exec.Command("go", "run", "./testdata/testprog").CombinedOutput()
+       if err == nil && string(out) != "ok\n" {
+               err = fmt.Errorf("expected ok")
+       }
+       if err != nil {
+               t.Errorf("%s\nOutput:\n%s", err, string(out))
        }
 }
diff --git a/misc/cgo/fortran/test.bash b/misc/cgo/fortran/test.bash
deleted file mode 100755 (executable)
index 2b61730..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2016 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# This directory is intended to test the use of Fortran with cgo.
-
-set -e
-
-FC=$1
-
-goos=$(go env GOOS)
-
-libext="so"
-if [ "$goos" = "darwin" ]; then
-       libext="dylib"
-elif [ "$goos" = "aix" ]; then
-       libtext="a"
-fi
-
-case "$FC" in
-*gfortran*)
-  libpath=$(dirname $($FC -print-file-name=libgfortran.$libext))
-  if [ "$goos" != "aix" ]; then
-         RPATH_FLAG="-Wl,-rpath,$libpath"
-  fi
-  export CGO_LDFLAGS="$CGO_LDFLAGS $RPATH_FLAG -L $libpath"
-  ;;
-esac
-
-if ! $FC helloworld/helloworld.f90 -o /dev/null >& /dev/null; then
-  echo "skipping Fortran test: could not build helloworld.f90 with $FC"
-  exit 0
-fi
-rm -f main.exe
-
-status=0
-
-if ! go test; then
-  echo "FAIL: go test"
-  status=1
-fi
-
-exit $status
similarity index 58%
rename from misc/cgo/fortran/fortran.go
rename to misc/cgo/fortran/testdata/testprog/fortran.go
index 0079b535d94ae8be9e7d3a759dcb04393efeeddd..d8004ceb6de9a6ada02f9ea6bbd4bc4af846b107 100644 (file)
@@ -2,11 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package fortran
+package main
 
 // int the_answer();
 import "C"
+import "os"
 
 func TheAnswer() int {
        return int(C.the_answer())
 }
+
+func main() {
+       if a := TheAnswer(); a != 42 {
+               println("Unexpected result for The Answer. Got:", a, " Want: 42")
+               os.Exit(1)
+       }
+       println("ok")
+}
index fa79e7e8ae1b9aefdbb04eb44a4ff1efaac34302..1663ff8c94868e4d3678338dfb08318d1d63f878 100644 (file)
@@ -746,19 +746,8 @@ func (t *tester) registerTests() {
                // Disabled on iOS. golang.org/issue/15919
                t.registerHostTest("cgo_stdio", "../misc/cgo/stdio", "misc/cgo/stdio", ".")
                t.registerHostTest("cgo_life", "../misc/cgo/life", "misc/cgo/life", ".")
-               fortran := os.Getenv("FC")
-               if fortran == "" {
-                       fortran, _ = exec.LookPath("gfortran")
-               }
-               if t.hasBash() && goos != "android" && fortran != "" {
-                       t.tests = append(t.tests, distTest{
-                               name:    "cgo_fortran",
-                               heading: "../misc/cgo/fortran",
-                               fn: func(dt *distTest) error {
-                                       t.addCmd(dt, "misc/cgo/fortran", "./test.bash", fortran)
-                                       return nil
-                               },
-                       })
+               if goos != "android" {
+                       t.registerHostTest("cgo_fortran", "../misc/cgo/fortran", "misc/cgo/fortran", ".")
                }
                if t.hasSwig() && goos != "android" {
                        t.tests = append(t.tests, distTest{