bug#9088: Java, JARS primary?

2013-05-15 Thread Michael Zucchi
On 15/05/13 22:39, Stefano Lattarini wrote:
> On 05/15/2013 01:52 PM, Michael Zucchi wrote:
>> On 14/05/13 03:47, Stefano Lattarini wrote:
>>
>>> Instead, let's start implementing something *correct*, in line with
>>> the Java philosophy, and with a clean API.  We'll think about enhancing
>>> it when (and if!) the need arise.

And then most of the objections are from trying the java way.  Oh well.

>> Seems the way to go.
>>
>> On that, here are a few more thoughts on java's specific way of doing
>> things ...
>>
>> files vs dirs
>> --
>>
>> java projects/build systems tend to have a fairly basic mechanism to
>> define the source tree(s) which would be nice to emulate, but may not
>> fit well with the portability requirements of automake.
>>
>> They simply define the root directory and let the build system do the rest.
>>
>> Not necessary but would be nice.  Or put another way it would basically
>> suck if it required every source file to be listed explicitly and auto*
>> having to be re-run every time one is added.
>>
> But then, how could make handle the case of generated java files?  I.e.,
> if half of your files are generated by (say) an awk+sed incantation,
> make has to know it must build them before trying to call the java compiler.
> But see below.

Well if that's a requirement, then it just has to be added right?  It's
not impossible, it's only software ...

Either explicitly listed separately or handled automatically, it's quite
easy to tell a file from a directory.

>> In a GNU makefile I can
>> just use $(shell find) (or other fancier stuff), but for automake?
>>
> The solution is simpler than it seems at first sight: we should just

Actually it isn't quite that simple.  I did consider this. More below
about resources.

> For an example of how this approach could work, take a look at the
> EXTRA_DIST support (and to the test 't/extra-dist-wildcards-gnu.sh').

Although ... one can specify directories to EXTRA_DIST (even if not
recommended).

EXTA_DIST is defined relative to the makefile it is in, but that isn't
good enough.  It works fine for a root makefile since well, its'
generating the source tree and that is by definition relative to the
root makefile.  For jars it needs to be relative to a another location
which is relative to the makefile.

The bit about nobase in the manual has an impractical solution of
listing every directory separately.

Somehow the makefile needs this information, either by listing it or by
it's location, it cannot determine it automatically.  More detail and an
example well below.

>> makefile location
>> -
>>
>> C projects often have a make file per directory, java has the build
>> script at the top-level at least, outside of the source trees.
>>
>> This is desirable.
>>
> In some ways, this is desirable also for C projects actually; see the
> article "Recursive Make Considered Harmful" from Peter Miller:
> 
> 

Yeah well that's just an opinion.  I don't like it myself because it
makes emacs a total pain to use and I personally consider that pretty
important.

>> For the resource files the Makefile needs to resolve the resource root,
>> and strip it out of the names used for the dependencies.  So either it
>> needs a (set of) explicit resource_root, resource_root_files variables,
>> or it just needs to be defined as the root dir and handled either in the
>> makefile fragment or in automake.in.
>>
> Doing too much pre-processing in automake.in (that is, at Automake time)
> would prevent us from being able to grasp GNU make specific stuff.  So
> let's try to keep such pre-processing at a minimum.

I'm only talking about iterating a list of strings and printing them in
various ways, i'm pretty sure it does that kind of thing already.  It
wont be running find or walking directory trees since that doesn't
provide anything useful at 'make' time.

>> javadoc, jni, check/test, etc
>> 
>>
>> Some built-in support would be good.  javadoc is easy, check/test should
>> run junit tests I guess although i'm not too familiar with junit,
>>
> Or we might leave that to the use from now (they can use the 'check-local'
> target), and maybe implement it in a later Automake version, once an usage
> pattern has emerged (and most importantly, *if* there actually is any
> request in that direction).

javadoc+test are pretty important in the java world, and of course
documentation is a critical component for any free software.  jni is
just a personal need and I am familiar with how it works.  I also bring
up jni because this is one area where java build tools really don't
stack up at all and automake some non-zero chance of becoming a primary
contender.

I'm afraid based on the state of things that 'waiting for a request'
will be a rather long wait ... the horse has quite bolted on the 'build
tool' front in the last few years for all languages, and one can only
surmise it was due to the com

bug#9088: Java, JARS primary?

2013-05-15 Thread Michael Zucchi
On 14/05/13 03:47, Stefano Lattarini wrote:

> Instead, let's start implementing something *correct*, in line with
> the Java philosophy, and with a clean API.  We'll think about enhancing
> it when (and if!) the need arise.

Seems the way to go.

On that, here are a few more thoughts on java's specific way of doing
things ...

files vs dirs
--

java projects/build systems tend to have a fairly basic mechanism to
define the source tree(s) which would be nice to emulate, but may not
fit well with the portability requirements of automake.

They simply define the root directory and let the build system do the rest.

Not necessary but would be nice.  Or put another way it would basically
suck if it required every source file to be listed explicitly and auto*
having to be re-run every time one is added.  In a GNU makefile I can
just use $(shell find) (or other fancier stuff), but for automake?

source vs data
--

A source tree can also include non-source data which is copied into the
jar file verbatim at the same relative path location.  At least this is
how ant does it and given the way these resources are resolved at
runtime makes the most sense.

Again I think this needs to be specified by root directory not file.  It
could just hang off the _SOURCES or use _RESOURCES.

makefile location
-

C projects often have a make file per directory, java has the build
script at the top-level at least, outside of the source trees.

This is desirable.

For the compiled code this is simple enough since the makefile will
compile every file every time and the compiler will dump the class files
where it's told.

For the resource files the Makefile needs to resolve the resource root,
and strip it out of the names used for the dependencies.  So either it
needs a (set of) explicit resource_root, resource_root_files variables,
or it just needs to be defined as the root dir and handled either in the
makefile fragment or in automake.in.

annotation processors
-

I think these can be handled by using _JAVACFLAGS or something similar.
 They can generate source for new classes at compile time, but this is
all handled by javac in separate locations so make doesn't need to know
about it.

javadoc, jni, check/test, etc


Some built-in support would be good.  javadoc is easy, check/test should
run junit tests I guess although i'm not too familiar with junit, jni
will need some thought but should be limited in scope (support for javah
basically, maybe not enough need to include it in automake so long as
the dev can depend on the jar).

first cut
-

I've attached a pretty nasty bit of unportable makefile which attempts
some of the above to see how it might be done.  Even with gnu make stuff
it still needs some support from automake.in to handle multiple resource
directories, and it doesn't handle everything quite properly.

The build steps from this are simple:

$ rm foo_jar.stamp ; make -f Auto.mak
javac -cp lib/jjmpeg.jar:lib/test.jar -sourcepath src -d
build/classes/foo_jar src/z/util/d.java src/z/util/c.java src/z/a.java
src/z/b.java
touch foo_jar.stamp
jar cf foo.jar -C build/classes/foo_jar . \
-C ./src ./z/util/util-names.txt \
-C ./res ./foo.txt
$

Regards,
 Michael

# default is /usr/share/java/package ?
jardir = $(datadir)/java/@PACKAGE@
srcdir=.

all: foo.jar

jar_JARS=foo.jar

foo_jar_SOURCES = src
# multiple resources dirs
foo_jar_RESOURCES = src res
# same as in the way one would add a in-package libtool lib, but this is in the 
build jar path
foo_jar_LIBADD = lib/jjmpeg.jar lib/test.jar

## foo.jar

# jar.am template, could handle multi-valued foo_jar_SOURCES
foo_jar_SOURCES_list=$(shell cd $(srcdir) ; find $(foo_jar_SOURCES) -name 
'*.java')
# automake.in generated, the find exclusions are not nearly enough to handle 
version control
foo_jar_RESOURCES_list0=$(shell cd $(srcdir)/src; find . -type f -a \! -name 
'*.java' \! -name '*~')
foo_jar_RESOURCES_list1=$(shell cd $(srcdir)/res; find . -type f -a \! -name 
'*.java' \! -name '*~')

# windows needs ;, of course ...
# automake.in generates this from LIBADD?
foo_jar_CLASSPATH=lib/jjmpeg.jar:lib/test.jar

foo_jar.stamp: $(foo_jar_SOURCES_list) $(foo_jar_LIBADD)
@-rm -rf build/classes/foo_jar
@-mkdir -p build/classes/foo_jar
javac -cp $(foo_jar_CLASSPATH) -sourcepath src -d build/classes/foo_jar 
$(filter %.java,$^)
touch $@

foo.jar: foo_jar.stamp $(patsubst %,src/%,$(foo_jar_RESOURCES_list0)) 
$(patsubst %,res/%,$(foo_jar_RESOURCES_list1))
jar cf $@ -C build/classes/foo_jar . \
$(patsubst %,-C $(srcdir)/src %,$(foo_jar_RESOURCES_list0)) \
$(patsubst %,-C $(srcdir)/res %,$(foo_jar_RESOURCES_list1))

.PHONY javadoc: javadoc-foo_jar
javadoc-foo_jar:
exit 1
build javadoc stuff, not done yet