From fee98138bdc01be98ab8765a90583fc2efd3c952 Mon Sep 17 00:00:00 2001 From: Waldek Herka <87032474+wherka-ama@users.noreply.github.com> Date: Fri, 11 Mar 2022 23:47:05 +0000 Subject: [PATCH] Added support for DEB packages (#13) * Added support for DEB packages Co-authored-by: Waldek Herka --- setup.cfg | 4 +- src/bdist_pyinstaller/__init__.py | 2 +- src/bdist_pyinstaller/bdist_pyinstaller.py | 84 ++++++++++++++++++++-- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/setup.cfg b/setup.cfg index 61f6fd2..87d00c4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,7 @@ [bumpversion] -current_version = 0.1.1 +current_version = 0.2.0 + +[bumpversion:file:src/bdist_pyinstaller/__init__.py] [metadata] name = bdist_pyinstaller diff --git a/src/bdist_pyinstaller/__init__.py b/src/bdist_pyinstaller/__init__.py index 6655893..cd57cb1 100644 --- a/src/bdist_pyinstaller/__init__.py +++ b/src/bdist_pyinstaller/__init__.py @@ -1,2 +1,2 @@ -__version__ = '0.1.1' +__version__ = '0.2.0' diff --git a/src/bdist_pyinstaller/bdist_pyinstaller.py b/src/bdist_pyinstaller/bdist_pyinstaller.py index f737f5b..b9f15ed 100644 --- a/src/bdist_pyinstaller/bdist_pyinstaller.py +++ b/src/bdist_pyinstaller/bdist_pyinstaller.py @@ -96,8 +96,9 @@ class PyInstalerCmd(Command): ), ("one-dir", None, "one directory mode", "(default: false)"), ("rpm", None, "create rpm deliverable", "(default: false)"), + ("deb", None, "create deb deliverable", "(default: false)"), ] - boolean_options = ["one-dir", "rpm"] + boolean_options = ["one-dir", "rpm", "deb"] def initialize_options(self): self.bdist_dir = None @@ -106,6 +107,7 @@ def initialize_options(self): self.extra_modules = None self.one_dir = False self.rpm = False + self.deb = False self.aliases = [] def finalize_options(self): @@ -479,10 +481,12 @@ def dispatch_{package_name}(): arcname=target_name, recursive=True, ) - if self.rpm: self.create_rpm(pyinstaller_dist, target_name) + if self.deb: + self.create_deb(pyinstaller_dist, target_name) + finally: sys.argv = _argv_ @@ -498,7 +502,7 @@ def create_rpm(self, dist_location, dist_name): spec_path = os.path.join(spec_dir, f"{self.distribution.get_name()}.spec") self.execute( write_file, - (spec_path, self._generate_spec_file(dist_location, dist_name)), + (spec_path, self._generate_rpm_spec_file(dist_location, dist_name)), "writing '%s'" % spec_path, ) @@ -556,7 +560,79 @@ def create_rpm(self, dist_location, dist_name): ("bdist_pyinstaller", pyversion, filename) ) - def _generate_spec_file(self, dist_location, dist_name): + def create_deb(self, dist_location, dist_name): + # Make all necessary directories + binary_target_base = "usr/bin" + deb_base = os.path.join(dist_location, "deb") + binaries_target_path = os.path.join(deb_base, binary_target_base) + spec_path = os.path.join(deb_base, "DEBIAN", "control") + self.mkpath(binaries_target_path) + self.mkpath(os.path.dirname(spec_path)) + for alias in self.aliases: + dst = os.path.join(binaries_target_path, alias) + src = os.path.join(dist_location, dist_name) + if os.path.exists(dst): + os.unlink(dst) + os.link(src, dst) + + arch_string = self._get_deb_build_arch() + self.execute( + write_file, + ( + spec_path, + self._generate_deb_spec_file(dist_location, dist_name, arch_string), + ), + f"writing '{spec_path}'", + ) + + os.chmod(deb_base, mode=0o755) + os.chmod(os.path.dirname(spec_path), mode=0o755) + + # build package + log.info("building DEBs") + release = "1" + deb_filename = os.path.join( + deb_base, + f"{self.distribution.get_name()}_{self.distribution.get_version()}_{release}_{arch_string}.deb", + ) + deb_cmd = ["dpkg-deb", "--build", "--root-owner-group", deb_base, deb_filename] + + self.spawn(deb_cmd) + if not self.dry_run: + pyversion = "any" + if os.path.exists(deb_filename): + self.move_file(deb_filename, self.dist_dir) + filename = os.path.join(self.dist_dir, os.path.basename(deb_filename)) + self.distribution.dist_files.append( + ("bdist_pyinstaller", pyversion, filename) + ) + + def _get_deb_build_arch(self): + arch_string = "amd64" + q_cmd = "dpkg-architecture -q DEB_BUILD_ARCH" + out = os.popen("dpkg-architecture -q DEB_BUILD_ARCH") + try: + line = out.readline() + if line: + arch_string = line.strip() + status = out.close() + if status: + raise DistutilsExecError(f"Failed to execute: {q_cmd}") + + finally: + out.close() + return arch_string + + def _generate_deb_spec_file(self, dist_location, dist_name, arch_string): + return [ + f"Package: {self.distribution.get_name()}", + f"Version: {self.distribution.get_version().replace('-','_')}", + f"Architecture: {arch_string}", + f"Maintainer: {self.distribution.get_author()} <{self.distribution.get_author_email()}>", + f"""Description: {self.distribution.get_description()}""", + ] + + def _generate_rpm_spec_file(self, dist_location, dist_name): """Generate the text of an RPM spec file and return it as a list of strings (one per line). """