Thread: Frustrating issue with PGXS

Frustrating issue with PGXS

From
Eddie Stanley
Date:
Hi, 

I spent the best part of the day trying to work this out - I was working on a
system setup with PG 8.2, and wanted to work with 8.3 for development.

I installed as follows:

1. CVS checkout
2. ./configure prefix=~/install_dir
3. gmake prefix=~/install_dir
4. gmake install prefix=~/install_dir

Got a datastore up and running with initdb; created some test tables, everything
seemed to be fine. 

The problem came when I wanted to build a simple C function - I used the
following makefile: 

MODULES = example
PGXS := $(shell ~/install_dir/bin/pg_config --pgxs)
include $(PGXS)

The program compiled fine, however I noticed the compilation was refering to
files in /usr/pkg (from the 8.2 installation). I would have thought specifing
the version of pg_config from the 8.3 installation would be sufficent, but it
wasn't. 

In /lib/postgresql/pgxs/src/Makefile.global, I needed to change

PG_CONFIG = pg_config
to
PG_CONFIG = ~/install_dir/bin/pg_config

Could this have been avoided if the Makefile.global had
PG_CONFIG = $(prefix)/bin/pg_config
?


Eddie



Re: Frustrating issue with PGXS

From
Magnus Hagander
Date:
On Mon, Jun 25, 2007 at 11:42:28PM +1200, Eddie Stanley wrote:
> Hi, 
> 
> I spent the best part of the day trying to work this out - I was working on a
> system setup with PG 8.2, and wanted to work with 8.3 for development.
> 
> I installed as follows:
> 
> 1. CVS checkout
> 2. ./configure prefix=~/install_dir
> 3. gmake prefix=~/install_dir
> 4. gmake install prefix=~/install_dir
> 
> Got a datastore up and running with initdb; created some test tables, everything
> seemed to be fine. 
> 
> The problem came when I wanted to build a simple C function - I used the
> following makefile: 
> 
> MODULES = example
> PGXS := $(shell ~/install_dir/bin/pg_config --pgxs)
> include $(PGXS)
> 
> The program compiled fine, however I noticed the compilation was refering to
> files in /usr/pkg (from the 8.2 installation). I would have thought specifing
> the version of pg_config from the 8.3 installation would be sufficent, but it
> wasn't. 
> 
> In /lib/postgresql/pgxs/src/Makefile.global, I needed to change
> 
> PG_CONFIG = pg_config
> to
> PG_CONFIG = ~/install_dir/bin/pg_config
> 
> Could this have been avoided if the Makefile.global had
> PG_CONFIG = $(prefix)/bin/pg_config
> ?

I was actually about to post on this just a couple of days ago - it seems
pgxs really needs pg_config to be in your PATH. The quick fix would be for
you to run

PATH=~/install_dir/bin/:$PATH make

That'll make sure your local pg_config gets picked up instaed. That's what
I ended up donig. It's just a workaround, but it's one that works :-)

//Magnus



Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
> I was actually about to post on this just a couple of days ago - it seems
> pgxs really needs pg_config to be in your PATH.

Correct --- how else is it going to find out where the installation is?

Eddie's proposed solution is of course circular reasoning...
        regards, tom lane


Re: Frustrating issue with PGXS

From
Magnus Hagander
Date:
On Mon, Jun 25, 2007 at 10:43:37AM -0400, Tom Lane wrote:
> Magnus Hagander <magnus@hagander.net> writes:
> > I was actually about to post on this just a couple of days ago - it seems
> > pgxs really needs pg_config to be in your PATH.
> 
> Correct --- how else is it going to find out where the installation is?

You can specify the full path in the command to pg_config in your Makefile.
It'd be neat if the makefile could fint that out and use it for further
references to pg_config. I haven't had time to look into if this is at all
possible, though.

This is the easy error btw - you can get some fairly funky results if you
have 8.3devel locally and then say 8.0 with different compile options in
your PATH. Then it'll use your 8.3devel pg_config for the first step and
then fall back on the one in the PATH for later steps..

//Magnus


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
> On Mon, Jun 25, 2007 at 10:43:37AM -0400, Tom Lane wrote:
>> Correct --- how else is it going to find out where the installation is?

> You can specify the full path in the command to pg_config in your Makefile.
> It'd be neat if the makefile could fint that out and use it for further
> references to pg_config. I haven't had time to look into if this is at all
> possible, though.

The trick is to override this bit in Makefile.global:

PG_CONFIG = pg_config

bindir := $(shell $(PG_CONFIG) --bindir)
datadir := $(shell $(PG_CONFIG) --sharedir)
... etc ...

It might be better if the standard invocation of a PGXS build were not

ifdef USE_PGXS
PGXS := $(shell pg_config --pgxs)
include $(PGXS)

but something like

ifdef USE_PGXS
PG_CONFIG := pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

to sync these invocations of pg_config with the ones in
Makefile.global.  I'm not sure though how to get this setting to
override the one in Makefile.global ... or should we just remove
that one?
        regards, tom lane


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Fabien COELHO <coelho@cri.ensmp.fr> writes:
>> ifdef USE_PGXS
>> PGXS := $(shell pg_config --pgxs)
>> include $(PGXS)
>> 
>> but something like
>> 
>> ifdef USE_PGXS
>> PG_CONFIG := pg_config
>> PGXS := $(shell $(PG_CONFIG) --pgxs)
>> include $(PGXS)

> That would break existing Makefiles that use the "please take the first 
> pg_config in the path" feature, which rather make sense (it just means 
> that you want the extension for your current postgresql).

How would it break them?  The default definition is still PG_CONFIG =
pg_config, this just moves where that definition appears.
        regards, tom lane


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
> ifdef USE_PGXS
> PGXS := $(shell pg_config --pgxs)
> include $(PGXS)
>
> but something like
>
> ifdef USE_PGXS
> PG_CONFIG := pg_config
> PGXS := $(shell $(PG_CONFIG) --pgxs)
> include $(PGXS)
>
> to sync these invocations of pg_config with the ones in
> Makefile.global.  I'm not sure though how to get this setting to
> override the one in Makefile.global ... or should we just remove
> that one?

That would break existing Makefiles that use the "please take the first 
pg_config in the path" feature, which rather make sense (it just means 
that you want the extension for your current postgresql).

However you may replace the other appearance with the following:

ifndef PG_CONFIG
PG_CONFIG    = pg_config
endif

So as to enable
    sh> make PG_CONFIG=/my/manual/path/to/pg_config install

invocations without fear to be overwritten, if some people do not like the 
path convention. Otherwise the following does the trick with a temporary 
replacement of the PATH environment variable just for one command under 
sh-compatible shells:
    sh> PATH=/my/manual/path/to:$PATH make install

and is shorter. This could be added to the documentation.

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
Dear Eddie,

> MODULES = example
> PGXS := $(shell ~/install_dir/bin/pg_config --pgxs)

This is indeed not the intented use of pgxs: it breaks a desirable 
property of the makefile that is should be "generic" wrt postgresql, that 
is not particular to an installation.

You are really expected to rely on the path, although the definition you 
wrote is indeed tempting, although doomed to failure. From the 
documentation, one finds:

"""
33.9.7. Extension Building Infrastructure

...

PGXS := $(shell pg_config --pgxs)
include $(PGXS)

The last two lines should always be the same. Earlier in the file, you 
assign variables or add custom make rules.

...

The extension is compiled and installed for the PostgreSQL installation 
that corresponds to the first pg_config command found in your path.
"""

There could be a clearer comment about the path assumption in "pgxs.mk" 
and how to change the path easily from the shell?  The "should be the 
same" could be changed for "MUST always be the same..." with some 
additional comments.


> Could this have been avoided if the Makefile.global had
> PG_CONFIG = $(prefix)/bin/pg_config ?

That would not work, because "pg_config" is needed to know what the prefix 
(or rather bindir) is, as Tom pointed out. I think this is also because 
the "installation" may be moved around, so it is not necessarily the 
configure-time prefix which is used with some package systems.

His suggestion about using a PG_CONFIG macro in the initial makefile, 
which may be redefined if required, would also provide an alternative way 
supplying the right pg_config, at the price of one additional line. Mm.
I think a doc improvement is at least welcome.

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
Dear Tom,

>> That would break existing Makefiles that use the "please take the first
>> pg_config in the path" feature, which rather make sense (it just means
>> that you want the extension for your current postgresql).
>
> How would it break them?  The default definition is still PG_CONFIG =
> pg_config, this just moves where that definition appears.

I think that I was answering to:

...
Tom> I'm not sure though how to get this setting to
Tom> override the one in Makefile.global ... 
Tom> or should we just remove that one?

With the assumption that the above "that one" refered to the "PG_CONFIG" 
macro definition in "Makefile.global". As existing extension makefiles do 
not defined PG_CONFIG, relying on one would break them wrt future 
releases? That's why I suggested to replace the "Makefile.global" 
definition by a conditional one.

But it is also entirely possible that I did not fully understand your 
sentence:-)

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Fabien COELHO <coelho@cri.ensmp.fr> writes:
> With the assumption that the above "that one" refered to the "PG_CONFIG" 
> macro definition in "Makefile.global". As existing extension makefiles do 
> not defined PG_CONFIG, relying on one would break them wrt future 
> releases?

Ah, I see.  I was thinking in terms of breaking them intentionally ;-)
but perhaps that's not such a great idea.  The reason that I was
thinking that way was that as long as module Makefiles look like

PGXS := $(shell pg_config --pgxs)
include $(PGXS)

there will be room for people to make the same mistake as Eddie, ie,
try to modify that shell command to select a pg_config that's not
first in $PATH.

If we're worrying about cross-version compatibility then it seems there
isn't any really nice way to make both combinations do the ideal thing.
If someone has an updated module Makefile, ie,

PG_CONFIG := pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

then it will look like changing PG_CONFIG in the Makefile would work;
but that will not work with an older PG release, because Makefile.global
will override the value.  So neither way of writing the module Makefile
is going to be foolproof with both old and new PG installations.

Reading between the lines in the gmake manual, it seems like writing
the module Makefile as

override PG_CONFIG := pg_config
etc

might work to override the setting in old copies of Makefile.global,
but this cure is worse than the disease, because it prevents specifying
PG_CONFIG on the make command line.  (And I'm not sure it works anyway;
have not tried it.)

Anyone see a way to handle all these cases at the same time?
        regards, tom lane


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
>> With the assumption that the above "that one" refered to the "PG_CONFIG"
>> macro definition in "Makefile.global". As existing extension makefiles do
>> not defined PG_CONFIG, relying on one would break them wrt future
>> releases?
>
> Ah, I see.  I was thinking in terms of breaking them intentionally ;-)

Well, if that is what you want, is was perfect:-)

But ISTM that the remedy (breaking all past makefiles for all extensions) 
is not worth the issue.

A better documentation, and possibly following your suggestion with an 
explicit PG_CONFIG in contrib makefiles, but without breaking existing 
extensions seems quite enough. The error made by Eddie is legitimate, but
it is also something rare, it did not come up in the last two years.

Please find attached a small patch which enhances the documentation on the 
issue in my broken English.

> If we're worrying about cross-version compatibility then it seems there
> isn't any really nice way to make both combinations do the ideal thing.
> If someone has an updated module Makefile, ie,
>
> PG_CONFIG := pg_config
> PGXS := $(shell $(PG_CONFIG) --pgxs)
> include $(PGXS)
>
> then it will look like changing PG_CONFIG in the Makefile would work; 
> but that will not work with an older PG release, because Makefile.global 
> will override the value.

Okay, there are indeed two different compatibility issues : - "old" makefiles with possibly "new" pgxs conventions -
possibly"new" makefiles with "old" pgxs conventions
 

Indeed for "old" Makefile.global the PG_CONFIG is overwritten.

It would be okay if it is made clear that the PG_CONFIG macro MUST not be 
updated from within the Makefile, but just from the commande line ?

Well that's still a little bit error prone anyway.

ISTM that the documentation update would suffice.

-- 
Fabien.

Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Fabien COELHO <fabien.coelho@ensmp.fr> writes:
> But ISTM that the remedy (breaking all past makefiles for all extensions) 
> is not worth the issue.
> A better documentation, and possibly following your suggestion with an 
> explicit PG_CONFIG in contrib makefiles, but without breaking existing 
> extensions seems quite enough. The error made by Eddie is legitimate, but
> it is also something rare, it did not come up in the last two years.

True.  OK, then let's add the ifndef to Makefile.global and change the
existing extension makefiles to
PG_CONFIG := pg_configPGXS := $(shell $(PG_CONFIG) --pgxs)include $(PGXS)

Any objections?
        regards, tom lane


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
> Let's add the ifndef to Makefile.global and change the
> existing extension makefiles to
>
>     PG_CONFIG := pg_config
>     PGXS := $(shell $(PG_CONFIG) --pgxs)
>     include $(PGXS)
>
> Any objections?

Maybe the ":=" for pg_config is not necessary, "=" is fine for a 
simple string definition ?

Some documentation (not just code) update seems important to me. The patch 
I sent which describes the current status may be applied to existing 
branches, and something else can be written for the explicit PG_CONFIG 
setting.

Otherwise it looks okay AFAIC.

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Fabien COELHO <coelho@cri.ensmp.fr> writes:
> Some documentation (not just code) update seems important to me.

Agreed.  I added this to xfunc.sgml's discussion of PGXS makefiles:

Index: doc/src/sgml/xfunc.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v
retrieving revision 1.128
diff -c -r1.128 xfunc.sgml
*** doc/src/sgml/xfunc.sgml    6 Jun 2007 23:00:36 -0000    1.128
--- doc/src/sgml/xfunc.sgml    26 Jun 2007 21:57:43 -0000
***************
*** 2071,2080 **** DATA_built = isbn_issn.sql DOCS = README.isbn_issn 
! PGXS := $(shell pg_config --pgxs) include $(PGXS) </programlisting>
!     The last two lines should always be the same.  Earlier in the     file, you assign variables or add custom
<application>make</application>rules.    </para>
 
--- 2071,2081 ---- DATA_built = isbn_issn.sql DOCS = README.isbn_issn 
! PG_CONFIG = pg_config
! PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) </programlisting>
!     The last three lines should always be the same.  Earlier in the     file, you assign variables or add custom
<application>make</application>rules.    </para>
 
***************
*** 2215,2220 ****
--- 2216,2233 ----        </para>       </listitem>      </varlistentry>
+ 
+      <varlistentry>
+       <term><varname>PG_CONFIG</varname></term>
+       <listitem>
+        <para>
+         path to <application>pg_config</> program for the
+         <productname>PostgreSQL</productname> installation to build against
+         (typically just <literal>pg_config</> to use the first one in your
+         <varname>PATH</>)
+        </para>
+       </listitem>
+      </varlistentry>     </variablelist>    </para> 
***************
*** 2222,2234 ****     Put this makefile as <literal>Makefile</literal> in the directory     which holds your
extension.Then you can do     <literal>make</literal> to compile, and later <literal>make
 
!     install</literal> to install your module.  The extension is     compiled and installed for the
<productname>PostgreSQL</productname>installation that
 
!     corresponds to the first <command>pg_config</command> command
!     found in your path.    </para>     <para>     The scripts listed in the <varname>REGRESS</> variable are used for
   regression testing of your module, just like <literal>make
 
--- 2235,2260 ----     Put this makefile as <literal>Makefile</literal> in the directory     which holds your
extension.Then you can do     <literal>make</literal> to compile, and later <literal>make
 
!     install</literal> to install your module.  By default, the extension is     compiled and installed for the
<productname>PostgreSQL</productname>installation that
 
!     corresponds to the first <command>pg_config</command> program
!     found in your path.  You can use a different installation by
!     setting <varname>PG_CONFIG</varname> to point to its
!     <command>pg_config</command> program, either within the makefile
!     or on the <literal>make</literal> command line.    </para> 
+    <caution>
+     <para>
+      Changing <varname>PG_CONFIG</varname> only works when building
+      against <productname>PostgreSQL</productname> 8.3 or later.
+      With older releases it does not work to set it to anything except
+      <literal>pg_config</>; you must alter your <varname>PATH</>
+      to select the installation to build against.
+     </para>
+    </caution>
+     <para>     The scripts listed in the <varname>REGRESS</> variable are used for     regression testing of your
module,just like <literal>make
 


It might be worth backpatching the Makefile.global.in patch (ie, the
ifndef addition) to the 8.2 branch, which would allow us to say "8.2.5
or later" instead of "8.3 or later", and would bring correspondingly
nearer the time when people can actually use the feature without
thinking much.  Comments?
        regards, tom lane


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
> It might be worth backpatching the Makefile.global.in patch (ie, the
> ifndef addition) to the 8.2 branch, which would allow us to say "8.2.5
> or later" instead of "8.3 or later", and would bring correspondingly
> nearer the time when people can actually use the feature without
> thinking much.  Comments?

My 2 euro cents (about $0.027) conservative comments on the subject:
 - It is more work for a minor issue. I would just update the doc for   previous releases. - New features belong to new
releases,on principles. It is not really a   bug which would require an update of previous releases, and changing the
PATHis a valid workaround anyway. - Do it your way:-)
 

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Peter Eisentraut
Date:
Am Dienstag, 26. Juni 2007 16:12 schrieb Tom Lane:
> True.  OK, then let's add the ifndef to Makefile.global and change the
> existing extension makefiles to
>
>         PG_CONFIG := pg_config
>         PGXS := $(shell $(PG_CONFIG) --pgxs)
>         include $(PGXS)
>
> Any objections?

Yes.  I think that solution is wrong.  It merely creates other possibilities 
to use mismatching combinations.  What was the problem with just making all 
uses of pg_config in Makefile.global use a hardcoded bindir directly?

-- 
Peter Eisentraut
http://developer.postgresql.org/~petere/


Re: Frustrating issue with PGXS

From
Fabien COELHO
Date:
Dear Peter,

> What was the problem with just making all uses of pg_config in 
> Makefile.global use a hardcoded bindir directly?

Because bindir is given by pg_config:-)

ISTM that the underlying issue, which was not foreseen in the initial pgxs 
and fixed later, is that some distributions use a different installation 
prefix at compile time and once the software is actually installed. You 
would end up with a /tmp/build/.. path which does not exist. If the 
installations are movable, you can only rely on pg_config.

-- 
Fabien.


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Fabien COELHO <coelho@cri.ensmp.fr> writes:
>> What was the problem with just making all uses of pg_config in 
>> Makefile.global use a hardcoded bindir directly?

> Because bindir is given by pg_config:-)

> ISTM that the underlying issue, which was not foreseen in the initial pgxs 
> and fixed later, is that some distributions use a different installation 
> prefix at compile time and once the software is actually installed.

Right, the installation tree is supposed to be relocatable.  Otherwise
we would not need to use pg_config to find the paths at all; we'd just
hardwire all of them when constructing Makefile.global.
        regards, tom lane


Re: Frustrating issue with PGXS

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Am Dienstag, 26. Juni 2007 16:12 schrieb Tom Lane:
>>         PG_CONFIG := pg_config
>>         PGXS := $(shell $(PG_CONFIG) --pgxs)
>>         include $(PGXS)
>> 
>> Any objections?

> Yes.  I think that solution is wrong.  It merely creates other possibilities 
> to use mismatching combinations.

Well, it's certainly *possible* to screw it up, but the idea is that the
"obvious" way of putting in a path will work; whereas before the obvious
way did not work.  So I think it's a step forward.
        regards, tom lane