Generating Java classes with xjc in one build execution

809 views
Skip to first unread message

toma...@googlemail.com

unread,
Jan 8, 2018, 4:30:54 AM1/8/18
to bazel-discuss
Hi @all,

my name is Thomas and I'm a software developer from Germany.
Last year I made my first tries with Bazel. My goal was to migrate a project from Gradle to Bazel. Unfortunately I ran out of time, because of other projects, but I had 1st successes for different libs and a web-app

Now I'm starting a new turn, but beginning with a fresh new project, which I would love to build with Bazel, because of it's polyglot approach.

Long story short. One of our basic things we often do when building Java projects, is to generate Java classes out of XSD schema files regardless of whether we built it with Maven or Gradle. There were always appropriate plugins for that (xmlbeans, jaxb).

I would like to do the same with Bazel. Based on some examples and comments I created a genrule to call xjc of the local_jdk. The genrule generates the Java source files to the src directory of the module location. I defined this genrule as dependency in my java_library which uses "src/**/*.java" as srsc

The problem is I can't get it to run in one step. If I call the genrule before I build the library the generated Java files are in place and everything works fine.
But if I call just the library build goal, the genrule isn't executed although it's a dependecy of the lib.

I created a sample project on github and hope anybody can help me with this.
https://github.com/tomask-de/bazel-xjc

I'm looking forward to hearing from you.

Thx in advance.

david.o...@gmail.com

unread,
Jan 8, 2018, 5:51:54 PM1/8/18
to bazel-discuss
On Monday, January 8, 2018 at 10:30:54 AM UTC+1, toma...@googlemail.com wrote:
> Hi @all,
>
> my name is Thomas and I'm a software developer from Germany.
> Last year I made my first tries with Bazel. My goal was to migrate a project from Gradle to Bazel. Unfortunately I ran out of time, because of other projects, but I had 1st successes for different libs and a web-app
>
> Now I'm starting a new turn, but beginning with a fresh new project, which I would love to build with Bazel, because of it's polyglot approach.
>
> Long story short. One of our basic things we often do when building Java projects, is to generate Java classes out of XSD schema files regardless of whether we built it with Maven or Gradle. There were always appropriate plugins for that (xmlbeans, jaxb).
>
> I would like to do the same with Bazel. Based on some examples and comments I created a genrule to call xjc of the local_jdk. The genrule generates the Java source files to the src directory of the module location. I defined this genrule as dependency in my java_library which uses "src/**/*.java" as srsc
>

The usual idiom for that is to create srcjar in genrule,
and provide this genrule label as source to java_library.
In Gerrit Code Review project we generate java sources
from prolog sources using prolog compiler and build it like
this:

def prolog_cafe_library(
name,
srcs,
deps = [],
**kwargs):
native.genrule(
name = name + '__pl2j',
cmd = '$(location //lib/prolog:compiler_bin) ' +
'$$(dirname $@) $@ ' +
'$(SRCS)',
srcs = srcs,
tools = ['//lib/prolog:compiler_bin'],
outs = [ name + '.srcjar' ],
)
native.java_library(
name = name,
srcs = [':' + name + '__pl2j'],
deps = ['//lib/prolog:runtime-neverlink'] + deps,
**kwargs
)

The only difference to your apporach is, we use a java
program that invokes the prolog compiler and creates
srcjar, but the principle is the same.

Just generate java sources to a temp directory, zip the
output to srcjar and use it as input and not as dependency
of java_library rule. Then it should work as expected.

Alpha Lam

unread,
Jan 8, 2018, 6:01:08 PM1/8/18
to david.o...@gmail.com, bazel-discuss
Please be aware that the srcjar have timestamps are different across multiple runs. This will invalidate the remote cache (if you use it). You can either touch the local files with a fixed timestamp or use the singlejar tool bundled in Bazel.

Alpha


--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discuss+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/13a079d8-bf6e-4173-959a-0702c8f33578%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

toma...@googlemail.com

unread,
Jan 10, 2018, 5:20:21 AM1/10/18
to bazel-discuss
@Alpha

Thx for your approach.

I have done it now. The other (second) trick is to pack the generated java files as a JAR to the output directory, like this guy copies the generated files to it: https://stackoverflow.com/questions/42251106/use-generated-code-in-a-bazel-build

For all interested: I commited the working BUILD.bazel file to the above github repository.

Here's the final version:


genrule(
name = "sample-messages",
srcs = [
"src/main/xsd/sample.xsd",
"src/main/xjb/sample.xjb",
],
outs = ["sample-messages.srcjar"],
cmd = """
echo "INFO: Generating to $(GENDIR)"
$(location @local_jdk//:xjc) -d $(GENDIR) -b $(location src/main/xjb/sample.xjb) -verbose $(location src/main/xsd/sample.xsd)
$(location @local_jdk//:jar) cvf $@ $(GENDIR)
""",
local = 1,
tools = [
"@local_jdk//:jdk-default",
"@local_jdk//:xjc",
"@local_jdk//:jar",
],
visibility = ["//:__pkg__"],
)

java_library(
name = "sample-lib",
srcs = [":sample-messages"],
visibility = ["//visibility:public"],
)

Thx for your help.

Best regards
Thomas

ahum...@google.com

unread,
Feb 22, 2022, 5:47:55 PM2/22/22
to bazel-discuss
The code snippets here no longer work with newer versions of bazel or newer versions of java, see here for some updated snippets:
Reply all
Reply to author
Forward
0 new messages