pg gem currently fails to compile on SmartOS against ruby 2.3. It builds against
After digging through compile output and various Solaris build reports from other projects, trying million things to get it built, I was able to build it by doing the following:
- cd to the
extfolder where previous build failed.
Makefile, and append
CPPFLAGSfield, resulting in this:
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" -I/opt/local/include -I/home/app/.rbenv/versions/2.3.0/include -std=iso9899:1999 -D_XOPEN_SOURCE=700 -D__EXTENSIONS__ $(DEFS) $(cppflags)
After this modification, running
make install completes installation of this gem.
I am deploying a Rails application, which is syntax-level dependent on ruby 2.3.0 on SmartOS (an open source descendant of the former Solaris OS https://smartos.org/), and I am running into a surprising compile issue.
This issue happens only when building with ruby 2.3.0, which I previous installed from the sources on the same OS using
When I use package-supplied ruby 2.2, the gem installs without any problem. Unfortunately, at this time Joyent does not offer ruby 2.3.0 package, which is why I resort to building it from sources. That said, it builds cleanly without any issues.
Here is what I know:
- pg gem installs against ruby 2.2 provided by Joyent via a package
- pg gem breaks with the complication error against ruby 2.3 compiled from sources
- here is the actual error as it happens during
gem install pg -- --with-pg-config=/opt/local/bin/pg_config.
compiling gvl_wrappers.c In file included from /usr/include/poll.h:41:0, from /home/app/.rbenv/versions/2.3.0/include/ruby-2.3.0/ruby/io.h:36, from pg.h:85, from gvl_wrappers.c:6: /usr/include/signal.h:92:1: error: unknown type name 'procset_t' Makefile:238: recipe for target 'gvl_wrappers.o' failed
However, during another compilation attempt, different file triggered the same error:
compiling pg_copy_coder.c In file included from /usr/include/poll.h:41:0, from /usr/local/include/ruby-2.3.0/ruby/io.h:36, from pg.h:85, from pg_copy_coder.c:6: /usr/include/signal.h:92:29: error: unknown type name 'procset_t' extern int sigsendset(const procset_t *, int); ^ Makefile:238: recipe for target 'pg_copy_coder.o' failed make: *** [pg_copy_coder.o] Error 1
So the error happens in the same place – it's unable to find the symbol
Now, I followed the include files starting from line 41 in
poll.h, and that file includes
sys/procset.h which does indeed define this symbol, but it's surrounded by two #defines:
/* * The following defines the operations which can be performed to * combine two simple sets of processes to form another set of * processes. */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) ..... ..... /* procset_t definition follows */
I did a quick search on these symbols, and found this helpful thread: http://stackoverflow.com/questions/1034587/how-does-xpg4-2-and-other-defines-work-on-solaris
Basically, they are saying that Solaris has an interesting way of including various features into
the compiled binary, which are controlled by
-D flags. The above discussion recommends adding the following defines:
I looked at the Makefile, and noticed that it already sets
D_XOPEN_SOURCE=700, so I spent good amount of time trying to add the second flag
-D_XOPEN_SOURCE_EXTENDED=1, to no avail. Now I was getting a very interesting message:
(output removed for brevity) /usr/include/sys/feature_tests.h:387:2: error: #error "Compiler or options invalid for pre-UNIX 03 X/Open applications and pre-2001 POSIX applications" In file included from /usr/include/poll.h:41:0, from /home/app/.rbenv/versions/2.3.0/include/ruby-2.3.0/ruby/io.h:36, from pg.h:85, from pg_type_map_in_ruby.c:7: /usr/include/signal.h:92:1: error: unknown type name 'procset_t' Makefile:238: recipe for target 'pg_type_map_in_ruby.o' failed
At this point I understood that I am fighting with Solaris features/compiled combination pairings, or something along those lines, and so I went back to the failing header file, and there was only one more flag to try:
I thought that the
-D_XOPEN_SOURCE_EXTENDED=1 is, perhaps, responsible for setting
__EXTENSIONS__, but as it turns out – no, it's not. And so I went ahead and just added the
-D__EXTENSIONS__ to the CPPFLAGS and ran make, everything compiled without a single warning:
app@app100 ~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/pg-0.18.4/ext master make compiling pg_copy_coder.c compiling pg_type_map_all_strings.c compiling pg_type_map_in_ruby.c compiling util.c compiling pg_type_map_by_column.c compiling pg_text_decoder.c compiling pg_text_encoder.c compiling gvl_wrappers.c compiling pg.c compiling pg_type_map_by_oid.c compiling pg_errors.c compiling pg_binary_decoder.c compiling pg_type_map_by_mri_type.c compiling pg_type_map_by_class.c compiling pg_binary_encoder.c compiling pg_result.c compiling pg_connection.c compiling pg_type_map.c compiling pg_coder.c linking shared-object pg_ext.so
Now, this is obviously a workaround, so I am hoping that someone figures out what is going on.
- Is the issue in how I built ruby 2.3.0 from sources? Is ruby config supposed to provide those defines to the extensions? I am not sure.
I will say one thing:
I found it very frustrating that there could be no way, other than manually modifying Makefile, to play with various options on the
gem command line. I really wanted to do something like this:
CPPFLAGS="-D__EXTENSION__" gem install pg
gem install pg -- --cppflags=-D__EXTENSIONS__
etc. I think it would be really nice to give users of the gem ways to supply various compile options without having to go and find the sources. Make it only available to power users, put it in the advanced README hidden inside a Makefile (LOL), but leave it there so that it's possible.
Thank you very much for building and maintaining this lovely gem. Using it and PostgreSQL since 2004.