Amit's complaint about unnecessary headers got me thinking about
src/tools/pginclude.  I think the the stuff in this directory is
trying to do something useful, because I think extra #include
directives that we don't need are a useful thing to eliminate.
However, in practice the contents are very hard for anybody to use
except maybe Bruce, who wrote it with his own environment in mind.  On
my system, any attempt to rerun pgcompinclude -- which is described as
a prerequisite to running pgrminclude -- produces enormous numbers of
bogus errors and warnings, both because of the attempt to call every
defined macro with made-up arguments and because I configure with
stuff like --with-includes=/opt/local/include which pgcompinclude
knows nothing about.

I wonder if we can do better.  The attached patch is the rest of a
couple of hours of hacking on a "see whether all of our includes
compile separately" project.  Directions:

1. configure
2. go to src/tools/pginclude
3. make test-compile-include

It strikes me that if we could make this robust enough to include in
the buidlfarm, that would be good.  And maybe we could then have a
pgrminclude tool which is a bit smarter also, and something that
anyone can easily run.  I don't think pgrminclude should be part of
the buildfarm, but being able to run it every release cycle with
relatively minimal pain instead of every 5 years with extensive
fallout seems like it would be a win.

Thoughts?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/src/tools/pginclude/Makefile b/src/tools/pginclude/Makefile
new file mode 100644
index 0000000..b7e5e7e
--- /dev/null
+++ b/src/tools/pginclude/Makefile
@@ -0,0 +1,15 @@
+subdir = src/tools/pginclude
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+include $(top_srcdir)/src/backend/common.mk
+
+test-compile-include:
+	rm -rf compile-includes
+	cd $(top_builddir) && $(subdir)/gen_compile_include.pl
+	$(MAKE) -C $(top_builddir)/src/backend generated-headers
+	$(MAKE) -C compile-includes
+	rm -rf compile-includes
+
+clean:
+	rm -rf compile-includes
diff --git a/src/tools/pginclude/gen_compile_include.pl b/src/tools/pginclude/gen_compile_include.pl
new file mode 100755
index 0000000..24f858d
--- /dev/null
+++ b/src/tools/pginclude/gen_compile_include.pl
@@ -0,0 +1,163 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $include_prefix = 'src/include';
+my $output_dir = 'src/tools/pginclude/compile-includes';
+
+#
+# Some include files need to be excluded from the "does it compile separately?"
+# test, either because they are platform-dependent stubs or because they aren't
+# actually intended to compile separately.
+#
+my %exclude_include = map { $_ => 1 } qw(
+	access/rmgrlist.h
+	parser/gram.h
+	parser/kwlist.h
+	port/atomics
+	port/cygwin.h
+	port/win32.h
+	port/win32
+	port/win32_msvc
+	regex/regerrs.h
+    storage/checksum_impl.h
+	rusagestub.h
+);
+
+my $top_builddir = $output_dir;
+$top_builddir =~ s@[^/]+@..@g;
+
+my @include_dir = ('');
+my @include_file;
+my @frontend_obj;
+my @backend_obj;
+
+#
+# Recurse through src/include and gather a list of all include files, excluding
+# those mentioned in the exclusion list, above.
+#
+while (@include_dir)
+{
+	my $include_dir = shift @include_dir;
+	my $include_path = $include_prefix . ($include_dir eq '' ? ''
+		: '/' . $include_dir);
+
+	opendir(my $directory, $include_path)
+		or die "could not opendir($include_path): $!";
+
+	while (my $entry = readdir($directory))
+	{
+		next if ($entry eq '.' || $entry eq '..');
+
+		$entry = $include_dir eq '' ? $entry : $include_dir . '/' . $entry;
+		next if exists $exclude_include{$entry};
+		my $path = $include_prefix . '/' . $entry;
+		if (-f $path)
+		{
+			push @include_file, $entry;
+		}
+		elsif (-d $path)
+		{
+			push @include_dir, $entry;
+		}
+	}
+}
+
+#
+# Create output directories.
+#
+mkdir($output_dir) or die "mkdir($output_dir): $!";
+mkdir($output_dir . '/backend') or die "mkdir($output_dir . '/backend'): $!";
+mkdir($output_dir . '/frontend') or die "mkdir($output_dir . '/frontend'): $!";
+
+#
+# For each include file, create a C file which includes either postgres.h
+# (for frontend includes) or postgres_fe.h (for backend includes), the
+# relevant header, and nothing else.
+#
+for my $include_file (@include_file)
+{
+	my $dotc_file = $include_file;
+	$dotc_file =~ s/\.h$/.c/;
+	$dotc_file =~ s@/@-@g;
+	my $is_frontend = ($include_file =~ m@^fe_utils/@);
+
+	my $dotc_path = $output_dir . ($is_frontend ? '/frontend/' : '/backend/')
+		. $dotc_file;
+	my $base_include = $is_frontend ? 'postgres_fe.h' : 'postgres.h';
+	$base_include = "postgres-fe.h" if $include_file =~ m@^fe_utils/@;
+
+	write_file($dotc_path, <<EOM);
+#include "postgres.h"
+
+#include "$include_file"
+EOM
+
+	# Record the name of the expected object file in the appropriate list.
+	my $object_file = $dotc_file;
+	$object_file =~ s/\.c$/.o/;
+	if ($is_frontend)
+	{
+		push @frontend_obj, $object_file;
+	}
+	else
+	{
+		push @backend_obj, $object_file;
+	}
+}
+
+#
+# Write a Makefile for the backend subdirectory.
+#
+my $backend_object_list = join(' ', @backend_obj);
+write_file($output_dir . '/backend/Makefile', <<EOM);
+subdir = $output_dir/backend
+top_builddir = $top_builddir/..
+include \$(top_builddir)/src/Makefile.global
+
+OBJS = $backend_object_list
+
+include \$(top_srcdir)/src/backend/common.mk
+
+EOM
+
+#
+# Write a Makefile for the frontend subdirectory.
+#
+my $frontend_object_list = join(' ', @frontend_obj);
+write_file($output_dir . '/frontend/Makefile', <<EOM);
+subdir = $output_dir/frontend
+top_builddir = $top_builddir/..
+include \$(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -DFRONTEND -I\$(libpq_srcdir) \$(CPPFLAGS)
+
+OBJS = $frontend_object_list
+
+include \$(top_srcdir)/src/backend/common.mk
+
+EOM
+
+#
+# Write a Makefile for the main output directory.
+#
+write_file($output_dir . '/Makefile', <<EOM);
+subdir = $output_dir
+top_builddir = $top_builddir
+include \$(top_builddir)/src/Makefile.global
+
+SUBDIRS = frontend backend
+
+include \$(top_srcdir)/src/backend/common.mk
+
+EOM
+
+sub write_file
+{
+	my ($path, $content) = @_;
+
+	open(my $file, '>', $path) or die "open($path): $!";
+	print $file $content;
+	close($file);
+}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to