From 13a15ee4545da955bdfc4a040c3b8e485621e398 Mon Sep 17 00:00:00 2001 From: Daniel Stonier <d.stonier@gmail.com> Date: Thu, 26 Jun 2014 10:54:45 +0900 Subject: [PATCH] solved some hideous cmake dependency sequencing issues. --- cmake/genjava-extras.cmake.em | 64 +++++++++++++----- src/genjava/genjava_main.py | 7 +- src/genjava/genjava_main.pyc | Bin 1300 -> 1631 bytes src/genjava/gradle_project.py | 21 +++++- .../templates/genjava_project/build.gradle.in | 25 ++++++- 5 files changed, 93 insertions(+), 24 deletions(-) diff --git a/cmake/genjava-extras.cmake.em b/cmake/genjava-extras.cmake.em index f08631d..dd6ed36 100644 --- a/cmake/genjava-extras.cmake.em +++ b/cmake/genjava-extras.cmake.em @@ -40,51 +40,72 @@ endmacro() # To facilitate this, the ARG_GENERATED_FILES is actually just the underlying ARG_MSG and ARG_SRV # files which we feed the commands as DEPENDS to trigger their execution. macro(_generate_module_java ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES) - ################################ # Gradle Subproject ################################ set(GRADLE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/java") set(GRADLE_BUILD_FILE "${GRADLE_BUILD_DIR}/${ARG_PKG}/build.gradle") list(APPEND ALL_GEN_OUTPUT_FILES_java ${GRADLE_BUILD_FILE}) - + # a marker for the compiling script later to discover + # this command will only get run when an underlying dependency changes, whereas the compiling + # add_custom_target always runs (this was so we can ensure compile time dependencies are ok). + # So we leave this dropping to inform it when gradle needs to run so that we can skip by + # without the huge latency whenever we don't. + set(DROPPINGS_FILE "${GRADLE_BUILD_DIR}/${ARG_PKG}/droppings") add_custom_command(OUTPUT ${GRADLE_BUILD_FILE} - DEPENDS ${GENJAVA_BIN} + DEPENDS ${GENJAVA_BIN} ${ARG_GENERATED_FILES} COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENJAVA_BIN} -o ${GRADLE_BUILD_DIR} -p ${ARG_PKG} + COMMAND touch ${DROPPINGS_FILE} COMMENT "Generating Java gradle project from ${ARG_PKG}" ) ################################ # Compile Gradle Subproject ################################ + # Push the compile back to the last thing that gets done before the generate messages + # is done for this package (see the PRE_LINK coupled with the TARGET option below). This + # is different to genpy, gencpp since it's a compile step. If you don't force it to be + # the last thing, then it may be trying to compile while dependencies are still getting + # themselves ready for ${ARG_PKG}_generate_messages in parallel. + # (i.e. beware of sequencing add_custom_command, it usually has to compete) set(ROS_GRADLE_VERBOSE $ENV{ROS_GRADLE_VERBOSE}) if(ROS_GRADLE_VERBOSE) - set(GRADLE_CMD "./gradlew") + set(verbosity "--verbosity") else() - set(GRADLE_CMD "./gradlew;-q") + set(verbosity "") endif() - set(GEN_OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/generated_java_messages.flag) - add_custom_command(OUTPUT ${GEN_OUTPUT_FILE} + add_custom_target(${ARG_PKG}_generate_messages_java_gradle + COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENJAVA_BIN} + ${verbosity} + --compile + -o ${GRADLE_BUILD_DIR} + -p ${ARG_PKG} DEPENDS ${GRADLE_BUILD_FILE} ${ARG_GENERATED_FILES} - COMMAND ${CATKIN_ENV} ${GRADLE_CMD} - COMMAND touch ${GEN_OUTPUT_FILE} WORKING_DIRECTORY ${GRADLE_BUILD_DIR}/${ARG_PKG} - COMMENT "Generating Java code for ${ARG_PKG}") - list(APPEND ALL_GEN_OUTPUT_FILES_java ${GEN_OUTPUT_FILE}) - - ################################ - # Debugging - ################################ - #foreach(gen_output_file ${ALL_GEN_OUTPUT_FILES_java}) - # message(STATUS "ALL_GEN_OUTPUT_FILES_java..........${gen_output_file}") - #endforeach() + COMMENT "Compiling Java code for ${ARG_PKG}" + ) + add_dependencies(${ARG_PKG}_generate_messages ${ARG_PKG}_generate_messages_java_gradle) ################################ # Dependent Targets ################################ + # This is a bad hack that needs to disappear. e.g. + # - topic_tools and roscpp are both packages with a couple of msgs + # - topic tools messages doesn't actually depend on roscpp messages + # this is guarded, so it's not doubling up on work when called from catkin_package (roscpp does this too) + # and we need it to get access to the build_depends list just in case people called generate_messages before catkin_package() + if(NOT DEFINED ${ARG_PKG}_BUILD_DEPENDS) + catkin_package_xml(DIRECTORY ${PROJECT_SOURCE_DIR}) + endif() + foreach(depends ${${ARG_PKG}_BUILD_DEPENDS}) + if(TARGET ${depends}_generate_messages_java_gradle) + message(STATUS "Adding dependency.....${depends}_generate_messages -> ${ARG_PKG}_generate_messages") + add_dependencies(${ARG_PKG}_generate_messages_java_gradle ${depends}_generate_messages_java_gradle) + endif() + endforeach() # Make sure we have built gradle-rosjava_bootstrap if it is in the source workspace # (otherwise package.xml will make sure it has installed via rosdep/deb. #if(TARGET gradle-rosjava_bootstrap) @@ -92,5 +113,12 @@ macro(_generate_module_java ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES) # is not defined till after this module is parsed, so add it all #add_dependencies(${ARG_PKG}_generate_messages gradle-rosjava_bootstrap) #endif() + + ################################ + # Debugging + ################################ + #foreach(gen_output_file ${ALL_GEN_OUTPUT_FILES_java}) + # message(STATUS "ALL_GEN_OUTPUT_FILES_java..........${gen_output_file}") + #endforeach() endmacro() diff --git a/src/genjava/genjava_main.py b/src/genjava/genjava_main.py index 43418d6..4305805 100644 --- a/src/genjava/genjava_main.py +++ b/src/genjava/genjava_main.py @@ -60,6 +60,8 @@ def parse_arguments(argv): #parser.add_argument('-m', '--message', action='store', help='the message file') parser.add_argument('-p', '--package', action='store', help='package to find the message file') parser.add_argument('-o', '--output-dir', action='store', help='output directory for the java code (e.g. build/foo_msgs)') + parser.add_argument('-c', '--compile', default=False, action='store_true', help='switch to compile mode (default is generating mode)') + parser.add_argument('-v', '--verbosity', default=False, action='store_true', help='enable verbosity in debugging (false)') #parser.add_argument('-I', '--include-path', action='append', help="include paths to the package and deps msg files") #myargs = rospy.myargv(argv=sys.argv) #return parser.parse_args(args=myargs[1:]) @@ -73,4 +75,7 @@ def parse_arguments(argv): def main(argv): args = parse_arguments(argv[1:]) #print("genjava %s/%s" % (args.package, args.message)) - gradle_project.create(args.package, args.output_dir) + if not args.compile: + gradle_project.create(args.package, args.output_dir) + else: + gradle_project.build(args.package, args.output_dir, args.verbosity) diff --git a/src/genjava/genjava_main.pyc b/src/genjava/genjava_main.pyc index 556d45fb04dfcf6d6b3d616f85af339e563a0c98..07cfc619d99a606c41854b70b93f6fa2bde78baf 100644 GIT binary patch delta 571 zcmbQjb)Scw`7<xqwu03Y*%xtfGB7YWGcYm~&z`tB(4UDRg@+-9mm!6Zp@f+sg_R+N zpCN^vAw__pnTeUPhLItQi6KRhAw>v7g)m$N3quV9Lo*{ou!hKHe#T{t^~FpK3=F!- z#UQJ6b(8aR3o>(3OV}A07*bNx5=(PRO1Kyp7>Y~si&EoDib_+9jX~V<%#!2`g_3*) zs0M}H{FGD$4X74{%wmP~)V$Q9#FEUsbg-Nz#GbNZZjg1lWvN9;`Nf$fl{&?$3=9mZ zd5K9msS0pWh0HvKl+>is^mLGZjkLs^;#5ry*2&wMOgUK@7#Q3@0+U}eb=UJSFfcH% z3Ngtr$}lQ1DzPLpGB7ZJyu<<vx*!Gyh7tylw^JAy<eM28Y8e?oVa3Q$Y{XE)#E``d z=CXiER)%IK2F5%Yuml@e2qpp2!_Lsm%)pq!z!0nfvcoS^3S^xI2Ll5`5I@KsP`E*Z zWb$=pZTS+AYm-Vdb5cq`0SxybSbGrfWKNcN2X9b-f{b8b6ky_Hlw{HXnF0>>`1rKa hlG38o_;`>n7=l2mN<cmi0@(|;GDv*#5|(^MQ2;V}c_9D* delta 216 zcmcc5Glh$t`7<w9@r+dy*%xuKGcYhXGcYm~hfmxb$j!`9!@$tY$Plc-vpJY?86%Sh z%j6}@rjs8tcO`N#FfcH%3Ngtr%CICeGB7YOF)%PN!?bHLFff!bfV8JDGRQYGGSo6M zlrS=6F)`FIGGsA>Nfw4?CI-e728Lh_kY2w`kSQ9h3=9lGJPZsBli66c*}*bFT$2M> o<9R$87#NCKK-Mw}Oy18bEy@P5gn=Olq!X+uNO1Cd)_g``07M}noB#j- diff --git a/src/genjava/gradle_project.py b/src/genjava/gradle_project.py index e061038..2606903 100644 --- a/src/genjava/gradle_project.py +++ b/src/genjava/gradle_project.py @@ -8,7 +8,7 @@ from __future__ import print_function import os import shutil - +import subprocess from catkin_pkg.packages import find_packages import rospkg @@ -98,7 +98,7 @@ def create_dependency_string(project_name, msg_package_index): dependency_package = msg_package_index[dep.name] except KeyError: continue # it's not a message package - gradle_dependency_string += "compile 'org.ros.rosjava_messages:" + dependency_package.name + ":" + dependency_package.version + "'\n" + gradle_dependency_string += " compile 'org.ros.rosjava_messages:" + dependency_package.name + ":" + dependency_package.version + "'\n" return gradle_dependency_string @@ -120,7 +120,8 @@ def create_msg_package_index(): ros_paths = [x for x in ros_paths.split(':') if x] for path in reversed(ros_paths): # make sure we pick up the source overlays last for unused_package_path, package in find_packages(path).items(): - if 'message_generation' in [dep.name for dep in package.build_depends]: + if ('message_generation' in [dep.name for dep in package.build_depends] or + 'genmsg' in [dep.name for dep in package.build_depends]): # print(package.name) # print(" version: %s" % package.version) # print(" dependencies: ") @@ -153,3 +154,17 @@ def create(msg_pkg_name, output_dir): pkg_directory = os.path.dirname(msg_package_index[msg_pkg_name].filename) msg_pkg_version = msg_package_index[msg_pkg_name].version populate_project(msg_pkg_name, msg_pkg_version, pkg_directory, genjava_gradle_dir, msg_dependencies) + + +def build(msg_pkg_name, output_dir, verbosity): + droppings_file = os.path.join(output_dir, msg_pkg_name, 'droppings') + if not os.path.isfile(droppings_file): + #print("Someone already left droppings here! %s" % droppings_file) + return + print("Scooping the droppings! [%s]" % droppings_file) + os.remove(droppings_file) + cmd = ['./gradlew'] + if not verbosity: + cmd.append('--quiet') + print("COMMAND........................%s" % cmd) + subprocess.call(cmd, stderr=subprocess.STDOUT,) diff --git a/src/genjava/templates/genjava_project/build.gradle.in b/src/genjava/templates/genjava_project/build.gradle.in index c0896ea..371d74f 100644 --- a/src/genjava/templates/genjava_project/build.gradle.in +++ b/src/genjava/templates/genjava_project/build.gradle.in @@ -55,8 +55,15 @@ task generateSources (type: JavaExec) { } dependencies { - compile 'org.ros.rosjava_bootstrap:message_generation:[0.1,)' - %(msg_dependencies)s + compile 'org.ros.rosjava_bootstrap:message_generation:[0.1,)' + %(msg_dependencies)s +} + +jar { + manifest = osgiManifest { + classesDir = sourceSets.main.output.classesDir + classpath = configurations.runtime + } } task info << { @@ -82,4 +89,18 @@ task info << { } } +/* Damon's message generator doesn't catch every message. It expects everything to be nicely under 'msg' + * and that directory to be under the package root. It also expects every msg it finds should be buildable. + * It kinda works until now because it ignores any package which doesn't conform to this and those are just + * test packages (we hope). + * + * Until we get this properly fixed (it fails in genjava), then we use the following bugfix to deal with the + * 'Could not copy MANIFEST.MF...' error that occurs when no sources are to be made for an artifact. + */ +task bugfixtask << { + mkdir sourceSets.main.output.classesDir +} + +jar.dependsOn(bugfixtask) + defaultTasks 'publishMavenJavaPublicationToMavenRepository' -- GitLab