{"id":539,"date":"2025-02-22T18:19:51","date_gmt":"2025-02-22T23:19:51","guid":{"rendered":"https:\/\/dpm.darkhorselinux.org\/?page_id=539"},"modified":"2025-02-23T00:45:32","modified_gmt":"2025-02-23T05:45:32","slug":"specification-files","status":"publish","type":"page","link":"https:\/\/dpm.darkhorselinux.org\/?page_id=539","title":{"rendered":"DPM Specification Files"},"content":{"rendered":"\n<p>To build a package, you&#8217;ll need a specification file.<\/p>\n\n\n\n<p>A <code>spec file<\/code> is a file that dpm is told to create a package with.  Think of it as a configuration file for the build process for DPM packages.<\/p>\n\n\n\n<p>For an example, imagine you&#8217;re building a package.  You&#8217;ve populated your directory tree and you&#8217;re ready to make the package.  You&#8217;d run something like this:<\/p>\n\n\n\n<p><code>dpm buildpkg --spec=.\/MyApp.SPEC --contents-path=.\/contents<\/code><\/p>\n\n\n\n<p>This is telling DPM to pass the spec file path and pre-populated contents tree to the <code>buildpkg<\/code> module. The package creation module would read the spec file&#8217;s contents and generate a package based on those contents. This allows repeatable package builds.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">On Source Compilation: DPM doesn&#8217;t do it.<\/h2>\n\n\n\n<p>Bear in mind that the use of the word <code>build<\/code> here is not meant to convey source compilation.  The compilation of binaries and the packaging of pre-compiled binaries are wholly separate processes that never should have been merged into a single unit of work, and DPM solves this problem by not attempting to include source compilation in any of its features &#8212; it assumes that the packager has already done this.<\/p>\n\n\n\n<p>There is room in the design for support for a <code>SDPM<\/code> file format, but this is not a priority for the system as a whole &#8212; merely allowance in the design for the capability of handling this, which will be elaborated on in a dedicated section for SDPM compilation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">DPM Spec File Structure<\/h2>\n\n\n\n<p>The DPM spec file is a structured file with headers for each section.  Each section is intended to be used by DPM during the buildpkg process to populate:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the package metadata<\/li>\n\n\n\n<li>the optional signature archive<\/li>\n\n\n\n<li> the DPM hooks contents<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Syntax<\/h2>\n\n\n\n<p>Syntax is very simple.  The file is read line by line and contains three types of data:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Comments<\/li>\n\n\n\n<li>Section Start\/Stop declarations<\/li>\n\n\n\n<li>Section Content<\/li>\n<\/ul>\n\n\n\n<p>Sections have a reserved name that match the corresponding filename in the DPM Package specification.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comments<\/h2>\n\n\n\n<p>Commented lines start with a <code>#<\/code> symbol.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sections<\/h2>\n\n\n\n<p>Each field represents a data value that the package will need.<\/p>\n\n\n\n<p>To start a section, the maintainer would have:<\/p>\n\n\n\n<p><code>%section metadata.NAME<\/code><\/p>\n\n\n\n<p>To likewise end a section:<\/p>\n\n\n\n<p><code>%section_end metadata.NAME<\/code><\/p>\n\n\n\n<p>Whatever is between these values will become the value in the resulting packages&#8217; metadata.  In the event that a section is multiline but the value is a single-line string, only the first line will be read.<\/p>\n\n\n\n<p>Whitespace between sections will not be read.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Environment Variables<\/h3>\n\n\n\n<p>Environment variables can be interpolated in DPM Spec files.  Their notation is a preceding <code>'[['<\/code> and proceeding <code>']]'<\/code> with a single space as padding around the variable name.<\/p>\n\n\n\n<p>So, if you set an environment variable prior to reading it DPM will interpolate it in the SPEC file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>yourshellprompt# PKG_NAME=\"Apache2\"\n\n... spec file ...\n...\n%section metadata.NAME\n&#91;&#91; PKG_NAME ]]\n%section_end metadata.NAME<\/code><\/pre>\n\n\n\n<p>Then <code>[[ PKG_NAME ]]<\/code> will be replaced with the string <code>Apache2<\/code>.<\/p>\n\n\n\n<p>If you would like to avoid negation of a variable name for a section declaration for whatever reason, such as when working with layers of templating engines, you can wrap literal statements with <code>[%literal]<\/code> and <code>[%\/literal]<\/code> indicators.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>%section hooks.POST-INSTALL\necho \"adding &#91;%literal] &#91;&#91; PKG_NAME ]] to %section hooks.POST-INSTALL &#91;%\/literal]\"\n%section_end hooks.POST-INSTALL<\/code><\/pre>\n\n\n\n<p>In this example, the echoed text will be:<\/p>\n\n\n\n<p><code>adding [[ PKG_NAME ]] to %section hooks.POST-INSTALL<\/code><\/p>\n\n\n\n<p>This allows the maintainer to do layered templating approaches of large sets of packages.<\/p>\n\n\n\n<p>If a variable is referenced but is empty or not defined, DPM will refuse to build the package and cite usage of an uninitialized variable as the reason.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Reserved Names<\/h3>\n\n\n\n<p>Reserved names for sections are:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">hooks<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>hooks.POST-INSTALL<\/li>\n\n\n\n<li>hooks.POST-INSTALL_ROLLBACK<\/li>\n\n\n\n<li>hooks.POST-REMOVE<\/li>\n\n\n\n<li>hooks.POST-REMOVE_ROLLBACK<\/li>\n\n\n\n<li>hooks.POST-UPDATE<\/li>\n\n\n\n<li>hooks.POST-UPDATE_ROLLBACK<\/li>\n\n\n\n<li>hooks.POST-INSTALL<\/li>\n\n\n\n<li>hooks.POST-INSTALL_ROLLBACK<\/li>\n\n\n\n<li>hooks.PRE-REMOVE<\/li>\n\n\n\n<li>hooks.PRE-REMOVE_ROLLBACK<\/li>\n\n\n\n<li>hooks.PRE-UPDATE<\/li>\n\n\n\n<li>hooks.PRE-UPDATE_ROLLBACK<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">metadata<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>metadata.ARCHITECTURE<\/li>\n\n\n\n<li>metadata.AUTHOR<\/li>\n\n\n\n<li>metadata.MAINTAINER<\/li>\n\n\n\n<li>metadata.DEPENDENCIES<\/li>\n\n\n\n<li>metadata.DESCRIPTION<\/li>\n\n\n\n<li>metadata.CONTENTS_MANIFEST_DIGEST<\/li>\n\n\n\n<li>metadata.LICENSE<\/li>\n\n\n\n<li>metadata.NAME<\/li>\n\n\n\n<li>metadata.PROVIDES<\/li>\n\n\n\n<li>metadata.REPLACES<\/li>\n\n\n\n<li>metadata.SOURCE<\/li>\n\n\n\n<li>metadata.CHANGELOG<\/li>\n\n\n\n<li>metadata.VERSION<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">On Signatures<\/h4>\n\n\n\n<p>You will likely immediately notice that there is no mention of signatures.  That&#8217;s because building a package and signing a package are different things, and signing is handled by a different DPM module prior to zipping up the package after the metadata is generated by the SPEC file.  Once generated, the resulting directory structure is able to be finalized into a packaged, or optionally signed first and then finalized.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example DPM Spec File<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code># This is an example DPM Spec file.\n# This is a comment.\n# Created by Chris Punches on 2025-02-22.\n\n# Whitespace is ignored between sections.\n# Comments are processed as ignored between sections.  Otherwise, they're included in the section data.\n\n# The name of the software we're creating.\n%section metadata.NAME\nMyApp\n%section_end metadata.NAME\n\n# The version of the software.\n%section metadata.VERSION\n0.1.0\n%section_end metadata.VERSION\n\n# The author of the software.\n%section metadata.AUTHOR\nChris Punches &lt;chris.punches@silogroup.org&gt;\n%section_end metadata.AUTHOR\n\n# Source of the software.  Usually a URL where an archive\n# of the source code can be downloaded.\n%section metadata.SOURCE\nhttps:&#47;&#47;source.silogroup.org\/Dark-Horse-Linux\/pyrois\n%section_end metadata.SOURCE\n\n# The package maintainer.\n%section metadata.MAINTAINER\nChris Punches &lt;chris.punches@silogroup.org&gt;\n%section_end metadata.MAINTAINER\n\n# Changelog - the changelog for THIS PACKAGE\n%section metadata.CHANGELOG\n*2025-02-23 Chris Punches chris.punches@silogroup.org\nFirst draft.\n%section_end metadata.CHANGELOG\n\n# The license (used for compliance tracking).\n%section metadata.LICENSE\nA\/GPL 3.0\n%section_end metadata.LICENSE\n\n# The architecture.  For this example, we'll supply it as an\n# environment variable.\n%section metadata.ARCHITECTURE\n&#91;&#91; target_architecture ]]\n%section_end metadata.ARCHITECTURE\n\n# Dependencies -- this is multiline.  \n# These are packages, and their versions, that must be present\n# in the DPMDB in order for this package to meet its required\n# dependencies.\n%section metadata.DEPENDENCIES\nglibc &gt;= 2.21\nglibc &lt;= 2.39\nlibstdc++ &gt; 0\n%section_end metadata.DEPENDENCIES\n\n# Provides -- these are package aliases for meeting \n# interchangeable dependencies.  Left blank here.\n%section metadata.PROVIDES\n%section_end metadata.PROVIDES\n\n# Replaces -- these are packages this package is meant to replace.\n%section metadata.REPLACES\n%section_end metadata.REPLACES\n\n# hooks -- these are triggered when the maintainer populates them and these are assumed to be shell scripts (\/bin\/sh not necessarily \/bin\/bash).\n%section hooks.POST-INSTALL\n%section_end hooks.POST-INSTALL\n%section hooks.POST-INSTALL_ROLLBACK\n%section_end hooks.POST-INSTALL_ROLLBACK\n\n%section hooks.POST-REMOVE\n%section_end hooks.POST-REMOVE\n%section hooks.POST-REMOVE_ROLLBACK\n%section_end hooks.POST-REMOVE_ROLLBACK\n\n%section hooks.POST-UPDATE\nsystemctl start MyAppD\n%section_end hooks.POST-UPDATE\n%section hooks.POST-UPDATE_ROLLBACK\n%section_end hooks.POST-UPDATE_ROLLBACK\n\n%section hooks.PRE-INSTALL\n%section_end hooks.PRE-INSTALL\n%section hooks.PRE-INSTALL_ROLLBACK\n%section_end hooks.PRE-INSTALL_ROLLBACK\n\n%section hooks.PRE-REMOVE\nsystemctl stop MyAppD\n%section_end hooks.PRE-REMOVE\n%section hooks.PRE-REMOVE_ROLLBACK\nsystemctl start MyAppD\n%section_end hooks.PRE-REMOVE_ROLLBACK\n\n%section hooks.PRE-UPDATE\nsystemctl stop MyAppD\n%section_end hooks.PRE-UPDATE\n%section hooks.PRE-UPDATE_ROLLBACK\nsystemctl start MyAppD\n%section_end hooks.PRE-UPDATE_ROLLBACK<\/code><\/pre>\n\n\n\n<p>The spec file format is simple and easy for a human to edit, and this can be populated with a web form in just a few seconds, or generated from a template.<\/p>\n\n\n\n<p><\/p>\n<div class=\"pdfprnt-buttons pdfprnt-buttons-page pdfprnt-bottom-right\"><a href=\"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=%2Fwp%2Fv2%2Fpages%2F539&print=pdf\" class=\"pdfprnt-button pdfprnt-button-pdf\" target=\"_blank\" ><span class=\"pdfprnt-button-title pdfprnt-button-pdf-title\">[ EXPORT TO PDF ]<\/span><\/a><a href=\"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=%2Fwp%2Fv2%2Fpages%2F539&print=print\" class=\"pdfprnt-button pdfprnt-button-print\" target=\"_blank\" ><\/a><\/div>","protected":false},"excerpt":{"rendered":"<p>To build a package, you&#8217;ll need a specification file. A spec file is a file that dpm is told to create a package with. Think of it as a configuration file for the build process for DPM packages. For an example, imagine you&#8217;re building a package. You&#8217;ve populated your directory tree and you&#8217;re ready to &hellip; <a href=\"https:\/\/dpm.darkhorselinux.org\/?page_id=539\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">DPM Specification Files<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-539","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/pages\/539","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=539"}],"version-history":[{"count":44,"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/pages\/539\/revisions"}],"predecessor-version":[{"id":587,"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=\/wp\/v2\/pages\/539\/revisions\/587"}],"wp:attachment":[{"href":"https:\/\/dpm.darkhorselinux.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=539"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}