diff --git a/bloom/generators/debian/generate_cmd.py b/bloom/generators/debian/generate_cmd.py index a0de06f8..ce64e88a 100644 --- a/bloom/generators/debian/generate_cmd.py +++ b/bloom/generators/debian/generate_cmd.py @@ -77,17 +77,20 @@ def prepare_arguments(parser): add('--ros-distro', help="ROS distro, e.g. %s (used for rosdep)" % get_non_eol_distros_prompt()) add('-i', '--debian-inc', help="debian increment number", default='0') add('--native', action='store_true', help="generate native package") + add('-r', '--runtime-pkg', default=False, action="store_true", + help="Generate -runtime package") return parser -def get_subs(pkg, os_name, os_version, ros_distro, deb_inc=0, native=False): +def get_subs(pkg, os_name, os_version, ros_distro, deb_inc=0, native=False, runtime_pkg=False): return generate_substitutions_from_package( pkg, os_name, os_version, ros_distro, deb_inc=deb_inc, - native=native + native=native, + runtime_pkg=runtime_pkg, ) @@ -125,7 +128,7 @@ def main(args=None, get_subs_fn=None): for path, pkg in pkgs_dict.items(): template_files = None try: - subs = get_subs_fn(pkg, os_name, os_version, ros_distro, args.debian_inc, args.native) + subs = get_subs_fn(pkg, os_name, os_version, ros_distro, args.debian_inc, args.native, args.runtime_pkg) if _place_template_files: # Place template files place_template_files(path, pkg.get_build_type()) diff --git a/bloom/generators/debian/generator.py b/bloom/generators/debian/generator.py index fe629c8d..771e15eb 100644 --- a/bloom/generators/debian/generator.py +++ b/bloom/generators/debian/generator.py @@ -195,7 +195,7 @@ def summarize_dependency_mapping(data, deps, build_deps, resolved_deps): info(template.format(key, resolved_deps[key])) -def format_depends(depends, resolved_deps): +def format_depends(depends, resolved_deps, ros_distro=""): versions = { 'version_lt': '<<', 'version_lte': '<=', @@ -206,6 +206,8 @@ def format_depends(depends, resolved_deps): formatted = [] for d in depends: for resolved_dep in resolved_deps[d.name]: + if ros_distro and resolved_dep.startswith(f"ros-{ros_distro}"): + resolved_dep = f"{resolved_dep}-runtime" version_depends = [k for k in versions.keys() if getattr(d, k, None) is not None] @@ -316,7 +318,8 @@ def generate_substitutions_from_package( peer_packages=None, releaser_history=None, fallback_resolver=None, - native=False + native=False, + runtime_pkg=False, ): peer_packages = peer_packages or [] data = {} @@ -346,8 +349,18 @@ def generate_substitutions_from_package( data['InstallationPrefix'] = installation_prefix # Resolve dependencies evaluate_package_conditions(package, ros_distro) + + if runtime_pkg: + exec_depends = [ + dep for dep in (package.exec_depends) + if dep.evaluated_condition is not False] + run_depends = package.build_export_depends + else: + exec_depends = [] + run_depends = package.run_depends + depends = [ - dep for dep in (package.run_depends + package.buildtool_export_depends) + dep for dep in (run_depends + package.buildtool_export_depends) if dep.evaluated_condition is not False] build_depends = [ dep for dep in (package.build_depends + package.buildtool_depends) @@ -361,12 +374,15 @@ def generate_substitutions_from_package( conflicts = [ dep for dep in package.conflicts if dep.evaluated_condition is not False] - unresolved_keys = depends + build_depends + test_depends + replaces + conflicts + unresolved_keys = exec_depends + depends + build_depends + test_depends + replaces + conflicts # The installer key is not considered here, but it is checked when the keys are checked before this resolved_deps = resolve_dependencies(unresolved_keys, os_name, os_version, ros_distro, peer_packages + [d.name for d in (replaces + conflicts)], fallback_resolver) + data['RuntimeDepends'] = sorted( + set(format_depends(exec_depends, resolved_deps, ros_distro)) + ) data['Depends'] = sorted( set(format_depends(depends, resolved_deps)) ) @@ -374,7 +390,7 @@ def generate_substitutions_from_package( # https://wiki.debian.org/BuildProfileSpec data['BuildDepends'] = sorted( set(format_depends(build_depends, resolved_deps)) | - set(p + ' ' for p in format_depends(test_depends, resolved_deps)) + set(p + ' ' for p in format_depends(test_depends, resolved_deps, ros_distro if runtime_pkg else "")) ) data['Replaces'] = sorted( set(format_depends(replaces, resolved_deps)) @@ -479,6 +495,7 @@ def generate_substitutions_from_package( else: licenses.append((str(l), 'See repository for full license text')) data['Licenses'] = licenses + data['RuntimePackage'] = runtime_pkg def convertToUnicode(obj): if sys.version_info.major == 2: @@ -555,6 +572,8 @@ def process_template_files(path, subs): if not os.path.exists(debian_dir): sys.exit("No debian directory found at '{0}', cannot process templates." .format(debian_dir)) + with open(os.path.join(debian_dir, f"{subs['Package']}-runtime.install"), "w", encoding="utf-8") as f: + f.write("debian/tmp/*") return __process_template_folder(debian_dir, subs) @@ -633,6 +652,8 @@ def prepare_arguments(self, parser): help='A list of debian (ubuntu) distros to generate for') add('--install-prefix', default=None, help="overrides the default installation prefix (/usr)") + add('-r', '--runtime-pkg', default=False, action="store_true", + help="Generate -runtime package") add('--os-name', default='ubuntu', help="overrides os_name, set to 'ubuntu' by default") add('--os-not-required', default=False, action="store_true", @@ -660,6 +681,7 @@ def handle_arguments(self, args): if args.install_prefix is None: self.install_prefix = self.default_install_prefix self.prefix = args.prefix + self.runtime_pkg = args.runtime_pkg self.branches = match_branches_with_prefix(self.prefix, get_branches, prune=not args.match_all) if len(self.branches) == 0: error( @@ -928,7 +950,8 @@ def get_subs(self, package, debian_distro, releaser_history=None): self.debian_inc, [p.name for p in self.packages.values()], releaser_history=releaser_history, - fallback_resolver=missing_dep_resolver + fallback_resolver=missing_dep_resolver, + runtime_pkg=self.runtime_pkg, ) def generate_debian(self, package, debian_distro): diff --git a/bloom/generators/debian/templates/ament_cmake/control.em b/bloom/generators/debian/templates/ament_cmake/control.em index 6d7b65c3..5fa462ed 100644 --- a/bloom/generators/debian/templates/ament_cmake/control.em +++ b/bloom/generators/debian/templates/ament_cmake/control.em @@ -6,9 +6,21 @@ Build-Depends: debhelper (>= @(debhelper_version).0.0), @(', '.join(BuildDepends Homepage: @(Homepage) Standards-Version: 3.9.2 +@[if RuntimePackage] +Package: @(Package)-runtime +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(RuntimeDepends)) +@[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ +Breaks: @(Package) (<<@(Version)) +Replaces: @(Package) (<<@(Version)), @(Replaces ? ', '.join(Replaces)) +Description: @(Description) + . + This package contains only the runtime files. + +@[end if] Package: @(Package) Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(Depends)) +Depends: ${shlibs:Depends}, ${misc:Depends}, @(RuntimePackage ? Package + "-runtime, ")@(', '.join(Depends)) @[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ @[if Replaces]Replaces: @(', '.join(Replaces))@\n@[end if]@ Description: @(Description) diff --git a/bloom/generators/debian/templates/ament_cmake/rules.em b/bloom/generators/debian/templates/ament_cmake/rules.em index 2ab7b14a..474ab820 100755 --- a/bloom/generators/debian/templates/ament_cmake/rules.em +++ b/bloom/generators/debian/templates/ament_cmake/rules.em @@ -65,3 +65,12 @@ override_dh_auto_install: # CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH. if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \ dh_auto_install +@[if RuntimePackage] + +execute_after_dh_install: + true # no op needed for make +ifneq (,$(realpath debian/@(Package)-runtime@(InstallationPrefix)/include)) + install -d "debian/@(Package)@(InstallationPrefix)/include" + mv "debian/@(Package)-runtime@(InstallationPrefix)/include" "debian/@(Package)@(InstallationPrefix)" +endif +@[end if] diff --git a/bloom/generators/debian/templates/ament_python/control.em b/bloom/generators/debian/templates/ament_python/control.em index bd232d2c..e678c02b 100644 --- a/bloom/generators/debian/templates/ament_python/control.em +++ b/bloom/generators/debian/templates/ament_python/control.em @@ -6,9 +6,21 @@ Build-Depends: debhelper (>= @(debhelper_version).0.0), @(', '.join(BuildDepends Homepage: @(Homepage) Standards-Version: 3.9.2 +@[if RuntimePackage] +Package: @(Package)-runtime +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(RuntimeDepends)) +@[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ +Breaks: @(Package) (<<@(Version)) +Replaces: @(Package) (<<@(Version)), @(Replaces ? ', '.join(Replaces)) +Description: @(Description) + . + This package contains only the runtime files. + +@[end if] Package: @(Package) Architecture: any -Depends: ${python3:Depends}, ${misc:Depends}, @(', '.join(Depends)) +Depends: ${python3:Depends}, ${misc:Depends}, @(RuntimePackage ? Package + "-runtime, ")@(', '.join(Depends)) @[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ @[if Replaces]Replaces: @(', '.join(Replaces))@\n@[end if]@ Description: @(Description) diff --git a/bloom/generators/debian/templates/catkin/control.em b/bloom/generators/debian/templates/catkin/control.em index 6d7b65c3..5fa462ed 100644 --- a/bloom/generators/debian/templates/catkin/control.em +++ b/bloom/generators/debian/templates/catkin/control.em @@ -6,9 +6,21 @@ Build-Depends: debhelper (>= @(debhelper_version).0.0), @(', '.join(BuildDepends Homepage: @(Homepage) Standards-Version: 3.9.2 +@[if RuntimePackage] +Package: @(Package)-runtime +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(RuntimeDepends)) +@[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ +Breaks: @(Package) (<<@(Version)) +Replaces: @(Package) (<<@(Version)), @(Replaces ? ', '.join(Replaces)) +Description: @(Description) + . + This package contains only the runtime files. + +@[end if] Package: @(Package) Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(Depends)) +Depends: ${shlibs:Depends}, ${misc:Depends}, @(RuntimePackage ? Package + "-runtime, ")@(', '.join(Depends)) @[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ @[if Replaces]Replaces: @(', '.join(Replaces))@\n@[end if]@ Description: @(Description) diff --git a/bloom/generators/debian/templates/catkin/rules.em b/bloom/generators/debian/templates/catkin/rules.em index 276329db..b9ef7949 100755 --- a/bloom/generators/debian/templates/catkin/rules.em +++ b/bloom/generators/debian/templates/catkin/rules.em @@ -65,3 +65,12 @@ override_dh_auto_install: # set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH. if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \ dh_auto_install +@[if RuntimePackage] + +execute_after_dh_install: + true # no op needed for make +ifneq (,$(realpath debian/@(Package)-runtime@(InstallationPrefix)/include)) + install -d "debian/@(Package)@(InstallationPrefix)/include" + mv "debian/@(Package)-runtime@(InstallationPrefix)/include" "debian/@(Package)@(InstallationPrefix)" +endif +@[end if] diff --git a/bloom/generators/debian/templates/cmake/control.em b/bloom/generators/debian/templates/cmake/control.em index 6d7b65c3..5fa462ed 100644 --- a/bloom/generators/debian/templates/cmake/control.em +++ b/bloom/generators/debian/templates/cmake/control.em @@ -6,9 +6,21 @@ Build-Depends: debhelper (>= @(debhelper_version).0.0), @(', '.join(BuildDepends Homepage: @(Homepage) Standards-Version: 3.9.2 +@[if RuntimePackage] +Package: @(Package)-runtime +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(RuntimeDepends)) +@[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ +Breaks: @(Package) (<<@(Version)) +Replaces: @(Package) (<<@(Version)), @(Replaces ? ', '.join(Replaces)) +Description: @(Description) + . + This package contains only the runtime files. + +@[end if] Package: @(Package) Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, @(', '.join(Depends)) +Depends: ${shlibs:Depends}, ${misc:Depends}, @(RuntimePackage ? Package + "-runtime, ")@(', '.join(Depends)) @[if Conflicts]Conflicts: @(', '.join(Conflicts))@\n@[end if]@ @[if Replaces]Replaces: @(', '.join(Replaces))@\n@[end if]@ Description: @(Description) diff --git a/bloom/generators/debian/templates/cmake/rules.em b/bloom/generators/debian/templates/cmake/rules.em index 284a0714..f16e7b20 100755 --- a/bloom/generators/debian/templates/cmake/rules.em +++ b/bloom/generators/debian/templates/cmake/rules.em @@ -59,7 +59,11 @@ override_dh_shlibdeps: # in the install tree and source it. It will set things like # CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH. if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \ +@[if RuntimePackage] + dh_shlibdeps -l$(CURDIR)/debian/@(Package)-runtime@(InstallationPrefix)/lib/:$(CURDIR)/debian/@(Package)-runtime@(InstallationPrefix)/lib/${DEB_HOST_MULTIARCH} +@[else] dh_shlibdeps -l$(CURDIR)/debian/@(Package)/@(InstallationPrefix)/lib/:$(CURDIR)/debian/@(Package)/@(InstallationPrefix)/lib/${DEB_HOST_MULTIARCH} +@[end if] override_dh_auto_install: # In case we're installing to a non-standard location, look for a setup.sh @@ -67,3 +71,12 @@ override_dh_auto_install: # CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH. if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \ dh_auto_install +@[if RuntimePackage] + +execute_after_dh_install: + true # no op needed for make +ifneq (,$(realpath debian/@(Package)-runtime@(InstallationPrefix)/include)) + install -d "debian/@(Package)@(InstallationPrefix)/include" + mv "debian/@(Package)-runtime@(InstallationPrefix)/include" "debian/@(Package)@(InstallationPrefix)" +endif +@[end if] diff --git a/bloom/generators/rosdebian.py b/bloom/generators/rosdebian.py index 6284680a..e879b571 100644 --- a/bloom/generators/rosdebian.py +++ b/bloom/generators/rosdebian.py @@ -70,7 +70,7 @@ def summarize(self): info("Releasing for rosdistro: " + self.rosdistro) return ret - def get_subs(self, package, debian_distro, releaser_history, deb_inc=0, native=False): + def get_subs(self, package, debian_distro, releaser_history, deb_inc=0, native=False, runtime_pkg=False): def fallback_resolver(key, peer_packages, rosdistro=self.rosdistro): if key in peer_packages: return [sanitize_package_name(rosify_package_name(key, rosdistro))] @@ -84,7 +84,8 @@ def fallback_resolver(key, peer_packages, rosdistro=self.rosdistro): self.debian_inc, [p.name for p in self.packages.values()], releaser_history=releaser_history, - fallback_resolver=fallback_resolver + fallback_resolver=fallback_resolver, + runtime_pkg=self.runtime_pkg, ) subs['Rosdistro'] = self.rosdistro subs['Package'] = rosify_package_name(subs['Package'], self.rosdistro) @@ -152,7 +153,7 @@ def rosify_package_name(name, rosdistro): return 'ros-{0}-{1}'.format(rosdistro, name) -def get_subs(pkg, os_name, os_version, ros_distro, deb_inc, native): +def get_subs(pkg, os_name, os_version, ros_distro, deb_inc, native, runtime_pkg): # No fallback_resolver provided because peer packages not considered. subs = generate_substitutions_from_package( pkg, @@ -161,7 +162,8 @@ def get_subs(pkg, os_name, os_version, ros_distro, deb_inc, native): ros_distro, RosDebianGenerator.default_install_prefix + ros_distro, deb_inc=deb_inc, - native=native + native=native, + runtime_pkg=runtime_pkg, ) subs['Package'] = rosify_package_name(subs['Package'], ros_distro) return subs