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.
15 var cmdClean
= &Command
{
16 UsageLine
: "clean [-i] [-r] [-n] [-x] [build flags] [packages]",
17 Short
: "remove object files",
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.
24 Specifically, clean removes the following files from each of the
25 source directories corresponding to the import paths:
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
34 DIR(.exe) from go build
35 DIR.test(.exe) from go test -c
36 MAINFILE(.exe) from go build MAINFILE.go
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
44 The -i flag causes clean to remove the corresponding installed
45 archive or binary (what 'go install' would create).
47 The -n flag causes clean to print the remove commands it would execute,
50 The -r flag causes clean to be applied recursively to all the
51 dependencies of the packages named by the import paths.
53 The -x flag causes clean to print remove commands as it executes them.
55 For more about build flags, see 'go help build'.
57 For more about specifying packages, see 'go help packages'.
61 var cleanI
bool // clean -i flag
62 var cleanR
bool // clean -r flag
66 cmdClean
.Run
= runClean
68 cmdClean
.Flag
.BoolVar(&cleanI
, "i", false, "")
69 cmdClean
.Flag
.BoolVar(&cleanR
, "r", false, "")
70 // -n and -x are important enough to be
71 // mentioned explicitly in the docs but they
72 // are part of the build flags.
74 addBuildFlags(cmdClean
)
77 func runClean(cmd
*Command
, args
[]string) {
78 for _
, pkg
:= range packagesAndErrors(args
) {
83 var cleaned
= map[*Package
]bool{}
85 // TODO: These are dregs left by Makefile-based builds.
86 // Eventually, can stop deleting these.
87 var cleanDir
= map[string]bool{
92 var cleanFile
= map[string]bool{
99 var cleanExt
= map[string]bool{
108 func clean(p
*Package
) {
115 errorf("can't load package: %v", p
.Error
)
118 dirs
, err
:= ioutil
.ReadDir(p
.Dir
)
120 errorf("go clean %s: %v", p
.Dir
, err
)
127 packageFile
:= map[string]bool{}
128 if p
.Name
!= "main" {
129 // Record which files are not in package main.
131 keep
:= func(list
[]string) {
132 for _
, f
:= range list
{
133 packageFile
[f
] = true
142 _
, elem
:= filepath
.Split(p
.Dir
)
143 var allRemove
[]string
145 // Remove dir-named executable only if this is package main.
146 if p
.Name
== "main" {
147 allRemove
= append(allRemove
,
153 // Remove package test executables.
154 allRemove
= append(allRemove
,
159 // Remove a potential executable for each .go file in the directory that
160 // is not part of the directory's package.
161 for _
, dir
:= range dirs
{
163 if packageFile
[name
] {
166 if !dir
.IsDir() && strings
.HasSuffix(name
, ".go") {
167 // TODO(adg,rsc): check that this .go file is actually
168 // in "package main", and therefore capable of building
169 // to an executable file.
170 base
:= name
[:len(name
)-len(".go")]
171 allRemove
= append(allRemove
, base
, base
+".exe")
175 if buildN || buildX
{
176 b
.showcmd(p
.Dir
, "rm -f %s", strings
.Join(allRemove
, " "))
179 toRemove
:= map[string]bool{}
180 for _
, name
:= range allRemove
{
181 toRemove
[name
] = true
183 for _
, dir
:= range dirs
{
186 // TODO: Remove once Makefiles are forgotten.
188 if buildN || buildX
{
189 b
.showcmd(p
.Dir
, "rm -r %s", name
)
194 if err
:= os
.RemoveAll(filepath
.Join(p
.Dir
, name
)); err
!= nil {
195 errorf("go clean: %v", err
)
205 if cleanFile
[name
] || cleanExt
[filepath
.Ext(name
)] || toRemove
[name
] {
206 removeFile(filepath
.Join(p
.Dir
, name
))
210 if cleanI
&& p
.target
!= "" {
211 if buildN || buildX
{
212 b
.showcmd("", "rm -f %s", p
.target
)
220 for _
, p1
:= range p
.imports
{
226 // removeFile tries to remove file f, if error other than file doesn't exist
227 // occurs, it will report the error.
228 func removeFile(f
string) {
230 if err
== nil || os
.IsNotExist(err
) {
233 // Windows does not allow deletion of a binary file while it is executing.
235 // Remove lingering ~ file from last attempt.
236 if _
, err2
:= os
.Stat(f
+ "~"); err2
== nil {
239 // Try to move it out of the way. If the move fails,
240 // which is likely, we'll try again the
241 // next time we do an install of this binary.
242 if err2
:= os
.Rename(f
, f
+"~"); err2
== nil {
247 errorf("go clean: %v", err
)