Package: termux-create-package
termux-create-packageA utility to createbinary deb packages.By default it creates binary deb packages for installation in theTermuxLinux environment, but by passing the--prefix /usrargument or defininginstallation_prefix: "/usr"field in theYAMLorJSONmanifest, a deb file can be created for linux distributions such as Debian or Ubuntu, etc.ContentsCompatibilityDownloadsInstallationCurrent FeaturesUsagePackage Control File FieldsPackage Create Info FieldsPackage Data Files FieldsOther Control FilesExamplesCompatibilityAndroid version>= 7.0usingTermux App.Linux distros.Windows usingcygwinorWSL.(Untested)DownloadsLatest version isv0.12.0.GitHub releases.InstallationCheckINSTALLATION.mdfile for theinstall instructions.Current FeaturesDefine package build info inYAML1.2.0orJSONmanifest files.Create binary deb packages as per debian policy.Automatically createcontrol,md5sums,conffilesfile.Automatically set permissions and ownership to files.Run specific actions on package files like setting shebangs.Usagetermux-create-package command is used to create binary deb packages.

Usage:
  termux-create-package [optional arguments] manifests...

positional arguments:
  manifests             YAML or JSON manifest file(s) describing the package(s)

optional arguments:
  -h, --help            show this help message and exit
  --help-extra          show extra help message and exit
  --version             show program's version number and exit
  -v                    "set verbose level,
                        pass once for log level "INFO" and twice for "DEBUG
  --control-files-dir CONTROL_FILES_DIR
                        path to directory of maintainer scripts and other control files,
                        (default: current directory,
                        unless "control_files_dir" field is set or "--files-dir" is passed or "files_dir" manifest field is set)
  --deb-dir DEB_DIR     path to directory to create deb file in,
                        (default: current directory,
                        unless "deb_dir" manifest field is set)
  --deb-name DEB_NAME   name of deb file to create,
                        (default: "${Package}_${Version}_S{Architecture}.deb",
                        unless "deb_name" manifest field is set)
  --files-dir FILES_DIR
                        path to directory of package files,
                        (default: relative to current directory,
                        unless "files_dir" manifest field is set)
  --pkg-arch PKG_ARCH   architecture the package was compiled for or will run on,
                        (default: "Architecture" manifest "control" dict field)
  --pkg-version PKG_VERSION
                        version for the package,
                        (default: "Version" manifest "control" dict field)
  --prefix PREFIX       path under which to install the files on the target system
                        (default: /data/data/com.termux/files/usr,
                        unless "installation_prefix" manifest field is set)
  --yaml                force consider manifest to be in yaml format,
                        (default: false

The paths to YAML or JSON manifest file(s) must be passed as "manifests".Thetermux-create-packagescript expects the package manifest files containing info on how to build the package to be defined inYAML1.2.0orJSONformat.YAMlis the preferred format since its a better configuration language thanJSON, specially due to support for comments and splitting strings on multiple lines.The deb file created will be as perDebian Policy Manualand will contain the following files:debian-binarywill contain the package format version number. Currently2.0.control.tar*will contain thecontrolfile containing package info,md5sumscontainingmd5hashes of package files, maintainer scripts and other control files. More info oncontrolfile can be found atdpkg-dev/deb-control.data.tar*will contain the package data files.Note that any optional arguments passed will override their respective manifest fields in ALL manifests passed, so use wisely, or use them only if passing only a single manifest.Beware of trailing commas inJSONmanifest for the last item of lists and dictionaries since otherwise an exception will be raised.Example YAML manifest:control:Package:hello-worldVersion:0.1.0Architecture:allMaintainer:GithubNick <GithubNick@gmail.com>Depends:python (>= 3.0), libandroid-supportHomepage:https://hello-world.comDescription:|-This is the hello world packageIt is just an example for termux-create-package.It is just prints 'Hello world'installation_prefix:/data/data/com.termux/files/usrdata_files:bin/hello-world:source:hello-world.pyset_shebang:"#!/data/data/com.termux/files/usr/bin/envpython3"share/man/man1/hello-world.1:source:hello-world.1Example JSON manifest:{"control":{"Package":"hello-world","Version":"0.1.0","Architecture":"all","Maintainer":"GithubNick <GithubNick@gmail.com>","Depends":"python (>= 3.0), libandroid-support","Homepage":"https://hello-world.com","Description":["This is the hello world package"," It is just an example for termux-create-package"," ."," It is just prints 'Hello, world'"]},"installation_prefix":"/data/data/com.termux/files/usr","data_files":{"bin/hello-world":{"source":"hello-world.py","set_shebang":"#!/data/data/com.termux/files/usr/bin/env python3"},"share/man/man1/hello-world.1":{"source":"hello-world.1"}}}Package Control File FieldsThe fields in the manifest file under thecontroldictionary will be added to thecontrolfile incontrol.tar*and should contain the package info.The field name must be composed ofUS-ASCIIcharacters within the range32/U+0021through126/U+007Eexcluding spaceand colon:characters and it must not begin with hyphen-or comment#characters. Field names are not case-sensitive, but it is usual to capitalize the first letter of words as perCamelCaseformat. The fields must be defined inCamelCasefor versions>= 0.12.0but old format is also supported to maintain backward compatibility. Some keys were named differently previously, which are also supported.The common fields that are added to the control file in order if they exist in the manifest arePackage,Source,Version,Architecture,Maintainer,Installed-Size,Section,Priority,Essential,Depends,Pre-Depends,Recommends,Suggests,Breaks,Conflicts,Replaces,Enhances,Provides,Homepage,Description. Any other field that exists in the manifest are added after theProvidesfield and before theHomepagefield. TheInstalled-Sizefield will be automatically added by calculating data files sizes if its not already defined in the manifest.ThePackage,Version,Architecture,MaintainerandDescriptionfields aremandatoryas per debian policy and their valid values must exist in the manifest. TheArchitecturevalue can optionally be passed as a command option if the manifest is to be shared between different architectures.If the field is not of typelist, then it is converted to a normal string and added to the control file. Fields that arenullor empty are not added. Checksyntax of control filessection in debian policy for further details.If the field is of typelistand is not one of the package relationship fields, then each item of the list will be joined together by newlines and added to the control file. This is helpful to define multi-line fields likeDescription.If the field is of typelistand is one of the package relationship fields, i.eDepends,Pre-Depends,Recommends,Suggests,Breaks,Conflicts,Replaces,EnhancesandProvides, then it will automatically be joined on a comma followed by space character,. If these fields are defined as a string, then a comma must be added between each package of the field in the manifest, otherwisedpkgwill throw an error likeparsing file '/var/lib/dpkg/tmp.ci/control' near line 6 package 'hello-world': 'Depends' field, syntax error after reference to package 'python3'duringdebinstallation. These fields are currently not validated due to them being a bit complex to easily parse/validate. Checkdeclaring relationships between packagessection in debian policy for further details.All below fields are of typestringunless otherwise specified.PackageThe name of the package. This field was namednamein versions< 0.12.0. Checkherefor more details.Valid Values:It must consist only of lower case lettersa-z, digits0-9, plus+and hyphen-signs, and periods.. It must be at least two characters long and must start with an alphanumeric character. The same rules apply to the optionalSourcefield.VersionThe version of the package. Checkherefor more details.Valid Values:It must be in the format[epoch:]upstream_version[-debian_revision].epochcan only be an integer.upstream_versionanddebian_revisionmust consist only of upper or lower case lettersa-zA-Z, digits0-9, plus+and tilde~signs, and periods.. Theupstream_versionmust start with a digit. The hyphen-is only allowed ifdebian_revisionis set.ArchitectureThe architecture the package was compiled for or will run on. This field was namedarchin versions< 0.12.0. Checkherefor more details.Set toallif the package only contains architecture-independent data. If installation prefix starts with/data/data/<app_package>/files/, then it must be one ofall,arm,i686,aarch64orx86_64since android only supports those architectures, however, you can override this by adding"ignore_android_specific_rules": trueentry to the manifest.Valid Values:It must must contain a space separated list of architectures or architecture wildcards that consist only of lower case lettersa-z, digits0-9, plus+and hyphen-signs, and periods.. It must be at least two characters long and must start with an alphanumeric character.MaintainerThe name and contact of the maintainer. It should be in the formatname <email>, example:Foo Bar <foo.bar@baz.com>. It is typically the person who created the package, as opposed to the author of the software that is to be packaged. Checkherefor more details.DependsComma-separated list of packages that this package depends on. Those packages will be installed automatically when this package is installed usingapt.HomepageThe project home page URL. Checkherefor more details.DescriptionContains the description of the binary package, consisting of two parts, the synopsis or the short description, and the long description. Checkherefor more details. It is amulti-linefield with the following format:Description: Single line short description
 extended description over several lines
 .
 some more descriptionFormulti-linefields incontrolfile, each line after the first line must have a space characteras the first character and must contain at least one non-whitespace character like a dot., otherwisedpkgwill throw an error likeparsing file '/var/lib/dpkg/tmp.ci/control' near line 8 package 'hello-world': field name 'It' must be followed by colonduringdebinstallation. To represent empty lines, set the line to a space character followed by a dot.To define amulti-linefield in aYAMLmanifest, the field value could be set as aliteral block style|withstrip block chomping indication-(to strip trailing newlines), like|-. Each line will be joined together with a newline character\n.Do not forget-after|, otherwise validation will fail since last line due to trailing newline will be considered an empty line.Description: |-
    Single line short description
     extended description over several lines
     .
     some more descriptionTo define a multi-line field in aJSONmanifest the field value could be set to alist. Each item of thelistwill be joined together with a newline character\n."Description": [
    "Single line short description",
    " extended description over several lines",
    " .",
    " some more description"
    ]Package Create Info FieldsThe fields in the manifest file outside thecontrolanddata_filesdictionaries are used for storing information on how to create the package and what files need to be added to the package. These fields are not added thecontrolfile.The currently used package create info fields are the following. All fields are of typestringunless otherwise specified.allow_bad_user_names_and_idsTheboolfield that decides whether is should be allowed to add package files to the deb that are considered invalid as per debian policy. Checkowner_uidandowner_unamefor details on what is considered valid.conffiles_prefix_to_replaceThe optional path prefix that should be replaced with the installation prefix in the files added in the locally definedconffilesfile incontrol_files_dirorfiles_dir. For example if this is set to/usrandconffilescontains a file with the path/usr/etc/hello-world/hello-world.configand installation prefix is set to/data/data/com.termux/files/usr, then the finalconffilesadded to the deb file with have the path set to/data/data/com.termux/files/usr/etc/hello-world/hello-world.configinstead. This does not apply to theconffilesfile dynamically generated withdata_filesthat haveis_conffileset totrue.control_files_dirThe path to directory containing maintainer scriptspreinst,postinst,prerm,postrm,configand other control filesconffiles,templates,shlibsto include in the deb package. The default is relative to current directory, unless--control-files-diror--files-dirargument is passed to the script orfiles_dirfield is set. This is useful if the same files/build directory is used for different distros or architectures but different maintainer scripts orconffilesfor each.deb_architecture_tagThe architecture tag to use for the file name of the deb file to be created. Ifdeb_nameis not set and--deb-nameargument is not passed to the script, then deb file will be named${Package}_${Version}_S{deb_architecture_tag}.debinstead of${Package}_${Version}_S{Architecture}.deb. This is helpful if you want to use the same package and version tag defined inPackageandVersionfields respectively but a different architectures tag than the one defined inArchitecturefield.deb_dirThe path of the directory to create the deb file in. The default is current directory, unless--deb-dirargument is passed to the script.deb_nameThe file name of the deb file to be created. If this is not set, then deb file will be named${Package}_${Version}_S{Architecture}.debby default, unless--deb-nameargument is passed to the script.files_dirThe path to directory containing package files to include in the deb package. The default is relative to current directory, unless--files-dirargument is passed to the script.fix_permsTheboolfield that decides whether permissions of source files that are added as packagedata_filesshould be automatically fixed when adding them to thedebfile as perdh_fixperms(impl) rules if needed.Thefix_permsvalue is the global value that can be set totrue(default) orfalseto enable or disable fixing permissions respectively foralldata_files. If it istrue, then you can optionally disable fixing permissions for specific files only by setting their file levelfix_permfield value tofalse. If it isfalse, then you can optionally enable fixing permissions for specific files only by setting their file levelfix_permfield value totrue. The permissions are not fixed if a data file has thepermfield set.ignore_android_specific_rulesTheboolfield that can be set totrueto ignore the following android specific rules:Only allow android specific architectures if prefix is set under the/data/data/<app_package>/files/path.Remove group and others permissions while setting permissions for files to be added todata.tar*under the/data/data/<app_package>/files/path ifpermfield is not set and globalfix_permsand/or file levelfix_permistrue.Set permissions of parent directory paths for files to be added todata.tar*under the/data/data/<app_package>/files/path to700instead of755.installation_prefixThe prefix under which to install the files on the target system. The termux prefix/data/data/com.termux/files/usris used by default if the field is not defined, unless--prefixargument is passed to the script. It must be an absolute path that starts with forward slash/, ends with/usrand must only contain characters in the rangea-zA-Z0-9_./. It cannot contain parent path references../.maintainer_scripts_shebangThe shebang that should be set on the maintainer scripts if the first line starts with#!. Example:#!/bin/bashfor linux distros and#!/data/data/com.termux/files/usr/bin/bashfor termux.tar_compressionThe compression type ofcontrol.tar*anddata.tar*. Thexztar compression is used by default if the field is not defined since that is the default for current versions ofdpkg. Ifnoneis set, then compression will not be done. Checkdpkg-dev/debfor more details.Valid Values:none,gzandxz.tar_formatThe tar format ofcontrol.tar*anddata.tar*. TheGNU tarformat is used by default if the field is not defined since that is officially supported bydpkg. You may get package corrupted errors if other formats are used, speciallypax. Checkdpkg-dev/debfor more details.Valid Values:gnutar,ustarandpax.Package Data Files FieldsThedata_filesdictionaryis amandatoryfield containing a nesteddictionarytype where the parent key is the destination path for the data file inside the deb package or target system and the value is adictionarycontaining the following keys/value pairs for version>= 0.12.0.If destination path is an absolute path starting with a forward slash/, then that will be used. Otherwise it will be considered relative to the installation prefix. If the destination path is an empty string"", then it automatically expand to the installation prefix.Fields that arenullor empty are not used, other thansourcepath.Nonutf-8characters are not allowed in any paths as per debian policy.Mandatory attribute key/value pairs:sourceThe source path for the data file from which to read the file that should be added to the package. If source path is an absolute path starting with a forward slash/, then that will be used, otherwise it will be considered relative to the current working directory, unless--files-dirargument is passed to the script orfiles_dirfield is set. If the source path is an empty string"", then an empty directory will be added at the destination path.Optional attribute key/value pairs:fix_permTheboolvalue that defines thefilelevel setting for whether fixing permissions should be done for the source file when adding it to the deb. Checkfix_permsfor more info.is_conffileTheboolvalue that defines whether this data file is aconffileand should be added to the dynamically generatedconffilesfile.owner_uidThe owner user id that should be set to the data file when adding it to the deb. It must be within the0-99,60000-64999and65534ranges. By default user id0is set, unlesssource_ownershipis set. Thesource_ownershiptakes precedence overowner_uid.Checkdebian policy,useradd manual,systemd uid/gid docsandshadowfind_new_uid.cfor more info.Note that when installing thedebfile on android with the termux app, any custom ownership value will not be set and all files will be set totermuxuser ownership.owner_unameThe owner user name that should be set to the data file when adding it to the deb. It must begin with a lower case letter or an underscore, followed by lower case letters, digits, underscores, or hyphens. It can end with a dollar sign. In regular expression terms:[a-z_][a-z0-9_-]*[$]?. It may also be only up to32characters long. By default user namerootis set, unlesssource_ownershipis set. Thesource_ownershiptakes precedence overowner_uname.Checkdebian policy,useradd manual,shadowuseradd.c,systemd user name docs,shadowchkname.candposix docsfor more info.group_uidThe group user id that should be set to the data file when adding it to the deb. Same rules asowner_uidapply.group_unameThe group user name that should be set to the data file when adding it to the deb. Same rules asowner_unameapply.permThe3or4digit permission octal that should be set to the data file when adding it to the deb. Example:755forrwxr-xr-xor4755forrwsr-xr-xwheresetuidbit is also set. If a custom value inpermfield is not set, then the permissions will be automatically fixed. Checkfix_permsfor more info.source_ownershipTheboolvalue for whether source ownership should be used when adding the data file to the deb. If source ownership is not compliant, as per debian policy, then it is ignored androot:rootownership is used. Checkowner_uidandowner_unamefor details on what is considered valid.Optional action key/value pairs:ignoreTheboolvalue for whether this data file defined in the manifest should be ignored and not added to the deb. Source file existence check is not done.ignore_if_no_existTheboolvalue for whether this data file defined in the manifest should be ignored and not added to the deb if it not does not exist atsourcepath instead of command exiting with failure.set_parent_permTheboolvalue for whether the permissions should be set to the parent directory paths for of the data file directory the same as the source permissions or the one defined byperm. For example, if a destination entry is added foropt/hello-world/cache, thenoptandopt/hello-worldwill also be set to the same permissions. This is useful to define a directory hierarchy with the same specific permissions.set_shebangThe shebang that should be set on the data file if the first line starts with#!. Example:#!/bin/bashfor linux distros and#!/data/data/com.termux/files/usr/bin/bashfor termux.source_readlinkTheboolvalue for whether thesourcepath should be traversed if its a symlink. By default ifsourcefile is asymlink, then thesymlinkitself is added to the deb file instead of its target file.source_recurseTheboolvalue for whether all files under thesourcepath should be recursively added to the deb if its a directory. By defaultfiles undersourcedirectories are not automatically/recursively added to the deb. Each file that needs to be added to the deb must be added separately.This is useful for cases where the files/build directory contains lots of files but you only want specific files to be added to the deb. You may optionally only add a directory entry and not add any file entries, which would ideally result in an empty directory at the target system if it didn't already exist there.symlink_destinationsThelistvalue that defines the symlinks that should automatically be created and added to the deb that target the destination data file path. For example adding the entry for the destination filebin/hello-world.1and addingbin/hello-worldtosymlink_destinationswill create a file atbin/hello-worldthat points tobin/hello-world.1. This is helpful in defining one or more symlinks dynamically for a file, without having to create symlink files on source system.If specific permission needs to be set to the parent directory of a file that needs to be installed at the target system, then add an emptysourceentry with thepermfield set before the entry of the file, optionally withset_parent_permset totrueas well. However, if the directory already exists at the target system, then the permission is unlikely to change, use maintainer scripts instead."data_files": {
    "bin": { "source": "", "perm": "755" },
    "bin/hello-world": { "source": "hello-world.py", "perm": "755" },
    "share/man/man1/hello-world.1": { "source": "hello-world.1", "perm": "644" }
}Oldfilesformat:Thisdata_filesfield was namedfilesin versions< 0.12.0and it had thesourceas the dictionary key instead of the destination. That had the design flaw that a single source file could only be added to one destination path in the deb. Moreover, since destination was the value instead of the key, multiple source files could be added for the same destination. The new design does not have such issues and paths are normalized to check for duplicates too. Old format is also fully supported to maintain backward compatibility. In version>= 0.8, with thefilesfield, the files in source path directories were recursively added to the deb, but that will not happen in version>= 0.12.0with the newdata_filesfield as mentioned insource_recurse.Note that any files whose ownership is not compliant with debian policy, as detailed inowner_uidandowner_uname, will have their ownership replaced withroot:root. That is likely the only breaking change and users on old formats should shift to newer format and setallow_bad_user_names_and_idstotrueif they want to go against debian policy."files": {
    "hello-world.py": "bin/hello-world",
    "hello-world.1": "share/man/man1/hello-world.1"
}Other Control FilesThe maintainer scriptspreinst,postinst,prerm,postrm,configand other control filesconffiles,templates,shlibsare automatically added tocontrol.tar*if they exist incontrol_files_dirorfiles_dir.The ownership of all files added to thecontrol.tar*is automatically set toroot:rootas per debian policy. The permission of maintainer scripts is automatically set to755and other control files to644.Themaintainer_scripts_shebangfield is helpful if the same architecture independent scripts need to be added to different debs for linux distros and termux. Checkscriptssection in debian policy for further details.Theconffilescan be added to the deb in two ways. Either a predefined file can be added tocontrol_files_dirorfiles_dirthat should be added or it can be dynamically generated by setting theis_conffilefield totruefor thedata_filesthat should be added to theconffiles. If even a single file hasis_conffileset totrue, then any predefinedconffilesincontrol_files_dirorfiles_dirwill not be added andconffilesgenerated dynamically will be added. All files in theconffilesadded are validated for existence in the deb and an error will be raised if any file does not exist. If a predefined file is defined, theconffiles_prefix_to_replacemay be useful as well if debs are being built for linux distros and termux. Theconffilesfile content must beutf-8encodable as per debian policy and all files must be regular files and not symlinks since that is not officially supported and can result in unpredictable behaviour, directories are not supported either. Each line must contain an absolute file path. Empty lines are not allowed. Checkconfiguration filessection in debian policy for further details.ExamplesAfter creating a manifest for the project, runtermux-create-package </path/to/manifest>command to create the deb file. Example manifests are provided for bothYAMLandJSONin theexamplesdirectory.Create a deb package file with defaults:termux-create-package manifest.ymlCreate a deb package file with specific installation prefix, files directory, deb directory and deb name:termux-create-package --prefix '/usr' --files-dir '/path/to/files_directory' --deb-dir '/path/to/deb_directory' --deb-name 'some-name.deb' manifest.jsonCreate example manifest deb fromtermux-create-packagerepo source:cd examples/hello-world; ../../src/termux-create-package -vv manifest-ubuntu.ymlThe deb file can be installed by runningdpkg -i package.deb. Thedpkginstall command will not install dependencies, you can install them by runningapt-get -f installafterwards.The deb file can also be added to a custom apt repository created withtermux-apt-repoor any other available tool.