github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/go/clean.go (about) 1 // Copyright 2012 The Go 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 main 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "strings" 13 ) 14 15 var cmdClean = &Command{ 16 UsageLine: "clean [-i] [-r] [-n] [-x] [packages]", 17 Short: "remove object files", 18 Long: ` 19 Clean removes object files from package source directories. 20 The go command builds most objects in a temporary directory, 21 so go clean is mainly concerned with object files left by other 22 tools or by manual invocations of go build. 23 24 Specifically, clean removes the following files from each of the 25 source directories corresponding to the import paths: 26 27 _obj/ old object directory, left from Makefiles 28 _test/ old test directory, left from Makefiles 29 _testmain.go old gotest file, left from Makefiles 30 test.out old test log, left from Makefiles 31 build.out old test log, left from Makefiles 32 *.[568ao] object files, left from Makefiles 33 34 DIR(.exe) from go build 35 DIR.test(.exe) from go test -c 36 MAINFILE(.exe) from go build MAINFILE.go 37 *.so from SWIG 38 39 In the list, DIR represents the final path element of the 40 directory, and MAINFILE is the base name of any Go source 41 file in the directory that is not included when building 42 the package. 43 44 The -i flag causes clean to remove the corresponding installed 45 archive or binary (what 'go install' would create). 46 47 The -n flag causes clean to print the remove commands it would execute, 48 but not run them. 49 50 The -r flag causes clean to be applied recursively to all the 51 dependencies of the packages named by the import paths. 52 53 The -x flag causes clean to print remove commands as it executes them. 54 55 For more about specifying packages, see 'go help packages'. 56 `, 57 } 58 59 var cleanI bool // clean -i flag 60 var cleanN bool // clean -n flag 61 var cleanR bool // clean -r flag 62 var cleanX bool // clean -x flag 63 64 func init() { 65 // break init cycle 66 cmdClean.Run = runClean 67 68 cmdClean.Flag.BoolVar(&cleanI, "i", false, "") 69 cmdClean.Flag.BoolVar(&cleanN, "n", false, "") 70 cmdClean.Flag.BoolVar(&cleanR, "r", false, "") 71 cmdClean.Flag.BoolVar(&cleanX, "x", false, "") 72 } 73 74 func runClean(cmd *Command, args []string) { 75 for _, pkg := range packagesAndErrors(args) { 76 clean(pkg) 77 } 78 } 79 80 var cleaned = map[*Package]bool{} 81 82 // TODO: These are dregs left by Makefile-based builds. 83 // Eventually, can stop deleting these. 84 var cleanDir = map[string]bool{ 85 "_test": true, 86 "_obj": true, 87 } 88 89 var cleanFile = map[string]bool{ 90 "_testmain.go": true, 91 "test.out": true, 92 "build.out": true, 93 "a.out": true, 94 } 95 96 var cleanExt = map[string]bool{ 97 ".5": true, 98 ".6": true, 99 ".8": true, 100 ".a": true, 101 ".o": true, 102 ".so": true, 103 } 104 105 func clean(p *Package) { 106 if cleaned[p] { 107 return 108 } 109 cleaned[p] = true 110 111 if p.Dir == "" { 112 errorf("can't load package: %v", p.Error) 113 return 114 } 115 dirs, err := ioutil.ReadDir(p.Dir) 116 if err != nil { 117 errorf("go clean %s: %v", p.Dir, err) 118 return 119 } 120 121 var b builder 122 b.print = fmt.Print 123 124 packageFile := map[string]bool{} 125 if p.Name != "main" { 126 // Record which files are not in package main. 127 // The others are. 128 keep := func(list []string) { 129 for _, f := range list { 130 packageFile[f] = true 131 } 132 } 133 keep(p.GoFiles) 134 keep(p.CgoFiles) 135 keep(p.TestGoFiles) 136 keep(p.XTestGoFiles) 137 } 138 139 _, elem := filepath.Split(p.Dir) 140 allRemove := []string{ 141 elem, 142 elem + ".exe", 143 elem + ".test", 144 elem + ".test.exe", 145 } 146 for _, dir := range dirs { 147 name := dir.Name() 148 if packageFile[name] { 149 continue 150 } 151 if !dir.IsDir() && strings.HasSuffix(name, ".go") { 152 base := name[:len(name)-len(".go")] 153 allRemove = append(allRemove, base, base+".exe") 154 } 155 } 156 if cleanN || cleanX { 157 b.showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " ")) 158 } 159 160 toRemove := map[string]bool{} 161 for _, name := range allRemove { 162 toRemove[name] = true 163 } 164 for _, dir := range dirs { 165 name := dir.Name() 166 if dir.IsDir() { 167 // TODO: Remove once Makefiles are forgotten. 168 if cleanDir[name] { 169 if cleanN || cleanX { 170 b.showcmd(p.Dir, "rm -r %s", name) 171 if cleanN { 172 continue 173 } 174 } 175 if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil { 176 errorf("go clean: %v", err) 177 } 178 } 179 continue 180 } 181 182 if cleanN { 183 continue 184 } 185 186 if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] { 187 removeFile(filepath.Join(p.Dir, name)) 188 } 189 } 190 191 if cleanI && p.target != "" { 192 if cleanN || cleanX { 193 b.showcmd("", "rm -f %s", p.target) 194 } 195 if !cleanN { 196 removeFile(p.target) 197 } 198 } 199 200 if cleanI && p.usesSwig() { 201 for _, f := range stringList(p.SwigFiles, p.SwigCXXFiles) { 202 dir := p.swigDir(&buildContext) 203 soname := p.swigSoname(f) 204 target := filepath.Join(dir, soname) 205 if cleanN || cleanX { 206 b.showcmd("", "rm -f %s", target) 207 } 208 if !cleanN { 209 removeFile(target) 210 } 211 } 212 } 213 214 if cleanR { 215 for _, p1 := range p.imports { 216 clean(p1) 217 } 218 } 219 } 220 221 // removeFile tries to remove file f, if error other than file doesn't exist 222 // occurs, it will report the error. 223 func removeFile(f string) { 224 if err := os.Remove(f); err != nil && !os.IsNotExist(err) { 225 errorf("go clean: %v", err) 226 } 227 }