github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-make/make.go (about)

     1  // Copyright 2018 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  // syz-make provides information required to build native code for the Makefile.
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"runtime"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/google/syzkaller/pkg/osutil"
    15  	"github.com/google/syzkaller/sys/targets"
    16  )
    17  
    18  func main() {
    19  	vars, err := impl()
    20  	if err != nil {
    21  		fmt.Printf("export SYZERROR=%v\n", err)
    22  		os.Exit(1)
    23  	}
    24  	for _, v := range vars {
    25  		fmt.Printf("export %v=%v\\n", v.Name, v.Val)
    26  	}
    27  }
    28  
    29  type Var struct {
    30  	Name string
    31  	Val  string
    32  }
    33  
    34  func impl() ([]Var, error) {
    35  	hostOS := or(os.Getenv("HOSTOS"), runtime.GOOS)
    36  	hostArch := or(os.Getenv("HOSTARCH"), runtime.GOARCH)
    37  	targetOS := or(os.Getenv("TARGETOS"), hostOS)
    38  	targetArch := or(os.Getenv("TARGETARCH"), hostArch)
    39  	targetVMArch := or(os.Getenv("TARGETVMARCH"), targetArch)
    40  	target := targets.Get(targetOS, targetArch)
    41  	if target == nil {
    42  		return nil, fmt.Errorf("unknown target %v/%v", targetOS, targetArch)
    43  	}
    44  	parallelism := runtime.NumCPU()
    45  	if os.Getenv("CI") != "" {
    46  		// Github actions VMs have 2 vCPUs (Standard_DS2_v2 class). So we don't get lots of speed up
    47  		// from make parallelism, but we are getting memory oversubscription and duplicated work
    48  		// because make invokes multiple go commands that potentially build same packages in parallel.
    49  		// Go command itself parallelizes compiler and test invocations. So disable make parallelism
    50  		// to avoid OOM kills.
    51  		parallelism = 1
    52  	}
    53  	if runtime.GOOS == targets.OpenBSD {
    54  		// Avoids too much concurrency on OpenBSD which can't handle this much.
    55  		parallelism = 1
    56  	}
    57  	if mem := osutil.SystemMemorySize(); mem != 0 {
    58  		// Ensure that we have at least 1GB per Go compiler/linker invocation.
    59  		// Go compiler/linker can consume significant amount of memory
    60  		// (observed to consume at least 600MB). See #1276 for context.
    61  		// And we have parallelization both on make and on go levels,
    62  		// this can severe oversubscribe RAM.
    63  		// Note: the result can be significantly lower than the CPU number,
    64  		// but this is fine because Go builds/tests are parallelized internally.
    65  		memLimit := int(mem / (1 << 30))
    66  		for parallelism > 1 && parallelism*parallelism > memLimit {
    67  			parallelism--
    68  		}
    69  	}
    70  	vars := []Var{
    71  		{"BUILDOS", runtime.GOOS},
    72  		{"NATIVEBUILDOS", target.BuildOS},
    73  		{"HOSTOS", hostOS},
    74  		{"HOSTARCH", hostArch},
    75  		{"TARGETOS", targetOS},
    76  		{"TARGETARCH", targetArch},
    77  		{"TARGETVMARCH", targetVMArch},
    78  		{"CC", target.CCompiler},
    79  		{"ADDCFLAGS", strings.Join(target.CFlags, " ")},
    80  		{"NCORES", strconv.Itoa(parallelism)},
    81  		{"EXE", target.ExeExtension},
    82  		{"NATIVEBUILDOS", target.BuildOS},
    83  		{"NO_CROSS_COMPILER", target.BrokenCompiler},
    84  	}
    85  	return vars, nil
    86  }
    87  
    88  func or(s1, s2 string) string {
    89  	if s1 != "" {
    90  		return s1
    91  	}
    92  	return s2
    93  }