buildr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Assaf Arkin" <>
Subject Re: request for enhancement: compile, package and artifacts support for C++
Date Mon, 28 Jul 2008 20:29:37 GMT
On Mon, Jul 28, 2008 at 5:18 AM, Ittay Dror <> wrote:
> another issue, inline
> Ittay Dror wrote:
>> Hi,
>> I'm working on adding C++ support to buildr. I already have a prototype
>> that builds libraries and executables in Linux. I'd like to share some of
>> the difficulties I had and request changes to buildr to accommodate C++ more
>> easily. (Right now, I've created parallel route to that of building
>> Java-like code)
>> compile
>> ========
>> overview
>> --------------------
>> the compile method in project returns a CompileTask that is generic and
>> uses a Compiler instance to do the actual compilation. In C++, compilation
>> is also dependency based (.o => .cpp, sometimes precompiling headers). Also,
>> the same code can produce several results (static and shared libraries, oj
>> files with debug, profiling, preprocessor defines turned on and off). [1]
>> there is the 'build' task, which is used as a stub to attach dependencies
>> to.
>> suggestion
>> ---------------------
>> * there should be an array of compile tasks (as in packages)
>> * #compile should delegate the call to a factory method which returns a
>> task (again, as in packages)
>> * generic pre-requisites (like 'resources') should either be tacked on
>> 'build' (relying on order of prerequisites), or the compile task can be
>> defined to be a composite (that is, from the outside it is a single task,
>> but it can use other tasks to accomplish its job).
>> package & artifacts
>> =========
>> overview
>> ---------------
>> buildr has a cool concept that all dependencies (in 'compile.with') are
>> converted to tasks that are then simple rake dependencies. However, the
>> conversion is not generic enough. to compile C++ code against a dependency
>> one needs 2 paths: a folder containing headers and another containing
>> libraries. To put this in a repository, these need to be packaged into one
>> file. To use after pulling from the repository, one needs to unpack. So a
>> task representing a repository artifact is in fact an unzip task, that
>> depends on the 'Artifact' task to pull the package from a remote repository.
>> furthermore, when building against another project, there is no need to
>> pack and unpack in the repository. one can simply use the artifacts produced
>> in the 'build' phase of the other project.
>> finally, in C++ in many cases you rely on a system library.
>> in all cases the resulting dependency is two-fold: on a include dir paths
>> and on a library paths. note that these do not necessarily reside under a
>> shared folder. for example, a dependency on another project may depend on
>> two include folders: one just a folder in the source tree, the other of
>> generated files in the target directory
>> suggestion
>> -------------------
>> While usage of Buildr.artifacts is only as a utility method, so one can
>> easily write his own implementation and use that, I think it will be nice to
>> be able to get some reuse.
>> * when given a project, use it as is (not 'spec.packages'), or allow it to
>> return its artifacts ('spec.artifacts').
>> * if a symbol, recursively call on the spec from the namespace
>> * if a struct, recursively call
>> * otherwise, classify the artifact and call a factory method to create it.
>> classification can be by packaging (e.g. jar). but actually, i don't have a
>> very good idea here. note that for c++, there need to be a way of defining
>> an artifact to look in the system for include files and libraries  (maybe
>> something like 'openssl:system'? - version and group ids are meaningless).
>>  * the factory method can create different artifacts. for c++ there would
>> be RepositoryArtifact (downloads and unpacks), ProjectArtifact (short
>> circuit to the project's target and source directories) and SystemArtifact.
>> I think that the use of artifact namespaces can help here as it allows to
>> create a more verbose syntax for declaring artifacts, while still allowing
>> the user to create shorter names for them. (as an example in C++ it will
>> allow me to add to the artifact the list of flags to use when
>> compiling/linking with it, assuming they're not inherent to the artifact,
>> e.g. turn debug on). The factory method receives the artifact definition
>> (which can actually be defined by each plugin) and decides what to do with
>> it.
> ordering
> =========
> overview
> -------------------
> to support jni, one needs to first compile java classes, then run javah to
> generate headers and then compile c code that implements these headers. so
> the javah task should be able to specify it depends on the java compile
> task. this can't be by depending on all compile tasks of course or on
> 'build'.


compile do |task|

This will run javah each time the compiler runs.

> suggestion
> -------------------
> when creating a compile task (whose name can be, as in the case of c++, the
> result library name - to allow for dependency checking), also create a "for
> ordering only" task with a symbolic name (e.g., 'java:compile') which
> depends on the actual task. then other tasks can depend on that task

And yes, you'll still need that if you want to run the C compiler
after the Java compiler, so I think the right thing to do would have
separate compile tasks.


>> I hope all this makes sense, and I'm looking forward to comments. I intend
>> to share the code once I'm finished.
>> Thank you,
>> Ittay
>> Notes:
>> [1] I don't consider linking a library as packaging. First, the obj files
>> are not used by themselves as in other languages. Second, packaging is
>> required to manage dependencies, because in order for project P to be built
>> against dependency D, D needs to contain both headers and libraries - this
>> is the package.
> --
> --
> Ittay Dror <>

View raw message