Commit 1360648d by Ben Clayton

Regres: Switch to building with LLVM 10

This is automatically downloaded and cached. This is another step towards having hermetic builds, and is required for generating code coverage. Bug: b/152192800 Change-Id: I7c35d92f5844b41ad326e7b11a7725cc6ea9696b Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43111Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 3ca41df3
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"math" "math"
"os" "os"
...@@ -48,9 +49,11 @@ import ( ...@@ -48,9 +49,11 @@ import (
"../../consts" "../../consts"
"../../deqp" "../../deqp"
"../../git" "../../git"
"../../llvm"
"../../shell" "../../shell"
"../../testlist" "../../testlist"
"../../util" "../../util"
gerrit "github.com/andygrunwald/go-gerrit" gerrit "github.com/andygrunwald/go-gerrit"
) )
...@@ -70,6 +73,7 @@ const ( ...@@ -70,6 +73,7 @@ const (
var ( var (
numParallelTests = runtime.NumCPU() numParallelTests = runtime.NumCPU()
llvmVersion = llvm.Version{Major: 10}
cacheDir = flag.String("cache", "cache", "path to the output cache directory") cacheDir = flag.String("cache", "cache", "path to the output cache directory")
gerritEmail = flag.String("email", "$SS_REGRES_EMAIL", "gerrit email address for posting regres results") gerritEmail = flag.String("email", "$SS_REGRES_EMAIL", "gerrit email address for posting regres results")
...@@ -111,20 +115,84 @@ func main() { ...@@ -111,20 +115,84 @@ func main() {
} }
type regres struct { type regres struct {
cmake string // path to cmake executable cmake string // path to cmake executable
make string // path to make executable make string // path to make executable
python string // path to python executable python string // path to python executable
cacheRoot string // path to the regres cache directory tar string // path to tar executable
gerritEmail string // gerrit email address used for posting results cacheRoot string // path to the regres cache directory
gerritUser string // gerrit username used for posting results toolchain *llvm.Toolchain // the LLVM toolchain used to build SwiftShader
gerritPass string // gerrit password used for posting results gerritEmail string // gerrit email address used for posting results
keepCheckouts bool // don't delete source & build checkouts after testing gerritUser string // gerrit username used for posting results
dryRun bool // don't post any reviews gerritPass string // gerrit password used for posting results
maxProcMemory uint64 // max virtual memory for child processes keepCheckouts bool // don't delete source & build checkouts after testing
dailyNow bool // start with a daily run dryRun bool // don't post any reviews
dailyOnly bool // run only the daily run maxProcMemory uint64 // max virtual memory for child processes
dailyChange string // Change hash to use for daily pass, HEAD if not provided dailyNow bool // start with a daily run
priority string // Prioritize a single change with the given id dailyOnly bool // run only the daily run
dailyChange string // Change hash to use for daily pass, HEAD if not provided
priority string // Prioritize a single change with the given id
}
// getToolchain returns the LLVM toolchain, possibly downloading and
// decompressing it if it wasn't found in the cache directory.
func getToolchain(tarExe, cacheRoot string) (*llvm.Toolchain, error) {
path := filepath.Join(cacheRoot, "llvm")
if toolchain := llvm.Search(path).Find(llvmVersion); toolchain != nil {
return toolchain, nil
}
// LLVM toolchain may have been updated, remove the directory if it exists.
os.RemoveAll(path)
log.Printf("Downloading LLVM %v toolchain...\n", llvmVersion)
tar, err := llvmVersion.Download()
if err != nil {
return nil, fmt.Errorf("Couldn't download LLVM %v: %v", llvmVersion, err)
}
tarFile := filepath.Join(cacheRoot, "llvm.tar.xz")
if err := ioutil.WriteFile(tarFile, tar, 0666); err != nil {
return nil, fmt.Errorf("Couldn't write '%v': %v", tarFile, err)
}
defer os.Remove(tarFile)
log.Printf("Decompressing LLVM %v toolchain...\n", llvmVersion)
target := filepath.Join(cacheRoot, "llvm-tmp")
os.MkdirAll(target, 0755)
defer os.RemoveAll(target)
if err := exec.Command(tarExe, "-xf", tarFile, "-C", target).Run(); err != nil {
return nil, fmt.Errorf("Couldn't decompress LLVM tar download: %v", err)
}
// The tar, once decompressed, holds a single root directory with a name
// starting with 'clang+llvm'. Move this to path.
files, err := filepath.Glob(filepath.Join(target, "*"))
if err != nil {
return nil, fmt.Errorf("Couldn't glob decompressed files: %v", err)
}
if len(files) != 1 || !util.IsDir(files[0]) {
return nil, fmt.Errorf("Unexpected decompressed files: %+v", files)
}
if err := os.Rename(files[0], path); err != nil {
return nil, fmt.Errorf("Couldn't move %v to %v", files[0], path)
}
// We should now have everything in the right place.
toolchain := llvm.Search(path).Find(llvmVersion)
if toolchain == nil {
return nil, fmt.Errorf("Couldn't find LLVM toolchain after downloading")
}
return toolchain, nil
}
// toolchainEnv() returns the environment variables for executing CMake commands.
func (r *regres) toolchainEnv() []string {
return append([]string{
"CC=" + r.toolchain.Clang(),
"CXX=" + r.toolchain.ClangXX(),
}, os.Environ()...)
} }
// resolveDirs ensures that the necessary directories used can be found, and // resolveDirs ensures that the necessary directories used can be found, and
...@@ -165,6 +233,7 @@ func (r *regres) resolveExes() error { ...@@ -165,6 +233,7 @@ func (r *regres) resolveExes() error {
{"cmake", &r.cmake}, {"cmake", &r.cmake},
{"make", &r.make}, {"make", &r.make},
{"python", &r.python}, {"python", &r.python},
{"tar", &r.tar},
} { } {
path, err := exec.LookPath(e.name) path, err := exec.LookPath(e.name)
if err != nil { if err != nil {
...@@ -192,6 +261,12 @@ func (r *regres) run() error { ...@@ -192,6 +261,12 @@ func (r *regres) run() error {
return cause.Wrap(err, "Couldn't resolve all directories") return cause.Wrap(err, "Couldn't resolve all directories")
} }
toolchain, err := getToolchain(r.tar, r.cacheRoot)
if err != nil {
return cause.Wrap(err, "Couldn't download LLVM toolchain")
}
r.toolchain = toolchain
client, err := gerrit.NewClient(gerritURL, nil) client, err := gerrit.NewClient(gerritURL, nil)
if err != nil { if err != nil {
return cause.Wrap(err, "Couldn't create gerrit client") return cause.Wrap(err, "Couldn't create gerrit client")
...@@ -211,10 +286,10 @@ func (r *regres) run() error { ...@@ -211,10 +286,10 @@ func (r *regres) run() error {
for { for {
if now := time.Now(); toDate(now) != lastUpdatedTestLists && now.Hour() >= dailyUpdateTestListHour { if now := time.Now(); toDate(now) != lastUpdatedTestLists && now.Hour() >= dailyUpdateTestListHour {
lastUpdatedTestLists = toDate(now) lastUpdatedTestLists = toDate(now)
if err := r.updateTestLists(client, subzero); err != nil { if err := r.updateTestLists(client, backendSubzero); err != nil {
log.Println(err.Error()) log.Println(err.Error())
} }
if err := r.updateTestLists(client, llvm); err != nil { if err := r.updateTestLists(client, backendLLVM); err != nil {
log.Println(err.Error()) log.Println(err.Error())
} }
} }
...@@ -820,7 +895,7 @@ func (r *regres) newTest(commit git.Hash) *test { ...@@ -820,7 +895,7 @@ func (r *regres) newTest(commit git.Hash) *test {
srcDir: srcDir, srcDir: srcDir,
resDir: resDir, resDir: resDir,
buildDir: filepath.Join(srcDir, "build"), buildDir: filepath.Join(srcDir, "build"),
reactorBackend: llvm, reactorBackend: backendLLVM,
} }
} }
...@@ -832,8 +907,8 @@ func (t *test) setReactorBackend(reactorBackend reactorBackend) *test { ...@@ -832,8 +907,8 @@ func (t *test) setReactorBackend(reactorBackend reactorBackend) *test {
type reactorBackend string type reactorBackend string
const ( const (
llvm reactorBackend = "LLVM" backendLLVM reactorBackend = "LLVM"
subzero reactorBackend = "Subzero" backendSubzero reactorBackend = "Subzero"
) )
type test struct { type test struct {
...@@ -842,6 +917,7 @@ type test struct { ...@@ -842,6 +917,7 @@ type test struct {
srcDir string // directory for the SwiftShader checkout srcDir string // directory for the SwiftShader checkout
resDir string // directory for the test results resDir string // directory for the test results
buildDir string // directory for SwiftShader build buildDir string // directory for SwiftShader build
toolchain llvm.Toolchain // the toolchain used for building
reactorBackend reactorBackend // backend for SwiftShader build reactorBackend reactorBackend // backend for SwiftShader build
} }
...@@ -896,7 +972,7 @@ func (t *test) build() error { ...@@ -896,7 +972,7 @@ func (t *test) build() error {
return cause.Wrap(err, "Failed to create build directory") return cause.Wrap(err, "Failed to create build directory")
} }
if err := shell.Shell(buildTimeout, t.r.cmake, t.buildDir, if err := shell.Env(buildTimeout, t.r.cmake, t.buildDir, t.r.toolchainEnv(),
"-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_BUILD_TYPE=Release",
"-DSWIFTSHADER_DCHECK_ALWAYS_ON=1", "-DSWIFTSHADER_DCHECK_ALWAYS_ON=1",
"-DREACTOR_VERIFY_LLVM_IR=1", "-DREACTOR_VERIFY_LLVM_IR=1",
......
...@@ -39,6 +39,10 @@ type Version struct { ...@@ -39,6 +39,10 @@ type Version struct {
Major, Minor, Point int Major, Minor, Point int
} }
func (v Version) String() string {
return fmt.Sprintf("%v.%v.%v", v.Major, v.Minor, v.Point)
}
// GreaterEqual returns true if v >= rhs. // GreaterEqual returns true if v >= rhs.
func (v Version) GreaterEqual(rhs Version) bool { func (v Version) GreaterEqual(rhs Version) bool {
if v.Major > rhs.Major { if v.Major > rhs.Major {
...@@ -138,6 +142,16 @@ type Toolchain struct { ...@@ -138,6 +142,16 @@ type Toolchain struct {
// Toolchains is a list of Toolchain // Toolchains is a list of Toolchain
type Toolchains []Toolchain type Toolchains []Toolchain
// Find looks for a toolchain with the specific version.
func (l Toolchains) Find(v Version) *Toolchain {
for _, t := range l {
if t.Version == v {
return &t
}
}
return nil
}
// FindAtLeast looks for a toolchain with the given version, returning the highest found version. // FindAtLeast looks for a toolchain with the given version, returning the highest found version.
func (l Toolchains) FindAtLeast(v Version) *Toolchain { func (l Toolchains) FindAtLeast(v Version) *Toolchain {
out := (*Toolchain)(nil) out := (*Toolchain)(nil)
...@@ -193,6 +207,16 @@ func Search(paths ...string) Toolchains { ...@@ -193,6 +207,16 @@ func Search(paths ...string) Toolchains {
return out return out
} }
// Clang returns the path to the clang executable.
func (t Toolchain) Clang() string {
return filepath.Join(t.BinDir, "clang"+exeExt())
}
// ClangXX returns the path to the clang++ executable.
func (t Toolchain) ClangXX() string {
return filepath.Join(t.BinDir, "clang++"+exeExt())
}
// Cov returns the path to the llvm-cov executable. // Cov returns the path to the llvm-cov executable.
func (t Toolchain) Cov() string { func (t Toolchain) Cov() string {
return filepath.Join(t.BinDir, "llvm-cov"+exeExt()) return filepath.Join(t.BinDir, "llvm-cov"+exeExt())
......
...@@ -31,7 +31,14 @@ var MaxProcMemory uint64 = 4 * 1024 * 1024 * 1024 // 4GB ...@@ -31,7 +31,14 @@ var MaxProcMemory uint64 = 4 * 1024 * 1024 * 1024 // 4GB
// directory wd. // directory wd.
// If the process does not finish within timeout a errTimeout will be returned. // If the process does not finish within timeout a errTimeout will be returned.
func Shell(timeout time.Duration, exe, wd string, args ...string) error { func Shell(timeout time.Duration, exe, wd string, args ...string) error {
if out, err := Exec(timeout, exe, wd, nil, args...); err != nil { return Env(timeout, exe, wd, nil, args...)
}
// Env runs the executable exe with the given arguments, in the working
// directory wd, with the custom env.
// If the process does not finish within timeout a errTimeout will be returned.
func Env(timeout time.Duration, exe, wd string, env []string, args ...string) error {
if out, err := Exec(timeout, exe, wd, env, args...); err != nil {
return cause.Wrap(err, "%s", out) return cause.Wrap(err, "%s", out)
} }
return nil return nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment