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.

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 <[EMAIL PROTECTED]>


Reply via email to