buildr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ittay Dror <>
Subject request for enhancement: compile, package and artifacts support for C++
Date Mon, 28 Jul 2008 09:42:39 GMT

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)

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.

* 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
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

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 

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.

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,

[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