41 It
's a tool for automatically creating the basic framework for a PHP extension.
45 Very simple. First, change to the ext/ directory of the PHP sources. Then run
48 php ext_skel.php --ext extension_name
50 and everything you need will be placed in directory ext/extension_name.
52 If you don't need to
test the existence of any external
header files,
53 libraries or
functions in them, the extension is ready to be compiled in
PHP.
54 To compile the extension run the following:
58 {$file_prefix}configure
61 Don
't forget to run tests once the compilation is done:
63 {$make_prefix}make test
65 Alternatively, to compile extension in the PHP:
68 {$file_prefix}buildconf
69 {$file_prefix}configure --enable-extension_name
71 {$make_prefix}make test TESTS=ext/extension_name/tests
73 The definition of PHP_extension_NAME_VERSION will be present in the
74 php_extension_name.h and injected into the zend_extension_entry definition.
75 This is required by the PECL website for the version string conformity checks
78SOURCE AND HEADER FILE NAME
80 The ext_skel.php script generates 'extension_name.c
' and 'php_extension_name.h
'
81 as the main source and header files. Keep these names.
83 extension functions (User functions) must be named
85 extension_name_function()
87 When you need to expose extension functions to other extensions, expose
88 functions strictly needed by others. Exposed internal function must be named
90 php_extension_name_function()
92 See also CODING_STANDARDS.md.
96 php ext_skel.php --ext <name> [--experimental] [--author <name>]
97 [--dir <path>] [--std] [--onlyunix]
98 [--onlywindows] [--help]
100 --ext <name> The name of the extension defined as <name>
101 --experimental Passed if this extension is experimental, this creates
102 the EXPERIMENTAL file in the root of the extension
103 --author <name> Your name, this is used if --std is passed and for the
105 --dir <path> Path to the directory for where extension should be
106 created. Defaults to the directory of where this script
108 --std If passed, the standard header used in extensions that
109 is included in the core, will be used
110 --onlyunix Only generate configure scripts for Unix
111 --onlywindows Only generate configure scripts for Windows
120function task($label, $callback) {
121 printf('%
s...
', $label);
125 printf('done%
s', PHP_EOL);
129/* {{{ print_success */
130function print_success() {
133 if (PHP_OS_FAMILY != 'Windows
') {
141 printf('%1$sSuccess. The extension is
now ready to be compiled. To
do so, use the%
s', PHP_EOL);
142 printf('following steps:%1
$s%1
$s', PHP_EOL);
143 printf('cd %
s%
s%
s', $options['dir'], $options['ext'], PHP_EOL);
144 printf('phpize%
s', PHP_EOL);
145 printf('%sconfigure%
s', $file_prefix, PHP_EOL);
146 printf('%smake%2
$s%2
$s', $make_prefix, PHP_EOL);
147 printf('Don\
't forget to run tests once the compilation is done:%s',
PHP_EOL);
162 'experimental' =>
false,
166 for($i = 1; $i < $argc; ++$i)
170 if($val[0] !=
'-' || $val[1] !=
'-')
184 case 'onlywindows': {
188 case 'experimental': {
199 if (!isset($argv[$i + 1]) || ($argv[$i + 1][0] ==
'-' && $argv[$i + 1][1] ==
'-')) {
200 error(
'Argument "' . $val .
'" expects a value, none passed');
201 }
else if ($opt ==
'dir' && empty($argv[$i + 1])) {
209 error(
'Unsupported argument "' . $val .
'" passed');
215 error(
'No extension name passed, use "--ext <name>"');
217 error(
'Cannot pass both --onlyunix and --onlywindows');
219 error(
'The skeleton directory was not found');
224 error(
'Invalid extension name. Valid names start with a letter,'
225 .
' followed by any number of letters, numbers, or underscores.'
226 .
' Using only lower case letters is preferred.');
242 error(
'Unable to open file for reading: ' . $short_name);
248 if (
strpos($short_name,
'.c') !==
false ||
strpos($short_name,
'.h') !==
false) {
254 $credits =
$options[
'author'] . ($author_len && $author_len <= 60 ?
str_repeat(
' ', 60 - $author_len) :
'');
256 $header = <<<
"HEADER"
286 error(
'Unable to save contents to file: ' . $short_name);
307 foreach(
$files as $config_script) {
310 if (!
copy(
$options[
'skel'] . $config_script .
'.in', $new_config_script)) {
311 error(
'Unable to copy config script: ' . $config_script);
324 'skeleton.c' =>
$options[
'ext'] .
'.c',
325 'skeleton.stub.php' =>
$options[
'ext'] .
'.stub.php',
326 'php_skeleton.h' =>
'php_' .
$options[
'ext'] .
'.h',
327 'skeleton_arginfo.h' =>
$options[
'ext'] .
'_arginfo.h'
330 foreach (
$files as $src_file => $dst_file) {
332 error(
'Unable to copy source file: ' . $src_file);
350 foreach ($test_files as
$test) {
358 error(
'Unable to copy file: ' . $new_test);
368 error(
'This script is only suited for CLI');
379 error(
'The selected output directory does not exist');
381 error(
'There is already a folder named "' .
$options[
'ext'] .
'" in the output directory');
383 error(
'Unable to create extension directory in the output directory');
385 error(
'Unable to create the tests directory');
389 print(
'Creating EXPERIMENTAL... ');
392 error(
'Unable to create the EXPERIMENTAL file');
399 print(
'Creating CREDITS... ');
402 error(
'Unable to create the CREDITS file');
410task(
'Copying config scripts',
'copy_config_scripts');
411task(
'Copying sources',
'copy_sources');
412task(
'Copying tests',
'copy_tests');
file_private const char ext[]
str_repeat(string $string, int $times)
file_get_contents(string $filename, bool $use_include_path=false, $context=null, int $offset=0, ?int $length=null)
strtoupper(string $string)
printf(string $format, mixed ... $values)
strpos(string $haystack, string $needle, int $offset=0)
str_replace(array|string $search, array|string $replace, string|array $subject, &$count=null)
copy(string $from, string $to, $context=null)
file_put_contents(string $filename, mixed $data, int $flags=0, $context=null)
dir(string $directory, $context=null)
strtolower(string $string)
header(string $header, bool $replace=true, int $response_code=0)
glob(string $pattern, int $flags=0)
mkdir(string $directory, int $permissions=0777, bool $recursive=false, $context=null)
substr(string $string, int $offset, ?int $length=null)
const DIRECTORY_SEPARATOR
if(PHP_SAPI !='cli') if($argc< 1) $options
process_args($argv, $argc)
process_source_tags($file, $short_name)
sprintf("0x%X", $numelems)
date_default_timezone_set(string $timezoneId)
date(string $format, ?int $timestamp=null)
preg_match(string $pattern, string $subject, &$matches=null, int $flags=0, int $offset=0)
exit(string|int $status=0)