-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/go: does not rebuild when source files are removed #3895
Comments
Labels changed: added priority-soon, removed priority-triage. Owner changed to @rsc. |
There are at least two possible fixes. One is to include in the .a file a hash of all the source file content that went into it (or the file names and mtimes). The hash will not match if a file is missing. Another, partial fix is to use a background process that watches file changes for the go command. It would see the deletion and be able to tell the go command that the package is out of date. That would speed ordinary builds too, and is something I want to explore for 1.3. Labels changed: added go1.3maybe. |
Issue #6294 has been merged into this issue. |
If I remove a file in a properly built Makefile, it fails to build. It does a) what is correct and b) what people expect. It comes at the cost of some extra metadata reads, but at least it is correct. I'm not trying to be antagonist, here, I'm just a bit incredulous that anyone defends NOT fixing this. Is there some perspective from which this behavior is "correct"? thockin@thockin-glaptop:/tmp$ rm -f foo a b thockin@thockin-glaptop:/tmp$ cat Makefile all: foo foo: a b cat a b > $@ a: a.in cat $^ | tr 'a-z' 'A-Z' > $@ b: b.in cat $^ | tr 'a-z' 'A-Z' > $@ thockin@thockin-glaptop:/tmp$ echo hello > a.in thockin@thockin-glaptop:/tmp$ echo world > b.in thockin@thockin-glaptop:/tmp$ make cat a.in | tr 'a-z' 'A-Z' > a cat b.in | tr 'a-z' 'A-Z' > b cat a b > foo thockin@thockin-glaptop:/tmp$ cat foo HELLO WORLD thockin@thockin-glaptop:/tmp$ rm b.in thockin@thockin-glaptop:/tmp$ make make: *** No rule to make target `b.in', needed by `b'. Stop. |
Typical to OSS, of course I don't have time to learn a new codebase and fix a bug deemed "difficult" by the core team. That's not fair. This will probably make me go away, which is what such a statement is really intended to do, but I go away muttering about how broken go is, and how we all need to work around it. Given that go says (more or less) "everyone should use our build tools" (and in fact makes it more or less impossible NOT to), and those tools do not work correctly, you can perhaps see why I am frustrated by the response? My intention was not to stir up a fight, just to vocally +1 an obvious bug and make my plea to not close it just because it is hard to fix. |
Tim, the issue is that the go command effectively creates the makefile on demand. The analogous situation in make is if you had written the Makefile in a more general way like: ALLOUT=$(shell ls *.in | sed 's/\.in$$//') all: foo foo: $(ALLOUT) cat $(ALLOUT) > $@ %: %.in cat $^ | tr 'a-z' 'A-Z' > $@ In that case: g% make foo cat a.in | tr 'a-z' 'A-Z' > a cat b.in | tr 'a-z' 'A-Z' > b cat a b > foo g% cat foo HELLO WORLD g% rm b.in b g% make foo make: `foo' is up to date. g% cat foo HELLO WORLD g% make -B foo cat a.in | tr 'a-z' 'A-Z' > a cat a > foo g% cat foo HELLO g% The reason things work in your version is that there is a duplication of information, so that when you remove b and forget to update the makefile, there is an inconsistency that stops the build, and get told things are wrong. But if you had also updated the makefile (or been using a self-updating makefile like the one above) you'd run into the same thing. As I mentioned in #13, we had intended to fix this in most cases by watching for file system updates, but that turned out to be very difficult to do in anything like a portable way. Every OS has invented a different API with wildly different semantics for that. It looks like we are going to have to fall back to some kind of content-based hashing instead of mtimes. But that's a big change, and we have higher priority bugs to fix right now. No one is saying it's not a problem, and no one is saying that we're just going to close the bug. |
I take it in the example in comment 31, that 'a' and 'b' are analogous to object files, 'a.in' and 'b.in', source files, and that 'foo' is a package/library file, such as foo.a. If 'a.in' is newer than 'a', than 'a' is rebuilt, and then so is 'foo'. But why can't we have that if an object file exists, and a corresponding source file does not, then the extraneous object file is removed and the package rebuilt? |
@anacrolix Source files and object files don't map 1:1, multiple sources are combined into one .a. See comments 13 and 16. |
CL https://golang.org/cl/9154 mentions this issue. |
The text was updated successfully, but these errors were encountered: