tim: Tim wearing a flannel shirt, against a brick wall (Default)
I more-or-less finished external crate inference, at least in the local-crate case. I spent most of the time on that fighting with the borrow checker. To add the right directories into the session's list of additional library search path, I wrote some visitor code that looks at all the view_items in the crate. There are two types of view_items: extern mod directives and use directives. For this, I only care about extern mod directives.

The problem is that the visitor wants an @-closure, which can't use borrowed pointers, so accumulating a mutable vector of found extern mod thing seems... hard. I eventually gave up and worked around it with massive amounts of copying.

Once I get some tidy stuff cleaned up, and figure out the copy issue, I'll be ready to check that in and close #5681.

If I can finish #6407 (allowing extern mod directives to name remote packages) and #5683 (the test runner for rustpkg, which I've already started a rudimentary version of) tomorrow, then I'll be on-schedule so far. It might happen.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
The remote-package-ID patch landed, so I'm on to teaching rustpkg how to find external crates.

Currently, if you include an extern mod directive at the top of a Rust file, like:
extern mod foo;


supposing foo lives in some arbitrary (non-system) directory like /home/tjc/quux/lib, you have to pass in a -L flag to rustc, like: -L /home/tjc/quux. That's so it knows where to find the foo library to link with.

But in rustpkg we're trying to make it possible for files to self-describe, and get away from compiler flags as much as possible. So rustpkg will, itself, scan files in the crate it's trying to build for extern mods and try to build their dependencies automatically. So far, it only looks in the same workspace that the package it's building is in, since it only knows about one workspace (the current directory). But once I implement RUST_PATH, that'll be a lot more powerful.

Even more so, the plan is to change the syntax of extern mod directives so they don't have to just name identifiers. So you'll be able to write:
extern mod foo = "github.com/catamorphism/foo";


Eventually, this will cause rustpkg to try to fetch the foo package from my repository on github and install it. The package can be referred to in the code with the short name foo, since the entire URL fragment isn't a valid Rust identifier.

So far, I've implemented the part where rustpkg scans for extern mods and builds the named packages and dependencies if possible. I'm working on getting it to pass the right directories to the rustc driver so as to actually find the resulting libraries.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Back once again from another (shorter) absence -- I had to go down to Olympia to say goodbye to my 11-year-old rabbit, who'd had a stroke and needed to be euthanized. This spring, I'm telling you...

This morning, Ron Garcia came over to the office from UBC to visit us and hear about Rust. It's always good to get a bit of external validation, and it seems like he and our team have at least some research interests in common.

After lunch, I got down to hacking, having previously gotten somewhat derailed by adding a few more tests to #6418, the URL-like package-ID pull request. I hit the "computing fictitious type" ICE that a lot of other people had hit, and so I figured it was time for me to fix it, since I knew it probably related to my recent changes to do with derived errors. Turned out the ICE has to do with erroneous matches on patterns of the form (foo, bar) where the scrutinee doesn't have a tuple type -- this is a common error because of, among other reasons, argument patterns where it should really be &(foo, bar). So I fixed that, but that was all over the weekend.

Today, that patch having landed, I went back to finishing #6418. Partly this required resolving merge conflicts, due to the intervening make-vectors-not-implicitly-copyable change which made PkgIds non-implicitly copyable. Partly, I fixed the ugly hack I was using where output file names would be of the form foo-0-1 instead of foo-0.1, where 0.1 is the version number. I was doing that so that rustc wouldn't drop the portion after the last dot in order to make the output .o filename. But it turns out the correct output file to pass is just foo, since for libraries, rustc pulls the version number out of the metadata (not the filename) anyway.

And so I can get this checked in before I leave the office tonight, I hope (which is a bit of a race against time, since all the bathrooms in the office are out of order).
tim: Tim wearing a flannel shirt, against a brick wall (Default)
I finished yesterday's work, in the "tests pass" sense, so now rustpkg can recognize package IDs that resemble URL fragments. For example, I can write:

rustpkg build github.com/catamorphism/test-pkg

and rustpkg will fetch the test-pkg repository from github, then build a local cached copy of it.

We also had a useful meeting today to discuss what Servo needs from rustpkg, resulting in ten or so new github issues. (The rustpkg metabug collects them all.) One thing we talked about will actually obviate the need for the tedious string-munging that I talked about in yesterday's post. Specifically, we'll change the syntax of the extern mod directive -- which says "link this external crate with this program" -- to take a string rather than an identifier. So instead of:

extern mod foo;

we'll allow:

extern mod "foo";

or

extern mod "github.com/catamorphism/foo";

But in the latter case, how will I refer to foo in my code, since the package ID here is not an identifier? The Rust compiler will either guess the package's short name from the package ID's file stem if it's a valid identifier; in other cases, it will support this syntax too:

extern mod foo = "github.com/catamorphism/foo-bar";

that gives a package with arbitrary characters in its package ID a valid Rust identifier.

Not rocket science, but incremental progress towards the dream of writing the Rust build system in Rust.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
After taking three days off to fly to Europe, attend a funeral, and fly back, then some time to catch up on the inevitable email and bug-triage backlog, I'm back to working on remote package IDs for rustpkg.

On the plane over the weekend, I was working on getting rustpkg to accept package IDs that resemble URLs. For example: rustpkg build github.com/catamorphism/test-pkg. So, not really a URL, but a URL fragment. rustpkg should do the obvious thing and use git to clone the remote repo into a local directory, then build the local cached copy as usual.

You'd think this wouldn't be hard, but I ran into issues because internally, rustpkg normalizes hyphens into underscores so that all package IDs can be legal Rust identifiers. (Rust identifiers can't contain dashes, but can contain underscores.) But for a remote package, you still need to keep track of the original package ID since that dictates the URL you need to fetch from. I solved this by adding two fields, a local path and a remote path, into rustpkg's internal representation of package IDs, but I'm still not sure this is the right solution. It beats calling a normalize function in an ad hoc way everywhere, as I was doing before, though.

Then the second thing is being consistent about which build artifacts contain the version number as part of their name (for example, the library name does, but the installed executable doesn't...) though I'm not sure why this wasn't coming up before.

And, doubtless, more than that. Details, details...
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Life does not, apparently, go on as fast as one hopes; yesterday I was too exhausted and depressed to work and took a day off. To which I credit me being semi-functional today.

In any case, today I learned about the magic of rustc's filesearch module. What seems like eons ago but probably only a week ago, I set up some wacky symbolic link inside my build directory to get rustpkg to be able to find the core library. After pulling a new LLVM version, I had to blow away my build directory, as one often does. And thus, the rustpkg tests no longer ran because once again, it couldn't find core. And of course, the same thing happened on the bots, causing tests to fail, because my hack was a truly terrible hack (that only worked on my local machine).

rustc infers the sysroot -- which is the root directory that it uses for searching for standard libraries -- from the name of the executable you're running. Keep in mind that rustc is just-a-library so there's more than one possible executable name. Most executables sit under build/x86_64-apple-darwin/stage2/bin/whatever in our build system (not even talking about installed builds here, just in-place builds). The stages refer to the stages of compiler bootstrapping, but for testing we usually run stage 2. And of course, the host and But it happens that the test executable containing all the #[test] functions lives in build/x86_64-apple-darwin/tests/ and so the parent directory getting inferred was totally wrong. The answer is basically for me to just add in some terrible hacks to override the sysroot from my test functions, but it took me a while to get to that.

They didn't tell me in grad school that there'd be days like these...
tim: Tim wearing a flannel shirt, against a brick wall (Default)
The past couple days, I've been unsurprisingly not very focused on work; you'll know why if you read my most recent blog post that doesn't have the "research" tag.

But life does go on. Having landed the file searching patch that I talked about in my previous Rust post, I went on to working on rustpkg install. Like a good little software developer, I wrote the tests first, making the actual implementation pretty painless. Right now my tests are failing because apparently, I'm creating directories with the wrong permissions. Although lsing the directories, they look fine, so the Rust permission-checking code I wrote was probably wrong.

That (and a triage meeting) was about all I could manage today.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Today's work was on bringing the reality of rustpkg up to the point described in my doc pull request, at least up to the point of the directory and file structure of packages and having rustpkg look for package source files in a src directory inside a workspace. Also, now it uses a one build directory per workspace for putting object files and other temporary files in, instead of one per package. A workspace is just a container for packages; right now, always a directory on your local filesystem, but in the future, also on github or some other remote server containing version control repositories.

Now most of the test scenarios that I checked in build, and I've crossed off one more task on the schedule. Yay crossing things off. This pull request contains the work I'm talking about.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
With rustpkg I'm trying as much as I can to stick to a tests-first/docs-first approach (I suppose strictly speaking, tests-first/docs-second), so this is my pull request for today: adding a draft of a manual (without much actual content, but starting to write things down) and rearranging the test scenarios again to have the directory structure that we agreed on.

I figure when I don't know exactly what I'm doing, writing things down as I go along (rather than waiting until the end to write the docs) helps me see if there's an area I'm still not clear on. I don't know why it's so hard for me to remember that that's the case for me :-)
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Today's work on rustpkg is all in my pending pull request. I wrote out a schedule containing all the significant pieces-of-work remaining on rustpkg that Graydon and I could think of right now, and estimated times for each task (like all software engineers I'm terribly bad at estimating time for things). I'm hoping having everything laid out in a linear fashion will help me stay on-track, though.

I'm also glad to have spent some time writing down hypothetical-rust-package-commands-that-should-work (in a text file in the pull request), even though we can't do automatic testing yet. It's good to know what you're doing before you do it...

As an end-of-the-day small task, I made the typechecker able to survive more errors; generally the typechecker should be able to emit a type error and then keep going (since most people like to see as many errors as possible so they can try to fix them in one go, rather than one at a time) but there are a few cases here and there where it's tricky to set up the right data in various environments for the typechecker to keep going. So there's two less of those cases now.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
I'd given feedback on a rustc pull request saying "try to get rid of that copy" in a pull request, but when asked how, I looked at the code and realized it wasn't easy to rewrite without a copy. So that was an hour gone!

Then, back to rustpkg; I started testing it on the test cases I wrote yesterday (just manually, for now, though writing a test runner needs to happen soon) and noticed that I wasn't naming the output executables or libraries correctly. So I added code to synthesize the link crate attributes with the inferred name and version, so you don't have to write it explicitly in the package file. Now, 2 out of 3 of my test cases work.

And finally, to round the day off, removing a few more bad copies.

Next:

  • Error out in the case where no lib.rs, main.rs, bench.rs, or test.rs fine is found
  • Split tests into pass and fail subdirectories (for tests expected to build correctly, and tests expected to fail)
  • Add a test case to test that a package without a lib, main, bench, or test file fails.
  • Submit a new pull request.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
I landed this commit from the end of last week, cleaning up tests and error handling in rustpkg, and I submitted this pull request that allows rustpkg to build executables.

When talking to Graydon about how to do regression tests for rustpkg, I realized I'd been doin' it wrong, at least a bit -- the new policy for rustpkg is that you're going to have to name your crate files main.rs if you want to get an executable and lib.rs if you want to get a library (both can coexist), with additional options for building tests and benchmarks. I'd been allowing an additional option, which is naming your main crate foo.rs for a package named foo, and inferring whether or not it was a library based on the presence or absence of a main function. This was all wrong, so I'll have to undo that work tomorrow. I'm trying to tell myself I'm "exhibiting flexibility and willingness to admit mistakes" rather than "spending all my time writing code that I then delete".

For an easy end-of-the-day task, I decided I'd try to kill off a few bad copies, but that involved rebasing a branch, which involved rebuilding LLVM, which is evidently going to involve deleting my build/ directory and starting from scratch. Which, amusingly, emphasizes the need for a functional rustpkg!
tim: Tim wearing a flannel shirt, against a brick wall (Default)
My pull request from yesterday landed, so I'm on to further cleanup. First, I submitted another pull request to use a condition for error handling instead of making a function return an Option. Conditions are supposed to be for rare errors; this particular case was the situation where creating the build directory in the package directory to put the build output in fails. I figured that would be pretty rare. I hadn't really written code with conditions before, but they're about as simple as it gets. Sort of like exceptions, but simpler and implemented in terms of Rust macros.

For my next trick, I wanted to make sure that rustpkg could compile a package that doesn't have a package script. For realism, I decided to see which of the Servo submodules had a relatively simple Makefile, meaning that rustpkg should be able to build it as-is; I picked rust-core-foundation, and am working on getting it to build now.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
So I finally submitted a pull request with my initial work on rustpkg. I'm embarrassed at how little this patch actually does; I've tested it with one command, build, on one package, my fork of rust-sdl. The difference now is that as per #5679, rustpkg doesn't require a package to explicitly declare its ID and version number; instead, it just looks for a directory with the name you give it. So if you write rustpkg build rust-sdl, rustpkg will expect the current directory to contain a directory called rust-sdl that contains the package. Likewise, if it was rustpkg build rust-sdl-0.1, it would infer the version to be 0.1 (though I don't think I actually implemented that part yet).

I still have to figure out how to write unit tests for this. Also, rather than trying to do everything at once, I made several of the commands other than build fail with "not yet implemented". rustpkg wasn't in a great state anyway, so I don't think this will make anyone too unhappy. I think it's better to explicitly fail than quietly do something not-quite-right.

Hopefully I can proceed faster now that I'm past the awkward initial "what am I doing?" stage of the project.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
My titles are un-creative lately.

So remember when I said I'd gotten rust-sdl building with rustpkg? I really... didn't. Or else, I broke a whole lot of code while rebasing. Either way, I spent today and yesterday (when not paying attention to the work week proceedings) getting it to work again. And, just now, I finally did, after learning a valuable lesson about Unix command line argument processing that doubtless I knew in 2004 but didn't know yesterday.

Next, continue cleaning up code so I'm not embarrassed by "oops, how did that get in there?" moments when I submit a pull request.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Today was the beginning of the research work week here in Vancouver, and I don't know about you, but I can't follow a discussion for 8 hours straight -- even with a break for lunch in the middle. So I tried to listen as well as I could to the parts that overlapped more with my knowledge, and during the rest, hack on stuff and listen with one ear.

I started cleaning up my rustpkg changes in preparation for submitting a pull request. Part of that was adding more documentation and such, part was removing bits of code that aren't needed now that we're using package IDs and not requiring a package script. I'm not sure whether to break existing code that uses rustpkg (not that there's a lot of it yet) or try to be backwards-compatible.

After that, it'll be submitting a pull request for the changes I made to rust-sdl, making the clean command work (since it's annoying to have to manually delete files every time to make sure my changes still worked), and making rust-http-client build as my second test project. And then, of course, making all the other commands work. That's just the beginning.

Figuring out how to write unit tests for rustpkg will be interesting as well. Necessary, but I'm not sure how.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
I said yesterday that I got LLVM to build without a Makefile, but I didn't, really. The Android-related message that I thought was a warning was actually an error, but it took me most of the day to figure out for sure. The cause of the problem? There was code in our Rust wrapper for the LLVM library that was unconditionally initializing the command-line arguments on every call to LLVMRustWriteOutputFile. Since rustpkg may call this function twice -- once to write the executable for the package script, and one to write the executable or library (library, in this case) we're compiling, the error resulted. Cryptic for several hours, to crystal clear within a minute. This wasn't a problem in previous iterations of rustpkg since the change to add some Android-related flags was made recently.

Fixing it was easy, since apparently in LLVM, the flags that say whether a particular command-line flag is toggled are global state, and I submitted a pull request.

But I'm still kicking myself that it took me hours to track this down. Software engineering, folks.

Next, cleaning up the changes I made to rustpkg and rust-sdl (in the latter case, getting it to build with incoming Rust) so I can actually submit pull requests!
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Rust 0.6 happened!

I set aside the trans bug I was working on before, just like I said I would do, because trans badly needs the Hatchet of Refactoring, but now is not the time.

Instead, I went back to working on rustpkg; the work that needs to be done is now better outlined (by Graydon). In the meantime, though, I'd wanted to make rustpkg able to build an actual, existing package and infer the package name and version from the path name. I succeeded in doing this today, with rust-sdl, except that I got some warnings at the end about the Android back-end that I need to investigate. The notable thing is that rust-sdl previously had a Makefile that renamed a symbol in the existing SDL library before building; I ported that logic into a package script -- a Rust file -- instead, so now it builds without a Makefile.

Of course, one of the things rustpkg needs to do is build packages that don't have a pkg.rs file -- in the current trunk version, it always requires one -- so perhaps I didn't pick the best example package to start with.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
The release work continues apace, with just 3 open issues left! I worked on documentation a bit and then when it seemed like there was nothing blocking the release that I could easily finish, went back to one of the bugs that got deferred, #4850. I had done some work on this last week but got over-ambitious in trying to restructure trans, when the urgent thing was to fix the bug.

Once I started over, with the knowledge I gleaned from last week's debugging, it was pretty obvious that the issue was that trans code was assuming that the self argument to a trait reference is always passed by reference. But Rust allows traits to be declared with their self argument passed by value; depending on what type self actually is (and this is usually, but not always, known at compile time, since Rust compiles polymorphism by monomorphization), that means either moving it into the callee, or copying it. So there was some code assuming self was passed by reference, other code assuming it was passed by value, so in some cases with by-value self, the result was generated code that segfaulted.

It seems like the trans code could be better structured as far as how many pieces of code know things about self. But I'm trying to make minimal changes right now, and am just patching up those places as they appear to take into account that the self argument to a method might not always be a pointer. However, I'm worried that the fact that the size of the self argument depends on the monomorphized code for the method is going to cause problems. It hasn't yet, but I'm afraid it will, and that this will mean bigger restructuring is needed for trans.

I'm setting this aside in any case once we tag the release, though, and moving on to focus on rustpkg for a while, so I don't get totally lost in bug-fixing.
tim: Tim wearing a flannel shirt, against a brick wall (Default)
Down to 35 open issues for the release. I'm still working on #4439 and trying to untangle the mysteries of owned self. Since it started looking like we're not releasing 0.6 this week, I decided (quite probably unwisely) to rewrite a lot of the trans code to use the Datum type, to make the error easier to track down. The older trans code passes around raw LLVM values, whereas some of the newer code uses a Datum, which is an LLVM value bundled with a Rust type t and an annotation as to whether this value is a value of type t, or a pointer to t. Modernizing things is hard and tedious and I don't really know whether it's more or less time-consuming than actually tracking down the bug without modernizing the code. But that's how it goes.

I also added a span (location in source code that tells you the line and column number of a location in some source file) field to the Datum type, which I don't know if reviewers will object to when I try to check it in, but it sure makes debugging easier!

I feel like I should be doing something more urgent for the release, but I don't know what it is.

Profile

tim: Tim wearing a flannel shirt, against a brick wall (Default)
Tim Chevalier

May 2013

S M T W T F S
   1 2 3 4
567 8 9 1011
1213 14 15 161718
19202122232425
262728293031 

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Style:
Yvonne

Expand Cut Tags

No cut tags