Gentoo Archives: gentoo-dev

From: zongyu <zzy2529420793@×××××.com>
To: gentoo-dev@l.g.o
Cc: zongyu <zzy2529420793@×××××.com>
Subject: [gentoo-dev] [PATCH 1/2] java-pkg-simple.eclass and java-utils-2.eclass: features and enhancements
Date: Tue, 25 Aug 2020 15:48:50
Message-Id: 20200825154613.149634-2-zzy2529420793@gmail.com
In Reply to: [gentoo-dev] [PATCH 0/2] eclass/java-{utils-2,pkg-simple}.eclass: features and enhancements by zongyu
1 1) support java resources
2 2) support java main class and launcher
3 3) enable java-pkg-simple_src_test()
4 4) support binary jars (both for resolve circular deps and for pkgdiff test)
5
6 Signed-off-by: zongyu <zzy2529420793@×××××.com>
7 ---
8 eclass/java-pkg-simple.eclass | 379 +++++++++++++++++++++++++++++++---
9 eclass/java-utils-2.eclass | 38 ++++
10 2 files changed, 388 insertions(+), 29 deletions(-)
11
12 diff --git a/eclass/java-pkg-simple.eclass b/eclass/java-pkg-simple.eclass
13 index 0b16cd5d40f..bfec305123f 100644
14 --- a/eclass/java-pkg-simple.eclass
15 +++ b/eclass/java-pkg-simple.eclass
16 @@ -22,11 +22,30 @@ if ! has java-pkg-2 ${INHERITED}; then
17 eerror "java-pkg-simple eclass can only be inherited AFTER java-pkg-2"
18 fi
19
20 -EXPORT_FUNCTIONS src_compile src_install
21 +EXPORT_FUNCTIONS src_compile src_install src_test
22
23 # We are only interested in finding all java source files, wherever they may be.
24 S="${WORKDIR}"
25
26 +# handle dependencies for testing frameworks
27 +if has test ${JAVA_PKG_IUSE}; then
28 + local test_deps
29 + for framework in ${JAVA_TESTING_FRAMEWORKS}; do
30 + case ${framework} in
31 + junit)
32 + test_deps+=" dev-java/junit:0";;
33 + junit-4)
34 + test_deps+=" dev-java/junit:4";;
35 + pkgdiff)
36 + test_deps+=" amd64? ( dev-util/pkgdiff
37 + dev-util/japi-compliance-checker )";;
38 + testng)
39 + test_deps+=" dev-java/testng:0";;
40 + esac
41 + done
42 + [[ ${test_deps} ]] && DEPEND="test? ( ${test_deps} )"
43 +fi
44 +
45 # @ECLASS-VARIABLE: JAVA_GENTOO_CLASSPATH
46 # @DEFAULT_UNSET
47 # @DESCRIPTION:
48 @@ -45,17 +64,46 @@ S="${WORKDIR}"
49 # Extra list of colon separated path elements to be put on the
50 # classpath when compiling sources.
51
52 +# @ECLASS-VARIABLE: JAVA_CLASSPATH_EXTRA
53 +# @DEFAULT_UNSET
54 +# @DESCRIPTION:
55 +# An extra comma or space separated list of java packages
56 +# that are needed only during compiling sources.
57 +
58 +# @ECLASS-VARIABLE: JAVA_NEEDS_TOOLS
59 +# @DEFAULT_UNSET
60 +# @DESCRIPTION:
61 +# add tools.jar to the gentoo.classpath. Should only be used
62 +# for build-time purposes, the dependency is not recorded to
63 +# package.env.
64 +
65 # @ECLASS-VARIABLE: JAVA_SRC_DIR
66 # @DEFAULT_UNSET
67 # @DESCRIPTION:
68 -# Directories relative to ${S} which contain the sources of the
69 -# application. The default of "" will be treated mostly as ${S}
70 -# itself. For the generated source package (if source is listed in
71 +# An array of directories relative to ${S} which contain the sources
72 +# of the application. If you set ${JAVA_SRC_DIR} to a string it works
73 +# as well. The default value "" means it will get all source files
74 +# inside ${S}.
75 +# For the generated source package (if source is listed in
76 # ${JAVA_PKG_IUSE}), it is important that these directories are
77 # actually the roots of the corresponding source trees.
78 #
79 # @CODE
80 -# JAVA_SRC_DIR="src/java/org/gentoo"
81 +# JAVA_SRC_DIR=( "impl/src/main/java/"
82 +# "arquillian/weld-ee-container/src/main/java/"
83 +# )
84 +# @CODE
85 +
86 +# @DESCRIPTION:
87 +# @ECLASS-VARIABLE: JAVA_RESOURCE_DIRS
88 +# @DEFAULT_UNSET
89 +# @DESCRIPTION:
90 +# An array of directories relative to ${S} which contain the
91 +# resources of the application. If you do not set the variable,
92 +# there will be no resources added to the compiled jar file.
93 +#
94 +# @CODE
95 +# JAVA_RESOURCE_DIRS=("src/java/resources/")
96 # @CODE
97
98 # @ECLASS-VARIABLE: JAVA_ENCODING
99 @@ -68,6 +116,17 @@ S="${WORKDIR}"
100 # @DESCRIPTION:
101 # Additional arguments to be passed to javac.
102
103 +# @ECLASS-VARIABLE: JAVA_MAIN_CLASS
104 +# @DEFAULT_UNSET
105 +# @DESCRIPTION:
106 +# If the java has a main class, you are going to set the
107 +# variable so that we can generate a proper MANIFEST.MF
108 +# and create a launcher.
109 +#
110 +# @CODE
111 +# JAVA_MAIN_CLASS="org.gentoo.java.ebuilder.Main"
112 +# @CODE
113 +
114 # @ECLASS-VARIABLE: JAVADOC_ARGS
115 # @DEFAULT_UNSET
116 # @DESCRIPTION:
117 @@ -78,34 +137,217 @@ S="${WORKDIR}"
118 # The name of the jar file to create and install.
119 : ${JAVA_JAR_FILENAME:=${PN}.jar}
120
121 +# @ECLASS-VARIABLE: JAVA_BINJAR_FILENAME
122 +# @DEFAULT_UNSET
123 +# @DESCRIPTION:
124 +# The name of the binary jar file to be installed if
125 +# USE FLAG 'binary' is set.
126 +
127 +# @ECLASS-VARIABLE: JAVA_LAUNCHER_FILENAME
128 +# @DESCRIPTION:
129 +# If ${JAVA_MAIN_CLASS} is set, we will create a launcher to
130 +# execute the jar, and ${JAVA_LAUNCHER_FILENAME} will be the
131 +# name of the script.
132 +: ${JAVA_LAUNCHER_FILENAME:=${PN}-${SLOT}}
133 +
134 +# @ECLASS-VARIABLE: JAVA_TESTING_FRAMEWORKS
135 +# @DEFAULT_UNSET
136 +# @DESCRIPTION:
137 +# A space separated list that defines which tests it should launch
138 +# during src_test.
139 +#
140 +# @CODE
141 +# JAVA_TESTING_FRAMEWORKS="junit pkgdiff"
142 +# @CODE
143 +
144 +# @ECLASS-VARIABLE: JAVA_TEST_EXCLUDES
145 +# @DEFAULT_UNSET
146 +# @DESCRIPTION:
147 +# A array of classes that should not be executed during src_test().
148 +#
149 +# @CODE
150 +# JAVA_TEST_EXCLUDES=( "net.sf.cglib.CodeGenTestCase" "net.sf.cglib.TestAll" )
151 +# @CODE
152 +
153 +# @ECLASS-VARIABLE: JAVA_TEST_GENTOO_CLASSPATH
154 +# @DEFAULT_UNSET
155 +# @DESCRIPTION:
156 +# The extra classpath we need while compiling and running the
157 +# source code for testing.
158 +
159 +# @ECLASS-VARIABLE: JAVA_TEST_SRC_DIR
160 +# @DEFAULT_UNSET
161 +# @DESCRIPTION:
162 +# An array of directories relative to ${S} which contain the
163 +# sources for testing. It is almost equivalent to
164 +# ${JAVA_SRC_DIR} in src_test.
165 +
166 +# @ECLASS-VARIABLE: JAVA_TEST_RESOURCE_DIRS
167 +# @DEFAULT_UNSET
168 +# @DESCRIPTION:
169 +# It is almost equivalent to ${JAVA_RESOURCE_DIRS} in src_test.
170 +
171 +# @FUNCTION: java-pkg-simple_getclasspath
172 +# @USAGE: java-pkg-simple_getclasspath [--runtime-only]
173 +# @INTERNAL
174 +# @DESCRIPTION:
175 +# Get proper ${classpath} from ${JAVA_GENTOO_CLASSPATH_EXTRA},
176 +# ${JAVA_NEEDS_TOOLS}, ${JAVA_CLASSPATH_EXTRA} and
177 +# ${JAVA_GENTOO_CLASSPATH}. We use it inside
178 +# java-pkg-simple_src_compile and java-pkg-simple_src_test.
179 +#
180 +# Note that if you need to define a "classpath" variable before
181 +# calling this function.
182 +java-pkg-simple_getclasspath() {
183 + debug-print-function ${FUNCNAME} $*
184 +
185 + local denpendency
186 + local deep_jars="--with-dependencies"
187 + local buildonly_jars="--build-only"
188 +
189 + # the extra classes that are not installed by portage
190 + classpath+=":${JAVA_GENTOO_CLASSPATH_EXTRA}"
191 +
192 + # whether we need tools.jar
193 + [[ ${JAVA_NEEDS_TOOLS} ]] && classpath+=":$(java-config --tools)"
194 +
195 + # the extra classes that are installed by portage
196 + for dependency in ${JAVA_CLASSPATH_EXTRA}; do
197 + classpath="${classpath}:$(java-pkg_getjars ${buildonly_jars}\
198 + ${deep_jars} ${dependency})"
199 + done
200 +
201 + # add test dependencies if USE FLAG 'test' is set
202 + if has test ${JAVA_PKG_IUSE} && use test; then
203 + for dependency in ${JAVA_TEST_GENTOO_CLASSPATH}; do
204 + classpath="${classpath}:$(java-pkg_getjars ${buildonly_jars}\
205 + ${deep_jars} ${dependency})"
206 + done
207 + fi
208 +
209 + # add the RUNTIME dependencies
210 + for dependency in ${JAVA_GENTOO_CLASSPATH}; do
211 + classpath="${classpath}:$(java-pkg_getjars ${deep_jars} ${dependency})"
212 + done
213 +
214 + # purify classpath
215 + while [[ $classpath = *::* ]]; do classpath="${classpath//::/:}"; done
216 + classpath=${classpath%:}
217 + classpath=${classpath#:}
218 +
219 + debug-print "CLASSPATH=${classpath}"
220 +}
221 +
222 +# @FUNCTION: java-pkg-simple_test_with_pkgdiff_
223 +# @INTERNAL
224 +# @DESCRIPTION:
225 +# use japi-compliance-checker the ensure the compabitily of \*.class files,
226 +# Besides, use pkgdiff to ensure the compabilty of resources.
227 +java-pkg-simple_test_with_pkgdiff_() {
228 + debug-print-function ${FUNCNAME} $*
229 +
230 + if [[ ! ${ARCH} == "amd64" ]]; then
231 + elog "For architectures other than amd64, "\
232 + "the pkgdiff test is currently unavailable "\
233 + "because 'dev-util/japi-compliance-checker "\
234 + "and 'dev-util/pkgdiff' do not support those architectures."
235 + return
236 + fi
237 +
238 + local report1=${PN}-japi-compliance-checker.html
239 + local report2=${PN}-pkgdiff.html
240 +
241 + # pkgdiff test
242 + if [[ -f "${DISTDIR}/${JAVA_BINJAR_FILENAME}" ]]; then
243 + # pkgdiff cannot deal with symlinks, so this is a workaround
244 + cp "${DISTDIR}/${JAVA_BINJAR_FILENAME}" ./ \
245 + || die "Cannot copy binjar file to ${S}."
246 +
247 + # japi-compliance-checker
248 + japi-compliance-checker ${JAVA_BINJAR_FILENAME} ${JAVA_JAR_FILENAME}\
249 + --lib=${PN} -v1 ${PV}-bin -v2 ${PV} -report-path ${report1}\
250 + --binary\
251 + || die "japi-compliance-checker returns $?,"\
252 + "check the report in ${S}/${report1}"
253 +
254 + # ignore META-INF since it does not matter
255 + # ignore classes because japi-compilance checker will take care of it
256 + pkgdiff ${JAVA_BINJAR_FILENAME} ${JAVA_JAR_FILENAME}\
257 + -vnum1 ${PV}-bin -vnum2 ${PV}\
258 + -skip-pattern "META-INF|.class$"\
259 + -name ${PN} -report-path ${report2}\
260 + || die "pkgdiff returns $?, check the report in ${S}/${report2}"
261 + fi
262 +}
263 +
264 +# @FUNCTION: java-pkg-simple_prepend_resources
265 +# @USAGE: java-pkg-simple_prepend-resources <${classes}> <"${RESOURCE_DIRS[@]}">
266 +# @INTERNAL
267 +# @DESCRIPTION:
268 +# Copy things under "${JAVA_RESOURCE_DIRS[@]}" or "${JAVA_TEST_RESOURCE_DIRS[@]}"
269 +# to ${classes}, so that `jar` will package resources together with classes.
270 +#
271 +# Note that you need to define a "classes" variable before calling
272 +# this function.
273 +java-pkg-simple_prepend_resources() {
274 + debug-print-function ${FUNCNAME} $*
275 +
276 + local destination="${1}"
277 + shift 1
278 +
279 + # return if there is no resource dirs defined
280 + [[ "$@" ]] || return
281 + local resources=("${@}")
282 +
283 + # add resources directory to classpath
284 + for resource in "${resources[@]}"; do
285 + cp -rT "${resource:-.}" "${destination}"\
286 + || die "Could copy resources to ${destination}"
287 + done
288 +}
289 +
290 # @FUNCTION: java-pkg-simple_src_compile
291 # @DESCRIPTION:
292 # src_compile for simple bare source java packages. Finds all *.java
293 # sources in ${JAVA_SRC_DIR}, compiles them with the classpath
294 # calculated from ${JAVA_GENTOO_CLASSPATH}, and packages the resulting
295 -# classes to ${JAVA_JAR_FILENAME}.
296 +# classes to a single ${JAVA_JAR_FILENAME}. If the file
297 +# target/META-INF/MANIFEST.MF exists, it is used as the manifest of the
298 +# created jar.
299 +#
300 +# If USE FLAG 'binary' exists and is set, it will just copy
301 +# ${JAVA_BINJAR_FILENAME} to ${S} and skip the rest of src_compile.
302 java-pkg-simple_src_compile() {
303 local sources=sources.lst classes=target/classes apidoc=target/api
304
305 # auto generate classpath
306 java-pkg_gen-cp JAVA_GENTOO_CLASSPATH
307
308 + # do not compile if we decide to install binary jar
309 + if has binary ${JAVA_PKG_IUSE} && use binary; then
310 + # register the runtime dependencies
311 + for dependency in ${JAVA_GENTOO_CLASSPATH//,/ }; do
312 + java-pkg_record-jar_ ${dependency}
313 + done
314 +
315 + cp "${DISTDIR}"/${JAVA_BINJAR_FILENAME} ${JAVA_JAR_FILENAME}\
316 + || die "Could not copy the binary jar file to ${S}"
317 + return 0
318 + fi
319 +
320 # gather sources
321 - find ${JAVA_SRC_DIR:-*} -name \*.java > ${sources}
322 + find "${JAVA_SRC_DIR[@]}" -name \*.java > ${sources}
323 +
324 + # create the target directory
325 mkdir -p ${classes} || die "Could not create target directory"
326
327 # compile
328 - local classpath="${JAVA_GENTOO_CLASSPATH_EXTRA}" dependency
329 - for dependency in ${JAVA_GENTOO_CLASSPATH}; do
330 - classpath="${classpath}:$(java-pkg_getjars ${dependency})" \
331 - || die "getjars failed for ${dependency}"
332 - done
333 - while [[ $classpath = *::* ]]; do classpath="${classpath//::/:}"; done
334 - classpath=${classpath%:}
335 - classpath=${classpath#:}
336 - debug-print "CLASSPATH=${classpath}"
337 - ejavac -d ${classes} -encoding ${JAVA_ENCODING} \
338 - ${classpath:+-classpath ${classpath}} ${JAVAC_ARGS} \
339 + local classpath=""
340 + java-pkg-simple_getclasspath
341 + java-pkg-simple_prepend_resources ${classes} "${JAVA_RESOURCE_DIRS[@]}"
342 +
343 + ejavac -d ${classes} -encoding ${JAVA_ENCODING}\
344 + ${classpath:+-classpath ${classpath}} ${JAVAC_ARGS}\
345 @${sources}
346
347 # javadoc
348 @@ -118,25 +360,33 @@ java-pkg-simple_src_compile() {
349 fi
350
351 # package
352 - local jar_args="cf ${JAVA_JAR_FILENAME}"
353 + local jar_args
354 if [[ -e ${classes}/META-INF/MANIFEST.MF ]]; then
355 jar_args="cfm ${JAVA_JAR_FILENAME} ${classes}/META-INF/MANIFEST.MF"
356 + elif [[ ${JAVA_MAIN_CLASS} ]]; then
357 + jar_args="cfe ${JAVA_JAR_FILENAME} ${JAVA_MAIN_CLASS}"
358 + else
359 + jar_args="cf ${JAVA_JAR_FILENAME}"
360 fi
361 jar ${jar_args} -C ${classes} . || die "jar failed"
362 }
363
364 # @FUNCTION: java-pkg-simple_src_install
365 # @DESCRIPTION:
366 -# src_install for simple single jar java packages. Simply packages the
367 -# contents from the target directory and installs it as
368 -# ${JAVA_JAR_FILENAME}. If the file target/META-INF/MANIFEST.MF exists,
369 -# it is used as the manifest of the created jar.
370 +# src_install for simple single jar java packages. Simply installs
371 +# ${JAVA_JAR_FILENAME}. It will also install a launcher if
372 +# ${JAVA_MAIN_CLASS} is set.
373 java-pkg-simple_src_install() {
374 local sources=sources.lst classes=target/classes apidoc=target/api
375
376 - # main jar
377 + # install the jar file that we need
378 java-pkg_dojar ${JAVA_JAR_FILENAME}
379
380 + # install a wrapper if ${JAVA_MAIN_CLASS} is defined
381 + if [[ ${JAVA_MAIN_CLASS} ]]; then
382 + java-pkg_dolauncher "${JAVA_LAUNCHER_FILENAME}" --main ${JAVA_MAIN_CLASS}
383 + fi
384 +
385 # javadoc
386 if has doc ${JAVA_PKG_IUSE} && use doc; then
387 java-pkg_dojavadoc ${apidoc}
388 @@ -145,12 +395,10 @@ java-pkg-simple_src_install() {
389 # dosrc
390 if has source ${JAVA_PKG_IUSE} && use source; then
391 local srcdirs=""
392 - if [[ ${JAVA_SRC_DIR} ]]; then
393 + if [[ "${JAVA_SRC_DIR[@]}" ]]; then
394 local parent child
395 - for parent in ${JAVA_SRC_DIR}; do
396 - for child in ${parent}/*; do
397 - srcdirs="${srcdirs} ${child}"
398 - done
399 + for parent in "${JAVA_SRC_DIR[@]}"; do
400 + srcdirs="${srcdirs} ${parent}"
401 done
402 else
403 # take all directories actually containing any sources
404 @@ -159,3 +407,76 @@ java-pkg-simple_src_install() {
405 java-pkg_dosrc ${srcdirs}
406 fi
407 }
408 +
409 +# @FUNCTION: java-pkg-simple_src_test
410 +# @DESCRIPTION:
411 +# src_test for simple single java jar file.
412 +# It will perform test with frameworks that are defined in
413 +# ${JAVA_TESTING_FRAMEWORKS}.
414 +java-pkg-simple_src_test() {
415 + local test_sources=test_sources.lst classes=target/test-classes
416 + local tests_to_run classpath
417 +
418 + # do not continue if the USE FLAG 'test' is explicitly unset
419 + # or no ${JAVA_TESTING_FRSerializingCAMEWORKS} specified
420 + if ! has test ${JAVA_PKG_IUSE}; then
421 + return
422 + elif ! use test; then
423 + return
424 + elif [[ ! "${JAVA_TESTING_FRAMEWORKS}" ]]; then
425 + return
426 + fi
427 +
428 + # create the target directory
429 + mkdir -p ${classes} || die "Could not create target directory for testing"
430 +
431 + # get classpath
432 + classpath="${classes}:${JAVA_JAR_FILENAME}"
433 + java-pkg-simple_getclasspath
434 + java-pkg-simple_prepend_resources ${classes} "${JAVA_TEST_RESOURCE_DIRS[@]}"
435 +
436 + # gathering sources for testing
437 + find "${JAVA_TEST_SRC_DIR[@]}" -name \*.java > ${test_sources}
438 +
439 + # compile
440 + [[ -s ${test_sources} ]] && ejavac -d ${classes} ${JAVAC_ARGS} \
441 + -encoding ${JAVA_ENCODING} ${classpath:+-classpath ${classpath}} \
442 + @${test_sources}
443 +
444 + # grab a set of tests that testing framework will run
445 + tests_to_run=$(find "${classes}" -type f\
446 + \( -name "*Test.class"\
447 + -o -name "Test*.class"\
448 + -o -name "*Tests.class"\
449 + -o -name "*TestCase.class" \)\
450 + ! -name "*Abstract*"\
451 + ! -name "*BaseTest*"\
452 + ! -name "*TestTypes*"\
453 + ! -name "*TestUtils*"\
454 + ! -name "*\$*")
455 + tests_to_run=${tests_to_run//"${classes}"\/}
456 + tests_to_run=${tests_to_run//.class}
457 + tests_to_run=${tests_to_run//\//.}
458 +
459 + # exclude extra test classes, usually corner cases
460 + # that the code above cannot handle
461 + for class in "${JAVA_TEST_EXCLUDES[@]}"; do
462 + tests_to_run=${tests_to_run//${class}}
463 + done
464 +
465 + # launch test
466 + for framework in ${JAVA_TESTING_FRAMEWORKS}; do
467 + case ${framework} in
468 + junit)
469 + ejunit -classpath "${classpath}" ${tests_to_run};;
470 + junit-4)
471 + ejunit4 -classpath "${classpath}" ${tests_to_run};;
472 + pkgdiff)
473 + java-pkg-simple_test_with_pkgdiff_;;
474 + testng)
475 + etestng -classpath "${classpath}" ${tests_to_run};;
476 + *)
477 + elog "No suitable function found for framework ${framework}"
478 + esac
479 + done
480 +}
481 diff --git a/eclass/java-utils-2.eclass b/eclass/java-utils-2.eclass
482 index 29f13e031f4..a33962f114d 100644
483 --- a/eclass/java-utils-2.eclass
484 +++ b/eclass/java-utils-2.eclass
485 @@ -1861,6 +1861,44 @@ ejunit4() {
486 ejunit_ "junit-4" "${@}"
487 }
488
489 +# @FUNCTION: etestng
490 +# @USAGE: etestng_ [-cp $classpath] <test classes>
491 +# @INTERNAL
492 +# @DESCRIPTION:
493 +# Testng wrapper function. Makes it easier to run the tests.
494 +# Launches the tests using org.testng.TestNG.
495 +#
496 +# @CODE
497 +# $1 - -cp or -classpath
498 +# $2 - the classpath passed to it
499 +# $@ - test classes for testng to run.
500 +# @CODE
501 +etestng() {
502 + debug-print-function ${FUNCNAME} $*
503 +
504 + local runner=org.testng.TestNG
505 + local cp=$(java-pkg_getjars --with-dependencies testng)
506 + local tests
507 +
508 + if [[ ${1} = -cp || ${1} = -classpath ]]; then
509 + cp="${cp}:${2}"
510 + shift 2
511 + else
512 + cp="${cp}:."
513 + fi
514 +
515 + for test in ${@}; do
516 + tests+="${test},"
517 + done
518 +
519 + debug-print "java -cp \"${cp}\" -Djava.io.tmpdir=\"${T}\""\
520 + "-Djava.awt.headless=true ${runner}"\
521 + "-usedefaultlisteners false -testclass ${tests}"
522 + java -cp "${cp}" -Djava.io.tmpdir=\"${T}\" -Djava.awt.headless=true\
523 + ${runner} -usedefaultlisteners false -testclass ${tests}\
524 + || die "Running TestNG failed."
525 +}
526 +
527 # @FUNCTION: java-utils-2_src_prepare
528 # @DESCRIPTION:
529 # src_prepare Searches for bundled jars
530 --
531 2.26.2

Replies