| package builder |
| |
| import ( |
| "context" |
| "fmt" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "strings" |
| |
| "cloud.google.com/go/storage" |
| "cos.googlesource.com/cos/tools.git/src/pkg/cos" |
| "cos.googlesource.com/cos/tools.git/src/pkg/gpuconfig" |
| "cos.googlesource.com/cos/tools.git/src/pkg/utils" |
| ) |
| |
| const ( |
| linkerLocation = "/bin/ld" |
| patchDir = "/build/patches" |
| installDirTemplate = "/install/%s" |
| defaultFilePermission = 0755 |
| kernelSrcTemplate = "usr/src/linux-headers-*" |
| ) |
| |
| func kernelSrcDirectory(dirName string) string { |
| files, err := filepath.Glob(filepath.Join(dirName, kernelSrcTemplate)) |
| if err != nil || len(files) != 1 { |
| return "" |
| } |
| return files[0] |
| } |
| |
| func nvidiaInstallerBuildCommand(dirName, runfile string, config gpuconfig.GPUPrecompilationConfig) *exec.Cmd { |
| cmd := exec.Command(filepath.Join(dirName, runfile), "--kernel-source-path="+kernelSrcDirectory(dirName), "--add-this-kernel", "--no-install-compat32-libs", "--silent", "--accept-license") |
| cmd.Dir = dirName |
| return cmd |
| } |
| |
| func nvidiaInstallerPatchCommand(dirName, runfile, patchDir, patchfile string) *exec.Cmd { |
| cmd := exec.Command(filepath.Join(dirName, runfile), "--apply-patch", filepath.Join(patchDir, patchfile)) |
| cmd.Dir = dirName |
| return cmd |
| } |
| |
| func BuildPrecompiledDriver(ctx context.Context, client *storage.Client, config gpuconfig.GPUPrecompilationConfig) (string, string, error) { |
| var err error |
| dirName := fmt.Sprintf(installDirTemplate, config.Version) |
| if err = os.MkdirAll(dirName, defaultFilePermission); err != nil { |
| return "", "", fmt.Errorf("failed to create installation dir: %v", err) |
| } |
| downloader := gpuconfig.NewGPUArtifactsDownloader(client, config) |
| // download NVIDIA runfile |
| var nvidiaInstaller string |
| if nvidiaInstaller, err = downloader.DownloadNVIDIARunfile(ctx, dirName); err != nil { |
| return "", "", fmt.Errorf("failed to download NVIDIA runfile: %v", err) |
| } |
| // install kernel headers and toolchain |
| // sets SYSROOT and PATH env vars |
| if err = cos.InstallCrossToolchain(ctx, downloader, dirName); err != nil { |
| return "", "", fmt.Errorf("failed to install toolchain: %v", err) |
| } |
| // set CC CXX env vars from toolchain_env |
| if err = cos.SetCompilationEnv(ctx, downloader); err != nil { |
| return "", "", fmt.Errorf("failed to set compilation env vars: %v", err) |
| } |
| // create symlink to ld - required by NVIDIA driver package |
| if err = cos.ForceSymlinkLinker(filepath.Join(dirName, linkerLocation)); err != nil { |
| return "", "", fmt.Errorf("failed to create symlink to COS linker: %v", err) |
| } |
| cc := os.Getenv("CC") |
| if cc == "" { |
| return "", "", fmt.Errorf("failed to find CC in env") |
| } else { |
| // create a wrapper removing -Werror=strict-prototypes from the CC command line. |
| if err = cos.AddCCWrapperToPath(dirName, dirName, cc); err != nil { |
| return "", "", fmt.Errorf("failed to create CC wrapper: %v", err) |
| } |
| } |
| // run NVIDIA driver package |
| if err = os.Chmod(filepath.Join(dirName, nvidiaInstaller), defaultFilePermission); err != nil { |
| return "", "", err |
| } |
| |
| // TODO: add driver patches arg to pb.COSGPUBuildRequest |
| // hardcoded list for known patches for now. |
| patches := patchesForDriverBuild(config) |
| for _, patch := range patches { |
| cmd := nvidiaInstallerPatchCommand(dirName, nvidiaInstaller, patchDir, patch) |
| if err := utils.RunCommandAndLogOutput(cmd, false); err != nil { |
| return "", "", fmt.Errorf("error applying provided patch to NVIDIA driver package: %v", err) |
| } |
| patchedInstaller := strings.Split(nvidiaInstaller, ".run")[0] + "-custom.run" |
| if err := os.Rename(filepath.Join(dirName, patchedInstaller), filepath.Join(dirName, nvidiaInstaller)); err != nil { |
| return "", "", fmt.Errorf("error moving patched NVIDIA driver package: %v", err) |
| } |
| } |
| |
| cmd := nvidiaInstallerBuildCommand(dirName, nvidiaInstaller, config) |
| if err = utils.RunCommandAndLogOutput(cmd, false); err != nil { |
| return "", "", fmt.Errorf("error running NVIDIA driver installation package: %v", err) |
| } |
| |
| outputFileName := strings.Split(nvidiaInstaller, ".run")[0] + "-custom.run" |
| return dirName, outputFileName, nil |
| } |
| |
| func patchesForDriverBuild(config gpuconfig.GPUPrecompilationConfig) []string { |
| pfnAffectedDriverVersions := []string{"470.199.02", "470.223.02", "525.125.06", "525.147.05", "535.104.05", "535.104.12", "535.129.03", "535.154.05"} |
| pfnAffectedMilestones := []string{"97", "101", "105"} |
| var patches []string |
| if utils.StringSliceContains(pfnAffectedDriverVersions, config.DriverVersion) && utils.StringSliceContains(pfnAffectedMilestones, config.Milestone) { |
| var kernelVersionDot string |
| if config.Milestone == "97" { |
| kernelVersionDot = "5.10" |
| } else { |
| kernelVersionDot = "5.15" |
| } |
| majorDriverVersion := strings.Split(config.DriverVersion, ".")[0] |
| patchFile := fmt.Sprintf("nvidia-drivers-%s-%s-gpl-pfn_valid.patch", majorDriverVersion, kernelVersionDot) |
| patches = append(patches, patchFile) |
| } |
| return patches |
| } |