TMI: Workcache!
Aug. 16th, 2013 08:42 pmSo that's exciting! Despite Graydon explaining it to me, I hadn't quite grokked how workcache works till now. It's a quite neat idea: most build systems (including) make are declarative. You write a whole other program to explain how to build your program (albeit in a very weird programming language, usually). Workcache, and a system called fbuild that it's based on, are imperative. You express your dependencies in your usual programming language, specifying how to determine if a particular target needs to be rebuilt. That made more sense in my head than it did when I tried to write it down just now.
In any case, the missing piece that I filled in today was the freshness map, which is part of the state that you have to pass around for workcache to work. The freshness map is a hash table that maps "kinds" (just strings) onto functions. The "kinds" in this case are "source file", "executable or library file", "URL", and maybe a few other things. The function takes a name (for example, a file path) and a value (for example, a hash of the file's contents) and returns a boolean indicating whether the given name and hash are up-to-date. The "given" name and hash come from the workcache database (which is persistent) and the freshness function is the code that (in this case) reads in the contents of the file, hashes it, and compares the two hashes for equality.
Most of the time that took was understanding the code well enough to write the previous paragraph; once I understood that, the code was quite simple.
Next step is to change the test cases to reflect that rustpkg won't just rebuild if the timestamp changes[*], and make sure they change the contents of the file if they want to test behavior-if-a-file-changes. But I feel like things are moving now.
[*] Or maybe it should, I'm not sure, but in that case the freshness function would have to be changed so that the hash is a hash of both the file's contents and its metadata.
TMI: While my try build runs...
Aug. 15th, 2013 06:38 pmWhat I did today: un-ignore most of the rustpkg tests -- except for the ones that depend on features that aren't implemented yet (workcache, and the do, test, and info commands). A bunch of the tests were xfailed because the tests weren't playing nicely with cross-compilation. That's fixed now, so they should work. But I spent most of today getting one test to work, which was one of the tests for custom build logic. The hard part had nothing to do with custom build logic, but rather to do with library names that contain dashes. Previously if you called your library foo-bar, rustpkg would generate a library called libfoo_bar-xxxxx-0.1.dylib (on Mac, anyway), where xxxxx is a hash. Now that we separate the name used as an identifier in Rust code from the actual package ID, we can call the library libfoo-bar-xxxxx-0.1.dylib, but since '-' also separates the name, hash, and version, the old parsing code didn't work anymore. Now it does! (I'm not completely sure that we should be naming libraries this way anyway, but hey, everything works now, or should.)
Running a try build now to make sure everything works on the bots where the host and target are potentially different, and then I'll submit a pull request. And, uh, tomorrow I'll work on workcache.
TMI: rustpkg status
Aug. 14th, 2013 06:26 pmTMI: A day of debugging-by-println
Aug. 13th, 2013 06:12 pmWhile browsing not-recently-updated bugs, I found #6702, an unclear-error-message bug in resolve, which was an easy fix.
The option/slice bug, which came up while working on rustpkg, took up some time, but tomorrow I really need to get back to rustpkg itself, hopefully finishing the workcache integration over the next few days.
Today's important safety message
Aug. 13th, 2013 08:43 am- Obey all traffic laws, including posted speed limits, even if you're on a freeway.
- If you're near a crosswalk, you should be driving slow enough to stop even for a pedestrian who "jumps out in front of you".
- Do not honk at cyclists or pedestrians. In many places, it's illegal to honk where there is no imminent danger. If you are causing the imminent danger, you should stop causing it instead.
- Do not shout death threats at cyclists or pedestrians.
- Stop at all stop signs.
- Always use turn signals before turning or changing lanes.
- Know how much space you're legally obligated to give cyclists, and give it to them.
- If a cyclist is taking the lane, don't try to run the cyclist off the road. They are doing that because they are safer riding that way and because it's their legal right. Treat a cyclist like any other slow-moving vehicle: pass the cyclist if and when you can do so safely, but otherwise stay behind and leave lots of room.
- Before you open your door while parked in a parking space, look outside to make sure no cyclists are passing by.
- Don't park in bike lanes.
- Don't drive drunk or while under the influence of other drugs that impair coordination.
- Don't text while driving.
- Don't talk on the phone while driving, not even using a hands-free device; in person, a conversation partner will be aware of your surroundings and can react to them by stopping or slowing down the conversation, whereas someone on the phone can't do that and thus is much more of a distraction.
- Before making a right turn (or left turn if you're in a country where you drive on the left), check to make sure you wouldn't be hitting a cyclist to your right (or left) who is riding straight through the intersection and has the right of way.
Whether or not you see cyclists riding without helmets, not coming to a complete stop at stop signs, or doing anything else you disapprove of, with power comes responsibility and it's your responsibility as an operator of a heavy, dangerous machine to prevent accidents. If everybody followed the above advice, we'd see a lot fewer fatal accidents involving pedestrians and cyclists.
Just as most advice about preventing rape seems to be targeted at women -- the group more likely to be a victim and less likely to be a perpetrator -- there seems to be vastly more advice about traffic safety targeted at cyclists, along with the assumption that motor vehicle operators know everything and can do no wrong. And just as conventional rape prevention advice perpetuates rape culture, the emphasis on cyclists perpetuates a culture where hit-and-run accidents are common and law enforcement (at least against white drivers who break the law) is rare.
The reality is that "safety" tips aimed at cyclists don't make anyone safer -- they just discourage cycling by making it seem dangerous, as well as empowering motorists to terrorize cyclists ("it's her fault I ran her over, she wasn't wearing a helmet"). And discouraging cycling actually does make it more dangerous to be a cyclist -- the fewer cyclists are on the road, the less likely it is that motorists will know what to do when they encounter one. Vehicular cycling (that is, riding a bike like a car and obeying traffic laws) does make cycling safer, but such "tips" rarely promote it since it sometimes involves taking the lane where it is legal to do so, and that would inconvenience motorists.
In any case, unless you always follow every item on the above list when you're driving a car, you really have no business criticizing cyclists' behavior. You should be focusing on your own obligation to use your vehicle in a responsible way.
TMI: Multithreaded Monday
Aug. 12th, 2013 08:50 pmWhile working on rustpkg, I discovered something was weird with OS X process spawning. For rustpkg I was able to work around it, but I thought I should isolate the test case anyway. The conclusion, so far, is that something is really weird with OS X process spawning.
And at some point tomorrow, I have to finish some paper reviews, documentation for my recent rustpkg changes, preparation for interviewing a candidate on Wednesday, my weekly status report, and checking if any pull requests I could review are in the queue. All of which I meant to do today. Good times.
The next big thing to finish will be using workcache. I'm realizing that the workcache library itself needs some work before rustpkg can use it. The first thing to do was to change it so that it actually saves and reloads its database to disk, so that you can see changes in between runs of rustpkg, and not just within the same run. I did that, and now it's complaining about something missing from the file when it reads it back in, which is at least progress.
When running up-to-date master on my local machine, I was noticing a segfault while building the docs that obviously didn't happen on the bots, but it seems to be due to the new scheduler and the handling of stack overflows (I git-bisected and saw that the first bad commit was the "Turn on the new runtime" commit). There's a patch in the queue to increase the stack size, so I'm going to go home and hope it'll magically be fixed in the morning.
TMI: Quick update
Aug. 6th, 2013 07:04 pmThe workcache branch is also blocked, because I don't understand the rules about what you can and can't capture in a ~ closure. I will probably need to consult with someone tomorrow.
In the background, doing some AST refactoring that is proving harder than I thought (as it always does).
TMI: Done! (until code review, anyway...)
Jul. 31st, 2013 07:33 pmI'd say more, but I want to get out of the office. Next priority is workcache (you know, so rustpkg can actually be a non-ridiculous replacement for make...); I should also be able to get #6409 out of the way in the foreseeable future.
No wait, one more thing! The very next thing I do will to be to get rid of the local_path / remote_path hack. See, right now, in rustpkg, package IDs look something like:
struct PackageId {
short_name: ~str,
local_path: LocalPath,
remote_path: RemotePath,
version: Version
}
LocalPath and RemotePath are both just newtype'd Paths (where Path is a path on the filesystem -- basically a newtype'd string with some extra operations):
struct LocalPath (Path); struct RemotePath (Path);
which in turn is special syntax Rust has for something like:
struct LocalPath { localpath: Path }
In any case, I implemented this because a lot of package names have dashes (hyphens) in them, but a Rust identifier can't contain a hyphen. Before #8176, because of extern mod directives, a package name had to be a legal Rust identifier. I implemented a hack in rustpkg that turns '-'s into '_'s, but, so it can still find the original directory on disk, keeps the original name with '-'s around as the RemotePath. Now that extern mods can have a path attached, though, I can just get rid of this special case. Hurrah!
TMI: Crawling towards doneness
Jul. 30th, 2013 06:51 pmNot very interesting today, hopefully tomorrow will be more interesting.
TMI: So close, and yet...
Jul. 29th, 2013 06:45 pmI got the whole test suite to pass with my branch-that-took-forever that extends the extern mod syntax! But as I often do, I decided I should address the many NOTEs[*] I'd added to the code before submitting a pull request. There's always the tension between getting it right and getting it in the codebase, but this time I felt like there were too many embarrassing things, tests passing or not.
One of the things is that I changed the PkgId constructor (shockingly, that's for the type that represents package IDs) to take the current directory as an argument, in case you give it something like foo/bar/baz and that turns out to be a git repository and you want to get the version. Well, that was super silly of me, because as with everything in rustpkg, we want to search the RUST_PATH rather than searching in the current directory in some ad hoc way. So I fixed that (I always enjoy getting paid to undo my own work) and now all but one of the rustpkg tests work, but I'll leave that for tomorrow so I can have a victory early in the day.
TMI: Feminist Friday
Jul. 26th, 2013 07:50 pmOn the train on the way there, I finally got my extern-mod test case to compile successfully. Among other things, it turns out the Mac OS X dynamic linker isn't very happy when you rename a .dylib file. So now, rustpkg is doing what it should have been doing and preserving the long name (libwhatever-hash-version.dylib) in the installed library, instead of building build/packagename/libwhatever-hash-version.dylib to lib/libwhatever-version.dylib). I'm not sure why I was ever doing it that way, except my own ignorance!
One thing that I still need to do is make rustc print out an error message that suggests using rustpkg to download the package, if the user writes something like extern mod github.com/catamorphism/whatever and there's no locally cached copy. rustc isn't responsible for downloading anything off the network, git is, but currently it'll just treat it like any other path that doesn't exist.
I also rebased my branch to use workcache for avoiding recompilation, now that Graydon's pull request to make the workcache context sendable landed. I'm sure it's not going to work yet, since I just did the minimum necessary to invoke the workcache and make it typecheck. Still waiting for the build there.
Finally, I got my pull request for handling non-numeric tags into the queue. Graydon pointed out I shouldn't assume a given refspec is meant to be a tag, and that git can do a pretty good job of working out whether it's a tag, revision, or so on. So I fixed that, and now it's just waiting for bors to get to it.
I worked more on extended extern mod names, but didn't finish that. Hacking on metadata::{filesearch, loader}: always a good time.
I also found this delightful bug to do with calling run process functions and specifying an environment, though I'm still not convinced it's not due to something weird happening on my machine. So if someone wanted to try reproducing it, that would be awesome.
In the background, worked a little more on making rustpkg understand tags that aren't version numbers. After talking to Graydon, we won't support branches after all; just tags. If a tag doesn't look like a version number, we'll match on it exactly rather than treating it as a number that can be compared with other versions.
TMI: More of the same!
Jul. 22nd, 2013 06:27 pm
diff --git a/mk/tests.mk b/mk/tests.mk
index 770e728..c3659e7 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -345,7 +345,8 @@ $(3)/stage$(1)/test/rustctest-$(2)$$(X_$(2)): \
$(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \
$$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS) \
- $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2))
+ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
+ $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2))
@$$(call E, compile_and_link: $$@)
See, totally trivial! Um. Workcache changes haven't landed yet, so I didn't work on that. Rather, I spent the rest of the day futzing with directories, again, because I haven't done enough of that, as part of making-general-extern-mods work. Admittedly some of that had to do with the above change -- making the test suite able to run rustpkg from the target directory instead of the host directly. (Cross-compilation thing. Makes perfect sense. Yeah.)
Another recompile is running, but it's time to go home.
TMI: link names and hidden dependencies
Jul. 19th, 2013 07:28 pmMostly I worked on #6407 some more. This is harder than it looks; among other things, I have to change what's expected in the link metadata so that a link name can be a qualified path. That's because if you're referring to things like extern mod foo = github.com/whatever/foo, the metadata loader expects the link name in the metadata in the compiled library to be github.com/whatever/foo. So I have to change the driver. And stuff. This necessitated some refactoring in rustpkg with respect to what paths get passed around and how it figures out where to put output files, which is totally unremarkable except in its annoyingness.
TMI: Tiny steps
Jul. 16th, 2013 04:55 pmrustpkg discovers dependencies as it goes along, doing parsing, so you could start installing one package A, find another package B that needs to be installed, go ahead and install B, then go back to building A. So the natural way to rewrite this code using workcache involves passing around the workcache database to recursive calls. But that's not allowed, since it's not sendable and since the workcache wrapper requires a sendable closure.
Graydon agreed it would be better to rewrite the workcache code so that the context is sendable, so now I'm blocked on him doing that.
In the meantime, though, I also figured out the duplicate package problem from yesterday. It was really silly; I was adding in both the .rust subdirectory of the home directory and of the current working directory -- and all ancestors of the CWD. But what if the home directory is an ancestor of the current working directory (as one would normally expect it to be)? sadtrombone.wav
And in the meantime, finishing extern mod is blocked on fixing the duplicate-package bug, which is easier now that I've found it.
Now I'm working on a few different things at once:
- Started trying to figure out how the mysterious workcache module works, as a prerequisite for 7075 (the "make rustpkg actually not rebuild everything all the time" bug).
- With #7681 landed, tried to un-block my pending pull request for making rustpkg build work without a package argument. I'm noticing that install doesn't actually check that a package with the same package ID isn't already installed, so I have to fix that, even though it's not related.
- For #6407, I have to move some code from rustpkg into rustc so that rustc itself knows how to use the RUST_PATH. Working on that.
TMI: Think globally, build locally
Jul. 9th, 2013 06:34 pmTo fix it, I made rustpkg handle fetching from a local git repository, and changed the tests to test that instead. If you supply rustpkg with a package ID referring to a github repo that's outside the RUST_PATH, it will clone that into a workspace in the RUST_PATH and build from there.
I can now go home feeling a bit more accomplished.