From 3e222451d089d6944370ca0ffce5a17f3182bcc5 Mon Sep 17 00:00:00 2001 From: "John M. Daly" Date: Mon, 13 Jun 2016 11:24:39 -0400 Subject: [PATCH 1/8] fix quoting of paths to handle spaces --- cmake/templates/setup.bat.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/templates/setup.bat.in b/cmake/templates/setup.bat.in index 154918159..33b85466f 100644 --- a/cmake/templates/setup.bat.in +++ b/cmake/templates/setup.bat.in @@ -6,7 +6,7 @@ REM It tries it's best to undo changes from a previously sourced setup file befo REM Supported command line options: REM --extend: skips the undoing of changes from a previously sourced setup file -set _SETUP_UTIL="@SETUP_DIR@/_setup_util.py" +set _SETUP_UTIL=@SETUP_DIR@/_setup_util.py if NOT EXIST "%_SETUP_UTIL%" ( echo "Missing Python script: %_SETUP_UTIL%" @@ -33,7 +33,7 @@ if NOT EXIST %_SETUP_TMP% ( ) REM invoke Python script to generate necessary exports of environment variables -%_PYTHON% %_SETUP_UTIL% %* > %_SETUP_TMP% +%_PYTHON% "%_SETUP_UTIL%" %* > %_SETUP_TMP% if NOT EXIST %_SETUP_TMP% ( echo "Could not create temporary file: %_SETUP_TMP%" return 1 From f9e892ddd0a921b31de9f4742f249b3343337031 Mon Sep 17 00:00:00 2001 From: Dirk Thomas Date: Thu, 4 Aug 2016 08:30:03 -0700 Subject: [PATCH 2/8] fix rollback logic for more than one value per environment variable and workspace --- cmake/templates/_setup_util.py.in | 46 +++++++++++++++--------------- test/unit_tests/test_setup_util.py | 22 +++++++------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/cmake/templates/_setup_util.py.in b/cmake/templates/_setup_util.py.in index 8a641ec22..1949c4cae 100755 --- a/cmake/templates/_setup_util.py.in +++ b/cmake/templates/_setup_util.py.in @@ -72,42 +72,42 @@ def rollback_env_variables(environ, env_var_subfolders): subfolders = env_var_subfolders[key] if not isinstance(subfolders, list): subfolders = [subfolders] - for subfolder in subfolders: - value = _rollback_env_variable(unmodified_environ, key, subfolder) - if value is not None: - environ[key] = value - lines.append(assignment(key, value)) + value = _rollback_env_variable(unmodified_environ, key, subfolders) + if value is not None: + environ[key] = value + lines.append(assignment(key, value)) if lines: lines.insert(0, comment('reset environment variables by unrolling modifications based on all workspaces in CMAKE_PREFIX_PATH')) return lines -def _rollback_env_variable(environ, name, subfolder): +def _rollback_env_variable(environ, name, subfolders): ''' For each catkin workspace in CMAKE_PREFIX_PATH remove the first entry from env[NAME] matching workspace + subfolder. - :param subfolder: str '' or subfoldername that may start with '/' + :param subfolders: list of str '' or subfoldername that may start with '/' :returns: the updated value of the environment variable. ''' value = environ[name] if name in environ else '' env_paths = [path for path in value.split(os.pathsep) if path] value_modified = False - if subfolder: - if subfolder.startswith(os.path.sep) or (os.path.altsep and subfolder.startswith(os.path.altsep)): - subfolder = subfolder[1:] - if subfolder.endswith(os.path.sep) or (os.path.altsep and subfolder.endswith(os.path.altsep)): - subfolder = subfolder[:-1] - for ws_path in _get_workspaces(environ, include_fuerte=True, include_non_existing=True): - path_to_find = os.path.join(ws_path, subfolder) if subfolder else ws_path - path_to_remove = None - for env_path in env_paths: - env_path_clean = env_path[:-1] if env_path and env_path[-1] in [os.path.sep, os.path.altsep] else env_path - if env_path_clean == path_to_find: - path_to_remove = env_path - break - if path_to_remove: - env_paths.remove(path_to_remove) - value_modified = True + for subfolder in subfolders: + if subfolder: + if subfolder.startswith(os.path.sep) or (os.path.altsep and subfolder.startswith(os.path.altsep)): + subfolder = subfolder[1:] + if subfolder.endswith(os.path.sep) or (os.path.altsep and subfolder.endswith(os.path.altsep)): + subfolder = subfolder[:-1] + for ws_path in _get_workspaces(environ, include_fuerte=True, include_non_existing=True): + path_to_find = os.path.join(ws_path, subfolder) if subfolder else ws_path + path_to_remove = None + for env_path in env_paths: + env_path_clean = env_path[:-1] if env_path and env_path[-1] in [os.path.sep, os.path.altsep] else env_path + if env_path_clean == path_to_find: + path_to_remove = env_path + break + if path_to_remove: + env_paths.remove(path_to_remove) + value_modified = True new_value = os.pathsep.join(env_paths) return new_value if value_modified else None diff --git a/test/unit_tests/test_setup_util.py b/test/unit_tests/test_setup_util.py index 3e4d3e7e7..722cf6e8a 100644 --- a/test/unit_tests/test_setup_util.py +++ b/test/unit_tests/test_setup_util.py @@ -101,20 +101,20 @@ def test_remove_from_env(self): mock_env = {varname: os.pathsep.join([foolib, barlib]), 'CMAKE_PREFIX_PATH': barws} # since workspace foo is not in CMAKE_PREFIX_PATH, it remains in varname - self.assertEqual(foolib, _rollback_env_variable(mock_env, varname, '/lib')) + self.assertEqual(foolib, _rollback_env_variable(mock_env, varname, ['/lib'])) # mock_env with both ws in CPP mock_env = {varname: os.pathsep.join([foolib, barlib]), wsvarname: os.pathsep.join([foows, barws]), 'CMAKE_PREFIX_PATH': os.pathsep.join([foows, barws])} - self.assertEqual(None, _rollback_env_variable(mock_env, varname, '')) - self.assertEqual(None, _rollback_env_variable(mock_env, varname, 'nolib')) - self.assertEqual(None, _rollback_env_variable(mock_env, varname, '/nolib')) - self.assertEqual('', _rollback_env_variable(mock_env, varname, 'lib')) - self.assertEqual('', _rollback_env_variable(mock_env, varname, '/lib')) - self.assertEqual(None, _rollback_env_variable(mock_env, varname, '')) - self.assertEqual('', _rollback_env_variable(mock_env, wsvarname, '')) + self.assertEqual(None, _rollback_env_variable(mock_env, varname, [''])) + self.assertEqual(None, _rollback_env_variable(mock_env, varname, ['nolib'])) + self.assertEqual(None, _rollback_env_variable(mock_env, varname, ['/nolib'])) + self.assertEqual('', _rollback_env_variable(mock_env, varname, ['lib'])) + self.assertEqual('', _rollback_env_variable(mock_env, varname, ['/lib'])) + self.assertEqual(None, _rollback_env_variable(mock_env, varname, [''])) + self.assertEqual('', _rollback_env_variable(mock_env, wsvarname, [''])) # nows: not a workspace nows = os.path.join(rootdir, 'nows') @@ -125,12 +125,12 @@ def test_remove_from_env(self): mock_env = {'varname': os.pathsep.join([foolib, nowslib, barlib, foolib]), 'CMAKE_PREFIX_PATH': os.pathsep.join([foows, barws])} # checks nows/lib remains, and second mention of foolib - self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', '/lib')) - self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', 'lib')) + self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', ['/lib'])) + self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', ['lib'])) # windows pathsep os.path.altsep = '\\' - self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', '\\lib')) + self.assertEqual(os.pathsep.join([nowslib, foolib]), _rollback_env_variable(mock_env, 'varname', ['\\lib'])) finally: os.path.altsep = altsep shutil.rmtree(rootdir) From d79fcd66cca64070c2faddb963012a4902520878 Mon Sep 17 00:00:00 2001 From: Michael Kopp Date: Thu, 19 Jan 2017 12:37:34 +0100 Subject: [PATCH 3/8] Minor changes in docu: Build messages for test --- doc/howto/format1/python_nose_configuration.rst | 14 ++++++++++++++ doc/howto/format2/python_nose_configuration.rst | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/doc/howto/format1/python_nose_configuration.rst b/doc/howto/format1/python_nose_configuration.rst index 10b926f1d..891470c51 100644 --- a/doc/howto/format1/python_nose_configuration.rst +++ b/doc/howto/format1/python_nose_configuration.rst @@ -26,6 +26,20 @@ You can also let nosetest find all tests recursively:: catkin_add_nosetests(tests) endif() +If you used a message of the current package in the nosetest, make sure to +specify the nosetest like this:: + + catkin_add_nosetests(tests/test_your_node.py + DEPENDENCIES ${${PROJECT_NAME}_EXPORTED_TARGETS}) + +If you used messages from other packages, use:: + + catkin_add_nosetests(tests/test_your_node.py + DEPENDENCIES ${catkin_EXPORTED_TARGETS}) + +The test will then make sure that the messages used in the test are built +before they are used. + For more info, please have a look at the :ref:`API `. .. _Nosetest: http://www.ros.org/wiki/nosetest diff --git a/doc/howto/format2/python_nose_configuration.rst b/doc/howto/format2/python_nose_configuration.rst index 6c29d4b47..485c2727f 100644 --- a/doc/howto/format2/python_nose_configuration.rst +++ b/doc/howto/format2/python_nose_configuration.rst @@ -26,6 +26,20 @@ You can also let nosetest find all tests recursively:: catkin_add_nosetests(tests) endif() +If you used a message of the current package in the nosetest, make sure to +specify the nosetest like this:: + + catkin_add_nosetests(tests/test_your_node.py + DEPENDENCIES ${${PROJECT_NAME}_EXPORTED_TARGETS}) + +If you used messages from other packages, use:: + + catkin_add_nosetests(tests/test_your_node.py + DEPENDENCIES ${catkin_EXPORTED_TARGETS}) + +The test will then make sure that the messages used in the test are built +before they are used. + For more info, please have a look at the :ref:`API `. .. _Nosetest: http://www.ros.org/wiki/nosetest From df9e38ec2f99ba45a4c8c7079bb03001123eab92 Mon Sep 17 00:00:00 2001 From: Dirk Thomas Date: Mon, 30 Jan 2017 10:27:54 -0800 Subject: [PATCH 4/8] add skipped / disabled tests to catkin_test_results summary (#848) * Fixes #839: Adding disabled tests to catkin_test_results summary. * maintain public API --- bin/catkin_test_results | 7 ++- python/catkin/test_results.py | 83 ++++++++++++++++++++++------ test/unit_tests/test_test_results.py | 31 ++++++++++- 3 files changed, 99 insertions(+), 22 deletions(-) diff --git a/bin/catkin_test_results b/bin/catkin_test_results index 95f1e26f0..8a1686e9b 100755 --- a/bin/catkin_test_results +++ b/bin/catkin_test_results @@ -8,7 +8,7 @@ import sys # find the import relatively if available to work before installing catkin or overlaying installed version if os.path.exists(os.path.join(os.path.dirname(__file__), '..', 'python', 'catkin', '__init__.py')): sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'python')) -from catkin.test_results import aggregate_results, print_summary, test_results +from catkin.test_results import aggregate_results, print_summary2, test_results2 def main(): @@ -24,10 +24,11 @@ def main(): sys.exit('Test results directory "%s" does not exist' % test_results_dir) try: - results = test_results( + results = test_results2( test_results_dir, show_verbose=args.verbose, show_all=args.all) _, sum_errors, sum_failures = aggregate_results(results) - print_summary(results, show_stable=args.all) + print_summary2(results, show_stable=args.all) + # Skipped tests alone should not count as a failure if sum_errors or sum_failures: sys.exit(1) except Exception as e: diff --git a/python/catkin/test_results.py b/python/catkin/test_results.py index d81d4dbc1..1a92d2c2d 100644 --- a/python/catkin/test_results.py +++ b/python/catkin/test_results.py @@ -96,12 +96,18 @@ def _get_missing_junit_result_filename(filename): def read_junit(filename): + """Same as `read_junit2` except it doesn't return num_skipped.""" + num_tests, num_errors, num_failures, _ = read_junit2(filename) + return (num_tests, num_errors, num_failures) + + +def read_junit2(filename): """ parses xml file expected to follow junit/gtest conventions see http://code.google.com/p/googletest/wiki/AdvancedGuide#Generating_an_XML_Report :param filename: str junit xml file name - :returns: num_tests, num_errors, num_failures + :returns: num_tests, num_errors, num_failures, num_skipped :raises ParseError: if xml is not well-formed :raises IOError: if filename does not exist """ @@ -110,17 +116,29 @@ def read_junit(filename): num_tests = int(root.attrib['tests']) num_errors = int(root.attrib['errors']) num_failures = int(root.attrib['failures']) - return (num_tests, num_errors, num_failures) + num_skipped = int(root.get('skip', '0')) + int(root.get('disabled', '0')) + return (num_tests, num_errors, num_failures, num_skipped) def test_results(test_results_dir, show_verbose=False, show_all=False): + """Same as `test_results2` except the returned values don't include num_skipped.""" + results = {} + results2 = test_results2( + test_results_dir, show_verbose=show_verbose, show_all=show_all) + for name, values in results2.items(): + num_tests, num_errors, num_failures, _ = values + results[name] = (num_tests, num_errors, num_failures) + return results + + +def test_results2(test_results_dir, show_verbose=False, show_all=False): ''' Collects test results by parsing all xml files in given path, attempting to interpret them as junit results. :param test_results_dir: str foldername :param show_verbose: bool show output for tests which had errors or failed - :returns: dict {rel_path, (num_tests, num_errors, num_failures)} + :returns: dict {rel_path, (num_tests, num_errors, num_failures, num_skipped)} ''' results = {} for dirpath, dirnames, filenames in os.walk(test_results_dir): @@ -130,12 +148,12 @@ def test_results(test_results_dir, show_verbose=False, show_all=False): filename_abs = os.path.join(dirpath, filename) name = filename_abs[len(test_results_dir) + 1:] try: - num_tests, num_errors, num_failures = read_junit(filename_abs) + num_tests, num_errors, num_failures, num_skipped = read_junit2(filename_abs) except Exception as e: if show_all: print('Skipping "%s": %s' % (name, str(e))) continue - results[name] = (num_tests, num_errors, num_failures) + results[name] = (num_tests, num_errors, num_failures, num_skipped) if show_verbose and (num_errors + num_failures > 0): print("Full test results for '%s'" % (name)) print('-------------------------------------------------') @@ -146,35 +164,68 @@ def test_results(test_results_dir, show_verbose=False, show_all=False): def aggregate_results(results, callback_per_result=None): + """Same as `aggregate_results2` except it doesn't return num_skipped.""" + callback = None + if callback_per_result is not None: + def callback(name, num_tests, num_errors, num_failures, num_skipped): + callback_per_result(name, num_tests, num_errors, num_failures) + sum_tests, sum_errors, sum_failures, _ = aggregate_results2( + results, callback_per_result=callback) + return (sum_tests, sum_errors, sum_failures) + + +def aggregate_results2(results, callback_per_result=None): """ Aggregate results :param results: dict as from test_results() - :returns: tuple (num_tests, num_errors, num_failures) + :returns: tuple (num_tests, num_errors, num_failures, num_skipped) """ - sum_tests = sum_errors = sum_failures = 0 + sum_tests = sum_errors = sum_failures = sum_skipped = 0 for name in sorted(results.keys()): - (num_tests, num_errors, num_failures) = results[name] + (num_tests, num_errors, num_failures, num_skipped) = results[name] sum_tests += num_tests sum_errors += num_errors sum_failures += num_failures + sum_skipped += num_skipped if callback_per_result: - callback_per_result(name, num_tests, num_errors, num_failures) - return sum_tests, sum_errors, sum_failures + callback_per_result( + name, num_tests, num_errors, num_failures, num_skipped) + return sum_tests, sum_errors, sum_failures, sum_skipped def print_summary(results, show_stable=False, show_unstable=True): + """Same as `print_summary2` except it doesn't print skipped tests.""" + print_summary2( + results, show_stable=show_stable, show_unstable=show_unstable, + print_skipped=False) + + +def print_summary2(results, show_stable=False, show_unstable=True, print_skipped=True): """ print summary to stdout :param results: dict as from test_results() :param show_stable: print tests without failures extra :param show_stable: print tests with failures extra + :param print_skipped: include skipped tests in output """ - def callback(name, num_tests, num_errors, num_failures): - if show_stable and not num_errors and not num_failures: + def callback(name, num_tests, num_errors, num_failures, num_skipped): + if show_stable and not num_errors and not num_failures and not num_skipped: print('%s: %d tests' % (name, num_tests)) - if show_unstable and (num_errors or num_failures): - print('%s: %d tests, %d errors, %d failures' % (name, num_tests, num_errors, num_failures)) - sum_tests, sum_errors, sum_failures = aggregate_results(results, callback) - print('Summary: %d tests, %d errors, %d failures' % (sum_tests, sum_errors, sum_failures)) + if show_unstable and (num_errors or num_failures or num_skipped): + msg = '{}: {} tests, {} errors, {} failures' + msg_args = [name, num_tests, num_errors, num_failures] + if print_skipped: + msg += ', {} skipped' + msg_args.append(num_skipped) + print(msg.format(*msg_args)) + sum_tests, sum_errors, sum_failures, sum_skipped = aggregate_results2(results, callback) + + msg = 'Summary: {} tests, {} errors, {} failures' + msg_args = [sum_tests, sum_errors, sum_failures] + if print_skipped: + msg += ', {} skipped' + msg_args.append(sum_skipped) + + print(msg.format(*msg_args)) diff --git a/test/unit_tests/test_test_results.py b/test/unit_tests/test_test_results.py index 324c40d9d..10e772613 100644 --- a/test/unit_tests/test_test_results.py +++ b/test/unit_tests/test_test_results.py @@ -26,9 +26,25 @@ def test_read_junit(self): result_file = os.path.join(rootdir, 'test1.xml') with open(result_file, 'w') as fhand: - fhand.write('') + fhand.write('') (num_tests, num_errors, num_failures) = catkin_test_results.read_junit(result_file) self.assertEqual((5, 1, 3), (num_tests, num_errors, num_failures)) + (num_tests, num_errors, num_failures, num_skipped) = catkin_test_results.read_junit2(result_file) + self.assertEqual((5, 1, 3, 2), (num_tests, num_errors, num_failures, num_skipped)) + finally: + shutil.rmtree(rootdir) + + def test_read_junit_skip(self): + try: + rootdir = tempfile.mkdtemp() + + result_file = os.path.join(rootdir, 'test1.xml') + with open(result_file, 'w') as fhand: + fhand.write('') + (num_tests, num_errors, num_failures) = catkin_test_results.read_junit(result_file) + self.assertEqual((5, 1, 3), (num_tests, num_errors, num_failures)) + (num_tests, num_errors, num_failures, num_skipped) = catkin_test_results.read_junit2(result_file) + self.assertEqual((5, 1, 3, 2), (num_tests, num_errors, num_failures, num_skipped)) finally: shutil.rmtree(rootdir) @@ -39,9 +55,11 @@ def test_test_results(self): for filename in ['test1.xml', 'test2.xml', 'foo.bar']: result_file = os.path.join(rootdir, filename) with open(result_file, 'w') as fhand: - fhand.write('') + fhand.write('') results = catkin_test_results.test_results(rootdir) self.assertEqual({'test1.xml': (5, 1, 3), 'test2.xml': (5, 1, 3)}, results) + results = catkin_test_results.test_results2(rootdir) + self.assertEqual({'test1.xml': (5, 1, 3, 2), 'test2.xml': (5, 1, 3, 2)}, results) finally: shutil.rmtree(rootdir) @@ -85,7 +103,7 @@ def test_test_results_detail_with_non_ascii(self): print(summary) def test_print_summary(self): - results = {'test1.xml': (5, 1, 3), 'test2.xml': (7, 2, 4)} + results = {'test1.xml': (5, 1, 3, 2), 'test2.xml': (7, 2, 4, 1)} try: oldstdout = sys.stdout sys.stdout = StringIO() @@ -95,5 +113,12 @@ def test_print_summary(self): self.assertTrue('7 tests, 2 errors, 4 failures' in summary, summary) self.assertTrue('12 tests, 3 errors, 7 failures' in summary, summary) + sys.stdout = StringIO() + catkin_test_results.print_summary2(results) + summary = sys.stdout.getvalue() + self.assertTrue('5 tests, 1 errors, 3 failures, 2 skipped' in summary, summary) + self.assertTrue('7 tests, 2 errors, 4 failures, 1 skipped' in summary, summary) + self.assertTrue('12 tests, 3 errors, 7 failures, 3 skipped' in summary, summary) + finally: sys.stdout = oldstdout From d159a258724782a4cee62605bca3f89a32a6befb Mon Sep 17 00:00:00 2001 From: Martin Pecka Date: Thu, 26 Jan 2017 23:50:44 +0100 Subject: [PATCH 5/8] Added notes about not filling the requires field. The idea for this edit originated here: https://github.com/ros-infrastructure/rosdep/issues/497 . --- doc/user_guide/setup_dot_py.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/user_guide/setup_dot_py.rst b/doc/user_guide/setup_dot_py.rst index f536cffe8..10638e7e3 100644 --- a/doc/user_guide/setup_dot_py.rst +++ b/doc/user_guide/setup_dot_py.rst @@ -67,6 +67,30 @@ sourcespace using the python exec() function. The version will be compared to that declared in package.xml, and raise an error on mismatch. +.. note:: + + If you have written non-ROS Python packages before, you have + probably used the ``requires`` field in the distuils setup function. + This field, however, *has no meaning* in ROS. + + All your Python + dependencies should be specified in ``package.xml`` as e.g. + ``python-numpy`` (for older version 1 + of package.xml) or ``python-numpy`` + (if you use format 2 of package.xml). + + Not all Python or pip packages are mapped to ROS dependencies. + For a quick check, try running ``rosdep resolve python-mypackage`` + or ``rosdep resolve python-mypackage-pip`` if you want to + add a dependency on ``mypackage`` Python package. If these calls + return error, you may want to search through the + `python.yaml file in rosdep`_ for similar names. If you don't + find the requested package, you may consider + `creating a Pull request to add it`_. + + .. _python.yaml file in rosdep: https://github.com/ros/rosdistro/blob/master/rosdep/python.yaml + .. _creating a Pull request to add it: http://docs.ros.org/independent/api/rosdep/html/contributing_rules.html + Using package.xml in setup.py ============================= @@ -100,6 +124,12 @@ one distributes to pypi. catkin_install_python(PROGRAMS scripts/myscript DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) +.. note:: + + See the note in previous section about the otherwise useful + field ``requires`` that's usually a part of distutils setup. + *Do not use it* in ROS. + Develspace limitations ====================== From 0ff22e5dae9b77c2d1c0583466a43c40ee03d2a3 Mon Sep 17 00:00:00 2001 From: Dirk Thomas Date: Wed, 8 Feb 2017 14:45:46 -0800 Subject: [PATCH 6/8] update --pkg help in cmi --- bin/catkin_make_isolated | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/catkin_make_isolated b/bin/catkin_make_isolated index ccef0fc39..26bf5da13 100755 --- a/bin/catkin_make_isolated +++ b/bin/catkin_make_isolated @@ -53,7 +53,7 @@ def parse_args(args=None): help='Disables colored output (only for catkin_make and CMake)') pkg = parser.add_mutually_exclusive_group(required=False) pkg.add_argument('--pkg', nargs='+', metavar='PKGNAME', dest='packages', - help="Invoke 'make' on specific packages " + help="Process only specific packages " "(only after catkin_make_isolated has been invoked before with the same install flag)") pkg.add_argument('--from-pkg', metavar='PKGNAME', dest='from_package', help='Restart catkin_make_isolated at the given package continuing from there ' From 6e090b4529d6f6f6f2dd315ae5838559ccef203a Mon Sep 17 00:00:00 2001 From: Marc Bestmann <0bestman@informatik.uni-hamburg.de> Date: Sat, 11 Feb 2017 16:19:58 +0100 Subject: [PATCH 7/8] Small addition to installing_cmake documentation (#854) * small addition to installing_cmake documentation * added same coment to format 1 documentation --- doc/howto/format1/installing_cmake.rst | 3 +++ doc/howto/format2/installing_cmake.rst | 3 +++ 2 files changed, 6 insertions(+) diff --git a/doc/howto/format1/installing_cmake.rst b/doc/howto/format1/installing_cmake.rst index 67af08814..f8cd1bd1b 100644 --- a/doc/howto/format1/installing_cmake.rst +++ b/doc/howto/format1/installing_cmake.rst @@ -10,6 +10,9 @@ want to export:: catkin_package(CFG_EXTRAS your_macros.cmake your_modules.cmake) +When another package uses ``find_package()`` on this package, the listed +CMake files are automatically included. + Since these data are platform-independent, they should be installed in your package's **share/** subtree. This example assumes your CMake sources are in the customary **cmake/** subdirectory:: diff --git a/doc/howto/format2/installing_cmake.rst b/doc/howto/format2/installing_cmake.rst index ee5336391..08506f076 100644 --- a/doc/howto/format2/installing_cmake.rst +++ b/doc/howto/format2/installing_cmake.rst @@ -10,6 +10,9 @@ want to export:: catkin_package(CFG_EXTRAS your_macros.cmake your_modules.cmake) +When another package uses ``find_package()`` on this package, the listed +CMake files are automatically included. + Since these data are platform-independent, they should be installed in your package's **share/** subtree. This example assumes your CMake sources are in the customary **cmake/** subdirectory:: From ab883e0b9ef4bd6ceb495a3b2a78331ef9008f5d Mon Sep 17 00:00:00 2001 From: Dirk Thomas Date: Tue, 28 Feb 2017 12:18:24 -0800 Subject: [PATCH 8/8] update generated CMake API --- doc/dev_guide/generated_cmake_api.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/dev_guide/generated_cmake_api.rst b/doc/dev_guide/generated_cmake_api.rst index 6cddc4581..6512c1271 100644 --- a/doc/dev_guide/generated_cmake_api.rst +++ b/doc/dev_guide/generated_cmake_api.rst @@ -160,7 +160,7 @@ Public CMake functions / macros .. note:: The test can be executed by calling ``nosetests`` directly or using: `` make run_tests_${PROJECT_NAME}_nosetests_${dir}`` - (where slashes in the ``dir`` are replaced with underscores) + (where slashes in the ``dir`` are replaced with periods) :param path: a relative or absolute directory to search for nosetests in or a relative or absolute file containing tests @@ -374,8 +374,10 @@ Public CMake functions / macros :param CFG_EXTRAS: a CMake file containing extra stuff that should be accessible to users of this package after ``find_package``\ -ing it. This file must live in the - subdirectory ``cmake`` or be an absolute path. Various additional - file extension are possible: + subdirectory ``cmake`` or be an absolute path. + All passed extra files must have unique basenames since they are + being installed into a single folder. + Various additional file extension are possible: for a plain cmake file just ``.cmake``, for files expanded using CMake's ``configure_file()`` use ``.cmake.in`` or for files expanded by empy use ``.cmake.em``. The templates can distinguish between