github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/pkg/uroot/source.go (about) 1 // Copyright 2015-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package uroot 6 7 import ( 8 "fmt" 9 "log" 10 "path/filepath" 11 12 "github.com/u-root/u-root/pkg/golang" 13 ) 14 15 // SourceBuild is an implementation of Build that compiles the Go toolchain 16 // (go, compile, link, asm) and an init process. It includes source files for 17 // packages listed in `opts.Packages` to build from scratch. 18 func SourceBuild(opts BuildOpts) (ArchiveFiles, error) { 19 af := NewArchiveFiles() 20 21 if err := af.AddFile(filepath.Join(opts.Env.GOROOT, "pkg/include"), "go/pkg/include"); err != nil { 22 return ArchiveFiles{}, err 23 } 24 25 log.Printf("Collecting package files and dependencies...") 26 deps := make(map[string]struct{}) 27 for _, pkg := range opts.Packages { 28 // Add high-level packages' src files to archive. 29 p := goListPkg(opts, pkg, &af) 30 if p == nil { 31 continue 32 } 33 for _, d := range p.Deps { 34 deps[d] = struct{}{} 35 } 36 } 37 // Add src files of dependencies to archive. 38 for dep := range deps { 39 goListPkg(opts, dep, &af) 40 } 41 42 // Add Go toolchain. 43 log.Printf("Building go toolchain...") 44 if err := buildToolchain(opts); err != nil { 45 return ArchiveFiles{}, err 46 } 47 48 // Build init. 49 if err := opts.Env.Build("github.com/u-root/u-root/cmds/init", filepath.Join(opts.TempDir, "init"), golang.BuildOpts{}); err != nil { 50 return ArchiveFiles{}, err 51 } 52 53 // Add Go toolchain and init to archive. 54 if err := af.AddFile(opts.TempDir, ""); err != nil { 55 return ArchiveFiles{}, err 56 } 57 return af, nil 58 } 59 60 // buildToolchain builds the needed Go toolchain binaries: go, compile, link, 61 // asm. 62 func buildToolchain(opts BuildOpts) error { 63 goBin := filepath.Join(opts.TempDir, "go/bin/go") 64 tcbo := golang.BuildOpts{ 65 ExtraArgs: []string{"-tags", "cmd_go_bootstrap"}, 66 } 67 if err := opts.Env.Build("cmd/go", goBin, tcbo); err != nil { 68 return err 69 } 70 71 toolDir := filepath.Join(opts.TempDir, fmt.Sprintf("go/pkg/tool/%v_%v", opts.Env.GOOS, opts.Env.GOARCH)) 72 for _, pkg := range []string{"compile", "link", "asm"} { 73 c := filepath.Join(toolDir, pkg) 74 if err := opts.Env.Build(fmt.Sprintf("cmd/%s", pkg), c, golang.BuildOpts{}); err != nil { 75 return err 76 } 77 } 78 return nil 79 } 80 81 func goListPkg(opts BuildOpts, importPath string, out *ArchiveFiles) *golang.ListPackage { 82 p, err := opts.Env.Deps(importPath) 83 if err != nil { 84 log.Printf("Can't list Go dependencies for %v; ignoring.", importPath) 85 return nil 86 } 87 88 // Add Go files in this package to archive. 89 for _, file := range append(append(p.GoFiles, p.SFiles...), p.HFiles...) { 90 relPath := filepath.Join("src", p.ImportPath, file) 91 srcFile := filepath.Join(p.Root, relPath) 92 if p.Goroot { 93 out.AddFile(srcFile, filepath.Join("go", relPath)) 94 } else { 95 out.AddFile(srcFile, relPath) 96 } 97 } 98 return p 99 }