-
Notifications
You must be signed in to change notification settings - Fork 12.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
Support for custom build logic in Cargo #1861
Support for custom build logic in Cargo #1861
Comments
My impression is that for compiling rust code we kind of want to avoid having cargo delegate to other build systems (cargo should just build the crates). For complex non-rust components I suppose something like this is inevitable. Do you need this much flexibility currently for the leveldb bindings? |
Most of the source code could probably be put into crate attributes with The main thing I would like to support, that this scheme allows, is configuration based logic before the build. LevelDB has optional snappy support for compressing blocks that hit the disk; I would like to be able to detect a Something like this can easily be supported with the above framework, but it does need a feature like #612 as well (because the configure logic needs to give some extra crate attrs.) It's not required, but it's nice to enable; especially as compression can regularly offset the I/O required for disk writes/reads enough to make a noticeable improvement, in my experience. Perhaps the scope here can be narrowed, to only encompass configuration logic for Cargo? I will say something like this is rather inevitable IMO, when you want to integrate a more complicated build scheme into Cargo packages - but of course an issue like this is also an issue of cost analysis - it's potentially not worth adding all this if we only have 1 or 2 packages (mine) using part of this infrastructure for like, the next year or however long. And when others come along, maybe it still won't be sufficient for them, or it'll just be terrible. ;) I'm more than willing to narrow down the scope here. An issue like this brings into question a lot of cargo's responsibilities/expected workflow, so please - tell me what you think. :) |
I do think we should add the minimum necessary to support current use cases, particularly because I just don't know much about how to properly design a package manager, nor build system (and I'm not sure exactly which cargo is). Maybe we can investigate what npm, cabal etc. do to support foreign code. I completely agree that something is necessary here. I'm a little scared of screwing this up, but I guess we can afford to make some mistakes here. We need to get graydon's buy-in before expanding cargo in this direction. I believe he as expressed strong opinions about not executing arbitrary build scripts before. I realize this is extremely non-committal and I'm sorry. |
I'm ok trying the design you suggest with cargo delegating to a script. There's no reason to hold this up if you need the feature now. |
Hi, I'm going to ask for a little bit of care and patience finding the right balance on this issue. Not to say that you shouldn't experiment -- please do! -- but I think that finding a "right" point that satisfies the various conflicting tensions in this design space is going to take a few iterations. With that in mind, my general preferences are:
You are probably going to block, here, on conditionalizing attribute processing, supporting some kind of read/write or read/rebind access to the dictionary of configuration-time variables, as well as adding some fresh attributes for new tasks. You are not the only one. I am somewhat blocked on it too and @DylanLukes is poking around at it as well. I'd welcome coherent work in this space. We need a "grammar" relating conditionals, variables, and attributes. There's a sketch @DylanLukes wrote over in https://github.com/mozilla/rust/wiki/Proposal-for-attribute-preprocessing and a bug #1242 that talks about this, and he put up a gist the other day as a result of a conversation we had on IRC, but I'm having trouble tracking it down. Talk some with him, or catch me on IRC tomorrow, I'd like to see more of this stuff come into focus soon. It's important if I keep saying "use attributes!" for there to be some credible system for expressing more complex logic in attributes. |
That proposal is very out of date... I'll TRY to have a new one with my new design up today sometime between 11:20 and 12:07. If not, I should manage by the end of the day. It'll be easier to discuss with something relatively concrete in place. |
This can probably be closed now. |
Closing as obsolete. |
The metaticket is #1850.
Summary: invariably, due to wanting to keep packages self contained, write wrappers for C++ code, invoke configuration-based build logic (i.e. I want to invoke some transparent compression, providing
zlib
is on the system, etc.) or any number of things, there is often going a need for a more complicated build system than what the crate mechanism provides. Specifically, libraries which do things like foreign bindings are extremely prone to needing this in my experience a lot of times, and requiring arduous - sometimes totally manual - installation on the users part is incredibly unsatisfactory.As of right now, Cargo only manually looks for crates in the source directory, followed by hitting them with
rustc
. I envision a world where most of the time - this is all that's needed. Cargo should not be responsible for complex code building logic.However, it most certainly needs support for allowing library creators to defer to a build system to run if the simple case doesn't cut it. The compression example is a real one - in writing Haskell bindings for LevelDB, I found it very nice that I could use autoconf to detect if the
snappy
compression library was available, and compile the LevelDB source code inline with that assumption if it was.I like the homebrew approach. Any build system it wants - but you express the build in Ruby as a 'formula' for building it, using system commands. So you can have cmake based software, autoconf based, just something with a makefile, etc. The formula merely invokes system commands and fails if they err. One thing to note here is that Homebrew does expect you to respect the installation prefix normally, so it gives ruby scripts a 'prefix' variable you can pass on, etc.
I envision something similar for Cargo - just a way to run commands for a build. A nice aspect of this is Cargo still doesn't really do any building on its own, you just give it commands. If your actual package build is handled in an
autoconf
andmakefile
like style, you can always just build like that during development. The metadata is only need to inform Cargo how to run a build at installation time.With the running LevelDB example, let's say I have a package, just called
leveldb
. It has a file structure like this:Name is arbitrary, but
build.cargo
contains a list of commands to run - it's basically the trigger for custom configuration logic. In fact, you could just say it's any arbitrary executable script, e.g:and
make
would take care of callinggcc
andrustc
on the crate, etc. This example in particular is kind of half-assed, but you get the gist. Ultimately, I think Cargo should always defer the responsibility of building onto a build system, and not say "you must have a configure script" or "must use a makefile."build.cargo
is just some script - you could write it in Perl or ruby/etc. But there are downsides to this approach:msvc
, and robustly on windows so people will need a way to specify builds for different platforms, particularly windows. I have no idea what this looks like.This does allow even the simplest of build systems to work, though. As an aside, this, along with support for something like #612 would most certainly make it very possible to bind a lot of packages, especially when you want autoconf-style feature detection at configuration time.
So I am personally a fan of this method or something like it. Does anybody have objections to something like this? Thoughts? I'm particularly hazy on saying something as flat out as "
build.cargo
is executable, just do it", but it is simple and flexible.The text was updated successfully, but these errors were encountered: