├── CREDITS ├── autoconf ├── php-executable.m4 └── pecl.m4 ├── tests └── skeleton_nop.phpt ├── config.w32 ├── .gitignore ├── config.m4 ├── Makefile.frag ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── .ci ├── appveyor.psm1 └── php-appveyor.psm1 ├── php_skeleton.h ├── skeleton.c ├── .appveyor.yml └── README.md /CREDITS: -------------------------------------------------------------------------------- 1 | NAME -------------------------------------------------------------------------------- /autoconf/php-executable.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl Generate run-php bash script 3 | dnl 4 | AC_CONFIG_COMMANDS_POST([ 5 | ln -s "$PHP_EXECUTABLE" build/php 6 | ]) 7 | -------------------------------------------------------------------------------- /tests/skeleton_nop.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | skeleton_nop basic test 3 | --FILE-- 4 | 8 | --EXPECT-- 9 | string(11) "Hello World" 10 | 11 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("skeleton", "enable skeleton", "no"); 5 | 6 | if (PHP_SKELETON != "no") { 7 | EXTENSION("skeleton", "skeleton.c"); 8 | AC_DEFINE('HAVE_SKELETON', 1 , 'whether skeleton is enabled'); 9 | PHP_INSTALL_HEADERS("ext/skeleton/", "php_skeleton.h"); 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | acinclude.m4 3 | aclocal.m4 4 | autom4te.cache/ 5 | build/ 6 | config.h 7 | config.log 8 | config.nice 9 | config.status 10 | config.guess 11 | config.h.in 12 | config.sub 13 | configure 14 | configure.in 15 | install-sh 16 | ltmain.sh 17 | missing 18 | mkinstalldirs 19 | run-tests.php 20 | Makefile 21 | Makefile.* 22 | !Makefile.frag 23 | libtool 24 | *~ 25 | modules/ 26 | .libs/ 27 | *.la 28 | *.lo 29 | php_test_results_*.txt 30 | tests/* 31 | !tests/*.phpt 32 | *~ 33 | configure.ac 34 | /cmake-* 35 | /run-php 36 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension skeleton 3 | 4 | sinclude(./autoconf/pecl.m4) 5 | sinclude(./autoconf/php-executable.m4) 6 | 7 | PECL_INIT([skeleton]) 8 | 9 | PHP_ARG_ENABLE(skeleton, whether to enable skeleton, [ --enable-skeleton Enable skeleton]) 10 | 11 | if test "$PHP_SKELETON" != "no"; then 12 | AC_DEFINE(HAVE_SKELETON, 1, [whether skeleton is enabled]) 13 | PHP_NEW_EXTENSION(skeleton, skeleton.c, $ext_shared) 14 | 15 | PHP_ADD_MAKEFILE_FRAGMENT 16 | PHP_INSTALL_HEADERS([ext/skeleton], [php_skeleton.h]) 17 | fi 18 | -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | clean-tests: 2 | rm -f tests/*.diff tests/*.exp tests/*.log tests/*.out tests/*.php tests/*.sh 3 | 4 | mrproper: clean clean-tests 5 | rm -rf autom4te.cache build modules vendor 6 | rm -f acinclude.m4 aclocal.m4 config.guess config.h config.h.in config.log config.nice config.status config.sub \ 7 | configure configure.ac install-sh libtool ltmain.sh Makefile Makefile.fragments Makefile.global \ 8 | Makefile.objects missing mkinstalldirs run-tests.php *~ 9 | 10 | info: $(all_targets) 11 | "$(PHP_EXECUTABLE)" -d "extension=$(phplibdir)/$(PHP_PECL_EXTENSION).so" --re "$(PHP_PECL_EXTENSION)" 12 | 13 | package.xml: php_$(PHP_PECL_EXTENSION).h 14 | $(PHP_EXECUTABLE) build-packagexml.php 15 | 16 | .PHONY: all clean install distclean test prof-gen prof-clean prof-use clean-tests mrproper info 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | EXTNAME: skeleton 3 | 4 | language: php 5 | php: 6 | - 7.2 7 | - 7.3 8 | - 7.4 9 | - 8.0 10 | 11 | matrix: 12 | allow_failures: 13 | - php: nightly 14 | 15 | branches: 16 | only: 17 | - master 18 | - travis 19 | - /^v\d+\.\d+\.\d+$/ 20 | 21 | install: 22 | - phpize 23 | - ./configure 24 | - make 25 | 26 | before_script: 27 | make install 28 | 29 | script: 30 | make test 31 | 32 | after_failure: 33 | - | 34 | for FILE in $(find tests -name '*.diff'); do 35 | echo $FILE 36 | cat FILE 37 | echo 38 | done 39 | 40 | before_deploy: 41 | - pecl package 42 | - export RELEASE_PACKAGE=$(ls "$EXTNAME"-*.tgz) 43 | 44 | deploy: 45 | provider: releases 46 | auth_token: 47 | secure: 48 | file: "$RELEASE_PACKAGE" 49 | skip_cleanup: true 50 | name: "$TRAVIS_TAG" 51 | prerelease: true 52 | on: 53 | tags: true 54 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(skeleton C) 3 | 4 | if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) 5 | message(SEND_ERROR "In-source builds are not allowed. They conflict with PHP's own Makefiles.") 6 | endif() 7 | 8 | add_compile_definitions(HAVE_SKELETON) 9 | 10 | set(SOURCE_FILES php_skeleton skeleton.c) 11 | 12 | execute_process ( 13 | COMMAND php-config --include-dir 14 | OUTPUT_VARIABLE PHP_SOURCE 15 | ) 16 | string(REGEX REPLACE "\n$" "" PHP_SOURCE "${PHP_SOURCE}") 17 | 18 | message("Using source directory: ${PHP_SOURCE}") 19 | 20 | include_directories(${PHP_SOURCE}) 21 | include_directories(${PHP_SOURCE}/main) 22 | include_directories(${PHP_SOURCE}/Zend) 23 | include_directories(${PHP_SOURCE}/TSRM) 24 | include_directories(${PROJECT_SOURCE_DIR}) 25 | 26 | add_custom_target(configure 27 | COMMAND phpize && ./configure 28 | DEPENDS ${SOURCE_FILES} 29 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) 30 | 31 | add_library(___ EXCLUDE_FROM_ALL ${SOURCE_FILES}) 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) YEAR NAME 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /.ci/appveyor.psm1: -------------------------------------------------------------------------------- 1 | Function InitializeBuildVars { 2 | switch ($Env:VC_VERSION) { 3 | 'vc14' { 4 | If (-not (Test-Path $Env:VS120COMNTOOLS)) { 5 | Throw'The VS120COMNTOOLS environment variable is not set. Check your VS installation' 6 | } 7 | 8 | $Env:VSDEVCMD = ($Env:VS120COMNTOOLS -replace '\\$', '') + '\VsDevCmd.bat' 9 | Break 10 | } 11 | 'vc15' { 12 | If (-not (Test-Path $Env:VS140COMNTOOLS)) { 13 | Throw'The VS140COMNTOOLS environment variable is not set. Check your VS installation' 14 | } 15 | 16 | $Env:VSDEVCMD = ($Env:VS140COMNTOOLS -replace '\\$', '') + '\VsDevCmd.bat' 17 | Break 18 | } 19 | default { 20 | $Env:VSDEVCMD = Get-ChildItem -Path "${Env:ProgramFiles(x86)}" -Filter "VsDevCmd.bat" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } 21 | 22 | If ("$Env:VSDEVCMD" -eq "") { 23 | Throw 'Unable to find VsDevCmd. Check your VS installation' 24 | } 25 | } 26 | } 27 | 28 | If ($Env:PLATFORM -eq 'x64') { 29 | $Env:ARCH = 'x86_amd64' 30 | } Else { 31 | $Env:ARCH = 'x86' 32 | } 33 | 34 | $Env:ENABLE_EXT = "--enable-{0}" -f ("${Env:EXTNAME}" -replace "_","-") 35 | 36 | $SearchInFolder = (Get-Item $Env:VSDEVCMD).Directory.Parent.Parent.FullName 37 | $Env:VCVARSALL = Get-ChildItem -Path "$SearchInFolder" -Filter "vcvarsall.bat" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } 38 | } 39 | 40 | Function InitializeReleaseVars { 41 | If ($Env:PLATFORM -eq 'x86') { 42 | If ($Env:BUILD_TYPE -Match "nts-Win32") { 43 | $Env:RELEASE_SUBFOLDER = "Release" 44 | } Else { 45 | $Env:RELEASE_SUBFOLDER = "Release_TS" 46 | } 47 | } Else { 48 | If ($Env:BUILD_TYPE -Match "nts-Win32") { 49 | $Env:RELEASE_SUBFOLDER = "${Env:PLATFORM}\Release" 50 | } Else { 51 | $Env:RELEASE_SUBFOLDER = "${Env:PLATFORM}\Release_TS" 52 | } 53 | } 54 | 55 | $Env:RELEASE_FOLDER = "${Env:APPVEYOR_BUILD_FOLDER}\${Env:RELEASE_SUBFOLDER}" 56 | $Env:RELEASE_ZIPBALL = "${Env:EXTNAME}_${Env:PLATFORM}_${Env:VC_VERSION}_php${Env:PHP_VERSION}_${Env:APPVEYOR_BUILD_VERSION}" 57 | } 58 | -------------------------------------------------------------------------------- /php_skeleton.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Skeleton PHP extension | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2018 NAME | 6 | +----------------------------------------------------------------------+ 7 | | Permission is hereby granted, free of charge, to any person | 8 | | obtaining a copy of this software and associated documentation files | 9 | | (the "Software"), to deal in the Software without restriction, | 10 | | including without limitation the rights to use, copy, modify, merge, | 11 | | publish, distribute, sublicense, and/or sell copies of the Software, | 12 | | and to permit persons to whom the Software is furnished to do so, | 13 | | subject to the following conditions: | 14 | | | 15 | | The above copyright notice and this permission notice shall be | 16 | | included in all copies or substantial portions of the Software. | 17 | | | 18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 19 | | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 20 | | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 21 | | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 22 | | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 23 | | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 24 | | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 25 | | SOFTWARE. | 26 | +----------------------------------------------------------------------+ 27 | | Author: NAME | 28 | +----------------------------------------------------------------------+ 29 | */ 30 | 31 | #ifndef PHP_SKELETON_H 32 | #define PHP_SKELETON_H 1 33 | 34 | #define PHP_SKELETON_VERSION "0.0.1-dev" 35 | #define PHP_SKELETON_EXTNAME "skeleton" 36 | 37 | #ifdef PHP_WIN32 38 | # define PHP_SKELETON_API __declspec(dllexport) 39 | #elif defined(__GNUC__) && __GNUC__ >= 4 40 | # define PHP_SKELETON_API __attribute__ ((visibility("default"))) 41 | #else 42 | # define PHP_SKELETON_API 43 | #endif 44 | 45 | /* Declare all functions and classes of the extension */ 46 | static PHP_FUNCTION(skeleton_nop); 47 | 48 | extern zend_module_entry skeleton_module_entry; 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /skeleton.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Skeleton PHP extension | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2018 NAME | 6 | +----------------------------------------------------------------------+ 7 | | Permission is hereby granted, free of charge, to any person | 8 | | obtaining a copy of this software and associated documentation files | 9 | | (the "Software"), to deal in the Software without restriction, | 10 | | including without limitation the rights to use, copy, modify, merge, | 11 | | publish, distribute, sublicense, and/or sell copies of the Software, | 12 | | and to permit persons to whom the Software is furnished to do so, | 13 | | subject to the following conditions: | 14 | | | 15 | | The above copyright notice and this permission notice shall be | 16 | | included in all copies or substantial portions of the Software. | 17 | | | 18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 19 | | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 20 | | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 21 | | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 22 | | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 23 | | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 24 | | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 25 | | SOFTWARE. | 26 | +----------------------------------------------------------------------+ 27 | | Author: NAME | 28 | +----------------------------------------------------------------------+ 29 | */ 30 | 31 | #ifdef HAVE_CONFIG_H 32 | # include "config.h" 33 | #endif 34 | 35 | #include "php.h" 36 | #include "php_ini.h" 37 | #include "php_skeleton.h" 38 | #include "zend_exceptions.h" 39 | #include "ext/standard/info.h" 40 | 41 | #if HAVE_SKELETON 42 | 43 | /* Argument info for each function, used for reflection */ 44 | ZEND_BEGIN_ARG_INFO_EX(arginfo_skeleton_nop, 0, 1, 0) 45 | ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 1) 46 | ZEND_END_ARG_INFO() 47 | 48 | /* Add all functions. (Keep PHP_FE_END as last element) */ 49 | static const zend_function_entry functions[] = { 50 | PHP_FE(skeleton_nop, arginfo_skeleton_nop) 51 | PHP_FE_END 52 | }; 53 | 54 | zend_module_entry skeleton_module_entry = { 55 | STANDARD_MODULE_HEADER, 56 | PHP_SKELETON_EXTNAME, 57 | functions, 58 | NULL, 59 | NULL, 60 | NULL, 61 | NULL, 62 | NULL, 63 | PHP_SKELETON_VERSION, 64 | STANDARD_MODULE_PROPERTIES 65 | }; 66 | 67 | #ifdef COMPILE_DL_SKELETON 68 | ZEND_GET_MODULE(skeleton) 69 | #endif 70 | 71 | /* Replace the example function with something better :) */ 72 | PHP_FUNCTION(skeleton_nop) 73 | { 74 | zend_string *str; 75 | 76 | ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) 77 | Z_PARAM_STR(str) 78 | ZEND_PARSE_PARAMETERS_END(); 79 | 80 | RETVAL_STR(str); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/sergeyklay/php-appveyor 2 | 3 | branches: 4 | only: 5 | - master 6 | - appveyor 7 | - w32 8 | - /^v\d+\.\d+\.\d+$/ 9 | 10 | environment: 11 | EXTNAME: skeleton 12 | 13 | matrix: 14 | - PHP_VERSION: 7.2 15 | BUILD_TYPE: Win32 16 | VC_VERSION: vc15 17 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 18 | 19 | - PHP_VERSION: 7.2 20 | BUILD_TYPE: nts-Win32 21 | VC_VERSION: vc15 22 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 23 | 24 | - PHP_VERSION: 7.3 25 | BUILD_TYPE: Win32 26 | VC_VERSION: vc15 27 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 28 | 29 | - PHP_VERSION: 7.3 30 | BUILD_TYPE: nts-Win32 31 | VC_VERSION: vc15 32 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 33 | 34 | - PHP_VERSION: 7.4 35 | BUILD_TYPE: Win32 36 | VC_VERSION: vc15 37 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 38 | 39 | - PHP_VERSION: 7.4 40 | BUILD_TYPE: nts-Win32 41 | VC_VERSION: vc15 42 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 43 | 44 | - PHP_VERSION: 8.0 45 | BUILD_TYPE: Win32 46 | VC_VERSION: vs16 47 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 48 | 49 | - PHP_VERSION: 8.0 50 | BUILD_TYPE: nts-Win32 51 | VC_VERSION: vs16 52 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 53 | 54 | PHP_SDK_VERSION: 2.2.0 55 | TEST_PHP_EXECUTABLE: C:\php\php.exe 56 | NO_INTERACTION: 1 57 | REPORT_EXIT_STATUS: 1 58 | 59 | matrix: 60 | fast_finish: true 61 | 62 | cache: 63 | - 'C:\Downloads -> .appveyor.yml' 64 | 65 | platform: 66 | - x86 67 | - x64 68 | 69 | init: 70 | - ps: $DebugPreference = 'SilentlyContinue' # Continue 71 | - ps: >- 72 | if ($env:APPVEYOR_REPO_TAG -eq "true") { 73 | Update-AppveyorBuild -Version "$($Env:APPVEYOR_REPO_TAG_NAME.TrimStart("v"))" 74 | } else { 75 | Update-AppveyorBuild -Version "${Env:APPVEYOR_REPO_BRANCH}-$($Env:APPVEYOR_REPO_COMMIT.Substring(0, 7))" 76 | } 77 | 78 | install: 79 | - ps: Import-Module .\.ci\php-appveyor.psm1 80 | 81 | - ps: InstallPhpSdk $Env:PHP_SDK_VERSION $Env:VC_VERSION $Env:PLATFORM 82 | - ps: InstallPhp $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM 83 | - ps: InstallPhpDevPack $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM 84 | 85 | build_script: 86 | - ps: Import-Module .\.ci\appveyor.psm1 87 | - ps: InitializeBuildVars 88 | - cmd: '"%VSDEVCMD%" -arch=%PLATFORM%' 89 | - cmd: '"%VCVARSALL%" %ARCH%' 90 | - cmd: C:\php-sdk\bin\phpsdk_setvars 91 | - cmd: C:\php-devpack\phpize 92 | - cmd: configure.bat --with-prefix=C:\php --with-php-build=C:\php-devpack --disable-all %ENABLE_EXT% 93 | - cmd: nmake 2> compile-errors.log 1> compile.log 94 | - ps: InitializeReleaseVars 95 | 96 | test_script: 97 | - cmd: nmake test 98 | 99 | after_build: 100 | - ps: Set-Location "${Env:APPVEYOR_BUILD_FOLDER}" 101 | - ps: >- 102 | PrepareReleasePackage ` 103 | -PhpVersion $Env:PHP_VERSION ` 104 | -BuildType $Env:BUILD_TYPE ` 105 | -Platform $Env:PLATFORM ` 106 | -ConverMdToHtml $true ` 107 | -ReleaseFiles "${Env:RELEASE_FOLDER}\php_${Env:EXTNAME}.dll",` 108 | "${Env:APPVEYOR_BUILD_FOLDER}\CREDITS",` 109 | "${Env:APPVEYOR_BUILD_FOLDER}\LICENSE" 110 | 111 | on_failure : 112 | - ps: >- 113 | If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log") { 114 | Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log" 115 | } 116 | 117 | If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log") { 118 | Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log" 119 | } 120 | 121 | Get-ChildItem "${Env:APPVEYOR_BUILD_FOLDER}\tests" -Recurse -Filter *.diff | Foreach-Object { 122 | [Environment]::NewLine 123 | Write-Output $_.FullName 124 | Get-Content -Path $_.FullName 125 | } 126 | 127 | artifacts: 128 | - path: '.\$(RELEASE_ZIPBALL).zip' 129 | name: '$(EXTNAME)' 130 | type: zip 131 | 132 | deploy: 133 | release: v$(appveyor_build_version) 134 | description: 'v$(appveyor_build_version)' 135 | provider: GitHub 136 | auth_token: 137 | secure: 138 | artifact: '$(RELEASE_ZIPBALL).zip' 139 | draft: false 140 | prerelease: true 141 | force_update: true 142 | on: 143 | branch: master 144 | APPVEYOR_REPO_TAG: true 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![improved PHP library](https://user-images.githubusercontent.com/100821/46372249-e5eb7500-c68a-11e8-801a-2ee57da3e5e3.png) 2 | 3 | # Skeleton PHP extension 4 | 5 | [![Build Status](https://travis-ci.org/improved-php-library/skeleton-php-ext.svg?branch=master)](https://travis-ci.org/improved-php-library/skeleton-php-ext) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/7rof1vr8mv4kam17/branch/master?svg=true)](https://ci.appveyor.com/project/jasny/skeleton-php-ext/branch/master) 7 | 8 | Skeleton project for PHP C-extension. 9 | 10 | > All other PHP extension skeletons that are available, including the one generated by PHP, are too minimalistic for 11 | > practical use. **Use this skeleton instead.** 12 | 13 | Includes; 14 | 15 | * Travis (Linux) and AppVeyor (Windows) configuration for continuous integration / platform tests. 16 | * Automatic deployment of package to GitHub releases 17 | * CMake config for editing in [CLion](https://www.jetbrains.com/clion/). (See [this article](https://dev.to/jasny/developing-a-php-extension-in-clion-3oo1)) 18 | * Supported for pecl dependencies. 19 | 20 | [> Create a new repository, using the skeleton php extension as template.](https://github.com/improved-php-library/skeleton-php-ext/generate) 21 | 22 | --- 23 | 24 | ## Requirements 25 | 26 | * PHP 7.x or 8.x 27 | 28 | ## Installation 29 | 30 | phpize 31 | ./configure 32 | make 33 | make test 34 | make install 35 | 36 | Add the following line to your `php.ini` 37 | 38 | extension=skeleton.so 39 | 40 | To try out the extension, you can run the following command 41 | 42 | php -a -d extension=modules/skeleton.so 43 | 44 | ## Functions 45 | 46 | ### skeleton_nop 47 | 48 | Return the input (which must be a string). 49 | 50 | string skeleton_nop(string input) 51 | 52 | --- 53 | 54 | ## Customize 55 | 56 | To customize this skeleton for your own extension (e.g. `foo_bar`), edit the following files; 57 | 58 | ### config.m4 and config.w32 59 | 60 | 1. Do a search/replace for `HAVE_SKELETON`, into `HAVE_FOO_BAR`. 61 | 2. Do a search/replace for the word `skeleton` into `foo_bar`. 62 | 3. If your extension name has name underscore, change the enable argument so it uses a dash. 63 | 64 | ``` 65 | PHP_ARG_ENABLE(foo_bar, whether to enable foo_bar, [ --enable-foo-bar Enable foo_bar]) 66 | ``` 67 | 68 | ``` 69 | ARG_ENABLE("foo-bar", "enable foo_bar", "no"); 70 | ``` 71 | 72 | ### php_skeleton.h 73 | 74 | 1. Rename the file using your extension name `php_foo_bar.h`. 75 | 2. Do a search/replace for `PHP_SKELETON_H` into `PHP_FOO_BAR_H`. 76 | 3. Do a search/replace for `HAVE_SKELETON` into `HAVE_FOO_BAR`. 77 | 4. Change the `zend_module_entry` from `skeleton_module_entry` to `foo_bar_module_entry` 78 | 79 | ### skeleton.c 80 | 81 | 1. Rename the file using your extension name `foo_bar.c`. 82 | 2. Do a search/replace for `PHP_SKELETON_H` into `PHP_FOO_BAR_H`. 83 | 3. Change `PHP_SKELETON_EXTNAME` to `PHP_FOO_BAR_EXTNAME` 84 | 4. Change the `zend_module_entry` from `skeleton_module_entry` to `foo_bar_module_entry` 85 | 5. In `ZEND_GET_MODULE` replace `skeleton` to `foo_bar`. 86 | 87 | ### .appveyor.yml and .travis.yml 88 | 89 | Change `skeleton` with your extension name for the `EXTNAME` env var. 90 | 91 | ``` 92 | env: 93 | EXTNAME: foo_bar 94 | ``` 95 | 96 | #### Deployment 97 | 98 | Both Travis and AppVeyor are configured to automatically deploy the generated packages to 99 | [GitHub releases](https://help.github.com/en/articles/creating-releases). In order to do so, you need to specify a 100 | GitHub API key. 101 | 102 | 1. Create a new [Personal access token](https://github.com/settings/tokens) on GitHub via developer settings with the 103 | `public_repo` privilege. 104 | 2. For AppVeyor, encrypt the token using the online [Encrypt Yaml](https://ci.appveyor.com/tools/encrypt) tool. Replace 105 | `` for the encrypted value in `.appveyor.yml`. 106 | 3. For Travis, install the Travis CLI (`gem install travis`) and use `travis encrypt` to encrypt the token. Replace 107 | `` for the encrypted value in `.travis.yml`. 108 | 109 | ### LICENSE 110 | 111 | Update the LICENSE with your (company) name and the year. 112 | 113 | _You may put your name in CREDITS, but don't add you e-mail address or the build may fail._ 114 | 115 | ### Replace example function 116 | 117 | Edit the header (`php_foo_bar.h`) and source (`foo_bar.c`) file, replace the declaration and implementation of 118 | `PHP_FUNCTION(skeleton_nop)` with your own function(s). Also update `zend_function_entry functions` and create 119 | the argument info for each function. 120 | 121 | ## PECL package 122 | 123 | If you wish to publish your extension to [pecl.php.net](PECL), you need your package to contain a valid `package.xml`. 124 | Create this via 125 | 126 | make package.xml 127 | 128 | You can enter the release notes manually or pipe it from a source like a git commit 129 | 130 | git log -1 --pretty=%B | make package.xml 131 | 132 | The version is determined base on the version defined in your main header file. Make sure this is correct prior to 133 | running `make package.xml`. 134 | 135 | When `package.xml` is first created, not all fields are filled out. Edit the file manually to fill this fields and 136 | verify it with 137 | 138 | pecl package-validate 139 | 140 | The make command will automatically update the package content entry and include all source and test files. Other files 141 | can be added manually. The script will only remove files that no longer exist. 142 | 143 | ## Getting started with PHP internals 144 | 145 | _There is a lot of information about the internals and writing PHP extensions online. Unfortunately but this information 146 | is often outdated, including the information found in the PHP manual._ 147 | 148 | * [PHP extension sample](https://github.com/ThomasWeinert/php-extension-sample) - Collection of sample features for a 149 | php extension 150 | * [phpinternals.net](https://phpinternals.net/) - An (accurate but incomplete) reference guide of PHP macros and 151 | functions 152 | * [PHP source code](https://github.com/php/php-src) - If all else fails, look up examples in the PHP source code 153 | 154 | -------------------------------------------------------------------------------- /autoconf/pecl.m4: -------------------------------------------------------------------------------- 1 | 2 | yes() { 3 | true 4 | } 5 | no() { 6 | false 7 | } 8 | dnl 9 | dnl PECL_INIT(name) 10 | dnl 11 | dnl Start configuring the PECL extension. 12 | dnl 13 | AC_DEFUN([PECL_INIT], [dnl 14 | m4_define([PECL_NAME],[$1])dnl 15 | ])dnl 16 | dnl 17 | dnl 18 | dnl PECL_VAR(name) 19 | dnl 20 | AC_DEFUN([PECL_VAR], [dnl 21 | AS_TR_CPP([PHP_]PECL_NAME[_$1])dnl 22 | ])dnl 23 | dnl 24 | dnl PECL_CACHE_VAR(name) 25 | dnl 26 | AC_DEFUN([PECL_CACHE_VAR], [dnl 27 | AS_TR_SH([PECL_cv_$1])dnl 28 | ])dnl 29 | dnl 30 | dnl PECL_SAVE_VAR(name) 31 | dnl 32 | AC_DEFUN([PECL_SAVE_VAR], [dnl 33 | AS_TR_SH([PECL_sv_$1])dnl 34 | ])dnl 35 | dnl 36 | dnl PECL_DEFINE(what, to[, desc]) 37 | dnl 38 | AC_DEFUN([PECL_DEFINE], [dnl 39 | AC_DEFINE(PECL_VAR([$1]), ifelse([$2],,1,[$2]), ifelse([$3],,[ ],[$3])) 40 | ])dnl 41 | dnl 42 | dnl PECL_DEFINE_UQ(what, to[, desc]) 43 | dnl 44 | AC_DEFUN([PECL_DEFINE_UQ], [dnl 45 | AC_DEFINE_UNQUOTED(PECL_VAR([$1]), [$2], ifelse([$3],,[ ],[$3])) 46 | ])dnl 47 | dnl 48 | dnl PECL_DEFINE_SH(what, to[, desc]) 49 | dnl 50 | AC_DEFUN([PECL_DEFINE_SH], [dnl 51 | PECL_VAR([$1])=$2 52 | PECL_DEFINE_UQ([$1], [$2], [$3]) 53 | ]) 54 | dnl 55 | dnl PECL_DEFINE_FN(fn) 56 | dnl 57 | AC_DEFUN([PECL_DEFINE_FN], [ 58 | AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [ ]) 59 | ]) 60 | dnl 61 | dnl PECL_SAVE_ENV(var, ns) 62 | dnl 63 | AC_DEFUN([PECL_SAVE_ENV], [ 64 | PECL_SAVE_VAR([$2_$1])=[$]$1 65 | ]) 66 | dnl 67 | dnl PECL_RESTORE_ENV(var, ns) 68 | dnl 69 | AC_DEFUN([PECL_RESTORE_ENV], [ 70 | $1=$PECL_SAVE_VAR([$2_$1]) 71 | ]) 72 | dnl 73 | dnl PECL_EVAL_LIBLINE(libline) 74 | dnl 75 | AC_DEFUN([PECL_EVAL_LIBLINE], [ 76 | PECL_SAVE_ENV(ext_shared, pecl) 77 | ext_shared=no 78 | PHP_EVAL_LIBLINE([$1], _pecl_eval_libline_dummy) 79 | PECL_RESTORE_ENV(ext_shared, pecl) 80 | ]) 81 | dnl 82 | dnl PECL_PROG_EGREP 83 | dnl 84 | dnl Checks for an egrep. Defines $EGREP. 85 | dnl 86 | AC_DEFUN([PECL_PROG_EGREP], [ 87 | ifdef([AC_PROG_EGREP], [ 88 | AC_PROG_EGREP 89 | ], [ 90 | AC_CHECK_PROG(EGREP, egrep, egrep) 91 | ]) 92 | ]) 93 | dnl 94 | dnl PECL_PROG_AWK 95 | dnl 96 | dnl Checks for an awk. Defines $AWK. 97 | dnl 98 | AC_DEFUN([PECL_PROG_AWK], [ 99 | ifdef([AC_PROG_AWK], [ 100 | AC_PROG_AWK 101 | ], [ 102 | AC_CHECK_PROG(AWK, awk, awk) 103 | ]) 104 | ]) 105 | dnl 106 | dnl PECL_PROG_SED 107 | dnl 108 | dnl Checks for the sed program. Defines $SED. 109 | dnl 110 | AC_DEFUN([PECL_PROG_SED], [ 111 | ifdef([AC_PROG_SED], [ 112 | AC_PROG_SED 113 | ], [ 114 | ifdef([LT_AC_PROG_SED], [ 115 | LT_AC_PROG_SED 116 | ], [ 117 | AC_CHECK_PROG(SED, sed, sed) 118 | ]) 119 | ]) 120 | ]) 121 | dnl 122 | dnl PECL_PROG_PKGCONFIG 123 | dnl 124 | dnl Checks for pkg-config program and defines $PKG_CONFIG (to false if not found). 125 | dnl 126 | AC_DEFUN([PECL_PROG_PKGCONFIG], [ 127 | if test -z "$PKG_CONFIG"; then 128 | AC_PATH_PROG([PKG_CONFIG], [pkg-config], [false]) 129 | fi 130 | ]) 131 | dnl 132 | dnl PECL_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]]) 133 | dnl 134 | dnl Check whether ext/$name is enabled in $PHP_EXECUTABLE (PECL build) 135 | dnl or if $PHP_ is defined to anything else than "no" (in-tree build). 136 | dnl Defines shell var PECL_VAR(HAVE_EXT_) to true or false. 137 | dnl 138 | AC_DEFUN([PECL_HAVE_PHP_EXT], [ 139 | AC_REQUIRE([PECL_PROG_EGREP])dnl 140 | AC_CACHE_CHECK([whether ext/$1 is enabled], PECL_CACHE_VAR([HAVE_EXT_$1]), [ 141 | PECL_CACHE_VAR([HAVE_EXT_$1])=no 142 | if test -x "$PHP_EXECUTABLE"; then 143 | if $PHP_EXECUTABLE -m | $EGREP -q ^$1\$; then 144 | PECL_CACHE_VAR([HAVE_EXT_$1])=yes 145 | fi 146 | elif test -n "$AS_TR_CPP([PHP_$1])" && test "$AS_TR_CPP([PHP_$1])" != "no"; then 147 | PECL_CACHE_VAR([HAVE_EXT_$1])=yes 148 | fi 149 | ]) 150 | if $PECL_CACHE_VAR([HAVE_EXT_$1]); then 151 | PECL_VAR([HAVE_EXT_$1])=true 152 | PECL_DEFINE([HAVE_EXT_$1]) 153 | $2 154 | else 155 | PECL_VAR([HAVE_EXT_$1])=false 156 | $3 157 | fi 158 | ]) 159 | dnl 160 | dnl PECL_HAVE_PHP_EXT_HEADER(ext[, header]) 161 | dnl 162 | dnl Check where to find a header for ext and add the found dir to $INCLUDES. 163 | dnl If header is not specified php_.h is assumed. 164 | dnl Defines shell var PHP__EXT__INCDIR to the found dir. 165 | dnl Defines PHP__HAVE_
to the found path. 166 | dnl 167 | AC_DEFUN([PECL_HAVE_PHP_EXT_HEADER], [dnl 168 | AC_REQUIRE([PECL_PROG_SED])dnl 169 | m4_define([EXT_HEADER], ifelse([$2],,php_$1.h,[$2]))dnl 170 | AC_CACHE_CHECK([for EXT_HEADER of ext/$1], PECL_CACHE_VAR([EXT_$1]_INCDIR), [ 171 | for i in $(printf "%s" "$INCLUDES" | $SED -e's/-I//g') $abs_srcdir ../$1; do 172 | if test -d $i; then 173 | for j in $i/EXT_HEADER $i/ext/$1/EXT_HEADER; do 174 | if test -f $j; then 175 | PECL_CACHE_VAR([EXT_$1]_INCDIR)=$(dirname "$j") 176 | break 177 | fi 178 | done 179 | fi 180 | done 181 | ]) 182 | PECL_VAR([EXT_$1]_INCDIR)=$PECL_CACHE_VAR([EXT_$1]_INCDIR) 183 | PHP_ADD_INCLUDE([$PECL_VAR([EXT_$1]_INCDIR)]) 184 | PECL_DEFINE_UQ([HAVE_]EXT_HEADER, "$PECL_VAR([EXT_$1]_INCDIR)/EXT_HEADER") 185 | ]) 186 | dnl 187 | dnl PECL_HAVE_CONST(header, const[, type=int[, code-if-yes[, code-if-mno]]]) 188 | dnl 189 | AC_DEFUN([PECL_HAVE_CONST], [dnl 190 | AC_REQUIRE([PECL_PROG_EGREP])dnl 191 | AC_CACHE_CHECK([for $2 in $1], PECL_CACHE_VAR([HAVE_$1_$2]), [ 192 | AC_TRY_COMPILE([ 193 | #include "$1" 194 | ], [ 195 | ]ifelse([$3],,int,[$3])[ _c = $2; 196 | (void) _c; 197 | ], [ 198 | PECL_CACHE_VAR([HAVE_$1_$2])=yes 199 | ], [ 200 | PECL_CACHE_VAR([HAVE_$1_$2])=no 201 | ]) 202 | ]) 203 | if $PECL_CACHE_VAR([HAVE_$1_$2]); then 204 | PECL_DEFINE([HAVE_$2]) 205 | $4 206 | else 207 | ifelse([$5],,:,[$5]) 208 | fi 209 | ]) 210 | dnl 211 | dnl _PECL_TR_VERSION(version) 212 | dnl 213 | AC_DEFUN([_PECL_TR_VERSION], [dnl 214 | AC_REQUIRE([PECL_PROG_AWK])dnl 215 | $(printf "%s" $1 | $AWK -F "[.]" '{print $[]1*1000000 + $[]2*10000 + $[]3*100 + $[]4}') 216 | ]) 217 | dnl 218 | dnl PECL_CHECKED_VERSION(name) 219 | dnl 220 | dnl Shell var name of an already checked version. 221 | dnl 222 | AC_DEFUN([PECL_CHECKED_VERSION], [PECL_VAR([$1][_VERSION])]) 223 | dnl 224 | dnl PECL_HAVE_VERSION(name, min-version[, code-if-yes[, code-if-not]]) 225 | dnl 226 | dnl Perform a min-version check while in an PECL_CHECK_* block. 227 | dnl Expands AC_MSG_ERROR when code-if-not is empty and the version check fails. 228 | dnl 229 | AC_DEFUN([PECL_HAVE_VERSION], [ 230 | aversion=_PECL_TR_VERSION([$PECL_CHECKED_VERSION([$1])]) 231 | mversion=_PECL_TR_VERSION([$2]) 232 | AC_MSG_CHECKING([whether $1 version $PECL_CHECKED_VERSION([$1]) >= $2]) 233 | if test -z "$aversion" || test "$aversion" -lt "$mversion"; then 234 | ifelse($4,,AC_MSG_ERROR([no]), [ 235 | AC_MSG_RESULT([no]) 236 | $4 237 | ]) 238 | else 239 | AC_MSG_RESULT([ok]) 240 | $3 241 | fi 242 | ]) 243 | dnl 244 | dnl PECL_CHECK_CUSTOM(name, path, header, lib, version) 245 | dnl 246 | AC_DEFUN([PECL_CHECK_CUSTOM], [ 247 | PECL_SAVE_ENV([CPPFLAGS], [$1]) 248 | PECL_SAVE_ENV([LDFLAGS], [$1]) 249 | PECL_SAVE_ENV([LIBS], [$1]) 250 | 251 | AC_MSG_CHECKING([for $1]) 252 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_prefix]), [ 253 | for path in $2 /usr/local /usr /opt; do 254 | if test "$path" = "" || test "$path" = "yes" || test "$path" = "no"; then 255 | continue 256 | elif test -f "$path/include/$3"; then 257 | PECL_CACHE_VAR([$1_prefix])="$path" 258 | break 259 | fi 260 | done 261 | ]) 262 | if test -n "$PECL_CACHE_VAR([$1_prefix])"; then 263 | CPPFLAGS="-I$PECL_CACHE_VAR([$1_prefix])/include" 264 | LDFLAGS="-L$PECL_CACHE_VAR([$1_prefix])/$PHP_LIBDIR" 265 | LIBS="-l$4" 266 | PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) 267 | 268 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_version]), [ 269 | pushd $PECL_CACHE_VAR([$1_prefix]) >/dev/null 270 | PECL_CACHE_VAR([$1_version])=$5 271 | popd >/dev/null 272 | ]) 273 | PECL_CHECKED_VERSION([$1])=$PECL_CACHE_VAR([$1_version]) 274 | 275 | if test -n "$PECL_CHECKED_VERSION([$1])"; then 276 | PECL_VAR([HAVE_$1])=true 277 | PECL_DEFINE([HAVE_$1]) 278 | PECL_DEFINE_UQ($1[_VERSION], "$PECL_CHECKED_VERSION([$1])") 279 | else 280 | PECL_VAR([HAVE_$1])=false 281 | fi 282 | else 283 | PECL_VAR([HAVE_$1])=false 284 | fi 285 | AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) 286 | ]) 287 | dnl 288 | dnl PECL_CHECK_CONFIG(name, prog-config, version-flag, cppflags-flag, ldflags-flag, libs-flag) 289 | dnl 290 | AC_DEFUN([PECL_CHECK_CONFIG], [ 291 | PECL_SAVE_ENV([CPPFLAGS], [$1]) 292 | PECL_SAVE_ENV([LDFLAGS], [$1]) 293 | PECL_SAVE_ENV([LIBS], [$1]) 294 | 295 | 296 | AC_MSG_CHECKING([for $1]) 297 | ifelse($2, [$PKG_CONFIG $1], [ 298 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_exists]), [ 299 | if $($2 --exists); then 300 | PECL_CACHE_VAR([$1_exists])=yes 301 | else 302 | PECL_CACHE_VAR([$1_exists])=no 303 | fi 304 | ]) 305 | if $PECL_CACHE_VAR([$1_exists]); then 306 | ]) 307 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_version]), [ 308 | PECL_CACHE_VAR([$1_version])=$($2 $3) 309 | ]) 310 | PECL_CHECKED_VERSION([$1])=$PECL_CACHE_VAR([$1_version]) 311 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_cppflags]), [ 312 | PECL_CACHE_VAR([$1_cppflags])=$($2 $4) 313 | ]) 314 | CPPFLAGS=$PECL_CACHE_VAR([$1_cppflags]) 315 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_ldflags]), [ 316 | PECL_CACHE_VAR([$1_ldflags])=$($2 $5) 317 | ]) 318 | LDFLAGS=$PECL_CACHE_VAR([$1_ldflags]) 319 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_libs]), [ 320 | PECL_CACHE_VAR([$1_libs])=$($2 $6) 321 | ]) 322 | LIBS=$PECL_CACHE_VAR([$1_libs]) 323 | PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) 324 | ifelse($2, [$PKG_CONFIG $1], [ 325 | fi 326 | ]) 327 | 328 | if test -n "$PECL_CHECKED_VERSION([$1])"; then 329 | PECL_VAR([HAVE_$1])=true 330 | PECL_DEFINE([HAVE_$1]) 331 | PECL_DEFINE_UQ([$1_VERSION], "$PECL_CHECKED_VERSION([$1])") 332 | else 333 | PECL_VAR([HAVE_$1])=false 334 | fi 335 | 336 | AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) 337 | ]) 338 | dnl 339 | dnl PECL_CHECK_PKGCONFIG(pkg[, additional-pkg-config-path]) 340 | dnl 341 | AC_DEFUN([PECL_CHECK_PKGCONFIG], [dnl 342 | AC_REQUIRE([PECL_PROG_PKGCONFIG])dnl 343 | ifelse($2,,, [ 344 | PECL_SAVE_VAR(pkgconfig_path)="$PKG_CONFIG_PATH" 345 | if test -d "$2"; then 346 | export PKG_CONFIG_PATH="$2/lib/pkgconfig:$PKG_CONFIG_PATH" 347 | fi 348 | ]) 349 | PECL_CHECK_CONFIG([$1], [$PKG_CONFIG $1], [--modversion], [--cflags-only-I], [--libs-only-L], [--libs-only-l]) 350 | ifelse($2,,, [ 351 | PKG_CONFIG_PATH="$PECL_SAVE_VAR(pkgconfig_path)" 352 | ]) 353 | ]) 354 | dnl 355 | dnl PECL_CHECK_DONE(name, success[, incline, libline]) 356 | dnl 357 | AC_DEFUN([PECL_CHECK_DONE], [ 358 | if $2; then 359 | incline=$CPPFLAGS 360 | libline="$LDFLAGS $LIBS" 361 | PECL_DEFINE([HAVE_$1]) 362 | else 363 | incline=$3 364 | libline=$4 365 | fi 366 | 367 | PECL_RESTORE_ENV([CPPFLAGS], [$1]) 368 | PECL_RESTORE_ENV([LDFLAGS], [$1]) 369 | PECL_RESTORE_ENV([LIBS], [$1]) 370 | 371 | PHP_EVAL_INCLINE([$incline]) 372 | PHP_EVAL_LIBLINE([$libline], AS_TR_CPP(PECL_NAME[_SHARED_LIBADD])) 373 | ]) 374 | 375 | dnl 376 | dnl PECL_CHECK_CA([additional-ca-paths,[ additional-ca-bundles]]) 377 | dnl 378 | AC_DEFUN([PECL_CHECK_CA], [ 379 | AC_CACHE_CHECK([for default CA path], PECL_CACHE_VAR([CAPATH]), [ 380 | PECL_VAR([CAPATH])= 381 | for ca_path in $1 \ 382 | /etc/ssl/certs \ 383 | /System/Library/OpenSSL 384 | do 385 | # check if it's actually a hashed directory 386 | if test -d "$ca_path" && ls "$ca_path"/@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@.0 >/dev/null 2>&1; then 387 | PECL_CACHE_VAR([CAPATH])=$ca_path 388 | break 389 | fi 390 | done 391 | ]) 392 | if test -n "$PECL_CACHE_VAR([CAPATH])"; then 393 | PECL_DEFINE_SH([CAPATH], "$PECL_CACHE_VAR([CAPATH])") 394 | fi 395 | 396 | AC_CACHE_CHECK([for default CA info], PECL_CACHE_VAR([CAINFO]), [ 397 | for ca_info in $2 \ 398 | /etc/ssl/{cert,ca-bundle}.pem \ 399 | /{etc,usr/share}/ssl/certs/ca-{bundle,ceritifcates}.crt \ 400 | /etc/{pki/ca-trust,ca-certificates}/extracted/pem/tls-ca-bundle.pem \ 401 | /etc/pki/tls/certs/ca-bundle{,.trust}.crt \ 402 | /usr/local/etc/{,open}ssl/cert.pem \ 403 | /usr/local/share/certs/ca-root-nss.crt \ 404 | /{usr,usr/local,opt}/local/share/curl/curl-ca-bundle.crt 405 | do 406 | if test -f "$ca_info"; then 407 | PECL_CACHE_VAR([CAINFO])=$ca_info 408 | break 409 | fi 410 | done 411 | ]) 412 | if test -n "$PECL_CACHE_VAR([CAINFO])"; then 413 | PECL_DEFINE_SH([CAINFO], "$PECL_CACHE_VAR([CAINFO])") 414 | fi 415 | ]) 416 | -------------------------------------------------------------------------------- /.ci/php-appveyor.psm1: -------------------------------------------------------------------------------- 1 | # This file is part of the php-appveyor.psm1 project. 2 | # 3 | # (c) Serghei Iakovlev 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE file that was distributed with this source code. 7 | 8 | # $ErrorActionPreference = "Stop" 9 | 10 | function InstallPhpSdk { 11 | param ( 12 | [Parameter(Mandatory=$true)] [System.String] $Version, 13 | [Parameter(Mandatory=$true)] [System.String] $VC, 14 | [Parameter(Mandatory=$true)] [System.String] $Platform, 15 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php-sdk" 16 | ) 17 | 18 | Write-Debug "Install PHP SDK binary tools: ${Version}" 19 | SetupPrerequisites 20 | 21 | $FileName = "php-sdk-${Version}" 22 | $RemoteUrl = "https://github.com/Microsoft/php-sdk-binary-tools/archive/${FileName}.zip" 23 | $Archive = "C:\Downloads\${FileName}.zip" 24 | 25 | if (-not (Test-Path "${InstallPath}\bin\php\php.exe")) { 26 | if (-not (Test-Path $Archive)) { 27 | DownloadFile -RemoteUrl $RemoteUrl -Destination $Archive 28 | } 29 | 30 | $UnzipPath = "${Env:Temp}\php-sdk-binary-tools-${FileName}" 31 | if (-not (Test-Path "${UnzipPath}")) { 32 | Expand-Item7zip -Archive $Archive -Destination $Env:Temp 33 | } 34 | 35 | Move-Item -Path $UnzipPath -Destination $InstallPath 36 | } 37 | 38 | EnsureRequiredDirectoriesPresent ` 39 | -Directories bin,lib,include ` 40 | -Prefix "${InstallPath}\phpdev\${VC}\${Platform}" 41 | } 42 | 43 | function InstallPhp { 44 | param ( 45 | [Parameter(Mandatory=$true)] [System.String] $Version, 46 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 47 | [Parameter(Mandatory=$true)] [System.String] $VC, 48 | [Parameter(Mandatory=$true)] [System.String] $Platform, 49 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php" 50 | ) 51 | 52 | SetupPrerequisites 53 | $FullVersion = SetupPhpVersionString -Pattern $Version 54 | 55 | Write-Debug "Install PHP v${FullVersion}" 56 | 57 | $ReleasesPart = "releases" 58 | if ([System.Convert]::ToDecimal($Version) -lt 7.1) { 59 | $ReleasesPart = "releases/archives" 60 | } 61 | 62 | $RemoteUrl = "http://windows.php.net/downloads/{0}/php-{1}-{2}-{3}-{4}.zip" -f 63 | $ReleasesPart, $FullVersion, $BuildType, $VC, $Platform 64 | 65 | $Archive = "C:\Downloads\php-${FullVersion}-${BuildType}-${VC}-${Platform}.zip" 66 | 67 | if (-not (Test-Path "${InstallPath}\php.exe")) { 68 | if (-not (Test-Path $Archive)) { 69 | DownloadFile $RemoteUrl $Archive 70 | } 71 | 72 | Expand-Item7zip $Archive $InstallPath 73 | } 74 | 75 | if (-not (Test-Path "${InstallPath}\php.ini")) { 76 | Copy-Item "${InstallPath}\php.ini-development" "${InstallPath}\php.ini" 77 | } 78 | } 79 | 80 | function InstallPhpDevPack { 81 | param ( 82 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 83 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 84 | [Parameter(Mandatory=$true)] [System.String] $VC, 85 | [Parameter(Mandatory=$true)] [System.String] $Platform, 86 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php-devpack" 87 | ) 88 | 89 | SetupPrerequisites 90 | $Version = SetupPhpVersionString -Pattern $PhpVersion 91 | 92 | Write-Debug "Install PHP Dev for PHP v${Version}" 93 | 94 | $ReleasesPart = "releases" 95 | if ([System.Convert]::ToDecimal($PhpVersion) -lt 7.1) { 96 | $ReleasesPart = "releases/archives" 97 | } 98 | 99 | $RemoteUrl = "http://windows.php.net/downloads/{0}/php-devel-pack-{1}-{2}-{3}-{4}.zip" -f 100 | $ReleasesPart, $Version, $BuildType, $VC, $Platform 101 | 102 | $Archive = "C:\Downloads\php-devel-pack-${Version}-${BuildType}-${VC}-${Platform}.zip" 103 | 104 | if (-not (Test-Path "${InstallPath}\phpize.bat")) { 105 | if (-not (Test-Path $Archive)) { 106 | DownloadFile $RemoteUrl $Archive 107 | } 108 | 109 | $UnzipPath = "${Env:Temp}\php-${Version}-devel-${VC}-${Platform}" 110 | if (-not (Test-Path "${UnzipPath}\phpize.bat")) { 111 | Expand-Item7zip $Archive $Env:Temp 112 | } 113 | 114 | if (Test-Path "${InstallPath}") { 115 | Move-Item -Path "${UnzipPath}\*" -Destination $InstallPath 116 | } else { 117 | Move-Item -Path $UnzipPath -Destination $InstallPath 118 | } 119 | } 120 | } 121 | 122 | function InstallPeclExtension { 123 | param ( 124 | [Parameter(Mandatory=$true)] [System.String] $Name, 125 | [Parameter(Mandatory=$true)] [System.String] $Version, 126 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 127 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 128 | [Parameter(Mandatory=$true)] [System.String] $VC, 129 | [Parameter(Mandatory=$true)] [System.String] $Platform, 130 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php\ext", 131 | [Parameter(Mandatory=$false)] [System.Boolean] $Headers = $false, 132 | [Parameter(Mandatory=$false)] [System.Boolean] $Enable = $false 133 | ) 134 | 135 | SetupPrerequisites 136 | 137 | $BaseUri = "https://windows.php.net/downloads/pecl/releases/${Name}/${Version}" 138 | $LocalPart = "php_${Name}-${Version}-${PhpVersion}" 139 | 140 | if ($BuildType -Match "nts-Win32") { 141 | $TS = "nts" 142 | } else { 143 | $TS = "ts" 144 | } 145 | 146 | $RemoteUrl = "${BaseUri}/${LocalPart}-${TS}-${VC}-${Platform}.zip" 147 | $DestinationPath = "C:\Downloads\${LocalPart}-${TS}-${VC}-${Platform}.zip" 148 | 149 | if (-not (Test-Path "${InstallPath}\php_${Name}.dll")) { 150 | if (-not (Test-Path $DestinationPath)) { 151 | DownloadFile $RemoteUrl $DestinationPath 152 | } 153 | 154 | Expand-Item7zip $DestinationPath $InstallPath 155 | } 156 | 157 | if ($Headers) { 158 | InstallPeclHeaders -Name $Name -Version $Version 159 | } 160 | 161 | if ($Enable) { 162 | EnablePhpExtension -Name $Name 163 | } 164 | } 165 | 166 | Function InstallPeclHeaders { 167 | Param( 168 | [Parameter(Mandatory=$true)] [System.String] $Name, 169 | [Parameter(Mandatory=$true)] [System.String] $Version, 170 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = 'C:\php-devpack\include\ext\' 171 | ) 172 | 173 | $RemoteUrl = "https://pecl.php.net/get/${Name}-${Version}.tgz" 174 | $DownloadFile = "C:\Downloads\${Name}-${Version}.tgz" 175 | 176 | If (-not [System.IO.File]::Exists($DownloadFile)) { 177 | DownloadFile $RemoteUrl $DownloadFile 178 | } 179 | 180 | Ensure7ZipIsInstalled 181 | 182 | Expand-Item7zip $DownloadFile "${Env:Temp}" 183 | 184 | Write-Debug "Copy header files to ${InstallPath}\${Name}" 185 | 186 | New-Item -Path "${InstallPath}" -Name "${Name}" -ItemType "directory" | Out-Null 187 | Copy-Item "${Env:Temp}\${Name}-${Version}\*.h" -Destination "${InstallPath}\${Name}" -Recurse 188 | } 189 | 190 | function InstallComposer { 191 | param ( 192 | [Parameter(Mandatory=$false)] [System.String] $PhpInstallPath = 'C:\php', 193 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = '.' 194 | ) 195 | 196 | $InstallPath = Resolve-Path $InstallPath 197 | 198 | $ComposerBatch = "${InstallPath}\composer.bat" 199 | $ComposerPhar = "${InstallPath}\composer.phar" 200 | 201 | if (-not (Test-Path -Path $ComposerPhar)) { 202 | DownloadFile "https://getcomposer.org/composer.phar" "${ComposerPhar}" 203 | 204 | Write-Output '@echo off' | Out-File -Encoding "ASCII" $ComposerBatch 205 | Write-Output "${PhpInstallPath}\php.exe `"${ComposerPhar}`" %*" | Out-File -Encoding "ASCII" -Append $ComposerBatch 206 | } 207 | } 208 | 209 | function EnablePhpExtension { 210 | param ( 211 | [Parameter(Mandatory=$true)] [System.String] $Name, 212 | [Parameter(Mandatory=$false)] [System.String] $PhpInstallPath = 'C:\php', 213 | [Parameter(Mandatory=$false)] [System.String] $ExtPath = 'C:\php\ext', 214 | [Parameter(Mandatory=$false)] [System.String] $PrintableName = '' 215 | ) 216 | 217 | $FullyQualifiedExtensionPath = "${ExtPath}\php_${Name}.dll" 218 | 219 | $IniFile = "${PhpInstallPath}\php.ini" 220 | $PhpExe = "${PhpInstallPath}\php.exe" 221 | 222 | if (-not (Test-Path $IniFile)) { 223 | throw "Unable to locate ${IniFile}" 224 | } 225 | 226 | if (-not (Test-Path "${ExtPath}")) { 227 | throw "Unable to locate ${ExtPath} direcory" 228 | } 229 | 230 | Write-Debug "Add `"extension = ${FullyQualifiedExtensionPath}`" to the ${IniFile}" 231 | Write-Output "extension = ${FullyQualifiedExtensionPath}" | Out-File -Encoding "ASCII" -Append $IniFile 232 | 233 | if (Test-Path -Path "${PhpExe}") { 234 | if ($PrintableName) { 235 | Write-Debug "Minimal load test using command: ${PhpExe} --ri `"${PrintableName}`"" 236 | $Result = (& "${PhpExe}" --ri "${PrintableName}") 237 | } else { 238 | Write-Debug "Minimal load test using command: ${PhpExe} --ri ${Name}" 239 | $Result = (& "${PhpExe}" --ri $Name) 240 | } 241 | 242 | $ExitCode = $LASTEXITCODE 243 | if ($ExitCode -ne 0) { 244 | throw "An error occurred while enabling ${Name} at ${IniFile}. ${Result}" 245 | } 246 | } 247 | } 248 | 249 | function TuneUpPhp { 250 | param ( 251 | [Parameter(Mandatory=$false)] [System.String] $MemoryLimit = '256M', 252 | [Parameter(Mandatory=$false)] [System.String[]] $DefaultExtensions = @(), 253 | [Parameter(Mandatory=$false)] [System.String] $IniFile = 'C:\php\php.ini', 254 | [Parameter(Mandatory=$false)] [System.String] $ExtPath = 'C:\php\ext' 255 | ) 256 | 257 | Write-Debug "Tune up PHP using file `"${IniFile}`"" 258 | 259 | if (-not (Test-Path $IniFile)) { 260 | throw "Unable to locate ${IniFile} file" 261 | } 262 | 263 | if (-not (Test-Path $ExtPath)) { 264 | throw "Unable to locate ${ExtPath} direcory" 265 | } 266 | 267 | Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile 268 | 269 | Write-Output "extension_dir = ${ExtPath}" | Out-File -Encoding "ASCII" -Append $IniFile 270 | Write-Output "memory_limit = ${MemoryLimit}" | Out-File -Encoding "ASCII" -Append $IniFile 271 | 272 | if ($DefaultExtensions.count -gt 0) { 273 | Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile 274 | 275 | foreach ($Ext in $DefaultExtensions) { 276 | Write-Output "extension = php_${Ext}.dll" | Out-File -Encoding "ASCII" -Append $IniFile 277 | } 278 | } 279 | } 280 | 281 | function PrepareReleaseNote { 282 | param ( 283 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 284 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 285 | [Parameter(Mandatory=$true)] [System.String] $Platform, 286 | [Parameter(Mandatory=$false)] [System.String] $ReleaseFile, 287 | [Parameter(Mandatory=$false)] [System.String] $ReleaseDirectory, 288 | [Parameter(Mandatory=$false)] [System.String] $BasePath 289 | ) 290 | 291 | $Destination = "${BasePath}\${ReleaseDirectory}" 292 | 293 | if (-not (Test-Path $Destination)) { 294 | New-Item -ItemType Directory -Force -Path "${Destination}" | Out-Null 295 | } 296 | 297 | $ReleaseFile = "${Destination}\${ReleaseFile}" 298 | $ReleaseDate = Get-Date -Format o 299 | 300 | $Image = $Env:APPVEYOR_BUILD_WORKER_IMAGE 301 | $Version = $Env:APPVEYOR_BUILD_VERSION 302 | $Commit = $Env:APPVEYOR_REPO_COMMIT 303 | $CommitDate = $Env:APPVEYOR_REPO_COMMIT_TIMESTAMP 304 | 305 | Write-Output "Release date: ${ReleaseDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 306 | Write-Output "Release version: ${Version}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 307 | Write-Output "Git commit: ${Commit}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 308 | Write-Output "Commit date: ${CommitDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 309 | Write-Output "Build type: ${BuildType}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 310 | Write-Output "Platform: ${Platform}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 311 | Write-Output "Target PHP version: ${PhpVersion}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 312 | Write-Output "Build worker image: ${Image}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 313 | } 314 | 315 | function PrepareReleasePackage { 316 | param ( 317 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 318 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 319 | [Parameter(Mandatory=$true)] [System.String] $Platform, 320 | [Parameter(Mandatory=$false)] [System.String] $ZipballName = '', 321 | [Parameter(Mandatory=$false)] [System.String[]] $ReleaseFiles = @(), 322 | [Parameter(Mandatory=$false)] [System.String] $ReleaseFile = 'RELEASE.txt', 323 | [Parameter(Mandatory=$false)] [System.Boolean] $ConverMdToHtml = $false, 324 | [Parameter(Mandatory=$false)] [System.String] $BasePath = '.' 325 | ) 326 | 327 | $BasePath = Resolve-Path $BasePath 328 | $ReleaseDirectory = "${Env:APPVEYOR_PROJECT_NAME}-${Env:APPVEYOR_BUILD_ID}-${Env:APPVEYOR_JOB_ID}-${Env:APPVEYOR_JOB_NUMBER}" 329 | 330 | PrepareReleaseNote ` 331 | -PhpVersion $PhpVersion ` 332 | -BuildType $BuildType ` 333 | -Platform $Platform ` 334 | -ReleaseFile $ReleaseFile ` 335 | -ReleaseDirectory $ReleaseDirectory ` 336 | -BasePath $BasePath 337 | 338 | $ReleaseDestination = "${BasePath}\${ReleaseDirectory}" 339 | 340 | $CurrentPath = Resolve-Path '.' 341 | 342 | if ($ConverMdToHtml) { 343 | InstallReleaseDependencies 344 | FormatReleaseFiles -ReleaseDirectory $ReleaseDirectory 345 | } 346 | 347 | if ($ReleaseFiles.count -gt 0) { 348 | foreach ($File in $ReleaseFiles) { 349 | Copy-Item "${File}" "${ReleaseDestination}" 350 | Write-Debug "Copy ${File} to ${ReleaseDestination}" 351 | } 352 | } 353 | 354 | if (!$ZipballName) { 355 | if (!$Env:RELEASE_ZIPBALL) { 356 | throw "Required parameter `"ZipballName`" is missing" 357 | } else { 358 | $ZipballName = $Env:RELEASE_ZIPBALL; 359 | } 360 | } 361 | 362 | Ensure7ZipIsInstalled 363 | 364 | Set-Location "${ReleaseDestination}" 365 | $Output = (& 7z a "${ZipballName}.zip" *) 366 | $ExitCode = $LASTEXITCODE 367 | 368 | $DirectoryContents = Get-ChildItem -Path "${ReleaseDestination}" 369 | Write-Debug ($DirectoryContents | Out-String) 370 | 371 | if ($ExitCode -ne 0) { 372 | Set-Location "${CurrentPath}" 373 | throw "An error occurred while creating release zippbal: `"${ZipballName}`". ${Output}" 374 | } 375 | 376 | Move-Item "${ZipballName}.zip" -Destination "${BasePath}" 377 | Set-Location "${CurrentPath}" 378 | } 379 | 380 | function FormatReleaseFiles { 381 | param ( 382 | [Parameter(Mandatory=$true)] [System.String] $ReleaseDirectory, 383 | [Parameter(Mandatory=$false)] [System.String] $BasePath = '.' 384 | ) 385 | 386 | EnsurePandocIsInstalled 387 | 388 | $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName 389 | 390 | $BasePath = Resolve-Path $BasePath 391 | Set-Location "${BasePath}" 392 | 393 | Get-ChildItem (Get-Item -Path ".\" -Verbose).FullName *.md | 394 | ForEach-Object{ 395 | $BaseName = $_.BaseName 396 | pandoc -f markdown -t html5 "${BaseName}.md" > "${BasePath}\${ReleaseDirectory}\${BaseName}.html" 397 | } 398 | 399 | Set-Location "${CurrentPath}" 400 | } 401 | 402 | function SetupPhpVersionString { 403 | param ( 404 | [Parameter(Mandatory=$true)] [String] $Pattern 405 | ) 406 | 407 | $RemoteUrl = 'http://windows.php.net/downloads/releases/sha256sum.txt' 408 | $Destination = "${Env:Temp}\php-sha256sum.txt" 409 | 410 | if (-not (Test-Path $Destination)) { 411 | DownloadFile $RemoteUrl $Destination 412 | } 413 | 414 | $VersionString = Get-Content $Destination | Where-Object { 415 | $_ -match "php-($Pattern\.\d+)-src" 416 | } | ForEach-Object { $matches[1] } 417 | 418 | if ($VersionString -NotMatch '\d+\.\d+\.\d+' -or $null -eq $VersionString) { 419 | throw "Unable to obtain PHP version string using pattern 'php-($Pattern\.\d+)-src'" 420 | } 421 | 422 | Write-Output $VersionString.Split(' ')[-1] 423 | } 424 | 425 | function SetupPrerequisites { 426 | Ensure7ZipIsInstalled 427 | EnsureRequiredDirectoriesPresent -Directories C:\Downloads 428 | } 429 | 430 | function Ensure7ZipIsInstalled { 431 | if (-not (Get-Command "7z" -ErrorAction SilentlyContinue)) { 432 | $7zipInstallationDirectory = "${Env:ProgramFiles}\7-Zip" 433 | 434 | if (-not (Test-Path "${7zipInstallationDirectory}")) { 435 | throw "The 7-zip file archiver is needed to use this module" 436 | } 437 | 438 | $Env:Path += ";$7zipInstallationDirectory" 439 | } 440 | } 441 | 442 | function InstallReleaseDependencies { 443 | EnsureChocolateyIsInstalled 444 | $Output = (choco install -y --no-progress pandoc) 445 | $ExitCode = $LASTEXITCODE 446 | 447 | if ($ExitCode -ne 0) { 448 | throw "An error occurred while installing pandoc. ${Output}" 449 | } 450 | } 451 | 452 | function EnsureChocolateyIsInstalled { 453 | if (-not (Get-Command "choco" -ErrorAction SilentlyContinue)) { 454 | $ChocolateyInstallationDirectory = "${Env:ChocolateyInstall}\bin" 455 | 456 | if (-not (Test-Path "$ChocolateyInstallationDirectory")) { 457 | throw "The choco is needed to use this module" 458 | } 459 | 460 | $Env:Path += ";$ChocolateyInstallationDirectory" 461 | } 462 | } 463 | 464 | function EnsurePandocIsInstalled { 465 | if (-not (Get-Command "pandoc" -ErrorAction SilentlyContinue)) { 466 | $PandocInstallationDirectory = "${Env:ChocolateyInstall}\bin" 467 | 468 | if (-not (Test-Path "$PandocInstallationDirectory")) { 469 | throw "The pandoc is needed to use this module" 470 | } 471 | 472 | $Env:Path += ";$PandocInstallationDirectory" 473 | } 474 | 475 | $Output = (& "pandoc" -v) 476 | $ExitCode = $LASTEXITCODE 477 | 478 | if ($ExitCode -ne 0) { 479 | throw "An error occurred while self testing pandoc. ${Output}" 480 | } 481 | } 482 | 483 | function EnsureRequiredDirectoriesPresent { 484 | param ( 485 | [Parameter(Mandatory=$true)] [String[]] $Directories, 486 | [Parameter(Mandatory=$false)] [String] $Prefix = "" 487 | ) 488 | 489 | foreach ($Dir in $Directories) { 490 | if (-not (Test-Path $Dir)) { 491 | if ($Prefix) { 492 | New-Item -ItemType Directory -Force -Path "${Prefix}\${Dir}" | Out-Null 493 | } else { 494 | New-Item -ItemType Directory -Force -Path "${Dir}" | Out-Null 495 | } 496 | 497 | } 498 | } 499 | } 500 | 501 | function DownloadFile { 502 | param ( 503 | [Parameter(Mandatory=$true)] [System.String] $RemoteUrl, 504 | [Parameter(Mandatory=$true)] [System.String] $Destination 505 | ) 506 | 507 | $RetryMax = 5 508 | $RetryCount = 0 509 | $Completed = $false 510 | 511 | $WebClient = New-Object System.Net.WebClient 512 | $WebClient.Headers.Add('User-Agent', 'AppVeyor PowerShell Script') 513 | 514 | Write-Debug "Downloading: '${RemoteUrl}' => '${Destination}' ..." 515 | 516 | while (-not $Completed) { 517 | try { 518 | $WebClient.DownloadFile($RemoteUrl, $Destination) 519 | $Completed = $true 520 | } catch { 521 | if ($RetryCount -ge $RetryMax) { 522 | $ErrorMessage = $_.Exception.Message 523 | Write-Error -Message "${ErrorMessage}" 524 | $Completed = $true 525 | } else { 526 | $RetryCount++ 527 | } 528 | } 529 | } 530 | } 531 | 532 | function Expand-Item7zip { 533 | param( 534 | [Parameter(Mandatory=$true)] [System.String] $Archive, 535 | [Parameter(Mandatory=$true)] [System.String] $Destination 536 | ) 537 | 538 | if (-not (Test-Path -Path $Archive -PathType Leaf)) { 539 | throw "Specified archive file does not exist: ${Archive}" 540 | } 541 | 542 | Write-Debug "Unzipping ${Archive} to ${Destination} ..." 543 | 544 | if (-not (Test-Path -Path $Destination -PathType Container)) { 545 | New-Item $Destination -ItemType Directory | Out-Null 546 | } 547 | 548 | $ExitCode = 0 549 | 550 | if ("${Archive}" -like "*.tgz") { 551 | $Output = (& 7z x -tgzip "$Archive" -bd -y "-o${Env:Temp}") 552 | $ExitCode = $LASTEXITCODE 553 | 554 | if ($ExitCode -eq 0) { 555 | $Archive = "${Env:Temp}/{0}.tar" -f [System.IO.Path]::GetFileNameWithoutExtension($Archive) 556 | } 557 | } 558 | 559 | if ($ExitCode -eq 0) { 560 | $Output = (& 7z x "$Archive" "-o$Destination" -aoa -bd -y -r) 561 | $ExitCode = $LASTEXITCODE 562 | } 563 | 564 | if ($ExitCode -ne 0) { 565 | throw "An error occurred while unzipping '${Archive}' to '${Destination}'. ${Output}" 566 | } 567 | } 568 | --------------------------------------------------------------------------------