<?xml version="1.0" encoding="UTF-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><id>https://blog.pgxn.org/tags/makefile/</id><title>Makefile</title><updated>2012-04-11T16:36:00Z</updated><link rel="self" type="application/atom+xml" href="https://blog.pgxn.org/tags/makefile/feed.xml"/><link rel="alternate" type="text/html" href="https://blog.pgxn.org/tags/makefile/"/><author><name>The PGXN Maintainers</name></author><generator uri="https://gohugo.io/" version="0.167.0">Hugo</generator><entry><id>https://blog.pgxn.org/post/20908326485</id><title type="html">Lose USE_PGXS in your Makefiles</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2012/lose-use-pgxs/"/><updated>2026-10-07T16:13:48Z</updated><published>2012-04-11T16:36:00Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="extension" label="Extension"/><category scheme="https://blog.pgxn.org/tags" term="use_pgxs" label="USE_PGXS"/><category scheme="https://blog.pgxn.org/tags" term="makefile" label="Makefile"/><category scheme="https://blog.pgxn.org/tags" term="make" label="make"/><category scheme="https://blog.pgxn.org/tags" term="pg_config" label="pg_config"/><category scheme="https://blog.pgxn.org/tags" term="contrib" label="contrib"/><summary type="html"><![CDATA[<p>Traditionally, folks have created extensions for PostgreSQL by copying one of
the <a href="https://www.postgresql.org/docs/current/static/contrib.html">contrib modules</a> and hacking it into something new. One of the things
that comes along for the ride is the <code>Makefile</code> (<a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=contrib/isn/Makefile;hb=HEAD">example</a>). As a result,
there are a lot of third-party extensions that use the <code>USE_PGXS</code> variable.</p>
<p>A bit of background. The core contrib extensions generally rely on a relative
path to include the core <code>Makefile</code>s needed to build the extension. Because
they ship with the core distribution, they can generally expect that the core
has already been compiled, the necessary <code>Makefile</code>s have been created, and
that they should be built against them. All the assumptions are that the
extensions should be built against the source tree in which they are
distributed. So there is no need to use <a href="https://www.postgresql.org/docs/current/static/app-pgconfig.html"><code>pg_config</code></a> to find <a href="https://www.postgresql.org/docs/current/static/extend-pgxs.html">PGXS</a>; it
already knows where to find what it needs.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>Traditionally, folks have created extensions for PostgreSQL by copying one of
the <a href="https://www.postgresql.org/docs/current/static/contrib.html">contrib modules</a> and hacking it into something new. One of the things
that comes along for the ride is the <code>Makefile</code> (<a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=contrib/isn/Makefile;hb=HEAD">example</a>). As a result,
there are a lot of third-party extensions that use the <code>USE_PGXS</code> variable.</p>
<p>A bit of background. The core contrib extensions generally rely on a relative
path to include the core <code>Makefile</code>s needed to build the extension. Because
they ship with the core distribution, they can generally expect that the core
has already been compiled, the necessary <code>Makefile</code>s have been created, and
that they should be built against them. All the assumptions are that the
extensions should be built against the source tree in which they are
distributed. So there is no need to use <a href="https://www.postgresql.org/docs/current/static/app-pgconfig.html"><code>pg_config</code></a> to find <a href="https://www.postgresql.org/docs/current/static/extend-pgxs.html">PGXS</a>; it
already knows where to find what it needs.</p>
<p>But as extensions, there is still the possibility that one might want to build
them against an existing installation of PostgreSQL, or an older version than
the source with which they&rsquo;re distributed. So the core hackers provided the
<code>USE_PGXS</code> variable so that one can in effect tell <code>make</code>, &ldquo;Don&rsquo;t build
against the local source tree, but find PGXS for some other install and build
against that, instead.&rdquo; It was expected to be exceptional, since most folks
would build against the local source tree, and not a big deal to make anyone
else build it with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">make <span class="nv">USE_PGXS</span><span class="o">=</span><span class="m">1</span>
</span></span></code></pre></div><p>Today things are different. There is a growing ecosystem of third party
extensions on <a href="https://pgxn.org/">PGXN</a>, <a href="https://pgfoundry.org/">pgFoundry</a>, <a href="https://github.com/">GitHub</a>, and <a href="https://bitbucket.org/">Bitbucket</a>, and obviously
they&rsquo;re not distributed with the PostgreSQL core. For these extensions, there
is no surrounding PostgreSQL source code to automatically include, so they
<em>must</em> use <code>pg_config</code> to find PGXS in order build.</p>
<p>Yet, there are quite a few third-party extensions that nevertheless assume
that they are in the <code>contrib</code> directory of the PostgreSQL source code
distribution, and so still have the <code>USE_PGXS</code> variable. The <a href="https://api.pgxn.org/src/twitter_fdw/twitter_fdw-1.0.0/Makefile">twitter_ftw
1.0.0 <code>Makefile</code></a> is a recent example. Just like core extensions, it has this
code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="err">ifdef</span> <span class="err">USE_PGXS</span>
</span></span><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">else</span>
</span></span><span class="line"><span class="cl"><span class="nv">subdir</span> <span class="o">=</span> contrib/twitter_fdw
</span></span><span class="line"><span class="cl"><span class="nv">top_builddir</span> <span class="o">=</span> ../..
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">top_builddir</span><span class="k">)</span><span class="err">/src/Makefile.global</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">top_srcdir</span><span class="k">)</span><span class="err">/contrib/contrib-global.mk</span>
</span></span><span class="line"><span class="cl"><span class="err">endif</span>
</span></span></code></pre></div><p>Because Hitoshi-san originally copied the <code>Makefile</code> from a core extension, it
still assumes it will be distributed in core by default. And as I said, there
are quite a few third-party extensions that exhibit this pattern.</p>
<p>And now the <a href="https://en.wikipedia.org/wiki/Public_service_announcement">PSA</a>: <strong>Please don&rsquo;t use <code>USE_PGXS</code> in PostgreSQL extension
<code>Makefile</code>s.</strong></p>
<p>Not only is it unnecessary, it makes no sense for third-party extensions. They
should <em>always</em> assume that they need to use <code>pg_config</code> to find PGXS. If you
have an extension <code>Makefile</code> with <code>USE_PGXS</code> like twitter_ftw 1.0.0 did, you
should change it to something like this (as Hitoshi-san did in the
<a href="https://api.pgxn.org/src/twitter_fdw/twitter_fdw-1.0.1/Makefile">twitter_ftw 1.0.1 <code>Makefile</code></a>):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span></code></pre></div><p>That&rsquo;s it. I am asking you to <em>make your <code>Makefile</code> simpler.</em></p>
<hr>
<p><em>An Aside</em></p>
<p>There is <em>one</em> situation in which you might need to include the core contrib
<code>Makefile</code>s. And it&rsquo;s pretty unusual. If you need to support PostgreSQL 8.1 or
earlier, <code>pg_config</code> will not be able to tell you where to find PGXS. So users
will have to copy the extension source directory into the PostgreSQL source
<code>contrib/</code> directory and build from there. They will need a way to tell <code>make</code>
<em>not</em> to use PGXS. In this one unusual case, I suggest you add a <code>NO_PGXS</code>
variable. <a href="https://api.pgxn.org/src/pgtap/pgtap-0.90.0/Makefile">pgTAP&rsquo;s <code>Makefile</code></a> provides an example. But honestly, very few
extensions need to support PostgreSQL 8.1 (the oldest release currently
supported by the core hackers is <em>8.3!</em>), so make use of this pattern only if
absolutely necessary.</p>
<p>Otherwise, please don&rsquo;t use <code>USE_PGXS</code>.</p>
<hr>
<p>If you want a complete guide to creating your extension <code>Makefile</code>, have a
look at the <a href="https://manager.pgxn.org/howto">PGXN Howto</a>, which includes some detailed examples that include
support for pre- and post-<a href="https://www.postgresql.org/docs/current/static/sql-createextension.html"><code>CREATE EXTENSION</code></a> support. The <a href="https://www.postgresql.org/docs/current/static/extend-pgxs.html">PGXS</a> docs
contain additional details about all the <code>Makefile</code> variables you can use to
simplify extension configuration and installation. Check &rsquo;em out.</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/5465631144</id><title type="html">PGXN Utils</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2011/pgxn-utils/"/><updated>2026-10-07T16:13:48Z</updated><published>2011-05-14T01:05:00Z</published><author><name>Dickson S. Guedes</name></author><category scheme="https://blog.pgxn.org/tags" term="build" label="Build"/><category scheme="https://blog.pgxn.org/tags" term="makefile" label="Makefile"/><category scheme="https://blog.pgxn.org/tags" term="control-file" label="Control File"/><category scheme="https://blog.pgxn.org/tags" term="readme" label="README"/><category scheme="https://blog.pgxn.org/tags" term="meta" label="Meta"/><category scheme="https://blog.pgxn.org/tags" term="create-extension" label="Create Extension"/><category scheme="https://blog.pgxn.org/tags" term="skeleton" label="Skeleton"/><category scheme="https://blog.pgxn.org/tags" term="generator" label="Generator"/><summary type="html"><![CDATA[<p>Do you ever have problems with copy and paste? I often did, and that is why I
create custom templates for often used files that match certain patterns.</p>
<p>With files from the structure of PostgreSQL&rsquo;s extensions was the same thing.</p>
<p>I was tired of creating the files and edit the META, controlfile, READMEs,
etc. every time I start a new extension and felt that I need something that
made me more productive, so I decided to create an automatic generator and
share it with the world.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>Do you ever have problems with copy and paste? I often did, and that is why I
create custom templates for often used files that match certain patterns.</p>
<p>With files from the structure of PostgreSQL&rsquo;s extensions was the same thing.</p>
<p>I was tired of creating the files and edit the META, controlfile, READMEs,
etc. every time I start a new extension and felt that I need something that
made me more productive, so I decided to create an automatic generator and
share it with the world.</p>
<p>I called it <a href="https://github.com/guedes/pgxn-utils/">pgxn-utils</a>, and you should give it a try: it is easy to install,
easy to use and will help you to start hacking quickly!</p>
<p><strong>How?</strong></p>
<ol>
<li>
<p>First install it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">gem install pgxn_utils
</span></span></code></pre></div></li>
<li>
<p>Then start a new extension:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">pgxn_utils skeleton my_cool_extension
</span></span></code></pre></div></li>
</ol>
<p>Thats all! It will create the initial skeleton for you and you can start
coding! But, if you don&rsquo;t want to install it, <a href="https://pgcasts.com/media/pgxn_utils-usage-example.mpeg">see it in action</a></p>
<p>Good hack!</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/5458118596</id><title type="html">New HOWTO</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2011/new-howto/"/><updated>2026-10-07T16:13:48Z</updated><published>2011-05-13T20:34:46Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="howto" label="HOWTO"/><category scheme="https://blog.pgxn.org/tags" term="build" label="Build"/><category scheme="https://blog.pgxn.org/tags" term="makefile" label="Makefile"/><category scheme="https://blog.pgxn.org/tags" term="readme" label="README"/><category scheme="https://blog.pgxn.org/tags" term="changes" label="Changes"/><category scheme="https://blog.pgxn.org/tags" term="documentation" label="Documentation"/><category scheme="https://blog.pgxn.org/tags" term="meta.json" label="META.json"/><category scheme="https://blog.pgxn.org/tags" term="control-file" label="Control File"/><summary type="html"><![CDATA[<p>I updated the <a href="https://manager.pgxn.org/">howto</a> yesterday. This document explains how to create a PGXN
distribution. If you&rsquo;re interested in releasing PostgreSQL extensions on
<a href="https://pgxn.org/">PGXN</a>, this document is worth a read.</p>
<p>In essence, it&rsquo;s really simple: Just create a <a href="https://pgxn.org/spec/"><code>META.json</code></a> and upload. But to
get the full benefit, there are quite a few other recommendations. Already
familiar with it? Here&rsquo;s the checklist:</p>
<ul>
<li>Create a <a href="https://pgxn.org/spec/"><code>META.json</code></a></li>
<li>Create a <a href="https://www.postgresql.org/docs/9.1/static/extend-extensions.html">control file</a></li>
<li>Create a <a href="https://www.postgresql.org/docs/current/static/xfunc-c.html#XFUNC-C-PGXS"><code>Makefile</code></a></li>
<li>Implement the code in the <code>sql</code> and <code>src</code> directories</li>
<li>Write tests in the <code>test</code> directory</li>
<li>Write a <a href="https://search.cpan.org/perldoc?Text::Markup">Text::Markup</a>-recognizable <code>README</code></li>
<li>Write <a href="https://search.cpan.org/perldoc?Text::Markup">Text::Markup</a>-recognizable documentation in the <code>doc</code> directory</li>
<li>Consider including other files: <code>Changes</code>, <code>LICENSE</code>, <code>INSTALL</code>, <code>COPYING</code>,
<code>AUTHORS</code></li>
<li><a href="https://manager.pgxn.org/">Release it</a>!</li>
</ul>
<p>Be sure to read the <a href="https://manager.pgxn.org/">howto</a> for details. Got feedback or suggestions? Leave a
comment!</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>I updated the <a href="https://manager.pgxn.org/">howto</a> yesterday. This document explains how to create a PGXN
distribution. If you&rsquo;re interested in releasing PostgreSQL extensions on
<a href="https://pgxn.org/">PGXN</a>, this document is worth a read.</p>
<p>In essence, it&rsquo;s really simple: Just create a <a href="https://pgxn.org/spec/"><code>META.json</code></a> and upload. But to
get the full benefit, there are quite a few other recommendations. Already
familiar with it? Here&rsquo;s the checklist:</p>
<ul>
<li>Create a <a href="https://pgxn.org/spec/"><code>META.json</code></a></li>
<li>Create a <a href="https://www.postgresql.org/docs/9.1/static/extend-extensions.html">control file</a></li>
<li>Create a <a href="https://www.postgresql.org/docs/current/static/xfunc-c.html#XFUNC-C-PGXS"><code>Makefile</code></a></li>
<li>Implement the code in the <code>sql</code> and <code>src</code> directories</li>
<li>Write tests in the <code>test</code> directory</li>
<li>Write a <a href="https://search.cpan.org/perldoc?Text::Markup">Text::Markup</a>-recognizable <code>README</code></li>
<li>Write <a href="https://search.cpan.org/perldoc?Text::Markup">Text::Markup</a>-recognizable documentation in the <code>doc</code> directory</li>
<li>Consider including other files: <code>Changes</code>, <code>LICENSE</code>, <code>INSTALL</code>, <code>COPYING</code>,
<code>AUTHORS</code></li>
<li><a href="https://manager.pgxn.org/">Release it</a>!</li>
</ul>
<p>Be sure to read the <a href="https://manager.pgxn.org/">howto</a> for details. Got feedback or suggestions? Leave a
comment!</p>
<p>Oh, and check out <a href="https://github.com/guedes/pgxn-utils/">pgxn-utils</a> and simplify your extension-development life.</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/4783001135</id><title type="html">Extension Makefiles for PostgreSQL 9.1</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2011/extension-makefiles/"/><updated>2026-10-07T16:13:48Z</updated><published>2011-04-20T19:29:00Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="extension" label="Extension"/><category scheme="https://blog.pgxn.org/tags" term="makefile" label="Makefile"/><category scheme="https://blog.pgxn.org/tags" term="make" label="make"/><category scheme="https://blog.pgxn.org/tags" term="pgxs" label="Pgxs"/><category scheme="https://blog.pgxn.org/tags" term="pg_config" label="pg_config"/><summary type="html"><![CDATA[<p>In order to keep distribution packaging as simple as possible, I worked up
this <code>Makefile</code> some time ago:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> <span class="k">$(</span>wildcard sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">DOCS</span> <span class="o">=</span> <span class="k">$(</span>wildcard doc/*.txt<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">TESTS</span> <span class="o">=</span> <span class="k">$(</span>wildcard test/sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS</span> <span class="o">=</span> <span class="k">$(</span>patsubst test/sql/%.sql,%,<span class="k">$(</span>TESTS<span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS_OPTS</span> <span class="o">=</span> --inputdir<span class="o">=</span><span class="nb">test</span> --load-language<span class="o">=</span>plpgsql
</span></span><span class="line"><span class="cl"><span class="nv">MODULES</span> <span class="o">=</span> <span class="k">$(</span>patsubst %.c,%,<span class="k">$(</span>wildcard src/*.c<span class="k">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span></code></pre></div><p>The nice thing about this code is that it has nothing specific to a
distribution in it. It figures out what SQL files there are, what doc files
there are, and what C files need compiling by just looking in the <code>sql</code>,
<code>doc</code>, and <code>src</code> directories, respectively. It also specifies that tests are
in the <code>test</code> directory. About the only thing I&rsquo;ve customized here is adding
<code>--load-language=plpgsql</code> to <code>REGRESS_OPTS</code>, as the tests for the distribution
I&rsquo;ve copied this from require PL/pgSQL to run. Simple, and anyone can use it
with very little need to tweak it, as long as they don&rsquo;t mind storing their
files in the specified directories.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>In order to keep distribution packaging as simple as possible, I worked up
this <code>Makefile</code> some time ago:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> <span class="k">$(</span>wildcard sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">DOCS</span> <span class="o">=</span> <span class="k">$(</span>wildcard doc/*.txt<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">TESTS</span> <span class="o">=</span> <span class="k">$(</span>wildcard test/sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS</span> <span class="o">=</span> <span class="k">$(</span>patsubst test/sql/%.sql,%,<span class="k">$(</span>TESTS<span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS_OPTS</span> <span class="o">=</span> --inputdir<span class="o">=</span><span class="nb">test</span> --load-language<span class="o">=</span>plpgsql
</span></span><span class="line"><span class="cl"><span class="nv">MODULES</span> <span class="o">=</span> <span class="k">$(</span>patsubst %.c,%,<span class="k">$(</span>wildcard src/*.c<span class="k">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span></code></pre></div><p>The nice thing about this code is that it has nothing specific to a
distribution in it. It figures out what SQL files there are, what doc files
there are, and what C files need compiling by just looking in the <code>sql</code>,
<code>doc</code>, and <code>src</code> directories, respectively. It also specifies that tests are
in the <code>test</code> directory. About the only thing I&rsquo;ve customized here is adding
<code>--load-language=plpgsql</code> to <code>REGRESS_OPTS</code>, as the tests for the distribution
I&rsquo;ve copied this from require PL/pgSQL to run. Simple, and anyone can use it
with very little need to tweak it, as long as they don&rsquo;t mind storing their
files in the specified directories.</p>
<p>Today, I&rsquo;m updating my distributions to support PostgreSQL 9.1&rsquo;s new
<code>CREATE EXTENSION</code> syntax, but I want to continue supporting older versions of
PostgreSQL, as well. Basically, this means that the files listed in the <code>DATA</code>
variable vary based on the version of PostgreSQL you&rsquo;re installing against.
Here are the additional things the <code>Makefile</code> needs to do:</p>
<ul>
<li>If installing against PostgreSQL less than version 9.1, exclude files in
<code>DATA</code> that contain <code>--</code>. Such files are are migration scripts, which aren&rsquo;t
supported before 9.1.</li>
<li>If installing against PostgreSQL greater than or equal to 9.1:
<ul>
<li>Copy the files <code>sql/$EXTENSION.sql</code> and <code>sql/$EXTENSION--unpackaged.sql</code>
to <code>sql/$EXTENSION--$EXTVERSION.sql</code> and
<code>sql/$EXTENSION--npackated--$EXTVERSION.sql</code>, respectively.
<code>CREATE EXTENSION</code> requires that the version string be in migration file
name. I&rsquo;d rather not have to rename the file in my repository before every
release (and I&rsquo;d rather keep it without the version for  9.1 anyway), so
it needs to be copied.</li>
<li>Add the new <code>sql/$EXTENSION--$VERSION.sql</code> file to <code>EXTRA_CLEAN</code>.</li>
<li>Include only files in <code>DATA</code> that contain <code>--</code>. There&rsquo;s no need to install
the original file without the version number, or any uninstall file,
either, since it&rsquo;s not needed on 9.1 anymore.</li>
</ul>
</li>
</ul>
<p>I&rsquo;ve been trying to figure out how to modify my standard <code>Makefile</code> to support
these changes, without requiring a lot of tweaking, so that other folks can
easily use it in the future. Thanks to help from <a href="https://people.planetpostgresql.org/andrew/">Andrew Dunstan</a>, this is
what I&rsquo;ve come up with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">EXTENSION</span><span class="o">=</span>semver
</span></span><span class="line"><span class="cl"><span class="nv">EXTVERSION</span><span class="o">=</span>0.2.2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> <span class="k">$(</span>filter-out <span class="k">$(</span>wildcard sql/*--*.sql<span class="k">)</span>,<span class="k">$(</span>wildcard sql/*.sql<span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="nv">DOCS</span> <span class="o">=</span> <span class="k">$(</span>wildcard doc/*.txt<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">TESTS</span> <span class="o">=</span> <span class="k">$(</span>wildcard test/sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS</span> <span class="o">=</span> <span class="k">$(</span>patsubst test/sql/%.sql,%,<span class="k">$(</span>TESTS<span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS_OPTS</span> <span class="o">=</span> --inputdir<span class="o">=</span><span class="nb">test</span> --load-language<span class="o">=</span>plpgsql
</span></span><span class="line"><span class="cl"><span class="nv">MODULES</span> <span class="o">=</span> <span class="k">$(</span>patsubst %.c,%,<span class="k">$(</span>wildcard src/*.c<span class="k">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">VERSION</span>     <span class="o">=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --version <span class="p">|</span> awk <span class="s1">&#39;{print $$2}&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">PGVER_MAJOR</span> <span class="o">=</span> <span class="k">$(</span>shell <span class="nb">echo</span> <span class="k">$(</span>VERSION<span class="k">)</span> <span class="p">|</span> awk -F. <span class="s1">&#39;{ print ($$1 + 0) }&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">PGVER_MINOR</span> <span class="o">=</span> <span class="k">$(</span>shell <span class="nb">echo</span> <span class="k">$(</span>VERSION<span class="k">)</span> <span class="p">|</span> awk -F. <span class="s1">&#39;{ print ($$2 + 0) }&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">ifeq</span> <span class="err">(</span><span class="k">$(</span><span class="nv">PGVER_MAJOR</span><span class="k">)</span><span class="err">,</span> <span class="err">9)</span>
</span></span><span class="line"><span class="cl"><span class="err">ifneq</span> <span class="err">(</span><span class="k">$(</span><span class="nv">PGVER_MINOR</span><span class="k">)</span><span class="err">,</span> <span class="err">0)</span>
</span></span><span class="line"><span class="cl"><span class="nf">all</span><span class="o">:</span> <span class="n">sql</span>/<span class="k">$(</span><span class="nv">EXTENSION</span><span class="k">)</span>--<span class="k">$(</span><span class="nv">EXTVERSION</span><span class="k">)</span>.<span class="n">sql</span> <span class="n">sql</span>/<span class="k">$(</span><span class="nv">EXTENSION</span><span class="k">)</span>--<span class="n">unpackaged</span>--<span class="k">$(</span><span class="nv">EXTVERSION</span><span class="k">)</span>.<span class="n">sql</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">sql/$(EXTENSION)--$(EXTVERSION).sql</span><span class="o">:</span> <span class="n">sql</span>/<span class="k">$(</span><span class="nv">EXTENSION</span><span class="k">)</span>.<span class="n">sql</span>
</span></span><span class="line"><span class="cl">    cp $&lt; <span class="nv">$@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">sql/$(EXTENSION)--unpackaged--$(EXTVERSION).sql</span><span class="o">:</span> <span class="n">sql</span>/<span class="k">$(</span><span class="nv">EXTENSION</span><span class="k">)</span>--<span class="n">unpackaged</span>.<span class="n">sql</span>
</span></span><span class="line"><span class="cl">    cp $&lt; <span class="nv">$@</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> <span class="k">$(</span>filter-out sql/<span class="k">$(</span>EXTENSION<span class="k">)</span>--unpackaged.sql,<span class="k">$(</span>wildcard sql/*--*.sql<span class="k">))</span> sql/<span class="k">$(</span>EXTENSION<span class="k">)</span>--<span class="k">$(</span>EXTVERSION<span class="k">)</span>.sql
</span></span><span class="line"><span class="cl"><span class="nv">EXTRA_CLEAN</span> <span class="o">=</span> sql/<span class="k">$(</span>EXTENSION<span class="k">)</span>--<span class="k">$(</span>EXTVERSION<span class="k">)</span>.sql sql/<span class="k">$(</span>EXTENSION<span class="k">)</span>--unpackaged--<span class="k">$(</span>EXTVERSION<span class="k">)</span>.sql
</span></span><span class="line"><span class="cl"><span class="err">endif</span>
</span></span><span class="line"><span class="cl"><span class="err">endif</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span></code></pre></div><p>This is not exactly ideal, but not <em>too</em> bad. It&rsquo;s not quite the drop-in
version we had before, because now the first line needs to name the extension
we&rsquo;re distributing, and the second needs to specify the version (and would
then need to be updated for every release). Maybe they could be read from the
control file somehow? Other than that, you should be able to just forget the
rest of the file (mostly). Here&rsquo;s how it addresses the above requirements:</p>
<ul>
<li>To exclude files with <code>--</code> in them on  9.1, the first <code>DATA</code> line filters
them out:</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> <span class="k">$(</span>filter-out <span class="k">$(</span>wildcard sql/*--*.sql<span class="k">)</span>,<span class="k">$(</span>wildcard sql/*.sql<span class="k">))</span>
</span></span></code></pre></div><ul>
<li>
<p>Next, we need to know if we&rsquo;re on 9.1 or higher. So we use
<code>pg_config --version</code> to get the version number and some <code>awk</code> stuff to get
the major and minor parts. Then, if the major version is 9 and the minor is
<em>not</em> 0, we:</p>
<ul>
<li>Add <code>sql/$(EXTENSION)--$(EXTVERSION).sql</code> and
<code>sql/$(EXTENSION)--unpackaged--$(EXTVERSION).sql</code> as dependencies of the
<code>all</code> rule (which is the default PGXS rule).</li>
<li>Add the <code>sql/$(EXTENSION)--$(EXTVERSION).sql</code> and
<code>sql/$(EXTENSION)--unpackated--$(EXTVERSION).sql</code> rules, which copy
<code>sql/$(EXTVERVERSION).sql</code> and <code>sql/$(EXTVERVERSION)--unpackaged.sql</code>
files. Of course this assumes that such files exist.</li>
<li>Add <code>sql/$(EXTENSION)--$(EXTVERSION).sql</code> and
<code>sql/$(EXTENSION)--unpackaged--$(EXTVERSION).sql</code> to <code>EXTRA_CLEAN</code>, so
that they&rsquo;ll be deleted by <code>make clean</code>.</li>
<li>Set <code>DATA</code> again, this time to include <em>only</em> files with <code>--</code> in them,
except for <code>sql/$(EXTENSION)--unpackaged.sql</code>.</li>
</ul>
</li>
</ul>
<p>And with that, it works. But it has some disadvantages over the previous, very
simple <code>Makefile</code> I&rsquo;ve been using up to now:</p>
<ul>
<li>One must modify it for every release, if only to set <code>EXTVERSION</code>.</li>
<li>It relies more on Unix tools than previously, specifically <code>awk</code>. I&rsquo;m not
sure how big a deal this is in practice; the <a href="https://github.com/theory/pgtap/blob/master/Makefile">pgTAP Makefile</a> has been
relying on <code>awk</code> an even worse gymnastics for some time and no one has
complained.</li>
<li>It&rsquo;s not perfectly future-proof. It will need to be modified when PostgreSQL
10.0.0 is released, and again when 11.0.0 is released.</li>
<li>It won&rsquo;t handle a distribution with multiple extension in it. I don&rsquo;t even
want to think about that.</li>
</ul>
<p>Suggestions for ways to eliminate these shortcomings would be greatly
appreciated, especially if it allows use extension authors to get back to
something as simple as the first example at the top of this post.</p>
<p><strong>UPDATE:</strong> Added the <code>unpackaged</code> bits I didn&rsquo;t realize I needed until after
I&rsquo;d released a new version of <a href="https://pgxn.org/dist/semver/">semver</a> and discovered that the &ldquo;unpackaged&rdquo;
script needs to always be tied to the default version.</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/1353947079</id><title type="html">Creating Distributions</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2010/creating-distributions/"/><updated>2026-10-07T16:13:48Z</updated><published>2010-10-19T22:28:00Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="distribution" label="Distribution"/><category scheme="https://blog.pgxn.org/tags" term="makefile" label="Makefile"/><category scheme="https://blog.pgxn.org/tags" term="pgxn" label="Pgxn"/><category scheme="https://blog.pgxn.org/tags" term="pgxs" label="Pgxs"/><category scheme="https://blog.pgxn.org/tags" term="pg_config" label="pg_config"/><category scheme="https://blog.pgxn.org/tags" term="pg_regress" label="pg_regress"/><category scheme="https://blog.pgxn.org/tags" term="directory-structure" label="Directory Structure"/><summary type="html"><![CDATA[<p>Following the <a href="https://blog.pgxn.org/post/1352326020/first-upload">upload of <code>pair</code></a> to PGXN, I wanted to take a few minutes to
write about how to structure a PGXN distribution.</p>
<h2 id="omg-distribution-wtf">OMG Distribution WTF?</h2>
<p>First of all, what is a &ldquo;distribution&rdquo; in the PGXN sense? Basically, it&rsquo;s a
collection of one or more PostgreSQL extensions. That&rsquo;s it.</p>
<p>So why allow more than one extension? Maybe no PGXN distribution will ever
have more than one extension. After all, the goal should be many focused,
minimalist tools that folks can combine in their apps. But sometimes it
doesn&rsquo;t work out that way.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>Following the <a href="https://blog.pgxn.org/post/1352326020/first-upload">upload of <code>pair</code></a> to PGXN, I wanted to take a few minutes to
write about how to structure a PGXN distribution.</p>
<h2 id="omg-distribution-wtf">OMG Distribution WTF?</h2>
<p>First of all, what is a &ldquo;distribution&rdquo; in the PGXN sense? Basically, it&rsquo;s a
collection of one or more PostgreSQL extensions. That&rsquo;s it.</p>
<p>So why allow more than one extension? Maybe no PGXN distribution will ever
have more than one extension. After all, the goal should be many focused,
minimalist tools that folks can combine in their apps. But sometimes it
doesn&rsquo;t work out that way.</p>
<p>As an example, I&rsquo;ve been planning to break <a href="https://pgtap.org/">pgTAP</a> up into two parts for a
while: one for scalar and relational testing, the other for schema testing.
Often one needs only the scalar and relational testing, while the schema
testing is more often needed only for testing replication and whatnot. Whether
or not I choose to distribute both parts in one package I have yet to
determine, but it could well make sense to keep them in one distribution.</p>
<p>Besides, I&rsquo;ve tried to write <a href="https://github.com/theory/pgxn-manager">PGXN::Manager</a> in such a way that it&rsquo;s not
specific to PostgreSQL. So that if someone wanted to create a Drupal XN with
it or something, they could. Or PyXN. Or, hell, even if <a href="https://cpan/org/">CPAN</a> wanted to
switch someday, they could. (Note that I&rsquo;ve registered myxn.org for fun. I may
or may not do anything with that, but see <a href="https://theory.github.com/mytap/">MyTAP</a>. Yes, I am insane.)</p>
<h2 id="thats-so-meta">That&rsquo;s So Meta</h2>
<p>Anyway, back to the structure of distributions. At its simplest, the only
thing PGXN requires is a single file, <code>META.json</code>, which describes the
package. This is (currently) the only file that PGXN Manager uses to index a
distribution, so it&rsquo;s important to get it right. The <a href="https://pgxn.org/meta/spec.html">PGXN Meta Spec</a> has a
rather complete example of a hypothetical pgTAP distribution <code>META.json</code>.</p>
<p>If you have only one .sql file for your extension and it&rsquo;s the same name as
the distribution (and I expect this would be common), then you can make it
pretty simple. For example, the <code>pair</code> distribution has only one SQL file. So
the <code>META.json</code> could be:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;pair&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;abstract&#34;</span><span class="p">:</span> <span class="s2">&#34;A key/value pair data type&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;0.1.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;maintainer&#34;</span><span class="p">:</span> <span class="s2">&#34;David E. Wheeler &lt;david@justatheory.com&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;license&#34;</span><span class="p">:</span> <span class="s2">&#34;postgresql&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;meta-spec&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;version&#34;</span><span class="p">:</span> <span class="s2">&#34;1.0.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;url&#34;</span><span class="p">:</span> <span class="s2">&#34;https://pgxn.org/meta/spec.txt&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>That&rsquo;s it. The only thing that may not be obvious from this example is that
all version numbers in a <code>META.json</code> <em>must</em> be <a href="https://semver.org/">semantic versions</a>. If they&rsquo;re
not, PGXN will make them so. So &ldquo;1.2&rdquo; will become &ldquo;1.2.0&rdquo;, and so would
&ldquo;1.02&rdquo;. So do try to use semantic versions and not worry about it.</p>
<p>In the short run, you won&rsquo;t need anything more in your <code>META.json</code> file. But
once I get to creating the search site and the command-line client for PGXN,
you&rsquo;re probably going to want to do more. Other useful keys to include are:</p>
<ul>
<li><a href="https://pgxn.org/meta/spec.html#tags"><code>tags</code></a>: An array of tags to associate with a distribution. Will help
with searching.</li>
<li><a href="https://pgxn.org/meta/spec.html#prereqs"><code>prereqs</code></a>: A list of prerequisite extensions or PostgreSQL contrib
moules (or PostgreSQL itself).</li>
<li><a href="https://pgxn.org/meta/spec.html#provides"><code>provides</code></a>: A list of included extensions. Useful if you have more than
one or the one has a different name that the distribution (silly, but it
happens). It also will index such extension names such that you are the
owner, if you&rsquo;re the first to update one with that name.</li>
<li><a href="https://pgxn.org/meta/spec.html#release_status"><code>release_status</code></a>: To label a distribution as &ldquo;stable,&rdquo; &ldquo;unstable,&rdquo; or
&ldquo;testing.&rdquo; Useful for uploading distributions for people to test but that
clients won&rsquo;t install by default.</li>
<li><a href="https://pgxn.org/meta/spec.html#resources"><code>resources</code></a>: A list of related links, such as to an SCM repository or
bug tracker. The search site will output these links.</li>
</ul>
<p>Have a look at <a href="https://github.com/theory/kv-pair/blob/master/META.json">the <code>META.json</code> in the <code>pair</code> distribution</a> for a more
extended example.</p>
<h2 id="new-order">New Order</h2>
<p>For PGXN, the general idea is that you&rsquo;ll use <a href="https://www.postgresql.org/docs/9/static/xfunc-c.html#XFUNC-C-PGXS">PGXS</a> to create your PostgreSQL
extensions. I&rsquo;m hoping to encourage a slight modification of the directory
layout for PGXN distributions, but as I hope I&rsquo;ve made clear so far, PGXN
itself doesn&rsquo;t really care how you structure things, or if you use PGXS. That
said, the proposed <a href="https://wiki.postgresql.org/wiki/PGXN#PGXN_Client">download and installation client</a> will assume the use of
PGXS (unless and until the PostgreSQL core adds some other kind of
extension-building support), so it&rsquo;s probably the best choice.</p>
<p>Most PGXS-powered distributions have the code files in the main directory,
with documentation in a <code>README.extension_name</code> file. What I&rsquo;d like to see
instead, and will encourage via the forthcoming <a href="https://wiki.postgresql.org/wiki/PGXN#Search_Site">search site</a>, is that things
be organized into subdirectories:</p>
<ul>
<li><code>src</code> for any C source code files</li>
<li><code>sql</code> for SQL source files. These usually are responsible for installing an
extension into a database</li>
<li><code>doc</code> for documentation files (the search site will likely look there for
Markdown, Textile, HTML, and other document formats)</li>
<li><code>test</code> for tests</li>
</ul>
<p>I&rsquo;ve tried to make the <code>pair</code> distribution a good <a href="https://github.com/theory/kv-pair/blob/">example of this</a>. To make
it all work, The <a href="https://github.com/theory/kv-pair/blob/master/Makefile">Makefile</a> is written like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-makefile" data-lang="makefile"><span class="line"><span class="cl"><span class="nv">DATA</span> <span class="o">=</span> sql/pair.sql sql/uninstall_pair.sql
</span></span><span class="line"><span class="cl"><span class="nv">TESTS</span> <span class="o">=</span> <span class="k">$(</span>wildcard test/sql/*.sql<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS</span> <span class="o">=</span> <span class="k">$(</span>patsubst test/sql/%.sql,%,<span class="k">$(</span>TESTS<span class="k">))</span>
</span></span><span class="line"><span class="cl"><span class="nv">REGRESS_OPTS</span> <span class="o">=</span> --inputdir<span class="o">=</span><span class="nb">test</span>
</span></span><span class="line"><span class="cl"><span class="nv">DOCS</span> <span class="o">=</span> doc/pair.txt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">ifdef</span> <span class="err">NO_PGXS</span>
</span></span><span class="line"><span class="cl"><span class="nv">top_builddir</span> <span class="o">=</span> ../..
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">top_builddir</span><span class="k">)</span><span class="err">/src/Makefile.global</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">top_srcdir</span><span class="k">)</span><span class="err">/contrib/contrib-global.mk</span>
</span></span><span class="line"><span class="cl"><span class="err">else</span>
</span></span><span class="line"><span class="cl"><span class="nv">PG_CONFIG</span> <span class="o">=</span> pg_config
</span></span><span class="line"><span class="cl"><span class="nv">PGXS</span> <span class="o">:=</span> <span class="k">$(</span>shell <span class="k">$(</span>PG_CONFIG<span class="k">)</span> --pgxs<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">include</span> <span class="k">$(</span><span class="nv">PGXS</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="err">endif</span>
</span></span></code></pre></div><p>The <code>DATA</code> variable identifies the files containing the extension, while
<code>TESTS</code> loads a list of all the tests, which are in the <code>test/sql</code> directory.
Note that I&rsquo;m using <code>pg_regress</code> for tests. It expects that tests be named and
that there be corresponding &ldquo;expected&rdquo; files to compare against. With the
<code>REGRESS_OPTS = --inputdir=test</code> line, I&rsquo;m telling <code>pg_regess</code> to find the
test files in <a href="https://github.com/theory/kv-pair/tree/master/test/sql/"><code>test/sql</code></a> and the expected output files in <a href="https://github.com/theory/kv-pair/tree/master/test/expected/"><code>test/expected</code></a>.
And finally, the <code>DOCS</code> variable points to a single file with the
documentation, <a href="https://github.com/theory/kv-pair/blob/master/doc/pair.txt"><code>doc/pair.txt</code></a>. If this extension had required any C code
(like <a href="https://pgtap.org/">pgTAP</a> or <a href="https://postgis.org/">PostGIS</a> do), I would have pointed the <code>MODULES</code> variable at
files in a <code>src</code> directory.</p>
<p>After that we just have build instructions. If called with <code>make NO_PGXS=1</code>,
it assumes that the unzipped distribution directory has been put in the
&ldquo;contrib&rdquo; directory of the PostgreSQL source tree used to build PostgreSQL.
That&rsquo;s probably only important if one is installing on PostgreSQL 8.1 or
lower. Otherwise, it assumes a plain <code>make</code> and uses the <a href="https://www.postgresql.org/docs/current/static/app-pgconfig.html"><code>pg_config</code></a> in your
path to find PGXS to do the build.</p>
<p>For more on PostgreSQL extension building support, please consult <a href="https://www.postgresql.org/docs/9/static/xfunc-c.html#XFUNC-C-PGXS">the
documentation</a>.</p>
<h2 id="zip-me-up">Zip Me Up</h2>
<p>Once you&rsquo;ve got your extension developed and well-tested, and your
distribution just right and the <code>META.json</code> file all proof-read and solid,
it&rsquo;s time to upload the distribution to PGXN. What you want to do is to zip it
up to create a distribution archive. Here&rsquo;s what I did for <code>pair</code>, exporting
it from Git:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git checkout-index -af --prefix ~/Desktop/pair-0.1.0/
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ~/Desktop/
</span></span><span class="line"><span class="cl">rm pair-0.1.0/.gitignore
</span></span><span class="line"><span class="cl">zip -r pair-0.1.0.zip pair-0.1.0
</span></span></code></pre></div><p>Then the <code>pair-0.1.0.zip</code> file was ready to upload. Simple, eh?</p>
<p>Now, one can upload any kind of archive file to PGXN, including a tarball, or
bzip2&hellip;um&hellip;ball? Basically, any kind of archive format recognized by
<a href="https://search.cpan.org/perldoc?Archive::Extract">Archive::Extract</a>. You can upload a <code>.pgz</code> if you like, in which case PGXN
will assume that it&rsquo;s a zip file. A zip file is best because then
PGXN::Manager won&rsquo;t have to rewrite it. It&rsquo;s also preferable that everything
be unpacked from an archive into a directory with the name
<code>$distribution-$version</code>. If not, PGXN will rewrite it to do so. But it saves
the server some effort if all it has to do is move a .zip file that&rsquo;s properly
formatted, so it would be appreciated if you would upload stuff that&rsquo;s already
nicely formatted for distribution in a zip archive.</p>
<h2 id="release-it">Release It!</h2>
<p>And that&rsquo;s it! Not too bad, eh? Just please do be very careful cutting and
pasting examples; I initially uploaded the <code>pair</code> distribution thinking that
it contained pgTAP. It was kind of a PITA to fix. Hopefully we&rsquo;ll be able to
build things up to the point where a lot of this stuff can be automated
(especially the creation of the <code>META.json</code>), but for now it&rsquo;s done by hand.
So be careful out there, and good luck!</p>
<p>Oh, and if you have an extension that you&rsquo;d like to release on PGXN now, I am
running a limited beta for interested extension developers. Please hit the
<a href="https://groups.google.com/group/pgxn-users/">mail list</a> for the details to be posted shortly.</p>
]]></content></entry></feed>