LMPX.COM |
Home | Linux | Mysql | PHP | XML | ||
|
|
|||
From: Keisial Date: Mon Aug 11 13:06:00 2008 Subject: A new way for creating extensions
I recently had the need to create a php-gtk extension, and what i found
wasn't too pleasant.
Most code (gen_*.c) is autogenerated from the defs file by
generator/generator.php. Which itself is made by running h2def.py on the
C header. Well, it turns out generator/h2def.py is outdated. And by
outdated i mean that generator/generator.php *won't be able to process
that file*. Oops.
The solution is using the newer one maintained by the pygtk folks at
http://svn.gnome.org/svn/pygobject/trunk/codegen
It also has improvements such as no longer needing to edit the defs file
in order to specify which is the constructor.
Where to get the other files an extension needs? Well, there's a
skeleton extension precisely for a basis for that, right? Wrong! It is
also outdated. php_skeleton_register_constants() doesn't expect a
module_number, but a const char* Using it you get a nice sigsegv on runtime.
Finally, there's ext_skel, a shell script to copy the skeleton dir to
the widget's and avoid you the trouble or replacing each skeleton
occurrence by the new widget's name. It's also broken, although this may
be just in my setup.
So, you end up copying one of the working widgets and changing the name
in lots of places, with different capitalizations. You invariably forget
some, and have to try compiling several times until you get it right. As
Bob said when i asked how to create php-gtk extensions, "it is just not
very fun to do".
That labour would better be achieved by a script, and so i went into
making it.
This new script resides in generator/ext_gen.php and hooks into the
build process, based on ext_data.php on each extension folder. You can
use it once to generate the files which you will then customize, or
leave them autogenerate on each build. This point is specially
interesting because most extensions haven't changed since they were
created by copy & replace, and provides a single point of improvement
into the system. Also, by keeping the generator in use by a number of
extensions, it is guaranteed to be kept up-to-date.
Each extension defines a few parameters into the file ext_data.php, and
can have most its files autogenerated. The new generated scripts are
(expected to be) equivalent to the old ones. In fact, much of it is the
same code, to make a cvs diff as smaller as possible. However, there's a
number of improvements:
-grep | sed process replaced by just a sed
-gen_*.h created a bit more independed from gen_*.c
-Makefiles actions in one line broken on several.
-gen_*.h will include the prototypes of the exported functions of
gen_*.c, which would have warned the issue of the register_constants()
parameter type at compile time.
-php_*.h will include gen_*.h instead of placing the prototypes.
-Minor differences on text presented to the user, usually just of
capitalization (eg. 'Disable libglade support' vs 'Disable libGlade
support').
Transitioned extensions: extra, html, libglade, libsexy
Unchanged: gtk+ (lots of special stuff), mozembed (three different
modules), scintilla (several customizations), spell (standalone)
I have done my best to ensure it doesn't break anything, but any
comments are welcome. You can also reach me at #php-gtk. The extensions
still build fine on Linux with the patch. On windows, it still fails, as
it did without it, so SNAFU.
Added files:
extra/ext_data.php
html/ext_data.php
libglade/ext_data.php
libsexy/ext_data.php
generator/ext_gen.php
Modified:
win32/buildconf.js
build2/build.mk
Removed:
generator/h2def.py
ext/ext_skel
ext/skeleton/* [keep skeleton.overrides?]
Deprecated:
extra/config.m4,config.w32,Makefile.frag,php_gtkextra.c,php_gtkextra.h
html/config.m4,config.w32,Makefile.frag,php_html.c,php_html.h
libglade/config.m4,config.w32,Makefile.frag,php_libglade.c,php_libglade.h
libsexy/config.m4,config.w32,Makefile.frag,php_libsexy.c,php_libsexy.h
Renamed (apply manually):
mv extra/gtkextra.defs extra/extra.defs
mv extra/gtkextra.overrides extra/extra.overrides
mv libsexy/sexy.overrides libsexy/libsexy.overrides
mv libsexy/sexy.defs libsexy/libsexy.defs
Opinions?
Index: build2/build.mk
===================================================================
RCS file: /repository/php-gtk/build2/build.mk,v
retrieving revision 1.11
diff -u -r1.11 build.mk
--- build2/build.mk 12 Sep 2005 17:01:08 -0000 1.11
+++ build2/build.mk 10 Aug 2008 17:52:54 -0000
@@ -12,6 +12,7 @@
@$(MAKE) -s -f build2/build2.mk
build2/generated_lists:
+ @for i in `find . -name ext_data.php`; do php generator/ext_gen.php $$i; done
@echo config_m4_files = ext/*/config*.m4 > $@
$(STAMP):
Index: ext/ext_skel
===================================================================
RCS file: ext/ext_skel
diff -N ext/ext_skel
--- ext/ext_skel 11 Apr 2002 02:19:45 -0000 1.4
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,82 +0,0 @@
-#!/bin/sh
-
-# $Id: ext_skel,v 1.4 2002/04/11 02:19:45 andrei Exp $
-
-file_list=".cvsignore Makefile.in Makefile.frag config.m4 php_skeleton.c php_skeleton.h skeleton.overrides"
-
-giveup() {
- echo $*
- echo ""
- exit 1
-}
-
-usage() {
- echo "$0 --widget=name"
- echo ""
- echo " --widget=name the name of the widget."
- echo " It's actually important to name the"
- echo " widget properly, e.g. SQPaned and"
- echo " not Sqpaned."
- echo ""
- exit 1
-}
-
-if test $# = 0; then
- usage
-fi
-
-while test $# -gt 0; do
- case "$1" in
- -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) optarg= ;;
- esac
-
- case $1 in
- --widget=?*)
- Widget=$optarg
- WIDGET=`echo $Widget | tr [a-z] [A-Z]`
- widget=`echo $Widget | tr [A-Z] [a-z]`
- ;;
- *)
- usage
- ;;
- esac
- shift
-done
-
-if test -d "$widget"; then
- giveup "Directory $widget already exists."
-fi
-
-test -f ext_skel || giveup "ext_skel must be in the current directory"
-test -d skeleton || giveup "subdirectory skeleton does not exist or is not directory"
-
-echo "Creating directory $widget"
-mkdir $widget || giveup "Cannot create directory $widget"
-
-echo "Creating skeleton files"
-cd skeleton
-cp -a $file_list ../$widget/
-cd ../$widget/
-
-perl -p -i -e "s/skeleton/$widget/g" $file_list
-perl -p -i -e "s/Skeleton/$Widget/g" $file_list
-perl -p -i -e "s/SKELETON/$WIDGET/g" $file_list
-perl -p -i -e "s/^dnl //" config.m4
-
-mv php_skeleton.c php_$widget.c
-mv php_skeleton.h php_$widget.h
-mv skeleton.overrides $widget.overrides
-
-echo "Skeleton built."
-echo ""
-echo "Now you can create your $widget/$widget.defs file with:"
-echo ""
-echo -e "\t../generator/h2def.py <path>/$widget.h >$widget/$widget.defs"
-echo ""
-echo "and don't forget to add the constructor line to $widget.defs:"
-echo ""
-echo -e "\t(is-constructor-of Gtk$Widget)"
-echo ""
-echo "in the definition of gtk_${widget}_new"
-echo ""
Index: ext/extra/ext_data.php
===================================================================
RCS file: ext/extra/ext_data.php
diff -N ext/extra/ext_data.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/extra/ext_data.php 10 Aug 2008 17:52:54 -0000
@@ -0,0 +1,16 @@
+<?php
+
+$Widget_Name = "GtkExtra";
+$required_version = "2.1.1";
+$module_name = "gtkextra-2.0";
+$lib_name = "gtkextra-2.0.lib";
+$include_header = "gtkextra/gtkextra.h";
+
+load_names();
+create_m4_config();
+create_makefile_frag();
+create_w32_config();
+create_php_ext_h();
+create_php_ext_c();
+create_cvsignore();
+
Index: ext/html/ext_data.php
===================================================================
RCS file: ext/html/ext_data.php
diff -N ext/html/ext_data.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/html/ext_data.php 10 Aug 2008 17:52:54 -0000
@@ -0,0 +1,19 @@
+<?php
+
+$Widget_Name = "GtkHtml";
+$required_version = "3.10.0";
+$module_name = "libgtkhtml-3.8";
+$lib_name = "gtkhtml-3.0.lib";
+$include_header = "gtkhtml/gtkhtml.h";
+
+load_names();
+create_m4_config();
+create_makefile_frag();
+create_w32_config();
+create_php_ext_h();
+create_php_ext_c();
+create_cvsignore();
+
+/* Rename to
+gtkhtml.overrides
+gtkhtml.defs*/
Index: ext/libglade/ext_data.php
===================================================================
RCS file: ext/libglade/ext_data.php
diff -N ext/libglade/ext_data.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/libglade/ext_data.php 10 Aug 2008 17:52:54 -0000
@@ -0,0 +1,16 @@
+<?php
+
+$Widget_Name = "libGlade";
+$required_version = "2.4.0";
+$module_name = "libglade-2.0";
+$lib_name = "glade-2.0.lib";
+$enable_default = true;
+
+load_names();
+create_m4_config();
+create_makefile_frag();
+create_w32_config();
+create_php_ext_h();
+create_php_ext_c();
+create_cvsignore();
+
Index: ext/libsexy/ext_data.php
===================================================================
RCS file: ext/libsexy/ext_data.php
diff -N ext/libsexy/ext_data.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ext/libsexy/ext_data.php 10 Aug 2008 17:52:54 -0000
@@ -0,0 +1,16 @@
+<?php
+
+$Widget_Name = "libSexy";
+$required_version = "0.1.10";
+$module_name = "libsexy";
+$lib_name = "libsexy.lib";
+$include_header = "libsexy/sexy.h";
+
+load_names();
+create_m4_config();
+create_makefile_frag();
+create_w32_config();
+create_php_ext_h();
+create_php_ext_c();
+create_cvsignore();
+
Index: ext/skeleton/Makefile.frag
===================================================================
RCS file: ext/skeleton/Makefile.frag
diff -N ext/skeleton/Makefile.frag
--- ext/skeleton/Makefile.frag 12 Oct 2005 20:05:37 -0000 1.3
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,11 +0,0 @@
-
-$(builddir)/php_skeleton.lo: $(builddir)/gen_ce_skeleton.h
-
-$(builddir)/gen_skeleton.lo: $(builddir)/gen_skeleton.c
-
-$(builddir)/gen_skeleton.c: $(srcdir)/skeleton.defs $(srcdir)/skeleton.overrides
- $(PHP) -f $(top_srcdir)/generator/generator.php -- -o $(srcdir)/skeleton.overrides -p Skeleton -r $(top_srcdir)/ext/gtk%2b/gtk.defs $(srcdir)/skeleton.defs > $@
-
-$(builddir)/gen_ce_skeleton.h: $(builddir)/gen_skeleton.c
- grep -h "^PHP_GTK_EXPORT_CE" $(srcdir)/gen_skeleton.c | sed -e "s!^!extern !" > $@
-
Index: ext/skeleton/config.m4
===================================================================
RCS file: ext/skeleton/config.m4
diff -N ext/skeleton/config.m4
--- ext/skeleton/config.m4 28 Jun 2003 02:09:06 -0000 1.9
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,30 +0,0 @@
-dnl $Id: config.m4,v 1.9 2003/06/28 02:09:06 alan_k Exp $
-dnl config.m4 for skeleton module
-
-dnl PHP_GTK_ARG_ENABLE(skeleton,for GtkSkeleton support,
-dnl [ --enable-skeleton Enable GtkSkeleton support])
-
-dnl if test "$PHP_GTK_SKELETON" != "no"; then
-dnl for x in /usr /usr/local; do
-dnl if test -f $x/include/gtkskeleton.h; then
-dnl SKELETON_DIR=$x
-dnl SKELETON_INCDIR=$x/include
-dnl fi
-dnl done
-dnl
-dnl if test -z "$SKELETON_DIR"; then
-dnl AC_MSG_ERROR(Cannot locate Skeleton)
-dnl fi
-dnl
-dnl SKELETON_LIBDIR=$SKELETON_DIR/lib
-dnl
-dnl AC_DEFINE(HAVE_SKELETON,1,[skeleton support])
-dnl PHP_ADD_INCLUDE($SKELETON_INCDIR)
-dnl if test "$php_gtk_ext_shared" = "yes"; then
-dnl PHP_ADD_LIBRARY_WITH_PATH(gtkskeleton, $SKELETON_LIBDIR, SKELETON_SHARED_LIBADD)
-dnl PHP_SUBST(SKELETON_SHARED_LIBADD)
-dnl else
-dnl PHP_ADD_LIBRARY_WITH_PATH(gtkskeleton, $SKELETON_LIBDIR, PHP_GTK_SHARED_LIBADD)
-dnl fi
-dnl PHP_GTK_EXTENSION(skeleton, $php_gtk_ext_shared)
-dnl fi
Index: ext/skeleton/php_skeleton.c
===================================================================
RCS file: ext/skeleton/php_skeleton.c
diff -N ext/skeleton/php_skeleton.c
--- ext/skeleton/php_skeleton.c 29 Feb 2008 19:05:53 -0000 1.5
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,45 +0,0 @@
-/*
- * PHP-GTK - The PHP language bindings for GTK+
- *
- * Copyright (C) 2001-2008 Andrei Zmievski <andrei@php.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* $Id: php_skeleton.c,v 1.5 2008/02/29 19:05:53 andrei Exp $ */
-
-#include "php_skeleton.h"
-
-#if HAVE_SKELETON
-
-#ifdef PHP_GTK_COMPILE_DL_SKELETON
-PHP_GTK_GET_EXTENSION(skeleton)
-#endif
-
-PHP_GTK_XINIT_FUNCTION(skeleton)
-{
- php_skeleton_register_constants(module_number TSRMLS_CC);
- php_skeleton_register_classes();
-
- return SUCCESS;
-}
-
-php_gtk_ext_entry skeleton_ext_entry = {
- "skeleton",
- PHP_GTK_XINIT(skeleton),
- NULL,
-};
-
-#endif /* HAVE_SKELETON */
Index: ext/skeleton/php_skeleton.h
===================================================================
RCS file: ext/skeleton/php_skeleton.h
diff -N ext/skeleton/php_skeleton.h
--- ext/skeleton/php_skeleton.h 29 Feb 2008 19:05:53 -0000 1.5
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,46 +0,0 @@
-/*
- * PHP-GTK - The PHP language bindings for GTK+
- *
- * Copyright (C) 2001-2008 Andrei Zmievski <andrei@php.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* $Id: php_skeleton.h,v 1.5 2008/02/29 19:05:53 andrei Exp $ */
-
-#ifndef PHP_SKELETON_H
-#define PHP_SKELETON_H
-
-#include "php_gtk.h"
-
-#if HAVE_SKELETON
-
-#include "gen_ce_skeleton.h"
-
-extern php_gtk_ext_entry skeleton_ext_entry;
-#define skeleton_ext_ptr &skeleton_ext_entry
-
-void php_skeleton_register_constants(int module_number TSRMLS_DC);
-void php_skeleton_register_classes();
-
-#else
-
-#define skeleton_ext_ptr NULL
-
-#endif /* HAVE_SKELETON */
-
-#define php_gtk_ext_skeleton_ptr skeleton_ext_ptr
-
-#endif /* PHP_SKELETON_H */
Index: ext/skeleton/skeleton.overrides
===================================================================
RCS file: ext/skeleton/skeleton.overrides
diff -N ext/skeleton/skeleton.overrides
--- ext/skeleton/skeleton.overrides 14 Oct 2001 16:21:54 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,10 +0,0 @@
-/* vim: set ft=cpp: */
-%%
-headers
-#include <gtkskeleton.h>
-#include "ext/gtk+/php_gtk+.h"
-%%
-constants
-%%
-ignore-glob
- *_get_type
Index: generator/ext_gen.php
===================================================================
RCS file: generator/ext_gen.php
diff -N generator/ext_gen.php
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ generator/ext_gen.php 10 Aug 2008 17:52:55 -0000
@@ -0,0 +1,246 @@
+<?php
+
+
+/* Usage: Pass a ext_data.php as parameter
+ * This script can generate config.m4,config.w32,Makefile.frag,
+ * the extension .c and .h files and .cvsignore
+ * To regenerate the .defs file, checkout from svn
+ * http://svn.gnome.org/svn/pygobject/trunk/codegen
+ * and run h2def.py <C header>
+ * When crating a new extension, remember to add the enum names
+ * at generator/generator.php is_php_type()
+ */
+
+/** Example of ext_data.php
+$Widget_Name = "GtkSpell";
+$required_version = "2.0.0";
+$module_name = "gtkspell-2.0"; #Linux
+$lib_name = "gtkspell-2.0.lib"; #Windows
+$enable_default = false;
+*
+load_names();
+create_m4_config();
+create_makefile_frag();
+create_w32_config();
+create_php_ext_h();
+create_php_ext_c();
+create_cvsignore();
+*/
+
+error_reporting (E_ALL | E_STRICT );
+function load_names() {
+ #Prepare different variations of the name we will use
+ global $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name, $widget_name_nolib, $WIDGET_NAME_NOLIB, $full_widget_name_nolib, $FULL_WIDGET_NAME_NOLIB, $include_header;
+
+ $Full_Widget_Name=$Widget_Name;
+ if (substr($Widget_Name, 0, 3) == "Gtk") $Widget_Name = substr($Widget_Name, 3);
+
+
+ $WIDGET_NAME=strtoupper($Widget_Name);
+ $widget_name=strtolower($Widget_Name);
+ $widget_name_nolib = (substr($widget_name, 0, 3) == "lib") ? substr($widget_name, 3) : $widget_name;
+ $FULL_WIDGET_NAME = strtoupper($Full_Widget_Name);
+ $full_widget_name = strtolower($Full_Widget_Name);
+ $full_widget_name_nolib = (substr($full_widget_name, 0, 3) == "lib") ? substr($full_widget_name, 3) : $full_widget_name;
+ $FULL_WIDGET_NAME_NOLIB = (substr($FULL_WIDGET_NAME, 0, 3) == "LIB") ? substr($FULL_WIDGET_NAME, 3) : $FULL_WIDGET_NAME;
+
+ if (!isset($include_header)) {
+ $include_header = "{$widget_name_nolib}/{$widget_name_nolib}.h";
+ }
+}
+
+function create_m4_config() {
+global $required_version, $module_name, $lib_name, $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name, $widget_name_nolib;
+global $enable_default, $extra_files;
+$files = "php_{$widget_name}.c " . implode(" ", $extra_files) . ", gen_{$widget_name}.c gen_{$widget_name}.h";
+
+$M4 = <<< EOF_CONFIG
+dnl Autogenerated by ext_gen.php
+
+define({$widget_name}_required_version, $required_version)
+PHP_GTK_ARG_WITH({$widget_name},for {$widget_name} support,
+
+
+EOF_CONFIG;
+if ($enable_default)
+ $M4 .= "[ --without-{$widget_name} Disable {$Full_Widget_Name} support],yes)";
+else
+ $M4 .= "[ --with-{$widget_name} Enable {$Full_Widget_Name} support],no)";
+
+$M4 .= <<< EOF_CONFIG
+
+if test "\$PHP_GTK_{$WIDGET_NAME}" != "no"; then
+ PKG_CHECK_MODULES($WIDGET_NAME, [{$module_name} >= {$widget_name}_required_version],
+ have_{$widget_name}=yes, have_{$widget_name}=no)
+ if test "\$have_{$widget_name}" != "yes"; then
+ AC_MSG_RESULT([Unable to locate $Widget_Name version {$widget_name}_required_version or higher: not building])
+ else
+ AC_DEFINE(HAVE_{$FULL_WIDGET_NAME}, 1, [$Widget_Name support])
+ PHP_EVAL_INCLINE(\${$WIDGET_NAME}_CFLAGS)
+ if test "\$php_gtk_ext_shared" = "yes"; then
+ PHP_EVAL_LIBLINE(\${$WIDGET_NAME}_LIBS, {$WIDGET_NAME}_SHARED_LIBADD)
+ PHP_SUBST({$WIDGET_NAME}_SHARED_LIBADD)
+ else
+ PHP_EVAL_LIBLINE(\${$WIDGET_NAME}_LIBS, PHP_GTK2_SHARED_LIBADD)
+ fi
+ PHP_GTK_EXTENSION({$widget_name}, \$php_gtk_ext_shared, $files)
+ fi
+fi
+EOF_CONFIG;
+
+file_put_contents ("config.m4", $M4);
+}
+
+function create_w32_config() {
+global $required_version, $module_name, $lib_name, $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name, $include_header, $extra_files;
+$files = "php_{$widget_name}.c gen_{$widget_name}.c " . implode(" ", $extra_files);
+$W32 = <<< EOF_CONFIG
+// Autogenerated by ext_gen.php
+
+ARG_WITH("{$widget_name}", "{$Full_Widget_Name} support", "no");
+
+if (PHP_GTK_{$WIDGET_NAME} != "no" || PHP_GTK_ALL != "no") {
+ if (CHECK_HEADER("$include_header") && CHECK_LIB("{$lib_name}", "{$widget_name}"))
+ {
+ if (FSO.FileExists("win32\\\\temp.bat")) {
+
+ var temp = FSO.OpenTextFile("win32\\\\temp.bat", 8);
+ temp.WriteLine("php -q generator\\\\generator.php -l win32\\\\logs\\\\config_{$widget_name}.log -o ext\\\\{$widget_name}\\\\{$widget_name}.overrides -p {$full_widget_name} -r ext\\\\gtk+\\\\gtk.defs ext\\\\{$widget_name}\\\\{$widget_name}.defs > ext\\\\{$widget_name}\\\\gen_{$widget_name}.c");
+ temp.WriteLine('sed -n "s/^PHP_GTK_EXPORT_CE/PHP_GTK_API extern \\\\0/p" ext\\\\{$widget_name}\\\\gen_{$widget_name}.c > ext\\\\{$widget_name}\\\\gen_{$widget_name}.h');
+ temp.WriteLine('sed -n "s/^void.*/\\\\0;/p" ext\\\\{$widget_name}\\\\gen_{$widget_name}.c >> ext\\\\{$widget_name}\\\\gen_{$widget_name}.h');
+ temp.Close();
+ }
+
+ /* The first parameter of ADD_FLAG must always match the first one of EXTENSION(), uppercased and with CFLAGS_ prepended. Otherwise, it's not passed to the compiler. */
+ ADD_FLAG("CFLAGS_{$WIDGET_NAME}", "/I ext\\\\{$widget_name} /I ..\\\\ext\\\\{$widget_name} /D HAVE_{$FULL_WIDGET_NAME}=1");
+ EXTENSION("{$widget_name}", "$files", true); // always shared
+ AC_DEFINE("HAVE_{$FULL_WIDGET_NAME}", 1, "{$Full_Widget_Name} enabled");
+
+ } else {
+ WARNING("{$Full_Widget_Name} not enabled; libraries and headers not found");
+ }
+}
+EOF_CONFIG;
+
+file_put_contents ("config.w32", $W32);
+}
+
+function create_php_ext_c() {
+global $required_version, $module_name, $lib_name, $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name, $FULL_WIDGET_NAME_NOLIB, $full_widget_name_nolib;
+
+$PHP_FILE = <<< EOF_FILE
+// Autogenerated by ext_gen.php
+#include "php_{$widget_name}.h"
+
+#if HAVE_{$FULL_WIDGET_NAME}
+
+#ifdef PHP_GTK_COMPILE_DL_$WIDGET_NAME
+PHP_GTK_GET_EXTENSION($widget_name)
+#endif
+
+PHP_GTK_XINIT_FUNCTION($widget_name)
+{
+ phpg_{$full_widget_name_nolib}_register_classes();
+ phpg_{$full_widget_name_nolib}_register_constants("{$FULL_WIDGET_NAME_NOLIB}_");
+
+ return SUCCESS;
+}
+
+php_gtk_ext_entry {$widget_name}_ext_entry = {
+ "$widget_name",
+ PHP_GTK_XINIT($widget_name),
+ NULL,
+};
+
+#endif /* HAVE_{$FULL_WIDGET_NAME} */
+
+EOF_FILE;
+
+file_put_contents ("php_$widget_name.c", $PHP_FILE);
+}
+
+function create_php_ext_h() {
+global $required_version, $module_name, $lib_name, $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name, $full_widget_name_nolib, $include_header;
+
+$PHP_FILE = <<< EOF_FILE
+// Autogenerated by ext_gen.php
+#ifndef PHP_{$FULL_WIDGET_NAME}_H
+#define PHP_{$FULL_WIDGET_NAME}_H
+
+#include "php_gtk.h"
+
+#if HAVE_{$FULL_WIDGET_NAME}
+#include "gen_{$widget_name}.h"
+
+#include <$include_header>
+
+extern php_gtk_ext_entry {$widget_name}_ext_entry;
+#define php_gtk_ext_{$widget_name}_ptr &{$widget_name}_ext_entry
+
+/** defined at gen_{$widget_name}.h
+void phpg_{$full_widget_name_nolib}_register_classes(void);
+void phpg_{$full_widget_name_nolib}_register_constants(const char *strip_prefix);
+**/
+
+#else
+
+#define php_gtk_ext_{$widget_name}_ptr NULL
+
+#endif /* HAVE_{$FULL_WIDGET_NAME} */
+
+#endif /* PHP_{$FULL_WIDGET_NAME}_H */
+
+EOF_FILE;
+
+file_put_contents ("php_$widget_name.h", $PHP_FILE);
+}
+
+function create_cvsignore() {
+
+$cvsignore = <<< EOF_CVSIGNORE
+*.cache
+*.lo
+*.la
+gen_*
+.libs
+libs.mk
+EOF_CVSIGNORE;
+
+file_put_contents (".cvsignore", $cvsignore);
+}
+
+
+function create_makefile_frag() {
+global $required_version, $module_name, $lib_name, $Widget_Name, $Full_Widget_Name, $WIDGET_NAME, $widget_name, $FULL_WIDGET_NAME, $full_widget_name;
+
+if (file_exists("{$widget_name}-types.defs"))
+ $extra_types = "\$(srcdir)/{$widget_name}-types.defs";
+else
+ $extra_types = "";
+
+$makefile = <<< EOF_MAKEFILE
+\$(builddir)/gen_{$widget_name}.c: \$(srcdir)/{$widget_name}.defs \$(srcdir)/{$widget_name}.overrides $extra_types
+ \$(PHP) \$(top_srcdir)/generator/generator.php \
+ -l \$(@D)/\$(*F).log \
+ -r ext/gtk+/atk-types.defs \
+ -r ext/gtk+/pango-types.defs \
+ -r ext/gtk+/gdk-types.defs \
+ -r ext/gtk+/gtk-types.defs \
+ -r $extra_types \
+ -o \$(srcdir)/{$widget_name}.overrides \
+ -p $Full_Widget_Name \
+ -f \$@ \$(srcdir)/{$widget_name}.defs
+
+\$(builddir)/gen_{$widget_name}.h: \$(builddir)/gen_{$widget_name}.c
+ sed -n 's/^PHP_GTK_EXPORT_CE/PHP_GTK_API extern \\0/p' \$@ > \$(@D)/\$(*F).h
+ sed -n 's/^void.*/\\0;/p' \$@ >> \$(@D)/\$(*F).h
+
+EOF_MAKEFILE;
+
+file_put_contents ("Makefile.frag", $makefile);
+}
+
+$enable_default = false;
+$extra_files = array();
+chdir(dirname($argv[1]));
+require (basename($argv[1]));
Index: generator/h2def.py
===================================================================
RCS file: generator/h2def.py
diff -N generator/h2def.py
--- generator/h2def.py 9 Jun 2006 15:50:45 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,345 +0,0 @@
-#!/usr/bin/env python
-# -*- Mode: Python; py-indent-offset: 4 -*-
-# Search through a header file looking for function prototypes.
-# For each prototype, generate a scheme style definition.
-# GPL'ed
-# Toby D. Reeves <toby@max.rl.plh.af.mil>
-
-# Modified by James Henstridge <james@daa.com.au> to output stuff in
-# Havoc's new defs format. Info on this format can be seen at:
-# http://www.gnome.org/mailing-lists/archives/gtk-devel-list/2000-January/0085.shtml
-
-
-import string, sys, re, types
-
-# ------------------ Find object definitions -----------------
-
-obj_name_pat = "[A-Z][a-z]+[A-Z][A-Za-z0-9]*"
-
-def find_obj_defs(buf, objdefs=[]):
- """
- Try to find object definitions in header files.
- """
-
- # filter out comments from buffer.
- pat = re.compile(r"""/[*](.|\n)*?[*]/""", re.MULTILINE)
- buf=pat.sub('',buf)
-
- # first find all structures that look like they may represent a GtkObject
- pat = re.compile("struct _(" + obj_name_pat + ")\s*{\s*" +
- "(" + obj_name_pat + ")\s+", re.MULTILINE)
- maybeobjdefs = [] # contains all possible objects from file
- pos = 0
- while pos < len(buf):
- m = pat.search(buf, pos)
- if not m: break
- maybeobjdefs.append((m.group(1), m.group(2)))
- pos = m.end()
-
- # now find all structures that look like they might represent a class:
- pat = re.compile("struct _(" + obj_name_pat + ")Class\s*{\s*" +
- "(" + obj_name_pat + ")Class\s+", re.MULTILINE)
- pos = 0
- while pos < len(buf):
- m = pat.search(buf, pos)
- if not m: break
- t = (m.group(1), m.group(2))
- # if we find an object structure together with a corresponding
- # class structure, then we have probably found a GtkObject subclass.
- if t in maybeobjdefs:
- objdefs.append(t)
- pos = m.end()
-
-def sort_obj_defs(objdefs):
- objdefs.sort() # not strictly needed, but looks nice
- pos = 0
- while pos < len(objdefs):
- klass,parent = objdefs[pos]
- for i in range(pos+1, len(objdefs)):
- # parent below subclass ... reorder
- if objdefs[i][0] == parent:
- objdefs.insert(i+1, objdefs[pos])
- del objdefs[pos]
- break
- else:
- pos = pos + 1
- return objdefs
-
-def write_obj_defs(objdefs, output):
- if type(output)==types.StringType:
- fp=open(output,'w')
- elif type(output)==types.FileType:
- fp=output
- else:
- fp=sys.stdout
-
- fp.write(';; -*- scheme -*-\n')
- fp.write('; object definitions ...\n')
-
- pat = re.compile('([A-Z][a-z]+)([A-Za-z0-9]+)')
- for klass, parent in objdefs:
- m = pat.match(klass)
- cmodule = None
- cname = klass
- if m:
- cmodule = m.group(1)
- cname = m.group(2)
- if parent:
- m = pat.match(parent)
- pmodule = None
- pname = parent
- if m:
- pmodule = m.group(1)
- pname = m.group(2)
-
- fp.write('(object ' + cname + '\n')
- if cmodule:
- fp.write(' (in-module ' + cmodule + ')\n')
- if parent:
- fp.write(' (parent ' + pname)
- if pmodule: fp.write(' (' + pmodule + ')')
- fp.write(')\n')
- fp.write(' (c-name ' + klass + ')\n')
- # should do something about accessible fields
- fp.write(')\n\n')
-
-# ------------------ Find enum definitions -----------------
-
-def find_enum_defs(buf, enums=[]):
- # strip comments
- # bulk comments
- pat = re.compile(r"""/[*](.|\n)*?[*]/""", re.MULTILINE)
- buf=pat.sub('',buf)
-
- buf = re.sub('\n', ' ', buf)
-
- enum_pat = re.compile(r'enum\s*{([^}]*)}\s*([A-Z][A-Za-z]*)(\s|;)')
- splitter = re.compile(r'\s*,\s', re.MULTILINE)
- pos = 0
- while pos < len(buf):
- m = enum_pat.search(buf, pos)
- if not m: break
-
- name = m.group(2)
- vals = m.group(1)
- isflags = string.find(vals, '<<') >= 0
- entries = []
- for val in splitter.split(vals):
- entries.append(string.split(val)[0])
- enums.append((name, isflags, entries))
-
- pos = m.end()
-
-def write_enum_defs(enums, output=None):
- if type(output)==types.StringType:
- fp=open(output,'w')
- elif type(output)==types.FileType:
- fp=output
- else:
- fp=sys.stdout
-
- fp.write(';; Enumerations and flags ...\n\n')
- pat = re.compile('([A-Z][a-z]+)([A-Za-z0-9]+)')
- trans = string.maketrans(string.uppercase + '_', string.lowercase + '-')
- for cname, isflags, entries in enums:
- name = cname
- module = None
- m = pat.match(cname)
- if m:
- module = m.group(1)
- name = m.group(2)
- if isflags:
- fp.write('(flags ' + name + '\n')
- else:
- fp.write('(enum ' + name + '\n')
- if module:
- fp.write(' (in-module ' + module + ')\n')
- fp.write(' (c-name ' + cname + ')\n')
- prefix = entries[0]
- for ent in entries:
- # shorten prefix til we get a match ...
- while ent[:len(prefix)] != prefix:
- prefix = prefix[:-1]
- for ent in entries:
- fp.write(' (value (name ' +
- string.translate(ent[len(prefix):], trans) +
- ') (c-name ' + ent + '))\n')
- fp.write(')\n\n')
-
-# ------------------ Find function definitions -----------------
-
-#comment_pat = re.compile(r"""(/[*](.|\n)*?[*]/)|(^;.*$)""", re.MULTILINE)
-
-def clean_func(buf):
- """
- Ideally would make buf have a single prototype on each line.
- Actually just cuts out a good deal of junk, but leaves lines
- where a regex can figure prototypes out.
- """
- # bulk comments
- pat = re.compile(r"""/[*](.|\n)*?[*]/""", re.MULTILINE)
- buf=pat.sub('',buf)
-
- # Preprocess directives
- pat = re.compile(r"""^[#].*?$""", re.MULTILINE)
- buf=pat.sub('',buf)
-
- #typedefs, stucts, and enums
- pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""", re.MULTILINE)
- buf=pat.sub('',buf)
-
- #multiple whitespace
- pat = re.compile(r"""\s+""", re.MULTILINE)
- buf=pat.sub(' ',buf)
-
- #clean up line ends
- pat = re.compile(r""";\s*""", re.MULTILINE)
- buf=pat.sub('\n',buf)
-
- #associate *, &, and [] with type instead of variable
- #pat=re.compile(r'\s+([*|&]+)\s*(\w+)')
- pat=re.compile(r' \s+ ([*|&]+) \s* (\w+)',re.VERBOSE)
- buf=pat.sub(r'\1 \2', buf)
- pat=re.compile(r'\s+ (\w+) \[ \s* \]',re.VERBOSE)
- buf=pat.sub(r'[] \1', buf)
-
- return buf
-
-proto_pat=re.compile(r"""
-(?P<ret>(\w|\&|\*)+\s*) # return type
-\s+ # skip whitespace
-(?P<func>\w+)\s*[(] # match the function name until the opening (
-(?P<args>.*?)[)] # group the function arguments
-""", re.IGNORECASE|re.VERBOSE)
-#"""
-arg_split_pat = re.compile("\s*,\s*")
-
-def define_func(buf,fp):
- buf=clean_func(buf)
- buf=string.split(buf,'\n')
- for p in buf:
- if len(p)==0: continue
- m=proto_pat.match(p)
- if m==None:
- if verbose:
- sys.stderr.write('No match:|%s|\n'%p)
- continue
- func = m.group('func')
- ret = m.group('ret')
- ret = string.replace(ret, 'const ', 'const-')
- args=m.group('args')
- args=arg_split_pat.split(args)
-
- for i in range(len(args)):
- args[i] = string.replace(args[i], 'const ', 'const-')
-
- write_func(fp, func, ret, args)
-
-get_type_pat = re.compile(r'(const-)?([A-Za-z0-9]+)\*?\s+')
-get_mod_pat = re.compile('([A-Z][a-z]+)([A-Za-z0-9]+)')
-
-def write_func(fp, name, ret, args):
- if len(args) >= 1:
- # methods must have at least one argument
- munged_name = string.replace(name, '_', '')
- m = get_type_pat.match(args[0])
- if m:
- obj = m.group(2)
- if munged_name[:len(obj)] == string.lower(obj):
- regex = string.join(map(lambda x: x+'_?',string.lower(obj)),'')
- mname = re.sub(regex, '', name)
- fp.write('(method ' + mname + '\n')
- m = get_mod_pat.match(obj)
- if m:
- fp.write(' (of-object ' + m.group(2) +
- ' (' + m.group(1) + '))\n')
- fp.write(' (c-name ' + name + ')\n')
- if ret != 'void':
- fp.write(' (return-type ' + ret + ')\n')
- else:
- fp.write(' (return-type none)\n')
- for arg in args[1:]:
- if arg == '...':
- fp.write(' (varargs t)\n')
- elif arg in ('void', 'void '):
- pass
- else:
- fp.write(' (parameter (type-and-name ' + arg + '))\n')
- fp.write(')\n\n')
- return
- # it is either a constructor or normal function
- # FIXME: put in constructor check
- fp.write('(function ' + name + '\n')
- # do in-module thingee
- fp.write(' (c-name ' + name + ')\n')
- if ret != 'void':
- fp.write(' (return-type ' + ret + ')\n')
- else:
- fp.write(' (return-type none)\n')
- for arg in args:
- if arg == '...':
- fp.write(' (varargs t)\n')
- elif arg == 'void' or arg == '':
- pass
- else:
- fp.write(' (parameter (type-and-name ' + arg + '))\n')
- fp.write(')\n\n')
-
-def write_def(input,output=None):
- fp = open(input)
- buf = fp.read()
- fp.close()
-
- if type(output) == types.StringType:
- fp = open(output,'w')
- elif type(output) == types.FileType:
- fp = output
- else:
- fp = sys.stdout
-
- fp.write('\n;; From %s\n\n' % input)
- buf = define_func(buf, fp)
- fp.write('\n')
-
-# ------------------ Glue code -----------------
-
-def make_gdk_defs():
- """ This is intended to be run only by the package maintainer!!! """
- p='/usr/local/src/gtk+-1.2.6/gdk/'
- gdk= [
- 'gdk.h',
- 'gdkrgb.h',
- #'gdktypes.h'
- ]
- fp=open('_gdk_func.defs','w')
- for h in gdk:
- write_def(p+h,fp)
- fp.close()
-
-verbose=0
-if __name__ == '__main__':
- import getopt
-
- opts, args = getopt.getopt(sys.argv[1:], 'v')
- for o, v in opts:
- if o=='-v': verbose=1
-
- if not args[0:1]:
- print 'Must specify at least one input file name'
- sys.exit(-1)
-
- # read all the object definitions in
- objdefs = []
- enums = []
- for filename in args:
- buf = open(filename).read()
- find_obj_defs(buf, objdefs)
- if len(filename) > 11 and filename[-11:] == 'gtkobject.h':
- objdefs.append(('GtkObject', None))
- find_enum_defs(buf, enums)
- objdefs = sort_obj_defs(objdefs)
- write_obj_defs(objdefs,None)
- write_enum_defs(enums,None)
-
- for filename in args:
- write_def(filename,None)
Index: win32/buildconf.js
===================================================================
RCS file: /repository/php-gtk/win32/buildconf.js,v
retrieving revision 1.9
diff -u -r1.9 buildconf.js
--- win32/buildconf.js 29 May 2007 12:40:22 -0000 1.9
+++ win32/buildconf.js 10 Aug 2008 17:52:58 -0000
@@ -112,6 +112,17 @@
continue;
}
+ /* We may need to generate the extensions files here */
+ c = FSO.BuildPath(fc.item(), "ext_data.php");
+ if (FSO.FileExists(c)) {
+ var WshShell = WScript.CreateObject("WScript.Shell");
+ if ( WshShell.Run("php generator/ext_gen.php " + c, 10, true) ) {
+ WScript.StdOut.WriteLine("\tError generating files");
+ WScript.Quit(1);
+ }
+ }
+
+ /* Now check if there's a config.w32, possibly created by */
c = FSO.BuildPath(fc.item(), "config.w32");
if (!FSO.FileExists(c)) {
@@ -120,7 +131,7 @@
} else {
- WScript.StdOut.WriteLine(" Available");
+ WScript.StdOut.WriteLine(" Available on Windows");
var dir_line = "configure_module_dirname = condense_path(FSO.GetParentFolderName('"
+ c.replace(new RegExp('(["\\\\])', "g"), '\\$1') + "'));\r\n";
| Navigate in group php.gtk.dev at sever news.php.net | |
| Previous | Next |
| © No Copyright You are free to use Anything |
Site Maintained by PHP Developer
Powered By PHP Consultants |