Skip to content
Browse files

add check for changed message dependencies changed (fix #41)

  • Loading branch information...
1 parent 63d9750 commit d8281d02d42708378b3520dd139ebfec92db628e @dirk-thomas dirk-thomas committed Feb 26, 2014
Showing with 127 additions and 11 deletions.
  1. +4 −0 CMakeLists.txt
  2. +8 −0 cmake/genmsg-extras.cmake.em
  3. +26 −2 cmake/pkg-genmsg.cmake.em
  4. +1 −0 cmake/pkg-genmsg.context.in
  5. +69 −0 scripts/genmsg_check_deps.py
  6. +19 −9 src/genmsg/deps.py
View
4 CMakeLists.txt
@@ -15,6 +15,10 @@ install(
catkin_python_setup()
+install(
+ PROGRAMS scripts/genmsg_check_deps.py
+ DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
+
if(CATKIN_ENABLE_TESTING)
catkin_add_nosetests(test)
endif()
View
8 cmake/genmsg-extras.cmake.em
@@ -8,6 +8,14 @@ set(_GENMSG_EXTRAS_INCLUDED_ TRUE)
# set destination for langs
set(GENMSG_LANGS_DESTINATION "etc/ros/genmsg")
+@[if DEVELSPACE]@
+# bin dir variables in develspace
+set(GENMSG_CHECK_DEPS_SCRIPT "@(CMAKE_CURRENT_SOURCE_DIR)/scripts/genmsg_check_deps.py")
+@[else]@
+# bin dir variables in installspace
+set(GENMSG_CHECK_DEPS_SCRIPT "${genmsg_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)/genmsg_check_deps.py")
+@[end if]@
+
include(CMakeParseArguments)
# find message generators in all workspaces
View
28 cmake/pkg-genmsg.cmake.em
@@ -34,16 +34,22 @@ if not messages and not services:
print('message(WARNING "Invoking generate_messages() without having added any message or service file before.\nYou should either add add_message_files() and/or add_service_files() calls or remove the invocation of generate_messages().")')
msg_deps = {}
+msg_dep_types = {}
for m in messages:
try:
- msg_deps[m] = genmsg.deps.find_msg_dependencies(pkg_name, m, dep_search_paths)
+ _deps = genmsg.deps.find_msg_dependencies_with_type(pkg_name, m, dep_search_paths)
+ msg_deps[m] = [d[1] for d in _deps]
+ msg_dep_types[m] = [d[0] for d in _deps]
except genmsg.MsgNotFound as e:
print('message(FATAL_ERROR "Could not find messages which \'%s\' depends on. Did you forget to specify generate_messages(DEPENDENCIES ...)?\n%s")' % (m, str(e)))
srv_deps = {}
+srv_dep_types = {}
for s in services:
try:
- srv_deps[s] = genmsg.deps.find_srv_dependencies(pkg_name, s, dep_search_paths)
+ _deps = genmsg.deps.find_srv_dependencies_with_type(pkg_name, s, dep_search_paths)
+ srv_deps[s] = [d[1] for d in _deps]
+ srv_dep_types[s] = [d[0] for d in _deps]
except genmsg.MsgNotFound as e:
print('message(FATAL_ERROR "Could not find messages which \'%s\' depends on. Did you forget to specify generate_messages(DEPENDENCIES ...)?\n%s")' % (s, str(e)))
@@ -61,6 +67,18 @@ find_package(@l REQUIRED)
add_custom_target(@(pkg_name)_generate_messages ALL)
+# verify that message/service dependencies have not changed since configure
+@{all_deps = dict(msg_deps.items() + srv_deps.items())}
+@{all_dep_types = dict(msg_dep_types.items() + srv_dep_types.items())}
+@[for f in all_deps.keys()]@
+@{dep_types = ':'.join(all_dep_types[f]).replace('\\','/')}
+message("F @(f) deps @(dep_types)")
+get_filename_component(_filename "@(f)" NAME_WE)
+add_custom_target(_@(pkg_name)_generate_messages_check_deps_${_filename}
+ COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_CHECK_DEPS_SCRIPT} "@(pkg_name)" "@(f)" "@(dep_types)"
+)
+@[end for]@# messages and services
+
#
# langs = @langs
#
@@ -99,6 +117,12 @@ add_custom_target(@(pkg_name)_generate_messages_@(l[3:])
)
add_dependencies(@(pkg_name)_generate_messages @(pkg_name)_generate_messages_@(l[3:]))
+# add dependencies to all check dependencies targets
+@[for f in all_deps.keys()]@
+get_filename_component(_filename "@(f)" NAME_WE)
+add_dependencies(@(pkg_name)_generate_messages_@(l[3:]) _@(pkg_name)_generate_messages_check_deps_${_filename})
+@[end for]@# messages and services
+
# target for backward compatibility
add_custom_target(@(pkg_name)_@(l))
add_dependencies(@(pkg_name)_@(l) @(pkg_name)_generate_messages_@(l[3:]))
View
1 cmake/pkg-genmsg.context.in
@@ -8,3 +8,4 @@ langs = "@GEN_LANGS@"
dep_include_paths_str = "@MSG_INCLUDE_DIRS@"
PYTHON_EXECUTABLE = "@PYTHON_EXECUTABLE@"
package_has_static_sources = '@package_has_static_sources@' == 'TRUE'
+genmsg_check_deps_script = "@GENMSG_CHECK_DEPS_SCRIPT@"
View
69 scripts/genmsg_check_deps.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2014, Open Source Robotics Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Open Source Robotics Foundation, Inc. nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from __future__ import print_function
+
+import os
+import sys
+
+from genmsg import EXT_MSG, EXT_SRV, MsgContext
+from genmsg.gentools import compute_full_type_name
+from genmsg.msg_loader import load_msg_from_file, load_srv_from_file
+from genmsg.msgs import bare_msg_type, is_builtin, resolve_type
+
+pkg_name = sys.argv[1]
+msg_file = sys.argv[2]
+deps = sys.argv[3].split(':') if len(sys.argv) > 3 else []
+
+msg_context = MsgContext.create_default()
+full_type_name = compute_full_type_name(pkg_name, os.path.basename(msg_file))
+
+if msg_file.endswith(EXT_MSG):
+ spec = load_msg_from_file(msg_context, msg_file, full_type_name)
+ unresolved_types = spec.types
+elif msg_file.endswith(EXT_SRV):
+ spec = load_srv_from_file(msg_context, msg_file, full_type_name)
+ unresolved_types = spec.request.types + spec.response.types
+else:
+ print("Processing file: '%s' - unknown file extension" % msg_file, file=sys.stderr)
+ sys.exit(1)
+
+package_context = spec.package
+for unresolved_type in unresolved_types:
+ bare_type = bare_msg_type(unresolved_type)
+ resolved_type = resolve_type(bare_type, package_context)
+ if not is_builtin(resolved_type) and resolved_type not in deps:
+ print("The dependencies of the message/service '%s' have changed. Please rerun cmake." % spec.full_name, file=sys.stderr)
+ sys.exit(1)
View
28 src/genmsg/deps.py
@@ -37,10 +37,10 @@
# pkg_name - string
# msg_file - string full path
# search_paths - dict of {'pkg':'msg_dir'}
-def find_msg_dependencies(pkg_name, msg_file, search_paths):
+def find_msg_dependencies_with_type(pkg_name, msg_file, search_paths):
- # Read and parse the source msg file
- msg_context = genmsg.msg_loader.MsgContext.create_default() # not used?
+ # Read and parse the source msg file
+ msg_context = genmsg.msg_loader.MsgContext.create_default()
full_type_name = genmsg.gentools.compute_full_type_name(pkg_name, os.path.basename(msg_file))
spec = genmsg.msg_loader.load_msg_from_file(msg_context, msg_file, full_type_name)
@@ -51,15 +51,20 @@ def find_msg_dependencies(pkg_name, msg_file, search_paths):
deps = set()
for dep_type_name in msg_context.get_all_depends(full_type_name):
- deps.add( msg_context.get_file(dep_type_name) )
+ deps.add((dep_type_name, msg_context.get_file(dep_type_name)))
return list(deps)
-def find_srv_dependencies(pkg_name, msg_file, search_paths):
+def find_msg_dependencies(pkg_name, msg_file, search_paths):
+ deps = find_msg_dependencies_with_type(pkg_name, msg_file, search_paths)
+ return [d[1] for d in deps]
+
- # Read and parse the source msg file
- msg_context = genmsg.msg_loader.MsgContext.create_default() # not used?
+def find_srv_dependencies_with_type(pkg_name, msg_file, search_paths):
+
+ # Read and parse the source msg file
+ msg_context = genmsg.msg_loader.MsgContext.create_default()
full_type_name = genmsg.gentools.compute_full_type_name(pkg_name, os.path.basename(msg_file))
spec = genmsg.msg_loader.load_srv_from_file(msg_context, msg_file, full_type_name)
@@ -72,13 +77,18 @@ def find_srv_dependencies(pkg_name, msg_file, search_paths):
deps = set()
for dep_type_name in msg_context.get_all_depends(spec.request.full_name):
- deps.add( msg_context.get_file(dep_type_name) )
+ deps.add((dep_type_name, msg_context.get_file(dep_type_name)))
for dep_type_name in msg_context.get_all_depends(spec.response.full_name):
- deps.add( msg_context.get_file(dep_type_name) )
+ deps.add((dep_type_name, msg_context.get_file(dep_type_name)))
return list(deps)
+
+def find_srv_dependencies(pkg_name, msg_file, search_paths):
+ deps = find_srv_dependencies_with_type(pkg_name, msg_file, search_paths)
+ return [d[1] for d in deps]
+
#paths = {'std_msgs':'/u/mkjargaard/repositories/mkjargaard/dist-sandbox/std_msgs/msg'}
#file = '/u/mkjargaard/repositories/mkjargaard/dist-sandbox/quux_msgs/msg/QuuxString.msg'
#find_msg_dependencies('quux_msgs', file, paths)

0 comments on commit d8281d0

Please sign in to comment.
Something went wrong with that request. Please try again.