On Jun 15, 2008, at 11:45 AM, Ittay Dror wrote:
Hi,
I want to create a plugin that will allow using Gradle to build C/C++
artifacts.
That would be very cool.
It might be also a good use case for implementing rules or synthetic
dependencies as offered by Rake. http://docs.rubyrake.org/user_guide/
chapter03.html
What do you think?
The issue I want to tackle is dependency management.
Basically, a project can create 4 types of artifacts: a library
(static /
shared) or an executable and header files. To compile, one needs the
headers, to link, one needs the library. So, in Ivy, if I have the
configuraitons 'executable', 'shared', 'static', 'devel', then
dependencies
map to 'devel->devel' and 'static'->'static' and executable/shared are
mapped to 'shared' or 'static' according to the type of library
that is
used. The different artifacts map to different configurations (via
publications).
In Gradle, I want to have 'shared' and 'static' dependencies of the
'compile' configuration and create from them the above Ivy
dependency. So if
i have 'compile-shared "some.org:amodule:1.0:shared"', it will
create an Ivy
module descriptor with a 'devel' configuration (for compiling) and
'shared'
configuration (for linking) mapped to 'shared' configuration of
'amodule'.
So far, sounds ok?
Yep.
In Gradle 0.2, which is planned to be released today, we have
introduced classifiers. The notation looks like: "org.testng:testng:
5.7:jdk14" which is similar to your one. On the other hand, this is
not relevant for C/C++ projects and as you provide an own instance of
the ModuleDescriptorConverter that should be fine.
My problem is then how to change the way Gradle maps the
dependencies in the
gradle file to Ivy modules. My digging shows this (for 0.1.4):
1. Ivy module descriptors are created by ModuleDescriptorConverter.
DefaultDependencyManger has an instance of it passed through its ctor.
2. The DependencyDescriptor is created by the Dependency instances,
created
by a DependencyFactory instance, also a member of
DefaultDependencyManger,
through its ctor
3. DefaultDependencyManager is created by
DefaultDependencyManagerFactory,
the instance of which is used by DefaultSettings and
ProjectFactory, both
are created statically through Build.newInstanceFactory (through
SettingsProcessor).
4. newInstanceFactory is called by Main and returns a closure, so
it is not
easily manipulated.
5. 'dependencies' used in the project file is a method in
DefaultProject
which calls DependencyManager methods. DependencyManager is an
interface,
I think all this means that I can't do what I want (extend the module
converter to create a special kind of Ivy module and create a new
Dependency
class so it create the right Ivy dependency construct).
I think this can be solved by using IOC conventions so that every
object has
'set' methods to set the services it uses. Then, even if Main/Build
create
default instances, a plugin can redefine them.
What do you think?
If I had Gradle written in Java there would be interfaces for all the
relevant classes and ctor or setter injection. For me Gradle has been
also an experiment how to possibly do things slightly different than
in Java. But I'm not really happy with the current situation.
First of all. Groovy has dynamic setters and getters. You can say in
Gradle 0.1.4:
dependencies. moduleDescriptorConverter = myNewConverterInstance
The big question is of course the type. In DefaultDependencyManager
we have declared: ModuleDescriptorConverter moduleDescriptorConverter
An alternative would be: def moduleDescriptorConverter (In Ruby for
example that would be the only choice). Than myNewConverterInstance
could be of any type (duck typing). And now we are in the current
dynamic vs static typing debate. I'm not sold on giving up static
typing. I love my IDE support enabled by this. I also think it makes
the code more readable.
Groovy, although an dynamic language, offers a kind of static typing
which Gradle usually uses. So how to do IoC then? What you can do is
to say:
dependencies. moduleDescriptorConverter = [convert:
{DefaultDependencyManager dependencyManager ->
myLogic
myReturnValue
} as ModuleDescriptorConverter
This assigns an instance of ModuleDescriptorConverter with an
overwritten convert method (I'm not saying that this is fantastic ;)).
Why not introducing interfaces like we would do in Java? We might
have to do this. Although interfaces in Groovy are somewhat a weak
construct. For example although the dependencies instance of Project
is of type DependencyManager, we can say dependencies.
moduleDescriptorConverter = something. This is not declared in the
interface but there is no runtime check for such stuff. After all
Groovy is a dynamic language. The only reason why I have introduced
the current interfaces is to avoid cyclic dependencies between packages.
My current favorite design would be to use a static language for the
core of Gradle which offers all the syntactic goodies of Groovy. For
the parts where we really need the dynamicity we would of course
still use Groovy (e.g. Project, Convention, Plugins, ...) On the
other hand, I have no plans to change this at the moment. I don't
feel its is that painful right now.
- Hans
Ittay
--
View this message in context: http://www.nabble.com/design-question-
tp17848015p17848015.html
Sent from the gradle-dev mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email