blob: 70e7775cabfdea0bc73eedecb388d9e48e2e3cbe [file] [log] [blame]
package dkms
import (
"context"
"cos.googlesource.com/cos/tools.git/src/pkg/cos"
"cos.googlesource.com/cos/tools.git/src/pkg/fs"
"fmt"
"github.com/golang/glog"
"os"
"os/exec"
"path"
)
// InstallCompilerToolchain installs the COS compiler toolchain in a target directory.
//
// Once the toolchain has been installed, the toolchain tarball is removed to save
// space, and a toolchain-installed.txt file is created. If the installation fails for
// any reason, toolchain-installed.txt file will not be written, so it can be used as a
// reliable indicator that the installation succeeded.
func InstallCompilerToolchain(ctx context.Context, downloader cos.ArtifactsDownloader, dstDir string) error {
if err := downloader.DownloadToolchainEnv(ctx, dstDir); err != nil {
return err
}
if err := downloader.DownloadToolchain(ctx, dstDir); err != nil {
return err
}
toolchainDir := path.Join(dstDir, "toolchain")
if err := os.MkdirAll(toolchainDir, 0777); err != nil {
return fmt.Errorf("error creating directory %s: %v", toolchainDir, err)
}
toolchainPath := path.Join(dstDir, "toolchain.tar.xz")
if err := UnpackCompilerToolchain(toolchainPath, toolchainDir); err != nil {
return err
}
// the toolchain tarball is not needed after it's extracted, so we remove it
if err := os.Remove(toolchainPath); err != nil {
return fmt.Errorf("error removing toolchain tarball: %v", err)
}
// write a file to indicate that the installation is finished
donePath := path.Join(dstDir, "toolchain-installed.txt")
if _, err := os.Create(donePath); err != nil {
return fmt.Errorf("error finalizing toolchain installation: %v", err)
}
return nil
}
// UnpackCompilerToolchain unpacks a compiler toolchain to a target directory.
// This omits the rust toolchain components since they are unused by COS and use
// a significant amount of space.
func UnpackCompilerToolchain(toolchainPath, dstDir string) error {
cmd := exec.Command(
"tar", "xf", toolchainPath, "-C", dstDir,
"--exclude=./usr/lib64/rustlib*",
"--exclude=./usr/lib/rustlib*",
"--exclude=./usr/lib64/libstd-*.so",
"--exclude=./lib/libstd-*.so",
"--exclude=./lib/librustc*",
"--exclude=./usr/lib64/librustc*",
)
out, err := cmd.CombinedOutput()
if err == nil {
glog.V(1).Infof(string(out))
} else {
glog.Errorf(string(out))
return fmt.Errorf("error unpacking compiler toolchain: %v", err)
}
return nil
}
// CompilerToolchainInstalled returns whether or not the toolchain has been
// installed in the target directory.
func CompilerToolchainInstalled(toolchainDir string) bool {
donePath := path.Join(toolchainDir, "toolchain-installed.txt")
return fs.IsFile(donePath)
}
// InstallKernelHeaders installs the COS kernel headers in a target directory.
//
// Once the headers have been installed, the header tarball is removed to save
// space, and a kernel-headers-installed.txt file is created. If the installation
// fails for any reason, the kernel-headers-installed.txt file will not be written,
// so it can be used as a reliable indicator that the installation succeeded.
func InstallKernelHeaders(ctx context.Context, downloader cos.ArtifactsDownloader, dstDir string) error {
kernelHeadersPath := path.Join(dstDir, "kernel-headers.tgz")
if err := downloader.DownloadKernelHeaders(ctx, dstDir); err != nil {
return err
}
if err := UnpackKernelHeaders(kernelHeadersPath, dstDir); err != nil {
return err
}
// the headers tarball is not needed after it's extracted, so we remove it
if err := os.Remove(kernelHeadersPath); err != nil {
return fmt.Errorf("error removing kernel headers tarball: %v", err)
}
// write a file to indicate that the installation is finished
donePath := path.Join(dstDir, "kernel-headers-installed.txt")
if _, err := os.Create(donePath); err != nil {
return fmt.Errorf("error finalizing kernel header installation: %v", err)
}
glog.Info("done installing kernel headers")
return nil
}
// UnpackKernelHeaders unpacks kernel headers to a target directory.
func UnpackKernelHeaders(headersPath, dstDir string) error {
cmd := exec.Command("tar", "xf", headersPath, "-C", dstDir, "--strip-components=4")
out, err := cmd.CombinedOutput()
if err == nil {
glog.V(1).Infof(string(out))
} else {
glog.Errorf(string(out))
return fmt.Errorf("error unpacking kernel headers: %v", err)
}
return nil
}
// KernelHeadersInstalled returns whether or not the kernel headers have been
// installed in the target directory.
func KernelHeadersInstalled(buildDir string) bool {
donePath := path.Join(buildDir, "kernel-headers-installed.txt")
return fs.IsFile(donePath)
}