mirror of
https://github.com/php-win-ext/php-sdk-binary-tools.git
synced 2026-03-24 17:12:12 +01:00
Compare commits
366 Commits
php-sdk-2.
...
php-sdk-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb51b8f716 | ||
|
|
77ae352d49 | ||
|
|
647f367c55 | ||
|
|
3040efb46f | ||
|
|
d584b2f1c5 | ||
|
|
5c7a304e77 | ||
|
|
b3fffba01c | ||
|
|
58a7bdcfa7 | ||
|
|
81aaa702b2 | ||
|
|
ccfc816560 | ||
|
|
cf6ded7cec | ||
|
|
c73ab2dc76 | ||
|
|
06e32545f5 | ||
|
|
b8bf87b831 | ||
|
|
70ed1c2418 | ||
|
|
8d1df4af8c | ||
|
|
7050077f31 | ||
|
|
94c9d6c97d | ||
|
|
2dab4068aa | ||
|
|
bbdc8dd597 | ||
|
|
e28c5e9b96 | ||
|
|
b359404509 | ||
|
|
912853c55f | ||
|
|
806f743f3c | ||
|
|
d13ff857f0 | ||
|
|
217ab7b4ca | ||
|
|
f740aface6 | ||
|
|
f160e68fbc | ||
|
|
9e3fcfdd77 | ||
|
|
51d2eaa463 | ||
|
|
15cc20920a | ||
|
|
df2eb74fee | ||
|
|
f59fd45ee5 | ||
|
|
43107058f8 | ||
|
|
b53316585a | ||
|
|
8b957129bd | ||
|
|
76ede8f900 | ||
|
|
60cfe587d5 | ||
|
|
e6b4a0d34d | ||
|
|
dac0e43fec | ||
|
|
1d69f089ca | ||
|
|
99112657d2 | ||
|
|
7eaeba9e73 | ||
|
|
ad95ee0c7b | ||
|
|
55cdd86d3a | ||
|
|
1045633875 | ||
|
|
c6a2644a57 | ||
|
|
9ffa736cbc | ||
|
|
79fbcfee08 | ||
|
|
f84b056d1c | ||
|
|
0ab9b8ddc6 | ||
|
|
794ef96470 | ||
|
|
cecf3df7f3 | ||
|
|
1e6ee7afaa | ||
|
|
05af1a3b06 | ||
|
|
c748916f5c | ||
|
|
bebb84afd7 | ||
|
|
841065efd4 | ||
|
|
c726890170 | ||
|
|
b2e52e36d8 | ||
|
|
b8713d8543 | ||
|
|
025290f6d3 | ||
|
|
1ed89bbba2 | ||
|
|
1d4f4966af | ||
|
|
a5b1137938 | ||
|
|
908f5eeea7 | ||
|
|
a7cc2823bf | ||
|
|
ff6a7245a3 | ||
|
|
9bb1377d59 | ||
|
|
95d712bde7 | ||
|
|
446f4272fe | ||
|
|
f6b6bd96e0 | ||
|
|
94b3d07034 | ||
|
|
6797238516 | ||
|
|
02f2f372b6 | ||
|
|
04832718bb | ||
|
|
b52a0c281a | ||
|
|
bc3606fbaf | ||
|
|
41a63dc0b4 | ||
|
|
99ae3ca016 | ||
|
|
777542838c | ||
|
|
82987940a0 | ||
|
|
45344d7691 | ||
|
|
02a726256a | ||
|
|
0a7732ba09 | ||
|
|
8583bb4f00 | ||
|
|
d6fc46edfd | ||
|
|
75740674e5 | ||
|
|
e81199f9af | ||
|
|
134556d419 | ||
|
|
6121772665 | ||
|
|
61dff2296a | ||
|
|
1b8473489f | ||
|
|
e494a28d4c | ||
|
|
22addaf53e | ||
|
|
bb8e318a4a | ||
|
|
87b60bc9d5 | ||
|
|
4936f1d7ca | ||
|
|
7d56095191 | ||
|
|
27c3431e92 | ||
|
|
e5ef707fa0 | ||
|
|
7df3de21ce | ||
|
|
64b37312f7 | ||
|
|
4a219a0d93 | ||
|
|
5d97e8e483 | ||
|
|
9a0f799055 | ||
|
|
4f5028d87a | ||
|
|
93437db5ae | ||
|
|
0572a3ec52 | ||
|
|
52badef774 | ||
|
|
b01fcd36e7 | ||
|
|
fbc6c40761 | ||
|
|
7501f5e567 | ||
|
|
e51c37a375 | ||
|
|
bd0ab3474c | ||
|
|
056e5643fb | ||
|
|
e039de13c4 | ||
|
|
59926c2903 | ||
|
|
7d2b6cf86f | ||
|
|
29d54c140e | ||
|
|
2ef8899939 | ||
|
|
c259e440b6 | ||
|
|
5470b5ae58 | ||
|
|
795ac45864 | ||
|
|
77408342bc | ||
|
|
f9aff35c14 | ||
|
|
a827b2f18f | ||
|
|
5352b3744a | ||
|
|
d816060d55 | ||
|
|
da1e89d23a | ||
|
|
eb3904741a | ||
|
|
6dc9fd3293 | ||
|
|
1d2dae619e | ||
|
|
2a7f364792 | ||
|
|
36570ced8e | ||
|
|
7f75a93bdd | ||
|
|
44925fe946 | ||
|
|
e8d07f824b | ||
|
|
a5426ba7bb | ||
|
|
871816e56c | ||
|
|
70c3290c08 | ||
|
|
d84784d37a | ||
|
|
8ad74abf3f | ||
|
|
9ad145c154 | ||
|
|
f3001d950e | ||
|
|
01ab6a1bad | ||
|
|
659fb3a71d | ||
|
|
d7dcab4c2f | ||
|
|
15ec0845c4 | ||
|
|
a1bab3dc92 | ||
|
|
08b81a4ffc | ||
|
|
569072060e | ||
|
|
b13a2df162 | ||
|
|
96fa91e16a | ||
|
|
8ad971020a | ||
|
|
386d36c251 | ||
|
|
bd9c9ca4d8 | ||
|
|
1d6561c7d5 | ||
|
|
307c5ed4bc | ||
|
|
c6874e5109 | ||
|
|
c3cf4266ad | ||
|
|
01e4fff84a | ||
|
|
4357adc956 | ||
|
|
0a33374aed | ||
|
|
ff16eebfce | ||
|
|
afc302d27e | ||
|
|
e6c79ecad5 | ||
|
|
80dc35f668 | ||
|
|
bd3e1603a9 | ||
|
|
8505dda9c4 | ||
|
|
b15cdb1f92 | ||
|
|
91302e8142 | ||
|
|
f655bcf7d1 | ||
|
|
89bc6e0eb8 | ||
|
|
4d9b189d04 | ||
|
|
ff33ae5143 | ||
|
|
3cf0f67f27 | ||
|
|
b0a93f01c5 | ||
|
|
e10c86c2d5 | ||
|
|
20ccc545bd | ||
|
|
0be0ba3a84 | ||
|
|
c2e3b0ec40 | ||
|
|
b0b61457b4 | ||
|
|
c4ba07a627 | ||
|
|
2c54b0baf5 | ||
|
|
ca942978ee | ||
|
|
6153bb9af2 | ||
|
|
c4ce390679 | ||
|
|
2040ea78bd | ||
|
|
90f5c1633e | ||
|
|
5a44f0b05d | ||
|
|
c84b3e6b9e | ||
|
|
a861392d45 | ||
|
|
0474318721 | ||
|
|
b21fad7268 | ||
|
|
5748dedb3b | ||
|
|
4cea7a4f66 | ||
|
|
7e8235f1a1 | ||
|
|
1122cbd9d9 | ||
|
|
7a054e9e6d | ||
|
|
a6f819dd75 | ||
|
|
b8b32aaa27 | ||
|
|
dbeb065486 | ||
|
|
c2880591f3 | ||
|
|
6911eacb83 | ||
|
|
218f23ab93 | ||
|
|
1684c7e2c7 | ||
|
|
fb396f33e6 | ||
|
|
1deb33bebc | ||
|
|
d00bcf80d0 | ||
|
|
1d645c9faf | ||
|
|
c9ff81440a | ||
|
|
c3a4890b8a | ||
|
|
ac53945a3f | ||
|
|
c7ad0fd314 | ||
|
|
76ed6e3374 | ||
|
|
f3cbba7fc5 | ||
|
|
1d4d208f4b | ||
|
|
6711f1f6d1 | ||
|
|
1ba1bf1dff | ||
|
|
1048a4d346 | ||
|
|
ed4f2d50d0 | ||
|
|
75124abf52 | ||
|
|
58d2c1a009 | ||
|
|
dfdea742dc | ||
|
|
0553f3219f | ||
|
|
2cbe03f44c | ||
|
|
550407fb29 | ||
|
|
dd4844b6d2 | ||
|
|
ae51b4e28f | ||
|
|
6705c85ebd | ||
|
|
8fd8187d28 | ||
|
|
353b184487 | ||
|
|
9345164d3a | ||
|
|
d2b2d58f84 | ||
|
|
9da65f2386 | ||
|
|
1f48f48b94 | ||
|
|
0cd8d902c0 | ||
|
|
c7c874e9b4 | ||
|
|
97112e4dd0 | ||
|
|
098f6457de | ||
|
|
a5afa11cff | ||
|
|
6b58f91d9d | ||
|
|
bb5ff05cc5 | ||
|
|
4b51347c35 | ||
|
|
7d48cafe29 | ||
|
|
d802183581 | ||
|
|
741063cdf1 | ||
|
|
a97d0bd292 | ||
|
|
5507b37b7d | ||
|
|
7c72855fd0 | ||
|
|
b5829cd502 | ||
|
|
de669c7610 | ||
|
|
f96fbeddab | ||
|
|
ceececf83f | ||
|
|
64c2ac973c | ||
|
|
79116d5051 | ||
|
|
c3bb9777bb | ||
|
|
eae3aab2ae | ||
|
|
e7e92b35d0 | ||
|
|
d158c3c032 | ||
|
|
69fb69fd93 | ||
|
|
aee165fe05 | ||
|
|
022333118e | ||
|
|
821c0d7c73 | ||
|
|
7d72596e85 | ||
|
|
2b317c62e1 | ||
|
|
61d589c424 | ||
|
|
eaa6ff57fa | ||
|
|
5efd876bb3 | ||
|
|
0319dc061f | ||
|
|
40fe451c8d | ||
|
|
55fddef1a3 | ||
|
|
af769d9604 | ||
|
|
8e3d43905b | ||
|
|
ebf3928220 | ||
|
|
f96329c0fd | ||
|
|
7cc831e6aa | ||
|
|
24e2464d8c | ||
|
|
738abd255e | ||
|
|
691d70fc09 | ||
|
|
412c512208 | ||
|
|
97a436c3fc | ||
|
|
9e5e7e6c17 | ||
|
|
e17b752c19 | ||
|
|
527b18189c | ||
|
|
f4e3f68ce5 | ||
|
|
99efb73f17 | ||
|
|
9d55fdee58 | ||
|
|
492de099e7 | ||
|
|
29453a9072 | ||
|
|
ac27d0e62e | ||
|
|
d413fe0899 | ||
|
|
bcb9c7346a | ||
|
|
43a11d2552 | ||
|
|
73eb340687 | ||
|
|
f4067b3439 | ||
|
|
adfc922c09 | ||
|
|
c8c80a07f7 | ||
|
|
65bc0a8552 | ||
|
|
d46b74b51b | ||
|
|
af2134b486 | ||
|
|
a2debffacc | ||
|
|
ad14edb0bf | ||
|
|
6b9f6bd7e5 | ||
|
|
f33ebdf261 | ||
|
|
079185a0d6 | ||
|
|
59c082a8f4 | ||
|
|
078554f4a6 | ||
|
|
f6e507fb5e | ||
|
|
14df5a921a | ||
|
|
7cc9c62cae | ||
|
|
7370f1c5b0 | ||
|
|
bb745349a9 | ||
|
|
a2277e746d | ||
|
|
c6bcad86e9 | ||
|
|
af74264b8f | ||
|
|
37fa9bb323 | ||
|
|
d5d2cf1c9d | ||
|
|
ffa802812b | ||
|
|
010ae42362 | ||
|
|
bcd7690d78 | ||
|
|
52932ecdeb | ||
|
|
4074dc7e18 | ||
|
|
bef5693b20 | ||
|
|
09a5e2bedc | ||
|
|
49f6a761e2 | ||
|
|
c385a12d58 | ||
|
|
07546d9304 | ||
|
|
79da1ed7af | ||
|
|
5ccdabeb39 | ||
|
|
31291b5aba | ||
|
|
dc0a5cce5b | ||
|
|
af67c49c46 | ||
|
|
513dd29f8a | ||
|
|
1a8c2e03b7 | ||
|
|
866ffa7b3c | ||
|
|
0b764877b2 | ||
|
|
9523a991d8 | ||
|
|
b2e434d5a1 | ||
|
|
42682a421b | ||
|
|
3dfcb7ccd1 | ||
|
|
b79e4ba51b | ||
|
|
1ce16ca360 | ||
|
|
80e2aec078 | ||
|
|
f88e36cc2b | ||
|
|
524f27bd17 | ||
|
|
e0d0c67953 | ||
|
|
6c2eee890e | ||
|
|
1e51c38c22 | ||
|
|
14c2e7f32e | ||
|
|
2329abeefb | ||
|
|
0050de4131 | ||
|
|
71cf47f6f2 | ||
|
|
4abd44bae4 | ||
|
|
d552f7118b | ||
|
|
f77a7e791a | ||
|
|
024c694807 | ||
|
|
5c7c222e8f | ||
|
|
9fe493edf7 | ||
|
|
5d51577cd5 | ||
|
|
cad50539cf | ||
|
|
6b50dabf00 | ||
|
|
f5f5620c55 | ||
|
|
139ea9a86d | ||
|
|
cf054fd362 |
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
*.m4 text eol=lf
|
||||
*.awk text eol=lf
|
||||
*.c text eol=lf
|
||||
*.h text eol=lf
|
||||
*.php text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -4,6 +4,7 @@ php55
|
||||
php56
|
||||
php70
|
||||
php71
|
||||
php72
|
||||
phpmaster
|
||||
php
|
||||
!lib/php
|
||||
@@ -18,3 +19,8 @@ oracle
|
||||
# either these two become submodules, or uncomment them
|
||||
#pgo-build
|
||||
#rmtools*
|
||||
phpsdk-local.bat
|
||||
pgo/work
|
||||
!pgo/tpl/php
|
||||
!lib/php/libsdk/SDK/Build/PGO/Server/PHP
|
||||
*.swp
|
||||
|
||||
9
LICENSE
Normal file
9
LICENSE
Normal file
@@ -0,0 +1,9 @@
|
||||
Copyright 2017-2019 Anatol Belski
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
317
README.md
317
README.md
@@ -1,110 +1,207 @@
|
||||
# PHP SDK
|
||||
|
||||
PHP SDK is a tool kit for Windows PHP builds
|
||||
|
||||
# License
|
||||
|
||||
The PHP SDK itself and the SDK own tools are licensed under the BSD 2-Clause license. With the usage of the other tools, you accept the respective licenses.
|
||||
|
||||
# Overview
|
||||
|
||||
The PHP SDK 2.0 is compatible with PHP 7.0 and above. The compatibility with older versions, eq. php-sdk-binary-tools-20110915.zip available from windows.php.net previously, is kept. Though, some irrelevant tools was removed. Newer tools are now available, better workflows are now possible. The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs.
|
||||
|
||||
# Requirements
|
||||
|
||||
- `Visual C++ 2015` must be installed prior SDK usage
|
||||
- if `Cygwin` is installed, please read notes in the pitfalls section
|
||||
- if a 64-bit build is intended, a 64-bit system is required. Cross compilation of 64-bit on 32-bit system is not supported at the moment
|
||||
|
||||
# Tools
|
||||
|
||||
All the tools included are either scripts or 32-bit binaries. They are therefore runable on any of x86 or x64 Windows system.
|
||||
|
||||
## SDK
|
||||
|
||||
- starter scripts, named phpsdk-<crt>-<arch>.bat
|
||||
- `phpsdk_buildtree` - initialize the development filesystem structure
|
||||
- `phpsdk_deps` - handle dependency libraries
|
||||
- `phpsdk_version` - show SDK version
|
||||
- `phpsdk_dllmap` - create a JSON listing of DLLs contained in zip files
|
||||
- `task.exe` - wrapper to hide the given command line
|
||||
|
||||
## Other tools
|
||||
|
||||
- `bison` 3.0.2, `re2c` 0.15.3, `lemon`
|
||||
- `awk`, `gawk`, `sed`, `grep`
|
||||
- `diff`, `diff3`, `patch`
|
||||
- `md5sum`, `sha1sum`, `sha224sum`, `sha256sum`, `sha384sum`, `sha512sum`
|
||||
- `7za`, `zip`, `unzip`, `unzipsfx`
|
||||
- `wget`
|
||||
|
||||
## Optional, not included
|
||||
|
||||
These are not included with the PHP SDK, but might be useful. While Visual C++ is the only required, the others might enable some additional functionality. Care yourself about making them available on your system, if relevant.
|
||||
|
||||
- `Git` - useful for PHP source management
|
||||
- `Cppcheck` - used for static analysis
|
||||
- `clang` - useful for experimental builds and for static analysis
|
||||
- `ICC` - useful for experimental builds
|
||||
|
||||
# Usage
|
||||
|
||||
The PHP SDK should be unzipped into the shortest possible path, preferrably somewhere near the drive root.
|
||||
|
||||
Usually, the first step to start the PHP SDK is by invoking one of the suitable starter scripts. This automatically puts the console on the correct environment relevant for the desired PHP build configuration.
|
||||
|
||||
It is not required to hold the source in the PHP SDK directory. It could be useful, for example, to simplify the SDK updates.
|
||||
|
||||
## Basic usage example
|
||||
|
||||
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
|
||||
- `cd c:\php-sdk`
|
||||
- `git checkout new_binary_tools`
|
||||
- invoke `phpsdk-vc14-x64.bat`
|
||||
- `phpsdk_buildtree phpmaster`
|
||||
- `git clone https://github.com/php/php-src.git && cd php-src`, or fetch a zipball
|
||||
- `phpsdk_deps --update --branch master`
|
||||
- do the build, eg. `buildconf && configure --enable-cli && nmake`
|
||||
|
||||
TODO more extensive documentation on the wiki.
|
||||
|
||||
## The old way
|
||||
|
||||
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
|
||||
- follow the instructions on the PHP [wiki page](https://wiki.php.net/internals/windows/stepbystepbuild "PHP wiki page")
|
||||
|
||||
# Customizing
|
||||
|
||||
## Custom environment setup
|
||||
|
||||
A sript called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local was injected into the startup sequence.
|
||||
|
||||
## Console emulator integration
|
||||
|
||||
The starter scripts can be also easy integrated with the consoles other than standard cmd.exe. For the reference, here's an example ConEmu task
|
||||
|
||||
`C:\php-sdk\phpsdk-vc14-x64.bat -cur_console:d:C:\php-sdk\php70\vc14\x64\php-src`
|
||||
|
||||
## Unattended builds
|
||||
|
||||
An elementary functionality to run unattended builds is included. See an example on how to setup a simple unattended build task in the doc directory.
|
||||
|
||||
# Upgrading
|
||||
|
||||
- backup phpsdk-local.bat
|
||||
- backup the source trees and any other custom files in the PHP SDK root
|
||||
- move the PHP SDK folder into trash
|
||||
- download, unpack and the new PHP SDK version under the same path
|
||||
- move the custom files back into their respective places
|
||||
|
||||
# Extending
|
||||
|
||||
The SDK tools are based on the KISS principle and should be kept so. Basic tools are implemented as simple batch script. The minimalistic `PHP` is available for internal SDK purposes. It can be used, if more complexity is required. If you have an idea for some useful tool or workflow, please open a ticket or PR, so it can be discussed, implemented and added to the SDK. By contributing an implementation, you should also accept the SDK license.
|
||||
|
||||
# Pitfalls
|
||||
|
||||
- SDK or PHP sources put into paths including spaces might cause issue.
|
||||
- SDK or PHP sources put into too long paths, will cause an issue.
|
||||
- If Cygwin is installed, it might cause issues. If it's unavoidable, to have Cygwin on the same machine, ensure SDK preceeds it on the PATH.
|
||||
- Tools, based on MSYS2, only accept paths with forward slashes.
|
||||
|
||||
# PHP SDK
|
||||
|
||||
PHP SDK is a tool kit for Windows PHP builds.
|
||||
|
||||
# License
|
||||
|
||||
The PHP SDK itself and the SDK own tools and code are licensed under the BSD 2-Clause license. With the usage of the other tools, you accept the respective licenses.
|
||||
|
||||
# Overview
|
||||
|
||||
The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs. It supports any workflows, be it a custom, local or a CI build whatsoever.
|
||||
|
||||
The PHP SDK 2.2+ is compatible with PHP 7.2 and above.
|
||||
|
||||
The PHP SDK 2.1 is required to build PHP 7.1 or 7.0.
|
||||
|
||||
The legacy binary tools SDK is available from the [legacy branch](https://github.com/Microsoft/php-sdk-binary-tools/tree/legacy) and is suitable to build PHP 5.
|
||||
|
||||
# Requirements
|
||||
|
||||
- A 64-bit build host
|
||||
- Windows 7 or later
|
||||
- `Visual C++ 2017` or `Visual C++ 2019` must be installed prior SDK usage. Required components
|
||||
- C++ dev
|
||||
- Windows SDK
|
||||
- .NET dev
|
||||
- if `Cygwin`, `MingW` or any other cross solution is installed, please read notes in the pitfalls section
|
||||
|
||||
# Tools
|
||||
|
||||
## SDK
|
||||
|
||||
- starter scripts, named phpsdk-<crt>-<arch>.bat
|
||||
- `phpsdk_buildtree` - initialize the development filesystem structure
|
||||
- `phpsdk_deps` - handle dependency libraries
|
||||
- `phpsdk_dllmap` - create a JSON listing of DLLs contained in zip files
|
||||
- `phpsdk_pgo` - run PGO training
|
||||
- `phpsdk_version` - show SDK version
|
||||
- `task.exe` - wrapper to hide the given command line
|
||||
|
||||
## Other tools
|
||||
|
||||
- `bison` 3.3.2, `re2c` 1.1.1, `lemon`
|
||||
- `awk`, `gawk`, `sed`, `grep`, `jq`
|
||||
- `diff`, `diff3`, `patch`
|
||||
- `md5sum`, `sha1sum`, `sha224sum`, `sha256sum`, `sha384sum`, `sha512sum`
|
||||
- `7za`, `zip`, `unzip`, `unzipsfx`
|
||||
- `wget`, `pwgen`
|
||||
|
||||
## Optional, not included
|
||||
|
||||
These are not included with the PHP SDK, but might be useful. While Visual C++ is the only required, the others might enable some additional functionality. Care yourself about making them available on your system, if relevant.
|
||||
|
||||
- `Git` - useful for PHP source management
|
||||
- `Cppcheck` - used for static analysis
|
||||
- `clang` - useful for experimental builds and for static analysis
|
||||
- `ICC` - useful for experimental builds
|
||||
- `ConEmu` - console emulator with tabs and more
|
||||
|
||||
# Usage
|
||||
|
||||
The PHP SDK should be unzipped into the shortest possible path, preferably somewhere near the drive root.
|
||||
|
||||
Usually, the first step to start the PHP SDK is by invoking one of the suitable starter scripts. This automatically puts the console on the correct environment relevant for the desired PHP build configuration.
|
||||
|
||||
It is not required to hold the source in the PHP SDK directory. It could be useful, for example, to simplify the SDK updates.
|
||||
|
||||
## Basic usage example
|
||||
|
||||
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
|
||||
- `cd c:\php-sdk`
|
||||
- `git checkout php-sdk-2.1.9` or later
|
||||
- invoke `phpsdk-vc15-x64.bat`
|
||||
- `phpsdk_buildtree phpmaster`
|
||||
- `git clone https://github.com/php/php-src.git && cd php-src`, or fetch a zipball
|
||||
- `phpsdk_deps --update --branch master`, use `phpsdk_deps --update --branch X.Y` for a non master branch
|
||||
- do the build, eg. `buildconf && configure --enable-cli && nmake`
|
||||
|
||||
More extensive documentation can be found on the [wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 "PHP wiki page").
|
||||
|
||||
## The old way
|
||||
|
||||
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
|
||||
- follow the instructions on the PHP [wiki page](https://wiki.php.net/internals/windows/stepbystepbuild "PHP wiki page")
|
||||
|
||||
# Customizing
|
||||
|
||||
## Custom environment setup
|
||||
|
||||
A script called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local.bat was injected into the startup sequence.
|
||||
|
||||
## Console emulator integration
|
||||
|
||||
The starter scripts can be also easy integrated with the consoles other than standard cmd.exe. For the reference, here's an example ConEmu task
|
||||
|
||||
`C:\php-sdk\phpsdk-vc15-x64.bat -cur_console:d:C:\php-sdk\php72\vc15\x64\php-src`
|
||||
|
||||
## Unattended builds
|
||||
|
||||
An elementary functionality to run unattended builds is included. See an example on how to setup a simple unattended build task in the doc directory.
|
||||
|
||||
Be aware, that starter scripts always start a new shell. Scripts intended to run as a task need to be passed with `-t` argument to a starter script.
|
||||
|
||||
# Upgrading
|
||||
|
||||
- backup phpsdk-local.bat
|
||||
- backup the source trees and any other custom files in the PHP SDK root, if any present
|
||||
- move the PHP SDK folder into trash
|
||||
- download, unpack and the new PHP SDK version under the same path
|
||||
- move the custom files back in their respective places
|
||||
|
||||
If the PHP SDK is kept as a git checkout, merely what is needed instead is to git fetch and to checkout an updated git tag.
|
||||
|
||||
# Extending
|
||||
|
||||
The SDK tools are based on the KISS principle and should be kept so. Basic tools are implemented as simple batch script. The minimalistic `PHP` is available for internal SDK purposes. It can be used, if more complexity is required. A suitable PHP binary is bound with the PHP SDK. If you have an idea for some useful tool or workflow, please open a ticket or PR, so it can be discussed, implemented and added to the SDK. By contributing an implementation, you should also accept the SDK license.
|
||||
|
||||
# PGO
|
||||
|
||||
As of the version 2.1.0, the SDK includes a tool for the [PGO](https://docs.microsoft.com/en-us/cpp/build/reference/profile-guided-optimizations) optimization. Several training cases are included by default, which are based on the real life opensource applications. The PGO optimization can give an overall speedup up to 30%. The work on adding more training scenarios for the widely used opensource apps is ongoing. If you have a training scenario to share, please create a PR to this repo. Any new training cases are thoroughly validated through the extensive performance tests.
|
||||
|
||||
## Preparing PGO training environment
|
||||
- the pgo folder in the SDK root dir contains templates and scenarios for PGO training
|
||||
- adjust and execute [doc/phpsdk_pgo_prep_elevated.bat.example](doc/phpsdk_pgo_prep_elevated.bat.example) to open ports required for PHP SDK training servers
|
||||
- run `phpsdk_pgo --init`
|
||||
|
||||
## Creating PGO build
|
||||
- compile PHP configured using `--enable-pgi`
|
||||
- run `phpsdk_pgo --train`
|
||||
- run `nmake clean-pgo`
|
||||
- rebuild PHP `--with-pgo`
|
||||
|
||||
## Adding custom PGO training scenario
|
||||
|
||||
A custom scenario can be used to produce a custom PHP binary dedicated to an arbitrary application.
|
||||
|
||||
The existing training cases can be found in [pgo/cases](pgo/cases). Assumed the case would be named `myapp`, the general steps to setup were
|
||||
|
||||
- create the case directory under `pgo/cases/myapp`
|
||||
- create `pgo/cases/myapp/phpsdk_pgo.json` with the necessary definitions
|
||||
- create `pgo/cases/myapp/nginx.partial.conf` with a partial NGINX template
|
||||
- create `pgo/cases/myapp/TrainingCaseHandler.php` with a class as defined in the [interface](lib/php/libsdk/SDK/Build/PGO/Interfaces/TrainingCase.php)
|
||||
|
||||
After a training case is implemented and put under `pgo/cases`, the work environment needs to be reinitialized. The tool puts all the training data and necessary applications under `pgo/work`. Rename or remove that directory and rerun `phpsdk_pgo --init`.
|
||||
|
||||
To skip a training case, add a file named `inactive` into the case folder.
|
||||
|
||||
# Debugging PHP
|
||||
|
||||
This part covers debugging possibilities for the builds produced by the native VS compilers.
|
||||
For the cross compiled builds produced with toolsets other than VC++, please check the
|
||||
documentation for the corresponding toolsets. In any case, general principles on debugging
|
||||
native programs apply.
|
||||
|
||||
Either a debug build of PHP or enabled debug symbols are required to be able to debug PHP.
|
||||
A debug build is usually more suitable for the development process and can be produced by
|
||||
adding `--enable-debug` to the configure options. A release build with debug symbols can
|
||||
be produced by adding `--enable-debug-pack`. These options are mutually exclusive.
|
||||
|
||||
## Debugging with Visual Studio
|
||||
|
||||
- Configure with either `--enable-debug` or `--enable-debug-pack`.
|
||||
- A debug build might bring better experience for dev, but sometimes you want to debug a release build.
|
||||
- `nmake run ARGS=yourscript.php DEBUGGER=1`, that will open a Visual Studio window.
|
||||
- Any additional runtime options for PHP or the script executed go to ARGS, too.
|
||||
- Select `Debug -> New Breakpoint -> Function Breakpoint` and add a function where the debugger should break.
|
||||
- Click `Start`.
|
||||
|
||||
Adding a breakpoint before starting debugging might be not necessary, if a crash is debugged. When such a script runs
|
||||
under the debugger, the debugger will stop at the crashing point. In that case, a breakpoint can be added
|
||||
around the crashed code directly.
|
||||
|
||||
## Debugging test suite with Visual Studio
|
||||
|
||||
The [Microsoft Child Process Debugging Power Tool](https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool)
|
||||
plugin for Visual Studio is required. After installing it, following these steps
|
||||
|
||||
- `nmake test TESTS=ext/myext/tests/sometest.phpt DEBUGGER=1`
|
||||
- Select `Debug -> Other Debug Targets -> Child Process Debugging Settings` and enable child process debugging.
|
||||
- If necessary, add a breakpoint and start debugging as described in the previous section.
|
||||
|
||||
## Debugging with WinDbg
|
||||
|
||||
PHP can also be debugged with the tools from the WinDbg package. There is currently no way
|
||||
implemented in the Makefile to start the WinDbg integrated, so it needs to de done manually.
|
||||
Either a debug build or a release build with debug symbols is still required, as described
|
||||
previously.
|
||||
|
||||
# Support
|
||||
|
||||
- Join `#winphp-dev` on Freenode to discuss any ideas or questions
|
||||
- File an issue on GitHub
|
||||
|
||||
# Pitfalls
|
||||
|
||||
- SDK or PHP sources put into paths including spaces might cause issue.
|
||||
- SDK or PHP sources put into too long paths, will cause an issue.
|
||||
- If Cygwin, MSYS2 or MinGW flavors are exposed in global PATH, it might cause issues. If it's unavoidable, ensure SDK preceeds it on the PATH.
|
||||
- When fetching the binary SDK from git, git `core.autocrlf` configuration directive set to `false` is recommended.
|
||||
- Tools, based on MSYS2, only accept paths with forward slashes.
|
||||
- Both Visual C++ toolset and the Windows SDK components have to be installed for the PHP SDK to work properly.
|
||||
- The VC++ toolset is still required, even if another compiler, fe. clang, is intended to be used.
|
||||
- `task.exe` is not a console application, some systems might not propagate exit code except the batch is explicitly run from `cmd /c`, etc.
|
||||
- `7za` should be preferred over `unzip` and `zip` for compatibility reasons.
|
||||
- If you experience some strange crashes on MSYS2 tools, try the phpsdk_rebase_msys2 tool. MSYS2 tools might be have unstable
|
||||
on ASLR enabled systems.
|
||||
|
||||
|
||||
BIN
bin/7za.dll
BIN
bin/7za.dll
Binary file not shown.
BIN
bin/7za.exe
BIN
bin/7za.exe
Binary file not shown.
BIN
bin/7zxa.dll
BIN
bin/7zxa.dll
Binary file not shown.
BIN
bin/jq.exe
Normal file
BIN
bin/jq.exe
Normal file
Binary file not shown.
@@ -1,3 +1,3 @@
|
||||
@echo ofF
|
||||
|
||||
%~dp0php.exe -c %~dp0php.ini -d extension_dir=%~dp0ext %*
|
||||
%~dp0php.exe -c %~dp0php.ini -d curl.cainfo=%PHP_SDK_ROOT_PATH%\msys2\usr\ssl\cert.pem -d extension_dir=%~dp0ext %*
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/php/ext/php_mysqli.dll
Normal file
BIN
bin/php/ext/php_mysqli.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/php/libcrypto-1_1-x64.dll
Normal file
BIN
bin/php/libcrypto-1_1-x64.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/php/libssl-1_1-x64.dll
Normal file
BIN
bin/php/libssl-1_1-x64.dll
Normal file
Binary file not shown.
BIN
bin/php/nghttp2.dll
Normal file
BIN
bin/php/nghttp2.dll
Normal file
Binary file not shown.
BIN
bin/php/php.exe
BIN
bin/php/php.exe
Binary file not shown.
@@ -4,7 +4,8 @@ extension=php_ftp.dll
|
||||
extension=php_sqlite3.dll
|
||||
extension=php_openssl.dll
|
||||
extension=php_mbstring.dll
|
||||
memory_limit=1G
|
||||
extension=php_mysqli.dll
|
||||
memory_limit=4G
|
||||
|
||||
error_reporting=-1
|
||||
display_errors=1
|
||||
|
||||
BIN
bin/php/php7.dll
BIN
bin/php/php7.dll
Binary file not shown.
Binary file not shown.
@@ -7,23 +7,27 @@ IF "%2" EQU "" SET _=%CD%\%1
|
||||
rem if we're in the starter script shell, create the only struct that corresponds to the current env
|
||||
rem otherwise - retain the old behavior, create structs for all the known build combinations and don't cd
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
if "%PHP_SDK_ARCH%" NEQ "" (
|
||||
if "%PHP_SDK_VC%" NEQ "" (
|
||||
MD %_%\%PHP_SDK_VC%\%PHP_SDK_ARCH%\deps\bin
|
||||
MD %_%\%PHP_SDK_VC%\%PHP_SDK_ARCH%\deps\lib
|
||||
MD %_%\%PHP_SDK_VC%\%PHP_SDK_ARCH%\deps\include
|
||||
cd %_%\%PHP_SDK_VC%\%PHP_SDK_ARCH%
|
||||
if "%PHP_SDK_VS%" NEQ "" (
|
||||
MD %_%\%PHP_SDK_VS%\%PHP_SDK_ARCH%\deps\bin
|
||||
MD %_%\%PHP_SDK_VS%\%PHP_SDK_ARCH%\deps\lib
|
||||
MD %_%\%PHP_SDK_VS%\%PHP_SDK_ARCH%\deps\include
|
||||
cd %_%\%PHP_SDK_VS%\%PHP_SDK_ARCH%
|
||||
goto exit
|
||||
)
|
||||
goto create_all
|
||||
) else (
|
||||
:create_all
|
||||
MD %_%\vc14\x86\deps\bin
|
||||
MD %_%\vc14\x86\deps\lib
|
||||
MD %_%\vc14\x86\deps\include
|
||||
MD %_%\vc14\x64\deps\bin
|
||||
MD %_%\vc14\x64\deps\lib
|
||||
MD %_%\vc14\x64\deps\include
|
||||
for %%i in (vc14 vc15 vs16) do (
|
||||
MD %_%\%%i\x86\deps\bin
|
||||
MD %_%\%%i\x86\deps\lib
|
||||
MD %_%\%%i\x86\deps\include
|
||||
MD %_%\%%i\x64\deps\bin
|
||||
MD %_%\%%i\x64\deps\lib
|
||||
MD %_%\%%i\x64\deps\include
|
||||
)
|
||||
)
|
||||
|
||||
set _=
|
||||
@@ -35,3 +39,5 @@ echo phpsdk_buildtree ^<nameofthetree^> [PATH]
|
||||
echo Create the common directory structure used by the PHP SDK
|
||||
|
||||
:EXIT
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@echo off
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
call %~dp0phpsdk_setvars.bat
|
||||
if "!PHP_SDK_PHP_CMD!"=="" (
|
||||
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
|
||||
call %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_deps.php %*
|
||||
|
||||
exit /b
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?php
|
||||
|
||||
include dirname(__FILE__) . "/../lib/php/libsdk/autoload.php";
|
||||
include __DIR__ . "/../lib/php/autoload.php";
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Exception;
|
||||
use SDK\{Config, Exception};
|
||||
|
||||
$sopt = "s:cuhb:a:d:t:";
|
||||
$sopt = "s:cuhb:a:d:t:fnp";
|
||||
$lopt = array(
|
||||
"branch:",
|
||||
"update",
|
||||
@@ -15,6 +14,9 @@ $lopt = array(
|
||||
"crt:",
|
||||
"help",
|
||||
"deps:",
|
||||
"force",
|
||||
"no-backup",
|
||||
"pack",
|
||||
);
|
||||
|
||||
$cmd = NULL;
|
||||
@@ -22,15 +24,19 @@ $stability = NULL;
|
||||
$arch = NULL;
|
||||
$branch = NULL;
|
||||
$crt = NULL;
|
||||
$force = false;
|
||||
$backup = true;
|
||||
|
||||
try {
|
||||
|
||||
$branch = NULL;
|
||||
|
||||
$opt = getopt($sopt, $lopt);
|
||||
foreach ($opt as $name => $val) {
|
||||
switch ($name) {
|
||||
default:
|
||||
throw new Exception("Unknown switch '$name'");
|
||||
break;
|
||||
break;
|
||||
|
||||
case "h":
|
||||
case "help":
|
||||
@@ -39,22 +45,18 @@ try {
|
||||
|
||||
case "b":
|
||||
case "branch":
|
||||
/* Branch config depends on other information. We can set it
|
||||
right away, because the option order can't be guaranteed. */
|
||||
$branch = $val;
|
||||
break;
|
||||
|
||||
case "s":
|
||||
case "stability":
|
||||
if ("stable" != $val && "staging" != $val) {
|
||||
throw new Exception("Unknown stability keyword, either stable or staging is accepted");
|
||||
}
|
||||
Config::setCurrentStabilityName($val);
|
||||
break;
|
||||
|
||||
case "a":
|
||||
case "arch":
|
||||
if ("x64" != $val && "x86" != $val) {
|
||||
throw new Exception("Unknown arch keyword, either x86 or x64 is accepted");
|
||||
}
|
||||
Config::setCurrentArchName($val);
|
||||
break;
|
||||
|
||||
@@ -76,99 +78,64 @@ try {
|
||||
case "crt":
|
||||
Config::setCurrentCrtName($val);
|
||||
break;
|
||||
|
||||
case "f":
|
||||
case "force":
|
||||
$force = true;
|
||||
break;
|
||||
|
||||
case "n":
|
||||
case "no-backup":
|
||||
$backup = false;
|
||||
break;
|
||||
|
||||
case "p":
|
||||
case "pack":
|
||||
$cmd = "pack";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == $branch) {
|
||||
$branch = Config::guessCurrentBranchName();
|
||||
if (NULL == $branch) {
|
||||
throw new Exception("Couldn't determine current branch name, expect an explicit input.");
|
||||
}
|
||||
}
|
||||
Config::setCurrentBranchName($branch);
|
||||
|
||||
if (NULL === $cmd) {
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!Config::getDepsLocalPath()) {
|
||||
if (file_exists("../deps")) {
|
||||
Config::setDepsLocalPath(realpath("../deps"));
|
||||
} else if (file_exists("main/php_version.h")) {
|
||||
/* Deps dir might not exist. */
|
||||
Config::setDepsLocalPath(realpath("..") . DIRECTORY_SEPARATOR . "deps");
|
||||
} else {
|
||||
usage(3);
|
||||
}
|
||||
if (NULL === Config::getDepsLocalPath()) {
|
||||
usage(3);
|
||||
}
|
||||
|
||||
if ($branch) {
|
||||
Config::setCurrentBranchName($branch);
|
||||
}
|
||||
if (!Config::getCurrentBranchName()) {
|
||||
/* Try to figure out the branch. For now it only works if CWD is in php-src. */
|
||||
$fl = "main/php_version.h";
|
||||
if (file_exists($fl)) {
|
||||
$s = file_get_contents($fl);
|
||||
$major = $minor = NULL;
|
||||
|
||||
if (preg_match(",PHP_MAJOR_VERSION (\d+),", $s, $m)) {
|
||||
$major = $m[1];
|
||||
}
|
||||
if (preg_match(",PHP_MINOR_VERSION (\d+),", $s, $m)) {
|
||||
$minor = $m[1];
|
||||
}
|
||||
|
||||
if (is_numeric($major) && is_numeric($minor)) {
|
||||
Config::setCurrentBranchName("$major.$minor");
|
||||
} else {
|
||||
usage(3);
|
||||
}
|
||||
} else {
|
||||
usage(3);
|
||||
}
|
||||
$branch = Config::getCurrentBranchName();
|
||||
if (NULL == $branch) {
|
||||
usage(3);
|
||||
}
|
||||
|
||||
if (NULL === Config::getCurrentArchName()) {
|
||||
/* XXX this might be not true for other compilers! */
|
||||
passthru("where cl.exe >nul", $status);
|
||||
if (!$status) {
|
||||
exec("cl.exe /? 2>&1", $a, $status);
|
||||
if (!$status) {
|
||||
if (preg_match(",x64,", $a[0])) {
|
||||
Config::setCurrentArchName("x64");
|
||||
} else {
|
||||
Config::setCurrentArchName("x86");
|
||||
}
|
||||
} else {
|
||||
usage(3);
|
||||
}
|
||||
} else {
|
||||
usage(3);
|
||||
}
|
||||
$arch = Config::getCurrentArchName();
|
||||
$arch = Config::getCurrentArchName();
|
||||
if (NULL === $arch) {
|
||||
usage(3);
|
||||
}
|
||||
|
||||
if (NULL === Config::getCurrentCrtName()) {
|
||||
$all_branches = Config::getKnownBranches();
|
||||
|
||||
if (!isset($all_branches[Config::getCurrentBranchName()])) {
|
||||
throw new Exception("Couldn't find any configuration for branch '" . Config::getCurrentBranchName() . "'");
|
||||
}
|
||||
|
||||
$branch = $all_branches[Config::getCurrentBranchName()];
|
||||
if (count($branch) > 1) {
|
||||
throw new Exception("Multiple CRTs are available for this branch, please choose one from " . implode(",", array_keys($branch)));
|
||||
} else {
|
||||
Config::setCurrentCrtName(array_keys($branch)[0]);
|
||||
}
|
||||
usage(3);
|
||||
}
|
||||
|
||||
if (NULL === Config::getCurrentStabilityName()) {
|
||||
if ("master" == Config::getCurrentBranchName()) {
|
||||
Config::setCurrentStabilityName("staging");
|
||||
} else {
|
||||
Config::setCurrentStabilityName("stable");
|
||||
}
|
||||
/* The current CRT needs to match the config one. */
|
||||
$active_crt = getenv("PHP_SDK_VS");
|
||||
if (Config::getCurrentCrtName() != $active_crt && !$force) {
|
||||
throw new Exception("Active CRT name '$active_crt' differs from the branch CRT name '" . Config::getCurrentCrtName() . "'.");
|
||||
}
|
||||
|
||||
$branch_data = Config::getCurrentBranchData();
|
||||
echo "\nConfiguration: " . Config::getCurrentBranchName() . "-$branch_data[crt]-$branch_data[arch]-$branch_data[stability]\n\n";
|
||||
|
||||
/* Let the dep manager to run the command. */
|
||||
$dm = new SDK\Dependency\Manager(Config::getDepsLocalPath(), $branch_data["stability"], $branch_data["arch"]);
|
||||
$dm = new SDK\Build\Dependency\Manager(Config::getDepsLocalPath(), $branch_data["stability"], $branch_data["arch"]);
|
||||
switch ($cmd) {
|
||||
default:
|
||||
throw new Exception("Unknown command '$cmd'");
|
||||
@@ -182,9 +149,22 @@ try {
|
||||
}
|
||||
break;
|
||||
case "update":
|
||||
$dm->performUpdate($msg);
|
||||
if ($force) {
|
||||
print "Replacing the current deps by the force option.\n\n";
|
||||
}
|
||||
$dm->performUpdate($msg, $force, $backup);
|
||||
msg($msg);
|
||||
break;
|
||||
case "pack":
|
||||
$path_to_pack = Config::getDepsLocalPath();
|
||||
$pack_path = dirname($path_to_pack) . DIRECTORY_SEPARATOR . "deps-$branch-$branch_data[crt]-$branch_data[arch].7z";
|
||||
print "Packaging '$path_to_pack' as '$pack_path'.\n\n";
|
||||
if ($force && is_file($pack_path)) {
|
||||
unlink($pack_path);
|
||||
}
|
||||
system("7za a $pack_path $path_to_pack", $st);
|
||||
exit((int)$st);
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (Throwable $e) {
|
||||
@@ -199,15 +179,18 @@ function usage(int $code = -1)
|
||||
echo "PHP SDK dependency handling tool.", PHP_EOL;
|
||||
echo "Usage: ", PHP_EOL, PHP_EOL;
|
||||
echo "Configuration:", PHP_EOL;
|
||||
echo " -b --branch Branch name, eg. 7.0, 7.1, etc. If omited, CWD is used to guess.", PHP_EOL;
|
||||
echo " -b --branch Branch name, eg. 7.0, 7.1, etc. If omited, several guess methods apply.", PHP_EOL;
|
||||
echo " -a --arch Architecture, x86 or x64. If omited, cl.exe is used to guess.", PHP_EOL;
|
||||
echo " -t --crt CRT, marked by the corresponding VC++ version, eg. vc11, vc14, etc.", PHP_EOL;
|
||||
echo " -s --stability One of stable or staging.", PHP_EOL, PHP_EOL;
|
||||
echo "Commands:", PHP_EOL;
|
||||
echo " -c --check Check for dependency updates. If updates are available, the exit code is set to 7.", PHP_EOL;
|
||||
echo " -u --update Update dependencies. If deps directory already exists, backup copy is created automatically.", PHP_EOL, PHP_EOL;
|
||||
echo " -u --update Update dependencies. If deps directory already exists, backup copy is created automatically.", PHP_EOL;
|
||||
echo " -p --pack Archive the dependency directory.", PHP_EOL, PHP_EOL;
|
||||
echo "Misc:", PHP_EOL;
|
||||
echo " -d --deps Path to the dependencies directory. If omited, CWD is used to guess.", PHP_EOL;
|
||||
echo " -f --force Force the operation even if there are no upgrades available.", PHP_EOL;
|
||||
echo " -n --no-backup Replace the current dependencies without creating backup.", PHP_EOL;
|
||||
echo " -h --help Show help message.", PHP_EOL, PHP_EOL;
|
||||
echo "Example: ", PHP_EOL;
|
||||
echo " phpsdk_deps -c -b master", PHP_EOL;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@echo off
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
call %~dp0phpsdk_setvars.bat
|
||||
if "!PHP_SDK_PHP_CMD!"=="" (
|
||||
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
|
||||
call %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_dllmap.php %*
|
||||
|
||||
exit /b
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- create mappings between dll filename and zip filename
|
||||
|
||||
Usage:
|
||||
php dllmap.php path0 [ path1 ... ] > dllmapping.json
|
||||
php dllmap.php [--pretty] path0 [ path1 ... ] > dllmapping.json
|
||||
*/
|
||||
|
||||
|
||||
@@ -20,8 +20,25 @@
|
||||
"C:\\tmp\\libs",
|
||||
);*/
|
||||
|
||||
$sopt = "p";
|
||||
$lopt = array(
|
||||
"pretty",
|
||||
);
|
||||
|
||||
$flags = 0;
|
||||
$opt = getopt($sopt, $lopt);
|
||||
foreach ($opt as $name => $val) {
|
||||
switch ($name) {
|
||||
case "p":
|
||||
case "pretty":
|
||||
$flags = JSON_PRETTY_PRINT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$dirs = array();
|
||||
foreach (array_slice($_SERVER["argv"], 1) as $item) {
|
||||
foreach (array_slice($_SERVER["argv"], (0 == $flags ? 1 : 2)) as $item) {
|
||||
if (file_exists($item) && is_dir($item)) {
|
||||
$dirs[] = $item;
|
||||
}
|
||||
@@ -32,26 +49,7 @@ if (empty($dirs)) {
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
$out = array(
|
||||
"vc9" => array(
|
||||
"x86" => array(),
|
||||
"x64" => array(),
|
||||
),
|
||||
"vc11" => array(
|
||||
"x86" => array(),
|
||||
"x64" => array(),
|
||||
),
|
||||
"vc12" => array(
|
||||
"x86" => array(),
|
||||
"x64" => array(),
|
||||
),
|
||||
"vc14" => array(
|
||||
"x86" => array(),
|
||||
"x64" => array(),
|
||||
),
|
||||
);
|
||||
|
||||
$out = array();
|
||||
|
||||
foreach ($dirs as $path) {
|
||||
$dir = new DirectoryIterator($path);
|
||||
@@ -74,22 +72,29 @@ foreach ($dirs as $path) {
|
||||
$crt = $m[1];
|
||||
$arch = $m[2];
|
||||
|
||||
if (!isset($out[$crt])) {
|
||||
$out[$crt] = array();
|
||||
}
|
||||
if (!isset($out[$crt][$arch])) {
|
||||
$out[$crt][$arch] = array();
|
||||
}
|
||||
|
||||
$zip = new ZipArchive();
|
||||
|
||||
$zip->open($pathname);
|
||||
|
||||
$dlls = array();
|
||||
|
||||
for( $i = 0; $i < $zip->numFiles; $i++ ){
|
||||
$stat = $zip->statIndex( $i );
|
||||
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
$stat = $zip->statIndex($i);
|
||||
|
||||
if (substr($stat['name'], -3) != "dll") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$dlls[] = basename($stat['name']);
|
||||
}
|
||||
|
||||
|
||||
$zip->close();
|
||||
unset($zip);
|
||||
|
||||
@@ -100,7 +105,7 @@ foreach ($dirs as $path) {
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($out);
|
||||
echo json_encode($out, $flags);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
@@ -5,6 +5,8 @@ if "%PHP_SDK_OS_ARCH%"=="" (
|
||||
exit /b 3
|
||||
)
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
echo.
|
||||
|
||||
call %PHP_SDK_BIN_PATH%\phpsdk_version.bat
|
||||
@@ -22,9 +24,9 @@ if "%PHP_SDK_ARCH%"=="x64" (
|
||||
echo Build architecture: 32-bit
|
||||
)
|
||||
|
||||
echo Visual C++: %PHP_SDK_VC:~2%
|
||||
echo Visual C++: %PHP_SDK_VC_TOOLSET_VER%
|
||||
echo PHP-SDK path: %PHP_SDK_ROOT_PATH%
|
||||
|
||||
|
||||
exit /b
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
14
bin/phpsdk_pgo.bat
Normal file
14
bin/phpsdk_pgo.bat
Normal file
@@ -0,0 +1,14 @@
|
||||
@echo off
|
||||
|
||||
if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
call %~dp0phpsdk_setvars.bat
|
||||
if "!PHP_SDK_PHP_CMD!"=="" (
|
||||
echo PHP SDK is not setup
|
||||
exit /b 3
|
||||
)
|
||||
)
|
||||
|
||||
cmd /c %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_pgo.php %*
|
||||
|
||||
exit /b %errorlevel%
|
||||
|
||||
134
bin/phpsdk_pgo.php
Normal file
134
bin/phpsdk_pgo.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
include __DIR__ . "/../lib/php/autoload.php";
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Exception;
|
||||
use SDK\Build\PGO\Controller;
|
||||
|
||||
$sopt = "itudhs:frc:";
|
||||
$lopt = array("init", "train", "up", "down", "help", "scenario:", "force", "ready", "cases:");
|
||||
|
||||
$cmd = NULL;
|
||||
/* TODO For now we simply check the current php build, this could be extended to take arbitrary binaries. */
|
||||
$deps_root = NULL;
|
||||
$php_root = NULL;
|
||||
$scenario = NULL;
|
||||
$force = false;
|
||||
$cases = NULL;
|
||||
|
||||
try {
|
||||
$opt = getopt($sopt, $lopt);
|
||||
foreach ($opt as $name => $val) {
|
||||
switch ($name) {
|
||||
case "i":
|
||||
case "init":
|
||||
$cmd = "init";
|
||||
break;
|
||||
case "ready":
|
||||
$cmd = "check_init";
|
||||
break;
|
||||
case "t":
|
||||
case "train":
|
||||
$cmd = "train";
|
||||
break;
|
||||
case "u":
|
||||
case "up":
|
||||
$cmd = "up";
|
||||
break;
|
||||
case "d":
|
||||
case "down":
|
||||
$cmd = "down";
|
||||
break;
|
||||
case "s":
|
||||
case "scenario":
|
||||
$scenario = $val;
|
||||
break;
|
||||
case "f":
|
||||
case "force":
|
||||
$force = true;
|
||||
break;
|
||||
/* XXX This option is for now only integrated for training. It
|
||||
would make sense to integrate it also with init. */
|
||||
case "c":
|
||||
case "cases":
|
||||
$cases = explode(",", $val);
|
||||
break;
|
||||
case "h": case "help":
|
||||
usage(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL === $cmd) {
|
||||
usage();
|
||||
}
|
||||
|
||||
$deps_root = Config::getDepsLocalPath();
|
||||
|
||||
if ("check_init" != $cmd) {
|
||||
/* XXX Need these checks for more safety, as long as the dist zipballs are not supported. */
|
||||
if (!file_exists("Makefile")) {
|
||||
throw new Exception("Makefile not found. Arbitrary php snapshots are not supported yet, switch to the php source dir.");
|
||||
}
|
||||
if (preg_match(",BUILD_DIR=(.+),", file_get_contents("Makefile"), $m)) {
|
||||
$php_root = trim($m[1]);
|
||||
}
|
||||
if (!$php_root || !file_exists($php_root)) {
|
||||
throw new Exception("Invalid php root dir encountered '$php_root'.");
|
||||
}
|
||||
}
|
||||
|
||||
$controller = new Controller($cmd, $scenario, $cases);
|
||||
$controller->handle($force);
|
||||
|
||||
if ("check_init" == $cmd) {
|
||||
/* 0 for success, fail otherwise. */
|
||||
$ret = ($controller->isInitialized() === false);
|
||||
exit((int)$ret);
|
||||
}
|
||||
|
||||
/*$env = getenv();
|
||||
$env["PATH"] = $deps_root . DIRECTORY_SEPARATOR . "bin;" . $env["PATH"];
|
||||
|
||||
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";
|
||||
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";*/
|
||||
|
||||
} catch (Throwable $e) {
|
||||
throw $e;
|
||||
exit(3);
|
||||
}
|
||||
|
||||
|
||||
function usage(int $code = -1)
|
||||
{
|
||||
echo "PHP SDK PGO training tool.", PHP_EOL;
|
||||
echo "Usage: ", PHP_EOL, PHP_EOL;
|
||||
echo "Commands:", PHP_EOL;
|
||||
echo " -i --init Initialize training environment.", PHP_EOL;
|
||||
echo " -t --train Run training. This involves startup, training and shutdown.", PHP_EOL;
|
||||
echo " -u --up Startup training environment.", PHP_EOL;
|
||||
echo " -d --down Shutdown training environment.", PHP_EOL;
|
||||
echo " -f --force Force requested operation. Not every option can be forced.", PHP_EOL;
|
||||
echo " -s --scenario Run training with a specified scenario.", PHP_EOL;
|
||||
echo " -c --cases Run training with specified cases only. If omited, all the active cases will be used.", PHP_EOL;
|
||||
|
||||
/*echo " -p --php-root PHP binary to train.", PHP_EOL;*/
|
||||
|
||||
$code = -1 == $code ? 0 : $code;
|
||||
exit($code);
|
||||
}
|
||||
|
||||
function msg(string $s, int $code = 0) {
|
||||
echo $s, PHP_EOL;
|
||||
exit($code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
40
bin/phpsdk_rebase_msys2.cmd
Normal file
40
bin/phpsdk_rebase_msys2.cmd
Normal file
@@ -0,0 +1,40 @@
|
||||
@echo off
|
||||
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
set PHPSDK_MSYS2_BASE_ADDR=0x100400000
|
||||
set PHPSDK_MSYS2_BASE_DYNAMIC=0
|
||||
|
||||
:getopt
|
||||
if /i "%1" equ "--help" goto help
|
||||
if /i "%1" equ "--addr" (
|
||||
set PHPSDK_MSYS2_BASE_ADDR=%2 & shift
|
||||
for /l %%a in (1,1,100) do if "!PHPSDK_MSYS2_BASE_ADDR:~-1!"==" " set PHPSDK_MSYS2_BASE_ADDR=!PHPSDK_MSYS2_BASE_ADDR:~0,-1!
|
||||
)
|
||||
shift
|
||||
if /i "%1" equ "--dynamic" (
|
||||
set PHPSDK_MSYS2_BASE_DYNAMIC=1
|
||||
shift
|
||||
)
|
||||
if not (%1)==() goto getopt
|
||||
|
||||
IF "1" EQU "%PHPSDK_MSYS2_BASE_DYNAMIC%" (
|
||||
echo Rebasing MSYS2 DLLs to load at a dynamic address
|
||||
editbin /NOLOGO /DYNAMICBASE %PHP_SDK_ROOT_PATH%\msys2\usr\bin\*.dll
|
||||
) else (
|
||||
echo Rebasing MSYS2 DLLs to load at %PHPSDK_MSYS2_BASE_ADDR%
|
||||
editbin /NOLOGO /REBASE:BASE=%PHPSDK_MSYS2_BASE_ADDR%,DOWN %PHP_SDK_ROOT_PATH%\msys2\usr\bin\*.dll
|
||||
)
|
||||
|
||||
set PHPSDK_MSYS2_BASE_ADDR=
|
||||
set PHPSDK_MSYS2_BASE_DYNAMIC=
|
||||
|
||||
GOTO EXIT
|
||||
|
||||
:help
|
||||
echo phpsdk_rebase_msys2 ^<address^>
|
||||
echo Rebase MSYS2 DLLs to the given address. If ommited, default is 0x100400000.
|
||||
|
||||
:EXIT
|
||||
exit /b %errorlevel%
|
||||
|
||||
@@ -13,12 +13,36 @@ if "%1"=="-h" goto :help
|
||||
if "%1"=="--help" goto :help
|
||||
if "%2"=="" goto :help
|
||||
|
||||
if /i not "%1"=="vc14" (
|
||||
if /i not "%1"=="vc15" (
|
||||
echo Unsupported runtime "%1"
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
set PHP_SDK_VS=%1
|
||||
if /i not "%PHP_SDK_VS:~0,2%"=="vc" (
|
||||
if /i not "%PHP_SDK_VS:~0,2%"=="vs" (
|
||||
:malformed_vc_string
|
||||
echo Malformed CRT string "%1"
|
||||
set PHP_SDK_VS=
|
||||
goto out_error
|
||||
)
|
||||
)
|
||||
if ""=="%PHP_SDK_VS:~2%" (
|
||||
goto malformed_vc_string
|
||||
)
|
||||
set /a TMP_CHK=%PHP_SDK_VS:~2%
|
||||
if 14 gtr %TMP_CHK% (
|
||||
if "0"=="%TMP_CHK%" (
|
||||
if not "0"=="%PHP_SDK_VS:~2%" (
|
||||
set TMP_CHK=
|
||||
goto malformed_vc_string
|
||||
)
|
||||
)
|
||||
|
||||
echo At least vc14 is required
|
||||
set PHP_SDK_VS=
|
||||
set TMP_CHK=
|
||||
goto out_error
|
||||
)
|
||||
set PHP_SDK_VS_NUM=%TMP_CHK%
|
||||
set TMP_CHK=
|
||||
|
||||
if /i not "%2"=="x64" (
|
||||
if /i not "%2"=="x86" (
|
||||
@@ -27,7 +51,6 @@ if /i not "%2"=="x64" (
|
||||
)
|
||||
)
|
||||
|
||||
set PHP_SDK_VC=%1
|
||||
set PHP_SDK_ARCH=%2
|
||||
|
||||
rem check OS arch
|
||||
@@ -45,58 +68,95 @@ if not errorlevel 1 (
|
||||
set TMPKEY=
|
||||
|
||||
rem get vc base dir
|
||||
if /i "%1"=="vc14" (
|
||||
if 15 gtr %PHP_SDK_VS_NUM% (
|
||||
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
|
||||
set TMPKEY=HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%PHP_SDK_VC:~2%.0\Setup\VC
|
||||
set TMPKEY=HKLM\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%PHP_SDK_VS:~2%.0\Setup\VC
|
||||
) else (
|
||||
set TMPKEY=HKLM\SOFTWARE\Microsoft\VisualStudio\%PHP_SDK_VC:~2%.0\Setup\VC
|
||||
set TMPKEY=HKLM\SOFTWARE\Microsoft\VisualStudio\%PHP_SDK_VS:~2%.0\Setup\VC
|
||||
)
|
||||
reg query !TMPKEY! /v ProductDir >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Couldn't determine VC%PHP_SDK_VC:~2% directory
|
||||
echo Couldn't determine VC%PHP_SDK_VS:~2% directory
|
||||
goto out_error;
|
||||
)
|
||||
for /f "tokens=2*" %%a in ('reg query !TMPKEY! /v ProductDir') do set PHP_SDK_VC_DIR=%%b
|
||||
) else (
|
||||
rem vc15 support only for now, could parse out and pass on later
|
||||
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version 15 -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do set PHP_SDK_VC_DIR=%%b\VC
|
||||
rem build the version range, e.g. "[15,16)"
|
||||
set /a PHP_SDK_VS_RANGE=PHP_SDK_VS_NUM + 1
|
||||
set PHP_SDK_VS_RANGE="[%PHP_SDK_VS_NUM%,!PHP_SDK_VS_RANGE%!)"
|
||||
|
||||
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version !PHP_SDK_VS_RANGE! -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do (
|
||||
set PHP_SDK_VC_DIR=%%b\VC
|
||||
)
|
||||
if not exist "!PHP_SDK_VC_DIR!" (
|
||||
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version !PHP_SDK_VS_RANGE! -products Microsoft.VisualStudio.Product.BuildTools -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do (
|
||||
set PHP_SDK_VC_DIR=%%b\VC
|
||||
)
|
||||
if not exist "!PHP_SDK_VC_DIR!" (
|
||||
rem check for a preview release
|
||||
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version !PHP_SDK_VS_RANGE! -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do (
|
||||
set PHP_SDK_VC_DIR=%%b\VC
|
||||
)
|
||||
if not exist "!PHP_SDK_VC_DIR!" (
|
||||
echo Could not determine '%PHP_SDK_VS%' directory
|
||||
goto out_error;
|
||||
)
|
||||
)
|
||||
)
|
||||
set VSCMD_ARG_no_logo=nologo
|
||||
)
|
||||
set TMPKEY=
|
||||
set PHP_SDK_VS_RANGE=
|
||||
|
||||
rem get sdk dir
|
||||
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1
|
||||
) else (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1
|
||||
)
|
||||
for /f "tokens=2*" %%a in ('reg query "!TMPKEY!" /v InstallationFolder') do (
|
||||
if exist "%%b\Include\um\Windows.h" (
|
||||
set PHP_SDK_WIN_SDK_DIR=%%b
|
||||
if 15 gtr %PHP_SDK_VS_NUM% (
|
||||
rem get sdk dir
|
||||
rem if 10.0 is available, it's ok
|
||||
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0
|
||||
) else (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0
|
||||
)
|
||||
)
|
||||
if not defined PHP_SDK_WIN_SDK_DIR (
|
||||
for /f "tokens=2*" %%a in ('reg query "!TMPKEY!" /v InstallationFolder') do (
|
||||
for /f "tokens=2*" %%c in ('reg query "!TMPKEY!" /v ProductVersion') do (
|
||||
if exist "%%bInclude\%%d.0\um\Windows.h" (
|
||||
goto got_sdk
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
rem Otherwise 8.1 should be available anyway
|
||||
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1
|
||||
) else (
|
||||
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1
|
||||
)
|
||||
for /f "tokens=2*" %%a in ('reg query "!TMPKEY!" /v InstallationFolder') do (
|
||||
if exist "%%b\Include\um\Windows.h" (
|
||||
goto got_sdk
|
||||
)
|
||||
)
|
||||
|
||||
echo Windows SDK not found.
|
||||
goto out_error;
|
||||
:got_sdk
|
||||
set TMPKEY=
|
||||
)
|
||||
set TMPKEY=
|
||||
|
||||
|
||||
if /i "%PHP_SDK_ARCH%"=="x64" (
|
||||
if /i "%1"=="vc14" (
|
||||
set PHP_SDK_VC_SHELL_CMD="!PHP_SDK_VC_DIR!\vcvarsall.bat" amd64
|
||||
if 15 gtr %PHP_SDK_VS_NUM% (
|
||||
set PHP_SDK_VS_SHELL_CMD="!PHP_SDK_VC_DIR!\vcvarsall.bat" amd64
|
||||
) else (
|
||||
set PHP_SDK_VC_SHELL_CMD="!PHP_SDK_VC_DIR!\Auxiliary\Build\vcvarsall.bat" amd64
|
||||
set PHP_SDK_VS_SHELL_CMD="!PHP_SDK_VC_DIR!\Auxiliary\Build\vcvarsall.bat" amd64
|
||||
)
|
||||
) else (
|
||||
if /i "%1"=="vc14" (
|
||||
set PHP_SDK_VC_SHELL_CMD="!PHP_SDK_VC_DIR!\vcvarsall.bat" x86
|
||||
if 15 gtr %PHP_SDK_VS_NUM% (
|
||||
set PHP_SDK_VS_SHELL_CMD="!PHP_SDK_VC_DIR!\vcvarsall.bat" x86
|
||||
) else (
|
||||
set PHP_SDK_VC_SHELL_CMD="!PHP_SDK_VC_DIR!\Auxiliary\Build\vcvarsall.bat" x86
|
||||
set PHP_SDK_VS_SHELL_CMD="!PHP_SDK_VC_DIR!\Auxiliary\Build\vcvarsall.bat" x86
|
||||
)
|
||||
)
|
||||
|
||||
rem echo Visual Studio path %PHP_SDK_VC_DIR%
|
||||
rem echo Visual Studio VC path %PHP_SDK_VC_DIR%
|
||||
rem echo Windows SDK path %PHP_SDK_WIN_SDK_DIR%
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@echo off
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
rem Add necessary dirs to the path
|
||||
|
||||
set PHP_SDK_BIN_PATH=%~dp0
|
||||
@@ -15,5 +17,12 @@ set PHP_SDK_PHP_CMD=%PHP_SDK_BIN_PATH%\php\do_php.bat
|
||||
|
||||
set PATH=%PHP_SDK_BIN_PATH%;%PHP_SDK_MSYS2_PATH%;%PATH%
|
||||
|
||||
exit /b
|
||||
for /f "tokens=1* delims=: " %%a in ('link /?') do (
|
||||
set PHP_SDK_VC_TOOLSET_VER=%%b
|
||||
goto break0
|
||||
)
|
||||
:break0
|
||||
set PHP_SDK_VC_TOOLSET_VER=%PHP_SDK_VC_TOOLSET_VER:~-13%
|
||||
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@echo off
|
||||
|
||||
cmd /c "exit /b 0"
|
||||
|
||||
if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
call %~dp0phpsdk_setvars.bat
|
||||
if "!PHP_SDK_PHP_CMD!"=="" (
|
||||
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
|
||||
|
||||
%PHP_SDK_PHP_CMD% -r "echo 'PHP SDK ' . file_get_contents(getenv('PHP_SDK_ROOT_PATH') . '\\VERSION');"
|
||||
|
||||
exit /b
|
||||
exit /b %errorlevel%
|
||||
|
||||
|
||||
BIN
bin/re2c.exe
BIN
bin/re2c.exe
Binary file not shown.
BIN
bin/sqlite3.exe
Normal file
BIN
bin/sqlite3.exe
Normal file
Binary file not shown.
BIN
bin/vswhere.exe
BIN
bin/vswhere.exe
Binary file not shown.
47
doc/phpsdk_pgo_prep_elevated.bat.example
Normal file
47
doc/phpsdk_pgo_prep_elevated.bat.example
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
|
||||
@echo off
|
||||
rem These are default ports for the servers used for the training. If these
|
||||
rem ports are changed in the config templates, the commands have to be
|
||||
rem adjusted as well. New servers have to be added here as well. Run this
|
||||
rem file on the elevated shell before starting the PGO environment setup
|
||||
rem using the relevant port numbers, especially for unattended PGO builds.
|
||||
rem We add opens inbound ports from the default PGO config templates and
|
||||
rem and the one increment by 1, just co cover a simple case the port number
|
||||
rem was incremented by the auto configuration.
|
||||
rem
|
||||
rem Alternatively, the firewall can be disabled on the build host.
|
||||
rem The commands to disable\enable firewall are
|
||||
rem netsh advfirewall set allprofiles state on
|
||||
rem netsh advfirewall set allprofiles state off
|
||||
@echo on
|
||||
|
||||
rem NGINX
|
||||
netsh advfirewall firewall add rule name="NGINX for PGO" dir=in action=allow program="C:\php-snap-build\php-sdk\pgo\work\server\nginx\nginx.exe" profile=private
|
||||
for \l %%p in (8081, 1, 8091) do (
|
||||
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=TCP localport=%%p profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=UDP localport=%%p profile=private
|
||||
)
|
||||
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=TCP localport=80 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=UDP localport=80 profile=private
|
||||
|
||||
rem MariaDB
|
||||
netsh advfirewall firewall add rule name="MariaDB for PGO" dir=in action=allow program="c:\php-snap-build\php-sdk\pgo\work\server\mariadb\bin\mysqld.exe" profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=TCP localport=3307 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=UDP localport=3307 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=TCP localport=3308 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=UDP localport=3308 profile=private
|
||||
|
||||
rem Postgres
|
||||
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=TCP localport=5434 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=UDP localport=5434 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=TCP localport=5435 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=UDP localport=5435 profile=private
|
||||
|
||||
rem PHP
|
||||
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=TCP localport=9001 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=UDP localport=9001 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=TCP localport=9002 profile=private
|
||||
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=UDP localport=9002 profile=private
|
||||
|
||||
|
||||
144
doc/task.c
144
doc/task.c
@@ -1,72 +1,72 @@
|
||||
/**
|
||||
* Run the passed command line hidden, suitable for a scheduled task.
|
||||
* Author: Anatol Belski <ab@php.net>
|
||||
* License: BSD 2-Clause
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CMD_PRE "cmd.exe /c "
|
||||
#define CMD_PRE_LEN (sizeof(CMD_PRE)-1)
|
||||
|
||||
#ifdef DEBUG
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
#else
|
||||
int
|
||||
APIENTRY WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPTSTR in_cmd, int show)
|
||||
#endif
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD exit_code;
|
||||
|
||||
char *cmd = NULL;
|
||||
size_t cmd_len = 0, arg_len = 0;
|
||||
char *arg = strchr(GetCommandLine(), ' ');
|
||||
|
||||
if (!arg) {
|
||||
return 3;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("passed cmd: '%s'\n", arg);
|
||||
#endif
|
||||
|
||||
arg_len = strlen(arg);
|
||||
cmd_len = CMD_PRE_LEN + arg_len + 1;
|
||||
|
||||
cmd = malloc(cmd_len * sizeof(char));
|
||||
memmove(cmd, CMD_PRE, CMD_PRE_LEN);
|
||||
memmove(cmd + CMD_PRE_LEN, arg, arg_len);
|
||||
cmd[cmd_len-1] = '\0';
|
||||
#ifdef DEBUG
|
||||
printf("constructed cmd: '%s'\n", cmd);
|
||||
#endif
|
||||
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
ZeroMemory( &pi, sizeof(pi) );
|
||||
|
||||
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
|
||||
CloseHandle( pi.hThread );
|
||||
} else {
|
||||
free(cmd);
|
||||
printf( "Error: CreatePracess 0x%08lx \n", GetLastError() );
|
||||
return 3;
|
||||
}
|
||||
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
|
||||
CloseHandle( pi.hProcess );
|
||||
|
||||
free(cmd);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the passed command line hidden, suitable for a scheduled task.
|
||||
* Author: Anatol Belski <ab@php.net>
|
||||
* License: BSD 2-Clause
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CMD_PRE "cmd.exe /c "
|
||||
#define CMD_PRE_LEN (sizeof(CMD_PRE)-1)
|
||||
|
||||
#ifdef DEBUG
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
#else
|
||||
int
|
||||
APIENTRY WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPTSTR in_cmd, int show)
|
||||
#endif
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD exit_code;
|
||||
|
||||
char *cmd = NULL;
|
||||
size_t cmd_len = 0, arg_len = 0;
|
||||
char *arg = strchr(GetCommandLine(), ' ');
|
||||
|
||||
if (!arg) {
|
||||
return 3;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("passed cmd: '%s'\n", arg);
|
||||
#endif
|
||||
|
||||
arg_len = strlen(arg);
|
||||
cmd_len = CMD_PRE_LEN + arg_len + 1;
|
||||
|
||||
cmd = malloc(cmd_len * sizeof(char));
|
||||
memmove(cmd, CMD_PRE, CMD_PRE_LEN);
|
||||
memmove(cmd + CMD_PRE_LEN, arg, arg_len);
|
||||
cmd[cmd_len-1] = '\0';
|
||||
#ifdef DEBUG
|
||||
printf("constructed cmd: '%s'\n", cmd);
|
||||
#endif
|
||||
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
ZeroMemory( &pi, sizeof(pi) );
|
||||
|
||||
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
|
||||
CloseHandle( pi.hThread );
|
||||
} else {
|
||||
free(cmd);
|
||||
printf( "Error: CreatePracess 0x%08lx \n", GetLastError() );
|
||||
return 3;
|
||||
}
|
||||
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
|
||||
CloseHandle( pi.hProcess );
|
||||
|
||||
free(cmd);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ rem Task batch example.
|
||||
rem Create a task, put an action with the following data:
|
||||
rem Action: start a program
|
||||
rem Program/script: C:\php-sdk\bin\task.exe
|
||||
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc14 -a x64 -t C:\php-sdk\unattended-build-task.bat"
|
||||
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc15 -a x64 -t C:\php-sdk\unattended-build-task.bat"
|
||||
rem Run the task
|
||||
|
||||
set LOG_NAME=%PHP_SDK_VC%-%PHP_SDK_ARCH%-task.log
|
||||
|
||||
pushd C:\php-sdk\php70\vc14\x64\php-src
|
||||
pushd C:\php-sdk\php72\vc14\x64\php-src
|
||||
|
||||
git pull --rebase > %LOG_NAME% 2>&1
|
||||
|
||||
|
||||
26
lib/php/autoload.php
Normal file
26
lib/php/autoload.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($name) {
|
||||
$fl = __DIR__ . DIRECTORY_SEPARATOR . "libsdk" . DIRECTORY_SEPARATOR . $name . ".php";
|
||||
|
||||
if (file_exists($fl)) {
|
||||
require_once $fl;
|
||||
}
|
||||
});
|
||||
|
||||
spl_autoload_register(function($name) {
|
||||
$fl = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases" . DIRECTORY_SEPARATOR . $name . ".php";
|
||||
|
||||
if (file_exists($fl)) {
|
||||
require_once $fl;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -1,25 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Dependency;
|
||||
namespace SDK\Build\Dependency;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Exception;
|
||||
use SDK\{Exception, FileOps};
|
||||
|
||||
class Fetcher
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $host;
|
||||
protected $port;
|
||||
protected $stability;
|
||||
protected $arch;
|
||||
protected $series;
|
||||
protected $scheme;
|
||||
|
||||
|
||||
public function __construct(string $host, int $port, string $arch = NULL, string $stability = NULL, Series $series = NULL)
|
||||
public function __construct(string $host, int $port, string $scheme = "https", string $arch = NULL, string $stability = NULL, Series $series = NULL)
|
||||
{/*{{{*/
|
||||
$this->stability = $stability;
|
||||
$this->arch = $arch;
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->scheme = $scheme;
|
||||
$this->series = $series;
|
||||
}/*}}}*/
|
||||
|
||||
public function getSeries() : Series
|
||||
@@ -27,23 +31,30 @@ class Fetcher
|
||||
return $this->series;
|
||||
}/*}}}*/
|
||||
|
||||
public function setSeries(Series $series)
|
||||
public function setSeries(Series $series) : void
|
||||
{/*{{{*/
|
||||
$this->series = $series;
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO more robust implementation. */
|
||||
/* TODO implement indicator. */
|
||||
public function getByUri($uri) : string
|
||||
public function getByUri(string $uri, int $retries = 3) : string
|
||||
{/*{{{*/
|
||||
$url = "http://{$this->host}:{$this->port}$uri";
|
||||
$s = file_get_contents($url);
|
||||
$url = "{$this->scheme}://{$this->host}:{$this->port}$uri";
|
||||
$ret = false;
|
||||
|
||||
if (false === $s) {
|
||||
throw new Exception("failed to fetch $url");
|
||||
retry:
|
||||
try {
|
||||
$ret = $this->download($url);
|
||||
} catch (Exception $e) {
|
||||
if ($retries > 0) {
|
||||
sleep(1);
|
||||
$retries--;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
return $s;
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
/*protected function fetch($uri) : string
|
||||
@@ -1,11 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Dependency;
|
||||
namespace SDK\Build\Dependency;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Cache;
|
||||
use SDK\Exception;
|
||||
use SDK\FileOps;
|
||||
use SDK\{Config, Cache, Exception, FileOps, Lock};
|
||||
|
||||
class Manager
|
||||
{
|
||||
@@ -14,8 +11,10 @@ class Manager
|
||||
protected $stability;
|
||||
protected $arch;
|
||||
protected $path;
|
||||
protected $cache;
|
||||
protected $series;
|
||||
protected $fetcher;
|
||||
protected $updatesFlag = NULL;
|
||||
|
||||
public function __construct(string $path, string $stability, string $arch)
|
||||
{/*{{{*/
|
||||
@@ -26,7 +25,8 @@ class Manager
|
||||
|
||||
$host = Config::getDepsHost();
|
||||
$port = Config::getDepsPort();
|
||||
$fetcher = new Fetcher($host, $port, $this->arch, $this->stability);
|
||||
$scheme = Config::getDepsUriScheme();
|
||||
$fetcher = new Fetcher($host, $port, $scheme, $this->arch, $this->stability);
|
||||
$series = new Series($this->stability, $this->arch, $this->cache, NULL);
|
||||
$fetcher->setSeries($series);
|
||||
$series->setFetcher($fetcher);
|
||||
@@ -35,23 +35,38 @@ class Manager
|
||||
$this->series = $series;
|
||||
}/*}}}*/
|
||||
|
||||
protected function getTmpSeriesPath()
|
||||
protected function getTmpSeriesPath() : string
|
||||
{/*{{{*/
|
||||
return Config::getTmpDir() . DIRECTORY_SEPARATOR . $this->series->getname();
|
||||
}/*}}}*/
|
||||
|
||||
public function updatesAvailable() : bool
|
||||
{/*{{{*/
|
||||
return $this->series->updatesAvailable();
|
||||
if (NULL !== $this->updatesFlag) {
|
||||
return $this->updatesFlag;
|
||||
}
|
||||
|
||||
$this->updatesFlag = $this->series->updatesAvailable() || !file_exists(Config::getDepsLocalPath());
|
||||
return $this->updatesFlag;
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO and implement --force. */
|
||||
/* FIXME implement rollback */
|
||||
public function performUpdate(string &$msg = NULL)
|
||||
public function performUpdate(string &$msg = NULL, bool $force = false, bool $backup = true) : void
|
||||
{/*{{{*/
|
||||
if (!$this->updatesAvailable()) {
|
||||
$msg = "No updates are available";
|
||||
return;
|
||||
if (!$force) {
|
||||
if (!$this->updatesAvailable()) {
|
||||
$msg .= "No updates are available";
|
||||
return;
|
||||
}
|
||||
|
||||
$lock = new Lock(Config::getDepsLocalPath());
|
||||
if (!$lock->locked()) {
|
||||
$msg .= "Dependencies was updated by another process.";
|
||||
echo "Another process is updating same dependency path. I'm just going to wait for it to finish and then exit.", PHP_EOL;
|
||||
$lock->exclusive(true);
|
||||
unset($lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$series_data = $this->series->getData();
|
||||
@@ -82,17 +97,32 @@ class Manager
|
||||
}
|
||||
|
||||
if (file_exists($this->path)) {
|
||||
$suffix = date("YmdHi");
|
||||
$new_path = "{$this->path}.$suffix";
|
||||
if ($backup) {
|
||||
$suffix = date("YmdHi");
|
||||
$new_path = "{$this->path}.$suffix";
|
||||
|
||||
/* This is fine, it's gonna be on the same drive. */
|
||||
if (!$this->mv($this->path, $new_path)) {
|
||||
throw new Exception("Unable to rename '{$this->path}' to '$new_path'");
|
||||
/* This is fine, it's gonna be on the same drive. */
|
||||
if (!$this->mv($this->path, $new_path)) {
|
||||
if (!$force) {
|
||||
unset($lock);
|
||||
}
|
||||
throw new Exception("Unable to rename '{$this->path}' to '$new_path'");
|
||||
}
|
||||
} else {
|
||||
if (!$this->rm($this->path)) {
|
||||
if (!$force) {
|
||||
unset($lock);
|
||||
}
|
||||
throw new Exception("Unable to remove the current dependency dir at '{$this->path}'");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$up = dirname($this->path);
|
||||
if (!file_exists($up)) {
|
||||
if (!$this->md($up)) {
|
||||
if (!$force) {
|
||||
unset($lock);
|
||||
}
|
||||
throw new Exception("Unable to create '{$this->path}'");
|
||||
}
|
||||
}
|
||||
@@ -106,9 +136,17 @@ class Manager
|
||||
$this->series->cache();
|
||||
|
||||
/* save new series file, move the updated deps and backup the old ones, cleanup.*/
|
||||
$msg = "Updates performed successfully. " . PHP_EOL;
|
||||
if (isset($new_path)) {
|
||||
$msg .= "Old dependencies backed up into '$new_path'.";
|
||||
$msg .= "Updates performed successfully. " . PHP_EOL;
|
||||
if ($backup) {
|
||||
if (isset($new_path)) {
|
||||
$msg .= "Old dependencies backed up into '$new_path'.";
|
||||
}
|
||||
} else {
|
||||
$msg .= "No backup was created.";
|
||||
}
|
||||
|
||||
if (!$force) {
|
||||
unset($lock);
|
||||
}
|
||||
}/*}}}*/
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Dependency;
|
||||
namespace SDK\Build\Dependency;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Exception;
|
||||
use SDK\{Config, Exception, FileOps};
|
||||
|
||||
class Package
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $name;
|
||||
protected $series;
|
||||
protected $fetcher;
|
||||
@@ -28,7 +29,7 @@ class Package
|
||||
return "$base/{$branch_data['crt']}/$arch/{$this->name}";
|
||||
}/*}}}*/
|
||||
|
||||
public function retrieve(string $path)
|
||||
public function retrieve(string $path) : void
|
||||
{/*{{{*/
|
||||
$this->filepath = $path . DIRECTORY_SEPARATOR . $this->name;
|
||||
|
||||
@@ -39,23 +40,16 @@ class Package
|
||||
fclose($fd);
|
||||
}/*}}}*/
|
||||
|
||||
public function unpack(string $path)
|
||||
public function unpack(string $path) : void
|
||||
{/*{{{*/
|
||||
if (!$this->filepath || !file_exists($this->filepath)) {
|
||||
throw new Exception("Invalid filepath '{$this->filepath}'");
|
||||
}
|
||||
$zip = new \ZipArchive;
|
||||
|
||||
$ret = $zip->open($this->filepath);
|
||||
if (true === $ret) {
|
||||
$zip->extractTo($path);
|
||||
$zip->close();
|
||||
} else {
|
||||
throw new Exception("Failed to unpack, error code '$ret'");
|
||||
}
|
||||
$this->unzip($this->filepath, $path);
|
||||
}/*}}}*/
|
||||
|
||||
public function cleanup()
|
||||
public function cleanup() : void
|
||||
{/*{{{*/
|
||||
unlink($this->filepath);
|
||||
}/*}}}*/
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Dependency;
|
||||
namespace SDK\Build\Dependency;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Cache;
|
||||
@@ -27,7 +27,7 @@ class Series
|
||||
return $this->fetcher;
|
||||
}/*}}}*/
|
||||
|
||||
public function setFetcher(Fetcher $fetcher)
|
||||
public function setFetcher(Fetcher $fetcher) : void
|
||||
{/*{{{*/
|
||||
$this->fetcher = $fetcher;
|
||||
}/*}}}*/
|
||||
@@ -37,14 +37,13 @@ class Series
|
||||
return $this->arch;
|
||||
}/*}}}*/
|
||||
|
||||
public function setArch(string $arch)
|
||||
public function setArch(string $arch) : void
|
||||
{/*{{{*/
|
||||
$this->arch = $arch;
|
||||
}/*}}}*/
|
||||
|
||||
public function getName() : string
|
||||
{/*{{{*/
|
||||
$base = Config::getDepsBaseUri();
|
||||
$branch_data = Config::getCurrentBranchData();
|
||||
|
||||
$file = "packages-" . Config::getCurrentBranchName() . "-{$branch_data['crt']}-{$this->arch}-{$this->stability}.txt";
|
||||
@@ -52,7 +51,7 @@ class Series
|
||||
return $file;
|
||||
}/*}}}*/
|
||||
|
||||
protected function getUri() : string
|
||||
protected function getUri() : string
|
||||
{/*{{{*/
|
||||
$base = Config::getDepsBaseUri();
|
||||
$file = $this->getName();
|
||||
@@ -79,12 +78,12 @@ class Series
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
public function getSavePath()
|
||||
public function getSavePath() : string
|
||||
{/*{{{*/
|
||||
return Config::getCacheDir() . DIRECTORY_SEPARATOR . $this->getname();
|
||||
}/*}}}*/
|
||||
|
||||
public function updatesAvailable()
|
||||
public function updatesAvailable() : bool
|
||||
{/*{{{*/
|
||||
$series_data = $this->getData(true);
|
||||
$series_file = $this->getSavePath();
|
||||
@@ -92,7 +91,7 @@ class Series
|
||||
return $this->cache->cachedContentDiffers($series_file, $series_data);
|
||||
}/*}}}*/
|
||||
|
||||
public function cache(string $path = NULL)
|
||||
public function cache(string $path = NULL) : void
|
||||
{/*{{{*/
|
||||
if (!$path) {
|
||||
$path = $this->getSavePath();
|
||||
233
lib/php/libsdk/SDK/Build/PGO/Abstracts/PHP.php
Normal file
233
lib/php/libsdk/SDK/Build/PGO/Abstracts/PHP.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Abstracts;
|
||||
|
||||
use SDK\Build\PGO\PHP\CLI;
|
||||
use SDK\{Config as SDKConfig, Exception};
|
||||
|
||||
abstract class PHP
|
||||
{
|
||||
protected $php_root;
|
||||
protected $php_ext_root;
|
||||
protected $opcache_file_cache;
|
||||
protected $id;
|
||||
protected $scenario;
|
||||
protected $conf;
|
||||
|
||||
protected function setupPaths()
|
||||
{
|
||||
$this->php_root = $this->getRootDir();
|
||||
if ($this->isDist()) {
|
||||
$this->php_ext_root = $this->php_root . DIRECTORY_SEPARATOR . "ext";
|
||||
if (!file_exists($this->php_ext_root)) {
|
||||
throw new Exception("Extension dir '{$this->php_ext_root}' doesn't exist.");
|
||||
}
|
||||
} else {
|
||||
$this->php_ext_root = $this->php_root;
|
||||
}
|
||||
if ("cache" == $this->scenario) {
|
||||
$this->opcache_file_cache = SDKConfig::getTmpDir() . DIRECTORY_SEPARATOR . $this->id;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO Might be improved. */
|
||||
public function isDist() : bool
|
||||
{
|
||||
return !file_exists("Makefile") && file_exists("php.exe");
|
||||
}
|
||||
|
||||
protected function createEnv() : array
|
||||
{
|
||||
$env = getenv();
|
||||
|
||||
if (!$this->isDist()) {
|
||||
$deps_root = SDKConfig::getDepsLocalPath();
|
||||
foreach ($env as $k => $v) {
|
||||
if (strtoupper($k) == "PATH") {
|
||||
$env[$k] = $deps_root . DIRECTORY_SEPARATOR . "bin;" . $env[$k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$drive = getenv("HOMEDRIVE");
|
||||
$path = getenv("HOMEPATH");
|
||||
if (!$drive || !$path) {
|
||||
$p = SDKConfig::getTmpDir();
|
||||
$drive = substr($p, 0, 2);
|
||||
$path = substr($p, 2);
|
||||
putenv("HOMEDRIVE=$drive");
|
||||
putenv("HOMEPATH=$path");
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
public function getExtRootDir() : string
|
||||
{
|
||||
return $this->php_ext_root;
|
||||
}
|
||||
|
||||
public function getRootDir() : string
|
||||
{
|
||||
if ($this->php_root) {
|
||||
return $this->php_root;
|
||||
}
|
||||
|
||||
/* XXX adapt for any possible PHP variants. */
|
||||
$root = getenv("PHP_SDK_PGO_TEST_PHP_ROOT");
|
||||
if (!$root) {
|
||||
if (!$this->isDist()) {
|
||||
$s = file_get_contents("Makefile");
|
||||
if (preg_match(",BUILD_DIR=(.+),", $s, $m) > 0) {
|
||||
$root = trim($m[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_exists($root)) {
|
||||
throw new Exception("'$root' doesn't exist.");
|
||||
}
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
|
||||
public function getVersion(bool $short = false) : string
|
||||
{
|
||||
$ret = NULL;
|
||||
$cli = new CLI($this->conf, $this->scenario);
|
||||
|
||||
$out = shell_exec($cli->getExeFilename() . " -n -v");
|
||||
|
||||
if ($short) {
|
||||
if (preg_match(",PHP (\d+\.\d+),", $out, $m)) {
|
||||
$ret = $m[1];
|
||||
}
|
||||
} else {
|
||||
if (preg_match(",PHP ([^ ]+),", $out, $m)) {
|
||||
$ret = $m[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL === $ret) {
|
||||
throw new Exception("Failed to determine the test PHP version.");
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function isThreadSafe() : bool
|
||||
{
|
||||
$cli = new CLI($this->conf, $this->scenario);
|
||||
|
||||
$out = shell_exec($cli->getExeFilename() . " -n -v");
|
||||
|
||||
if (preg_match(",NTS,", $out, $m) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Need to cleanup it somewhere. */
|
||||
public function getIniFilename()
|
||||
{
|
||||
$ret = tempnam(sys_get_temp_dir(), "ini");
|
||||
|
||||
$tpl_vars = array(
|
||||
$this->conf->buildTplVarName("php", "extension_dir") => $this->php_ext_root,
|
||||
$this->conf->buildTplVarName("php", "error_log") => $this->getRootDir() . DIRECTORY_SEPARATOR . "pgo_run_error.log",
|
||||
);
|
||||
|
||||
$k = SDKConfig::getCurrentArchName();
|
||||
$scenario_vars = (array)$this->conf->getSectionItem("php", "scenario", $this->scenario, "ini", $k);
|
||||
if ($scenario_vars) {
|
||||
foreach ($scenario_vars as $k => $v) {
|
||||
//$tpl_vars[$this->conf->buildTplVarName("php", "scenario", $this->scenario, str_replace(array(".", "-"), "_", $k))] = $v;
|
||||
$tpl_vars[$this->conf->buildTplVarName("php", str_replace(array(".", "-"), "_", $k))] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special handling, otherwise it'll need functionality to extrapolate ini values. */
|
||||
if ("cache" == $this->scenario) {
|
||||
$tpl_vars[$this->conf->buildTplVarName("php", "opcache", "file_cache")] = $this->opcache_file_cache;
|
||||
}
|
||||
|
||||
$this->conf->processTplFile(
|
||||
$this->getIniTplFilename(),
|
||||
$ret,
|
||||
$tpl_vars
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
protected function getIniTplFilename()
|
||||
{
|
||||
$tpl_path = $this->conf->getTplDir("php");
|
||||
$version = $this->getVersion(true);
|
||||
$ts = $this->isThreadSafe() ? "ts" : "nts";
|
||||
|
||||
$construct = $tpl_path . DIRECTORY_SEPARATOR . "php-$version-pgo-$ts" . ("default" == $this->scenario ? "" : "-{$this->scenario}") . ".ini";
|
||||
|
||||
if (!file_exists($construct)) {
|
||||
throw new Exception("Couldn't locate PHP config under '$construct'.");
|
||||
}
|
||||
|
||||
return $construct;
|
||||
}
|
||||
|
||||
public function exec(string $php_cmd, string $args = NULL, array $extra_env = array()) : int
|
||||
{
|
||||
$env = $this->createEnv();
|
||||
$exe = $this->getExeFilename();
|
||||
$ini = $this->getIniFilename();
|
||||
|
||||
$cert_path = getenv("PHP_SDK_ROOT_PATH") . "\\msys2\\usr\\ssl\\cert.pem";
|
||||
$ini .= " -d curl.cainfo=$cert_path";
|
||||
|
||||
$spent_key = array();
|
||||
foreach ($env as $k0 => &$v0) {
|
||||
foreach ($extra_env as $k1 => $v1) {
|
||||
if (strtoupper($k0) == strtoupper($k1)) {
|
||||
/* XXX some more things could require extra handling. */
|
||||
if (strtoupper($k0) == "PATH") {
|
||||
$v0 = "$v1;$v0";
|
||||
} else {
|
||||
$v0 = $v1;
|
||||
}
|
||||
$spent_key[] = $k1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($extra_env as $k => $v) {
|
||||
if (in_array($k, $spent_key)) {
|
||||
continue;
|
||||
}
|
||||
$env[$k] = $v;
|
||||
}
|
||||
|
||||
$cmd = "$exe -n -c $ini " . ($args ? "$args " : "") . $php_cmd;
|
||||
|
||||
$desc = array(
|
||||
0 => array("file", "php://stdin", "r"),
|
||||
1 => array("file", "php://stdout", "w"),
|
||||
2 => array("file", "php://stderr", "w")
|
||||
);
|
||||
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $env);
|
||||
|
||||
return proc_close($p);
|
||||
}
|
||||
|
||||
public function getIdString(): string
|
||||
{
|
||||
return $this->getVersion() . "-"
|
||||
. SDKConfig::getCurrentCrtName() . "-"
|
||||
. ($this->isThreadSafe() ? "ts" : "nts") . "-"
|
||||
. SDKConfig::getCurrentArchName()
|
||||
. "-" . substr(md5(uniqid()), 0, 8);
|
||||
}
|
||||
}
|
||||
19
lib/php/libsdk/SDK/Build/PGO/Abstracts/Server.php
Normal file
19
lib/php/libsdk/SDK/Build/PGO/Abstracts/Server.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Abstracts;
|
||||
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
|
||||
abstract class Server
|
||||
{
|
||||
public function getName() : string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getPhp() : Interfaces\PHP
|
||||
{
|
||||
return $this->php;
|
||||
}
|
||||
|
||||
}
|
||||
151
lib/php/libsdk/SDK/Build/PGO/Abstracts/TrainingCase.php
Normal file
151
lib/php/libsdk/SDK/Build/PGO/Abstracts/TrainingCase.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Abstracts;
|
||||
|
||||
use SDK\FileOps;
|
||||
use SDK\Build\PGO\Tool;
|
||||
|
||||
abstract class TrainingCase
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
const TYPE_WEB = "web";
|
||||
const TYPE_CLI = "cli";
|
||||
|
||||
protected $stat = array();
|
||||
/** @var \SDK\Build\PGO\Config */
|
||||
protected $conf;
|
||||
|
||||
public function getType() : string
|
||||
{
|
||||
$type = $this->conf->getSectionItem($this->getName(), "type");
|
||||
|
||||
if (!$type) {
|
||||
$type = "web";
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function run() : void
|
||||
{
|
||||
$training = new Tool\Training($this->conf, $this);
|
||||
$pgo = new Tool\PGO($this->conf, $this->php);
|
||||
|
||||
echo "Running " . $this->getName() . " training.\n";
|
||||
|
||||
$max_runs = $this->max_runs ?? 1;
|
||||
$max_runs = (int)$max_runs > 0 ? $max_runs : 1;
|
||||
$training->run($max_runs, $stat);
|
||||
|
||||
if ($this->getType() == "web") {
|
||||
echo "HTTP responses:\n";
|
||||
foreach ($stat["http_code"] as $code => $num) {
|
||||
printf(" %d received %d times\n", $code, $num);
|
||||
}
|
||||
if (count($stat["not_ok"]) > 0) {
|
||||
foreach($stat["not_ok"] as $st) {
|
||||
echo "Code: $st[http_code], URL: $st[url]", ($st["redirect_url"] ? ", Redirected to: $st[redirect_url]" : ""), "\n";
|
||||
}
|
||||
printf("\033[31m WARNING: Not all HTTP responses have indicated success, the PGO data might be unsuitable!\033[0m\n");
|
||||
}
|
||||
}
|
||||
|
||||
echo $this->getName() . " training complete.\n";
|
||||
|
||||
echo "Dumping PGO data for " . $this->getName() . ".\n";
|
||||
$pgo->dump();
|
||||
echo "Finished dumping training data for " . $this->getName() . ".\n";
|
||||
}
|
||||
|
||||
public function getHttpPort() : string
|
||||
{
|
||||
$port = $this->conf->getSectionItem($this->getName(), "http_port");
|
||||
if (!$port) {
|
||||
$port = $this->conf->getNextPort();
|
||||
$this->conf->setSectionItem($this->getName(), "http_port", $port);
|
||||
}
|
||||
|
||||
return $port;
|
||||
}
|
||||
|
||||
public function getHttpHost() : string
|
||||
{
|
||||
$host = $this->conf->getSectionItem($this->getName(), "http_host");
|
||||
if (!$host) {
|
||||
$srv = $this->conf->getSrv(
|
||||
$this->conf->getSectionItem($this->getName(), "srv_http")
|
||||
);
|
||||
if ($srv) {
|
||||
$host = $this->conf->getSectionItem($srv->getName(), "host");
|
||||
$this->conf->setSectionItem($this->getName(), "http_host", $host);
|
||||
}
|
||||
}
|
||||
|
||||
return $host;
|
||||
}
|
||||
|
||||
protected function getDbConf(string $item) : string
|
||||
{
|
||||
$val = $this->conf->getSectionItem($this->getName(), "db_$item");
|
||||
if (!$val) {
|
||||
$srv = $this->conf->getSrv(
|
||||
$this->conf->getSectionItem($this->getName(), "srv_db")
|
||||
);
|
||||
if ($srv) {
|
||||
$val = $this->conf->getSectionItem($srv->getName(), $item);
|
||||
$this->conf->setSectionItem($this->getName(), "db_$item", $val);
|
||||
}
|
||||
}
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
public function getDbPass() : string
|
||||
{
|
||||
return $this->getDbConf("pass");
|
||||
}
|
||||
|
||||
public function getDbUser() : string
|
||||
{
|
||||
return $this->getDbConf("user");
|
||||
}
|
||||
|
||||
public function getDbHost() : string
|
||||
{
|
||||
return $this->getDbConf("host");
|
||||
}
|
||||
|
||||
public function getDbPort() : string
|
||||
{
|
||||
return $this->getDbConf("port");
|
||||
}
|
||||
|
||||
public function httpStatusOk(int $status) : bool
|
||||
{
|
||||
$ok = array();
|
||||
|
||||
$ok = array_merge($ok, range(200, 206));
|
||||
$ok = array_merge($ok, range(300, 307));
|
||||
|
||||
return in_array($status, $ok);
|
||||
}
|
||||
|
||||
public function probeUrl(string $url) : bool
|
||||
{
|
||||
$ret = false;
|
||||
$c = curl_init($url);
|
||||
|
||||
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($c);
|
||||
|
||||
if (!curl_errno($c)) {
|
||||
$st = curl_getinfo($c, CURLINFO_HTTP_CODE);
|
||||
$ret = $this->httpStatusOk((int)$st);
|
||||
}
|
||||
|
||||
curl_close($c);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
369
lib/php/libsdk/SDK/Build/PGO/Config.php
Normal file
369
lib/php/libsdk/SDK/Build/PGO/Config.php
Normal file
@@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO;
|
||||
|
||||
use SDK\Exception;
|
||||
|
||||
class Config
|
||||
{
|
||||
const MODE_INIT = 0;
|
||||
const MODE_RUN = 1;
|
||||
const MODE_REINIT = 2; /* currently unused */
|
||||
const MODE_CHECK_INIT = 3;
|
||||
|
||||
protected $mode;
|
||||
protected $last_port = 8081;
|
||||
protected $sections = array();
|
||||
protected $scenario = "default";
|
||||
protected $tpl_vars = array();
|
||||
protected $srv = array();
|
||||
|
||||
public function __construct(int $mode = self::MODE_RUN)
|
||||
{
|
||||
if (self::MODE_CHECK_INIT == $mode) {
|
||||
// XXX The check is simple right now, so this is sufficient.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->isInitialized()) {
|
||||
$this->initWorkDir();
|
||||
}
|
||||
|
||||
if (self::MODE_REINIT == $mode) {
|
||||
$fn = $this->getWorkSectionsFilename();
|
||||
if (file_exists($fn)) {
|
||||
unlink($fn);
|
||||
}
|
||||
$mode = self::MODE_INIT;
|
||||
}
|
||||
|
||||
$this->mode = $mode;
|
||||
|
||||
|
||||
if (self::MODE_INIT == $mode) {
|
||||
foreach (array("nginx", "mariadb", "postgresql", "php") as $i) {
|
||||
$this->importSectionFromDir($i, $this->getTplDir() . DIRECTORY_SEPARATOR . $i);
|
||||
}
|
||||
} else if (self::MODE_RUN == $mode) {
|
||||
$fn = $this->getWorkSectionsFilename();
|
||||
if (!file_exists($fn)) {
|
||||
throw new Exception("Required config doesn't exist under '$fn'.");
|
||||
}
|
||||
$s = file_get_contents($fn);
|
||||
$this->sections = json_decode($s, true);
|
||||
foreach($this->sections as $k => $v) {
|
||||
$this->importTplVars($k, $v);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Exception("Unknown config mode '$mode'.");
|
||||
}
|
||||
}
|
||||
|
||||
protected function initWorkDir() : void
|
||||
{
|
||||
if (!mkdir($this->getWorkDir())) {
|
||||
throw new Exception("Failed to create " . $this->getWorkDir());
|
||||
}
|
||||
}
|
||||
|
||||
public function isInitialized()
|
||||
{
|
||||
/* XXX Could be some better check. */
|
||||
return is_dir($this->getWorkDir());
|
||||
}
|
||||
|
||||
|
||||
public function getToolsDir() : string
|
||||
{
|
||||
$base = $this->getWorkDir();
|
||||
|
||||
return $base . DIRECTORY_SEPARATOR . "tools";
|
||||
}
|
||||
|
||||
public function getWorkDir() : string
|
||||
{
|
||||
$base = getenv("PHP_SDK_ROOT_PATH");
|
||||
|
||||
return $base . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "work";
|
||||
}
|
||||
|
||||
public function getPkgCacheDir() : string
|
||||
{
|
||||
$base = $this->getWorkDir();
|
||||
|
||||
return $base . DIRECTORY_SEPARATOR . "package_cache";
|
||||
}
|
||||
|
||||
public function getJobDir(string $name = NULL) : string
|
||||
{
|
||||
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "job";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getSrvDir(string $name = NULL) : string
|
||||
{
|
||||
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "server";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getHtdocs(string $name = NULL) : string
|
||||
{
|
||||
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getTplDir(string $name = NULL) : string
|
||||
{
|
||||
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "tpl";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getCaseWorkDir(string $name = NULL) : string
|
||||
{
|
||||
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getCasesTplDir(string $name = NULL) : string
|
||||
{
|
||||
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases";
|
||||
|
||||
if ($name) {
|
||||
$ret .= DIRECTORY_SEPARATOR . $name;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function sectionItemExists(...$args) : bool
|
||||
{
|
||||
$i = 0;
|
||||
$k = strtolower($args[$i]);
|
||||
$it = $this->sections;
|
||||
|
||||
while (array_key_exists($k, $it)) {
|
||||
$it = $it[$k];
|
||||
|
||||
if (++$i >= count($args)) break;
|
||||
|
||||
$k = strtolower($args[$i]);
|
||||
}
|
||||
|
||||
return $i == count($args);
|
||||
}
|
||||
|
||||
public function getSectionItem(...$args)
|
||||
{
|
||||
$i = 0;
|
||||
$k = strtolower($args[$i]);
|
||||
$it = $this->sections;
|
||||
|
||||
while (array_key_exists($k, $it)) {
|
||||
$it = $it[$k];
|
||||
|
||||
if (++$i >= count($args)) break;
|
||||
|
||||
$k = strtolower($args[$i]);
|
||||
}
|
||||
|
||||
if ($i != count($args)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $it;
|
||||
}
|
||||
|
||||
public function setSectionItem(...$args) : void
|
||||
{
|
||||
$val = array_pop($args);
|
||||
|
||||
$i = 0;
|
||||
$k = strtolower($args[$i]);
|
||||
$it = &$this->sections;
|
||||
|
||||
while (true) {
|
||||
$it = &$it[$k];
|
||||
if (++$i >= count($args)) break;
|
||||
$k = strtolower($args[$i]);
|
||||
}
|
||||
|
||||
$it = $val;
|
||||
|
||||
$this->syncTplVars();
|
||||
$this->dump();
|
||||
}
|
||||
|
||||
public function importSectionFromDir(string $name, string $dir) : void
|
||||
{
|
||||
$fn = $dir . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
|
||||
if (!file_exists($fn)) {
|
||||
throw new Exception("Couldn't import section, file '$fn' doesn't exist.");
|
||||
}
|
||||
|
||||
$s = file_get_contents($fn);
|
||||
$this->setSectionItem($name, json_decode($s, true));
|
||||
}
|
||||
|
||||
protected function syncTplVars() : void
|
||||
{
|
||||
$this->tpl_vars = array();
|
||||
foreach ($this->sections as $k => $v) {
|
||||
$this->importTplVars($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
public function buildTplVarName(...$args) : string
|
||||
{
|
||||
$tpl_k = array("PHP_SDK_PGO");
|
||||
|
||||
foreach ($args as $a) {
|
||||
$tpl_k[] = strtoupper($a);
|
||||
}
|
||||
|
||||
return implode("_", $tpl_k);
|
||||
}
|
||||
|
||||
protected function importTplVars(string $section_name, array $section) : void
|
||||
{
|
||||
foreach($section as $k0 => $v0) {
|
||||
|
||||
if (is_array($v0)) {
|
||||
if (substr($k0, -4) == ":env") {
|
||||
/* Don't put env vars as tpl vars for now. */
|
||||
continue;
|
||||
}
|
||||
$this->importTplVars($section_name . "_" . $k0, $v0);
|
||||
} else {
|
||||
$tpl_k = $this->buildTplVarName($section_name, $k0);
|
||||
$this->tpl_vars[$tpl_k] = $v0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function processTpl(string $s, array $additional_vars = array()) : string
|
||||
{
|
||||
$vars = array_merge($this->tpl_vars, $additional_vars);
|
||||
|
||||
$s = str_replace(array_keys($vars), array_values($vars), $s);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
public function processTplFile(string $tpl_fn, string $dst_fn, array $additional_vars = array()) : void
|
||||
{
|
||||
if (!file_exists($tpl_fn)) {
|
||||
throw new Exception("Template file '$tpl_fn' doesn't exist.");
|
||||
}
|
||||
|
||||
$s = file_get_contents($tpl_fn);
|
||||
if (false === $s) {
|
||||
throw new Exception("Couldn't read '$tpl_fn'.");
|
||||
}
|
||||
|
||||
$s = $this->processTpl($s, $additional_vars);
|
||||
|
||||
if (false === file_put_contents($dst_fn, $s)) {
|
||||
throw new Exception("Failed to write '$dst_fn'.");
|
||||
}
|
||||
}
|
||||
|
||||
public function getWorkSectionsFilename()
|
||||
{
|
||||
return $this->getWorkDir() . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
|
||||
}
|
||||
|
||||
public function dump(string $fn = NULL) : void
|
||||
{
|
||||
$fn = $fn ? $fn : $this->getWorkSectionsFilename();
|
||||
|
||||
$s = json_encode($this->sections, JSON_PRETTY_PRINT);
|
||||
|
||||
$ret = file_put_contents($fn, $s);
|
||||
if (false === $ret || strlen($s) !== $ret) {
|
||||
throw new Exception("Errors with writing to '$fn'.");
|
||||
}
|
||||
}
|
||||
|
||||
public function setScenario(string $scenario) : void
|
||||
{
|
||||
if (!in_array($scenario, array("default", "cache"), true)) {
|
||||
throw new Exception("Unknown scenario '$scenario'.");
|
||||
}
|
||||
$this->scenario = $scenario;
|
||||
}
|
||||
|
||||
public function getScenario() : string
|
||||
{
|
||||
return $this->scenario;
|
||||
}
|
||||
|
||||
public function getNextPort() : int
|
||||
{
|
||||
return ++$this->last_port;
|
||||
}
|
||||
|
||||
public function setLastPort(int $port) : void
|
||||
{
|
||||
$this->last_port = $port;
|
||||
}
|
||||
|
||||
public function getSdkPhpCmd() : string
|
||||
{
|
||||
return getenv("PHP_SDK_PHP_CMD");
|
||||
}
|
||||
|
||||
public function addSrv($item) : void
|
||||
{
|
||||
$name = strtolower($item->getName());
|
||||
|
||||
if (isset($this->srv[$name])) {
|
||||
throw new Exception("Server '$name' already exists.");
|
||||
}
|
||||
|
||||
/* XXX Additional checks could not harm. */
|
||||
$this->srv[$name] = $item;
|
||||
}
|
||||
|
||||
public function getSrv(?string $name = NULL)
|
||||
{
|
||||
$ret = NULL;
|
||||
|
||||
$name = strtolower($name);
|
||||
|
||||
if (!$name) {
|
||||
return NULL;
|
||||
} else if ("all" == $name) {
|
||||
return $this->srv;
|
||||
} else if (isset($this->srv[$name])) {
|
||||
return $this->srv[$name];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
272
lib/php/libsdk/SDK/Build/PGO/Controller.php
Normal file
272
lib/php/libsdk/SDK/Build/PGO/Controller.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO;
|
||||
|
||||
use SDK\{Exception, Lock};
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\Build\PGO\Server\{MariaDB, NGINX, PostgreSQL};
|
||||
use SDK\Build\PGO\PHP;
|
||||
use SDK\Build\PGO\Tool\{PGO, PackageWorkman};
|
||||
|
||||
|
||||
/* TODO add bench action */
|
||||
|
||||
class Controller
|
||||
{
|
||||
protected $cmd;
|
||||
protected $scenario;
|
||||
protected $conf;
|
||||
protected $cases;
|
||||
|
||||
public function __construct(string $cmd, ?string $scenario, ?array $cases)
|
||||
{
|
||||
$this->cmd = $cmd;
|
||||
|
||||
if (NULL == $scenario) {
|
||||
$scenario = "default";
|
||||
}
|
||||
$this->scenario = $scenario;
|
||||
$this->cases = $cases;
|
||||
}
|
||||
|
||||
protected function vitalizeSrv()
|
||||
{
|
||||
$all = $this->conf->getSrv("all");
|
||||
|
||||
if (empty($all)) {
|
||||
$php_fcgi_tcp = new PHP\FCGI($this->conf, true);
|
||||
$this->conf->addSrv(new NGINX($this->conf, $php_fcgi_tcp));
|
||||
|
||||
$this->conf->addSrv(new MariaDB($this->conf));
|
||||
/* Uncomment to enable PostgreSQL*/
|
||||
/* $this->conf->addSrv(new PostgreSQL($this->conf));*/
|
||||
|
||||
$all = $this->conf->getSrv("all");
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
protected function setupConfig($cmd)
|
||||
{
|
||||
switch ($cmd) {
|
||||
default:
|
||||
throw new Exception("Unknown action '{$cmd}'.");
|
||||
break;
|
||||
case "check_init":
|
||||
$cnf = new PGOConfig(PGOConfig::MODE_CHECK_INIT);
|
||||
break;
|
||||
case "init":
|
||||
$cnf = new PGOConfig(PGOConfig::MODE_INIT);
|
||||
break;
|
||||
case "train":
|
||||
case "up":
|
||||
case "down":
|
||||
$cnf = new PGOConfig(PGOConfig::MODE_RUN);
|
||||
}
|
||||
$cnf->setScenario($this->scenario);
|
||||
|
||||
return $cnf;
|
||||
}
|
||||
|
||||
public function handle($force)
|
||||
{
|
||||
/*$mode = (int)("init" !== $this->cmd);
|
||||
$mode = (PGOConfig::MODE_INIT == $mode && $force) ? PGOConfig::MODE_REINIT : $mode;
|
||||
$this->conf = new PGOConfig("init" !== $this->cmd);
|
||||
$this->conf->setScenario($this->scenario);*/
|
||||
$this->conf = $this->setupConfig($this->cmd);
|
||||
|
||||
switch ($this->cmd) {
|
||||
default:
|
||||
throw new Exception("Unknown action '{$this->cmd}'.");
|
||||
break;
|
||||
case "init":
|
||||
$lk = new Lock("pgo_init");
|
||||
if (!$lk->locked()) {
|
||||
echo "Another process runs initialization right now, waiting.", PHP_EOL;
|
||||
$lk->exclusive(true);
|
||||
echo "Another process finished running initialization, I quit as well.", PHP_EOL;
|
||||
return;
|
||||
}
|
||||
$this->init($force);
|
||||
break;
|
||||
case "train":
|
||||
$lk = new Lock("pgo_train");
|
||||
if (!$lk->locked()) {
|
||||
echo "Another process runs training right now, I have to wait.", PHP_EOL;
|
||||
$lk->exclusive(true);
|
||||
echo "Another process finished training, I may continue.", PHP_EOL;
|
||||
}
|
||||
$this->train();
|
||||
break;
|
||||
case "up":
|
||||
$this->up();
|
||||
break;
|
||||
|
||||
case "down":
|
||||
$this->down($force);
|
||||
break;
|
||||
case "check_init":
|
||||
// pass
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function initWorkDirs() : void
|
||||
{
|
||||
$dirs = array(
|
||||
$this->conf->getSrvDir(),
|
||||
$this->conf->getToolsDir(),
|
||||
$this->conf->getHtdocs(),
|
||||
$this->conf->getJobDir(),
|
||||
$this->conf->getPkgCacheDir(),
|
||||
);
|
||||
|
||||
foreach ($dirs as $dir) {
|
||||
if (!is_dir($dir)) {
|
||||
if (!mkdir($dir)) {
|
||||
throw new Exception("Failed to create '$dir'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareStandaloneTools(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
$php = new PHP\CLI($this->conf);
|
||||
|
||||
$composer = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar";
|
||||
if (!file_exists($composer) || $force) {
|
||||
/* XXX this needs to go into the config, specifically for composer maybe even separate class. */
|
||||
$url = "https://getcomposer.org/installer";
|
||||
/* XXX remove the explicit version option when symfony demo is fixed. */
|
||||
$tool = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer-setup.php";
|
||||
$pw->fetch($url, $tool, $force);
|
||||
$php->exec("$tool --install-dir=" . $this->conf->getToolsDir());
|
||||
unlink($tool);
|
||||
}
|
||||
}
|
||||
|
||||
public function init(bool $force = false)
|
||||
{
|
||||
echo "\nInitializing PGO training environment.\n\n";
|
||||
|
||||
$this->initWorkDirs();
|
||||
|
||||
$pw = new PackageWorkman($this->conf);
|
||||
|
||||
$this->prepareStandaloneTools($pw, $force);
|
||||
|
||||
$srvs = $this->vitalizeSrv();
|
||||
foreach ($srvs as $srv) {
|
||||
$srv->prepareInit($pw, $force);
|
||||
}
|
||||
|
||||
foreach (new TrainingCaseIterator($this->conf) as $handler) {
|
||||
$handler->prepareInit($pw, $force);
|
||||
}
|
||||
|
||||
foreach ($srvs as $srv) {
|
||||
$srv->init();
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
foreach (new TrainingCaseIterator($this->conf) as $handler) {
|
||||
$handler->init();
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
echo "PGO training environment Initialization complete.\n";
|
||||
}
|
||||
|
||||
public function isInitialized()
|
||||
{
|
||||
return $this->conf->isinitialized();
|
||||
}
|
||||
|
||||
public function train()
|
||||
{
|
||||
if (!$this->isInitialized()) {
|
||||
throw new Exception("PGO training environment is not initialized.");
|
||||
}
|
||||
|
||||
echo "\nStarting PGO training using scenario '{$this->scenario}'.\n\n";
|
||||
$this->up();
|
||||
|
||||
/* Clean the PGO db files, only needed once.
|
||||
Imply also, that any data created during init or
|
||||
startup is wasted. It is done by dumpbing the data
|
||||
from the current running processes and subsequently
|
||||
removing the files. */
|
||||
$php = $this->conf->getSrv("nginx")->getPhp();
|
||||
$pgo = new PGO($this->conf, $php);
|
||||
$pgo->waste();
|
||||
$pgo->clean();
|
||||
unset($pgo);
|
||||
|
||||
$cases = $this->cases;
|
||||
foreach (new TrainingCaseIterator($this->conf) as $handler) {
|
||||
$name = $handler->getName();
|
||||
/* Just a white list handling for now. */
|
||||
if (is_array($cases)) {
|
||||
if (!in_array($name, $cases)) {
|
||||
continue;
|
||||
}
|
||||
$key = array_search($name, $cases);
|
||||
unset($cases[$key]);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
$handler->run();
|
||||
}
|
||||
if (is_array($cases) && !empty($cases)) {
|
||||
echo "\n\033[31m WARNING: The cases " . implode(",", $cases) . " don't exist and was ignored!\033[0m\n\n";
|
||||
}
|
||||
|
||||
/* All the PGC files are merged, simply clean them out. */
|
||||
$pgo = new PGO($this->conf, $php);
|
||||
$pgo->clean(true, false);
|
||||
unset($pgo);
|
||||
|
||||
$this->down();
|
||||
echo "PGO training complete.\n";
|
||||
}
|
||||
|
||||
public function up()
|
||||
{
|
||||
|
||||
if (!$this->isInitialized()) {
|
||||
throw new Exception("PGO training environment is not initialized.");
|
||||
}
|
||||
echo "\nStarting up PGO environment.\n\n";
|
||||
|
||||
foreach ($this->vitalizeSrv("all") as $srv) {
|
||||
$srv->up();
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
echo "The PGO environment is up.\n";
|
||||
}
|
||||
|
||||
public function down(bool $force = false)
|
||||
{
|
||||
if (!$this->isInitialized()) {
|
||||
throw new Exception("PGO training environment is not initialized.");
|
||||
}
|
||||
/* XXX check it was started of course. */
|
||||
echo "\nShutting down PGO environment.\n\n";
|
||||
|
||||
foreach ($this->vitalizeSrv("all") as $srv) {
|
||||
$srv->down($force);
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
echo "The PGO environment has been shut down.\n";
|
||||
}
|
||||
}
|
||||
16
lib/php/libsdk/SDK/Build/PGO/Interfaces/PHP.php
Normal file
16
lib/php/libsdk/SDK/Build/PGO/Interfaces/PHP.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Interfaces;
|
||||
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
interface PHP
|
||||
{
|
||||
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
|
||||
public function init() : void;
|
||||
public function up() : void;
|
||||
public function down(bool $force = false) : void;
|
||||
public function getVersion(bool $short = false) : string;
|
||||
public function getExeFilename() : string;
|
||||
}
|
||||
15
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server.php
Normal file
15
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Interfaces;
|
||||
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
interface Server
|
||||
{
|
||||
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
|
||||
public function init() : void;
|
||||
public function up() : void;
|
||||
public function down(bool $force = false) : void;
|
||||
public function getName() : string;
|
||||
}
|
||||
12
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server/DB.php
Normal file
12
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server/DB.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Interfaces\Server;
|
||||
|
||||
use SDK\Build\PGO\Config;
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
|
||||
interface DB extends Interfaces\Server
|
||||
{
|
||||
public function __construct(Config $conf);
|
||||
public function query(string $s, string $db = NULL) : void;
|
||||
}
|
||||
13
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server/HTTP.php
Normal file
13
lib/php/libsdk/SDK/Build/PGO/Interfaces/Server/HTTP.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Interfaces\Server;
|
||||
|
||||
use SDK\Build\PGO\Config;
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
|
||||
interface HTTP extends Interfaces\Server
|
||||
{
|
||||
public function __construct(Config $conf, Interfaces\PHP $php);
|
||||
public function getPhp() : Interfaces\PHP;
|
||||
public function addServer(string $part_tpl_fn, array $tpl_vars = array());
|
||||
}
|
||||
27
lib/php/libsdk/SDK/Build/PGO/Interfaces/TrainingCase.php
Normal file
27
lib/php/libsdk/SDK/Build/PGO/Interfaces/TrainingCase.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Interfaces;
|
||||
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
|
||||
interface TrainingCase
|
||||
{
|
||||
public function __construct(PGOConfig $conf, ?Server $srv_http, ?Server\DB $srv_db);
|
||||
|
||||
/* Name of the training case, usually should be same as dirname and namespace. */
|
||||
public function getName() : string;
|
||||
|
||||
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
|
||||
|
||||
/* Initialize the case, run only once on a new checkout. */
|
||||
public function init() : void;
|
||||
|
||||
/* Run training. */
|
||||
public function run() : void;
|
||||
|
||||
/* Get training type, it's like "web", "cli", etc.*/
|
||||
public function getType() : string;
|
||||
}
|
||||
0
lib/php/libsdk/SDK/Build/PGO/PHP/Apache.php
Normal file
0
lib/php/libsdk/SDK/Build/PGO/PHP/Apache.php
Normal file
55
lib/php/libsdk/SDK/Build/PGO/PHP/CLI.php
Normal file
55
lib/php/libsdk/SDK/Build/PGO/PHP/CLI.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\PHP;
|
||||
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
use SDK\Build\PGO\Abstracts;
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\{Exception};
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
class CLI extends Abstracts\PHP implements Interfaces\PHP
|
||||
{
|
||||
public function __construct(PGOConfig $conf)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->scenario = $conf->getScenario();
|
||||
// Don't do that, it'll be a recursive dependency.
|
||||
// Once we need to train CLI, we'll need to split
|
||||
// a new class, this one is a utility class.
|
||||
//$this->id = $this->getIdString();
|
||||
|
||||
$this->setupPaths();
|
||||
}
|
||||
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
public function init() : void
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
public function up() : void
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
public function down(bool $force = false) : void
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
public function getExeFilename() : string
|
||||
{
|
||||
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php.exe";
|
||||
|
||||
if (!file_exists($exe)) {
|
||||
throw new Exception("Path '$exe' doesn't exist.");
|
||||
}
|
||||
|
||||
return $exe;
|
||||
}
|
||||
}
|
||||
128
lib/php/libsdk/SDK/Build/PGO/PHP/FCGI.php
Normal file
128
lib/php/libsdk/SDK/Build/PGO/PHP/FCGI.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\PHP;
|
||||
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
use SDK\Build\PGO\Abstracts;
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\{Exception, FileOps};
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
class FCGI extends Abstracts\PHP implements Interfaces\PHP
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $is_tcp;
|
||||
|
||||
public function __construct(PGOConfig $conf, bool $is_tcp)
|
||||
{
|
||||
if (!$is_tcp) {
|
||||
throw new Exception("FCGI training other than through TCP is not implemented yet.");
|
||||
}
|
||||
|
||||
$this->conf = $conf;
|
||||
$this->is_tcp = $is_tcp;
|
||||
$this->scenario = $conf->getScenario();
|
||||
$this->id = $this->getIdString();
|
||||
|
||||
$this->setupPaths();
|
||||
}
|
||||
|
||||
public function getExeFilename() : string
|
||||
{
|
||||
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php-cgi.exe";
|
||||
|
||||
if (!file_exists($exe)) {
|
||||
throw new Exception("Path '$exe' doesn't exist.");
|
||||
}
|
||||
|
||||
return $exe;
|
||||
}
|
||||
|
||||
protected function createEnv() : array
|
||||
{
|
||||
$env = parent::createEnv();
|
||||
|
||||
$fcgi_env = (array)$this->conf->getSectionItem("php", "fcgi:env");
|
||||
|
||||
foreach ($fcgi_env as $k => $v) {
|
||||
$env[$k] = $v;
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
}
|
||||
|
||||
public function init() : void
|
||||
{
|
||||
/* echo "Initializing PHP FCGI.\n";
|
||||
echo "PHP FCGI initialization done.\n";*/
|
||||
}
|
||||
|
||||
public function up() : void
|
||||
{
|
||||
echo "Starting PHP FCGI.\n";
|
||||
|
||||
if ("cache" == $this->scenario) {
|
||||
if (file_exists($this->opcache_file_cache)) {
|
||||
$this->rm($this->opcache_file_cache);
|
||||
}
|
||||
if (!mkdir($this->opcache_file_cache)) {
|
||||
throw new Exception("Failed to create '{$this->opcache_file_cache}'");
|
||||
}
|
||||
}
|
||||
|
||||
$exe = $this->getExeFilename();
|
||||
$ini = $this->getIniFilename();
|
||||
$host = $this->conf->getSectionItem("php", "fcgi", "host");
|
||||
$port = $this->conf->getSectionItem("php", "fcgi", "port");
|
||||
|
||||
$cmd = "start /b $exe -n -c $ini -b $host:$port 2>&1";
|
||||
|
||||
$desc = array(
|
||||
0 => array("file", "php://stdin", "r"),
|
||||
1 => array("file", "php://stdout", "w"),
|
||||
2 => array("file", "php://stderr", "w"),
|
||||
);
|
||||
|
||||
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $this->createEnv());
|
||||
|
||||
/* Give some time, it might be slow on PGI enabled proc. */
|
||||
sleep(3);
|
||||
|
||||
/*while(false !== ($s = fread($pipes[2], 1024))) {
|
||||
echo "$s";
|
||||
}*/
|
||||
|
||||
$c = proc_close($p);
|
||||
|
||||
if ($c) {
|
||||
throw new Exception("PHP FCGI process exited with code '$c'.");
|
||||
}
|
||||
|
||||
/* XXX for Opcache, setup also file cache. */
|
||||
|
||||
echo "PHP FCGI started.\n";
|
||||
}
|
||||
|
||||
public function down(bool $force = false) : void
|
||||
{
|
||||
echo "Stopping PHP FCGI.\n";
|
||||
|
||||
exec("taskkill /f /im php-cgi.exe >nul 2>&1");
|
||||
|
||||
/* XXX Add cleanup interface. */
|
||||
if ("cache" == $this->scenario) {
|
||||
try {
|
||||
$this->rm($this->opcache_file_cache);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "PHP FCGI stopped.\n";
|
||||
}
|
||||
}
|
||||
143
lib/php/libsdk/SDK/Build/PGO/Server/MariaDB.php
Normal file
143
lib/php/libsdk/SDK/Build/PGO/Server/MariaDB.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Server;
|
||||
|
||||
use SDK\Build\PGO\Interfaces\Server\DB;
|
||||
use SDK\Build\PGO\Abstracts\Server;
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\{Exception, FileOps};
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
class MariaDB extends Server implements DB
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $conf;
|
||||
protected $base;
|
||||
protected $name = "MariaDB";
|
||||
|
||||
public function __construct(PGOConfig $conf)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->base = $conf->getSrvDir(strtolower($this->name));
|
||||
}
|
||||
|
||||
protected function setupDist()
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
$url = $this->conf->getSectionItem($this->name, "pkg_url");
|
||||
$pw->fetchAndUnzip($url, "mariadb.zip", $this->conf->getSrvDir(), "mariadb", $force);
|
||||
}
|
||||
|
||||
public function init() : void
|
||||
{
|
||||
echo "Initializing " . $this->name . ".\n";
|
||||
|
||||
$this->setupDist();
|
||||
|
||||
$this->up();
|
||||
$this->down(true);
|
||||
|
||||
echo $this->name . " initialization done.\n";
|
||||
}
|
||||
|
||||
public function up() : void
|
||||
{
|
||||
echo "Starting " . $this->name . ".\n";
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
//$h = popen("start /b .\\bin\\mysqld.exe --port=$port >nul 2>&1", "r");
|
||||
$h = popen("start /b .\\bin\\mysqld.exe --port=$port 2>&1", "r");
|
||||
|
||||
if (!is_resource($h)) {
|
||||
chdir($cwd);
|
||||
throw new Exception("Failed to start MariaDB.");
|
||||
}
|
||||
sleep(3);
|
||||
|
||||
while (!feof($h)) {
|
||||
echo fread($h, 1024);
|
||||
}
|
||||
pclose($h);
|
||||
|
||||
chdir($cwd);
|
||||
|
||||
echo $this->name . " started.\n";
|
||||
}
|
||||
|
||||
public function down(bool $force = false) : void
|
||||
{
|
||||
echo "Stopping " . $this->name . ".\n";
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$pass = $this->conf->getSectionItem($this->name, "pass");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$cmd = sprintf(".\\bin\\mysqladmin.exe --host=$host --port=$port -u $user %s--shutdown_timeout=0 shutdown", ($pass ? "-p$pass " : ""));
|
||||
exec($cmd);
|
||||
|
||||
if ($force) {
|
||||
sleep(1);
|
||||
exec("taskkill /f /im mysqld.exe >nul 2>&1");
|
||||
}
|
||||
|
||||
chdir($cwd);
|
||||
|
||||
echo $this->name . " stopped.\n";
|
||||
}
|
||||
|
||||
public function query(string $s, string $db = NULL) : void
|
||||
{
|
||||
$ret = NULL;
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$pass = $this->conf->getSectionItem($this->name, "pass");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$pass_arg = $pass ? "-p$pass " : "";
|
||||
$db_arg = $db ? "-D $db" : "";
|
||||
shell_exec(".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port $db_arg -e \"$s\"");
|
||||
//var_dump($this->base, getcwd(), ".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port -e \"$s\"");
|
||||
|
||||
chdir($cwd);
|
||||
}
|
||||
|
||||
public function import(string $path, string $db = NULL) : void
|
||||
{
|
||||
$ret = NULL;
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$pass = $this->conf->getSectionItem($this->name, "pass");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$pass_arg = $pass ? "-p$pass " : "";
|
||||
$db_arg = $db ? "-D $db" : "";
|
||||
shell_exec(".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port $db_arg < \"$path\"");
|
||||
|
||||
chdir($cwd);
|
||||
}
|
||||
}
|
||||
149
lib/php/libsdk/SDK/Build/PGO/Server/NGINX.php
Normal file
149
lib/php/libsdk/SDK/Build/PGO/Server/NGINX.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Server;
|
||||
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
use SDK\Build\PGO\Abstracts;
|
||||
use SDK\Build\PGO\{Config as PGOConfig};
|
||||
use SDK\{Exception, FileOps};
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
class NGINX extends Abstracts\Server implements Interfaces\Server\HTTP
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $name = "NGINX";
|
||||
protected $conf;
|
||||
protected $base;
|
||||
protected $php;
|
||||
|
||||
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->base = $conf->getSrvDir(strtolower($this->name));
|
||||
$this->php = $php;
|
||||
}
|
||||
|
||||
protected function setupDist() : void
|
||||
{
|
||||
$nginx_conf_in = $this->conf->getTplDir($this->name) . DIRECTORY_SEPARATOR . "nginx.conf";
|
||||
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
|
||||
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
if (!$port) {
|
||||
$port = $this->conf->getNextPort();
|
||||
$this->conf->setSectionItem($this->name, "port", $port);
|
||||
}
|
||||
|
||||
$vars = array(
|
||||
$this->conf->buildTplVarName($this->name, "docroot") => str_replace("\\", "/", $this->base . DIRECTORY_SEPARATOR . "html"),
|
||||
);
|
||||
|
||||
$this->conf->processTplFile(
|
||||
$nginx_conf_in,
|
||||
$conf_fn,
|
||||
$vars
|
||||
);
|
||||
}
|
||||
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
$url = $this->conf->getSectionItem($this->name, "pkg_url");
|
||||
$pw->fetchAndUnzip($url, "nginx.zip", $this->conf->getSrvDir(), "nginx", $force);
|
||||
}
|
||||
|
||||
public function init() : void
|
||||
{
|
||||
echo "Initializing " . $this->name . ".\n";
|
||||
|
||||
$this->setupDist();
|
||||
|
||||
$this->upMe();
|
||||
$this->downMe(true);
|
||||
|
||||
|
||||
echo $this->name . " initialization done.\n";
|
||||
}
|
||||
|
||||
protected function upMe() : void
|
||||
{
|
||||
echo "Starting " . $this->name . ".\n";
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
$h = popen("start /b .\\nginx.exe 2>&1", "r");
|
||||
if (!is_resource($h)) {
|
||||
chdir($cwd);
|
||||
throw new Exception("Failed to start MariaDB.");
|
||||
}
|
||||
sleep(3);
|
||||
|
||||
/* while (!feof($h)) {
|
||||
echo fread($h, 1024);
|
||||
}*/
|
||||
|
||||
pclose($h);
|
||||
|
||||
chdir($cwd);
|
||||
|
||||
echo $this->name . " started.\n";
|
||||
}
|
||||
|
||||
public function up() : void
|
||||
{
|
||||
|
||||
$this->php->up();
|
||||
$this->upMe();
|
||||
}
|
||||
|
||||
public function downMe(bool $force = false) : void
|
||||
{
|
||||
echo "Stopping " . $this->name . ".\n";
|
||||
|
||||
$cwd = getcwd();
|
||||
|
||||
chdir($this->base);
|
||||
|
||||
exec(".\\nginx.exe -s quit");
|
||||
|
||||
if ($force) {
|
||||
sleep(1);
|
||||
exec("taskkill /f /im nginx.exe >nul 2>&1");
|
||||
}
|
||||
|
||||
chdir($cwd);
|
||||
|
||||
echo $this->name . " stopped.\n";
|
||||
}
|
||||
|
||||
public function down(bool $force = false) : void
|
||||
{
|
||||
$this->php->down();
|
||||
$this->downMe($force);
|
||||
}
|
||||
|
||||
/* Use only for init phase! */
|
||||
public function addServer(string $part_tpl_fn, array $tpl_vars = array())
|
||||
{
|
||||
if (!file_exists($part_tpl_fn)) {
|
||||
throw new Exception("Template file '$part_tpl_fn' doesn't exist.");
|
||||
}
|
||||
|
||||
/* We've already did a fresh (re)config, so use the work file now. */
|
||||
$nginx_conf_in = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
|
||||
$cur_conf = file_get_contents($nginx_conf_in);
|
||||
|
||||
$in = file_get_contents($part_tpl_fn);
|
||||
$out = $this->conf->processTpl($in, $tpl_vars);
|
||||
|
||||
$tpl = " # PHP_SDK_PGO_NGINX_SERVERS_INC_TPL";
|
||||
$new_conf = str_replace($tpl, "$out\n$tpl", $cur_conf);
|
||||
|
||||
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
|
||||
if (!file_put_contents($conf_fn, $new_conf)) {
|
||||
throw new Exception("Couldn't write '$conf_fn'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
136
lib/php/libsdk/SDK/Build/PGO/Server/PostgreSQL.php
Normal file
136
lib/php/libsdk/SDK/Build/PGO/Server/PostgreSQL.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Server;
|
||||
|
||||
use SDK\Build\PGO\Interfaces\Server\DB;
|
||||
use SDK\Build\PGO\Abstracts\Server;
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\{Exception, FileOps};
|
||||
use SDK\Build\PGO\Tool\PackageWorkman;
|
||||
|
||||
class PostgreSQL extends Server implements DB
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $conf;
|
||||
protected $base;
|
||||
protected $data_dir;
|
||||
protected $name = "PostgreSQL";
|
||||
|
||||
public function __construct(PGOConfig $conf)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->base = $conf->getSrvDir(strtolower($this->name));
|
||||
$this->data_dir = $this->base . DIRECTORY_SEPARATOR . "data";
|
||||
}
|
||||
|
||||
protected function setupDist()
|
||||
{
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
if (!$user) {
|
||||
$user = trim(shell_exec("pwgen -1 -s 8"));
|
||||
$this->conf->setSectionItem($this->getName(), "user", $user);
|
||||
}
|
||||
$pass = $this->conf->getSectionItem($this->name, "pass");
|
||||
if (!$pass) {
|
||||
$pass = trim(shell_exec("pwgen -1 -s 8"));
|
||||
$this->conf->setSectionItem($this->getName(), "pass", $pass);
|
||||
}
|
||||
|
||||
if (!is_dir($this->data_dir)) {
|
||||
$pwfile = tempnam(sys_get_temp_dir(), "tmp");
|
||||
if (strlen($pass) !== file_put_contents($pwfile, $pass)) {
|
||||
throw new Exception("Couldn't write '$pwfile'.");
|
||||
}
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --pwfile=$pwfile --encoding=UTF8 " . $this->data_dir;
|
||||
//$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --encoding=UTF8 " . $this->data_dir;
|
||||
/*echo "$cmd\n";
|
||||
echo file_get_contents($pwfile) . "\n";*/
|
||||
exec($cmd);
|
||||
unlink($pwfile);
|
||||
}
|
||||
}
|
||||
|
||||
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
|
||||
{
|
||||
$url = $this->conf->getSectionItem($this->name, "pkg_url");
|
||||
$pw->fetchAndUnzip($url, "postgresql.zip", $this->conf->getSrvDir(), "postgresql", $force);
|
||||
}
|
||||
|
||||
public function init() : void
|
||||
{
|
||||
echo "Initializing " . $this->name . ".\n";
|
||||
|
||||
$this->setupDist();
|
||||
|
||||
$this->up();
|
||||
$this->down(true);
|
||||
|
||||
echo $this->name . " initialization done.\n";
|
||||
}
|
||||
|
||||
public function up() : void
|
||||
{
|
||||
echo "Starting " . $this->name . ".\n";
|
||||
|
||||
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe start -D " . $this->data_dir . " -o \"-h $host -p $port\"";
|
||||
$h = popen($cmd, "r");
|
||||
/* XXX error check*/
|
||||
pclose($h);
|
||||
|
||||
echo $this->name . " started.\n";
|
||||
}
|
||||
|
||||
public function down(bool $force = false) : void
|
||||
{
|
||||
echo "Stopping " . $this->name . ".\n";
|
||||
|
||||
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe stop -D " . $this->data_dir . " -m fast";
|
||||
exec($cmd);
|
||||
|
||||
if ($force) {
|
||||
//sleep(1);
|
||||
//exec("taskkill /f /im nginx.exe >nul 2>&1");
|
||||
}
|
||||
|
||||
echo $this->name . " stopped.\n";
|
||||
}
|
||||
|
||||
public function createDb(string $db_name) : void
|
||||
{
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "createdb.exe -h $host -p $port -U $user $db_name";
|
||||
exec($cmd);
|
||||
}
|
||||
|
||||
public function dropDb(string $db_name) : void
|
||||
{
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "dropdb.exe --if-exists -h $host -p $port -U $user $db_name";
|
||||
exec($cmd);
|
||||
}
|
||||
|
||||
public function query(string $s, string $db = NULL) : void
|
||||
{
|
||||
$ret = NULL;
|
||||
|
||||
$user = $this->conf->getSectionItem($this->name, "user");
|
||||
$host = $this->conf->getSectionItem($this->name, "host");
|
||||
$port = $this->conf->getSectionItem($this->name, "port");
|
||||
|
||||
$db_arg = $db ? "-d $db" : "";
|
||||
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "psql.exe -h $host -p $port -U $user $db_arg -c \"$s\"";
|
||||
shell_exec($cmd);
|
||||
}
|
||||
}
|
||||
106
lib/php/libsdk/SDK/Build/PGO/Tool/PGO.php
Normal file
106
lib/php/libsdk/SDK/Build/PGO/Tool/PGO.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Tool;
|
||||
|
||||
use SDK\Exception;
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\Build\PGO\Interfaces;
|
||||
|
||||
class PGO
|
||||
{
|
||||
protected $php;
|
||||
protected $conf;
|
||||
protected $idx = 0;
|
||||
|
||||
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->php = $php;
|
||||
}
|
||||
|
||||
protected function getPgcName(string $fname) : string
|
||||
{
|
||||
$bn = basename($fname, substr($fname, -4, 4));
|
||||
$dn = dirname($fname);
|
||||
|
||||
return $dn . DIRECTORY_SEPARATOR . $bn . "!" . $this->idx . ".pgc";
|
||||
}
|
||||
|
||||
protected function getPgdName(string $fname) : string
|
||||
{
|
||||
$bn = basename($fname, substr($fname, -4, 4));
|
||||
$dn = dirname($fname);
|
||||
|
||||
return $dn . DIRECTORY_SEPARATOR . $bn . ".pgd";
|
||||
}
|
||||
|
||||
protected function getWorkItems() : array
|
||||
{
|
||||
$exe = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.exe");
|
||||
$dll = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.dll");
|
||||
$dll = array_merge($dll, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "php*.dll"));
|
||||
|
||||
/* find out next index */
|
||||
$tpl = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "php{7,8,}{ts,}.dll", GLOB_BRACE)[0];
|
||||
if (!$tpl) {
|
||||
throw new Exception("Couldn't find php7[ts].dll in the PHP root dir.");
|
||||
}
|
||||
do {
|
||||
if (!file_exists($this->getPgcName($tpl))) {
|
||||
break;
|
||||
}
|
||||
$this->idx++;
|
||||
} while (true);
|
||||
|
||||
return array_unique(array_merge($exe, $dll));
|
||||
}
|
||||
|
||||
public function dump(bool $merge = true) : void
|
||||
{
|
||||
$its = $this->getWorkItems();
|
||||
|
||||
foreach ($its as $base) {
|
||||
$pgc = $this->getPgcName($base);
|
||||
$pgd = $this->getPgdName($base);
|
||||
|
||||
shell_exec("pgosweep $base $pgc");
|
||||
//passthru("pgosweep $base $pgc");
|
||||
|
||||
if ($merge) {
|
||||
shell_exec("pgomgr /merge:1000 $pgc $pgd");
|
||||
//passthru("pgomgr /merge:1000 $pgc $pgd");
|
||||
/* File is already spent, no need to keep it.
|
||||
If seeing linker warnings about no pgc
|
||||
were found for some object - most
|
||||
likely the object were not included in
|
||||
any training scenario. */
|
||||
@unlink($pgc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function waste() : void
|
||||
{
|
||||
$this->dump(false);
|
||||
}
|
||||
|
||||
public function clean(bool $clean_pgc = true, bool $clean_pgd = true) : void
|
||||
{
|
||||
if ($clean_pgc) {
|
||||
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgc");
|
||||
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgc"));
|
||||
foreach (array_unique($its) as $pgc) {
|
||||
unlink($pgc);
|
||||
}
|
||||
}
|
||||
|
||||
if ($clean_pgd) {
|
||||
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgd");
|
||||
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgd"));
|
||||
foreach (array_unique($its) as $pgd) {
|
||||
shell_exec("pgomgr /clear $pgd");
|
||||
//passthru("pgomgr /clear $pgd");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
lib/php/libsdk/SDK/Build/PGO/Tool/PackageWorkman.php
Normal file
56
lib/php/libsdk/SDK/Build/PGO/Tool/PackageWorkman.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Tool;
|
||||
|
||||
use SDK\{Exception, FileOps};
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
|
||||
|
||||
class PackageWorkman
|
||||
{
|
||||
use FileOps;
|
||||
|
||||
protected $conf;
|
||||
|
||||
public function __construct(PGOConfig $conf)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
}
|
||||
|
||||
public function fetch(string $url, string $tgt_fn, bool $force = false) : void
|
||||
{
|
||||
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . basename($tgt_fn);
|
||||
|
||||
if ($force || !file_exists($cache_fn)) {
|
||||
echo "Fetching '$url' into '$tgt_fn'\n";
|
||||
$this->download($url, $cache_fn);
|
||||
}
|
||||
|
||||
if ($force || !file_exists($tgt_fn)) {
|
||||
if ($cache_fn != $tgt_fn && !$this->cp($cache_fn, $tgt_fn)) {
|
||||
throw new Exception("Failed to copy '$cache_fn' to '$tgt_fn'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only for zips! */
|
||||
public function fetchAndUnzip(string $url, string $zip_bn, string $zip_tgt_dn, string $tgt_bn = NULL, bool $force = false) : void
|
||||
{
|
||||
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . $zip_bn;
|
||||
|
||||
if ($force || !file_exists($cache_fn)) {
|
||||
$this->fetch($url, $cache_fn, $force);
|
||||
}
|
||||
|
||||
$tgt_name = $zip_tgt_dn . ($tgt_bn ? DIRECTORY_SEPARATOR . $tgt_bn : "");
|
||||
if ($force || $tgt_bn && !file_exists($tgt_name) || !$tgt_bn /* This means unzip always if no rename. */) {
|
||||
echo "Unpacking '$cache_fn' to '$tgt_name'\n";
|
||||
try {
|
||||
$this->unzip($cache_fn, $zip_tgt_dn, $tgt_bn);
|
||||
} catch (\Throwable $e) {
|
||||
$this->rm($cache_fn);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
lib/php/libsdk/SDK/Build/PGO/Tool/Training.php
Normal file
121
lib/php/libsdk/SDK/Build/PGO/Tool/Training.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO\Tool;
|
||||
|
||||
use SDK\{Config as SDKConfig, Exception};
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
use SDK\Build\PGO\Interfaces\TrainingCase;
|
||||
|
||||
class Training
|
||||
{
|
||||
protected $conf;
|
||||
protected $t_case;
|
||||
|
||||
public function __construct(PGOConfig $conf, TrainingCase $t_case)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->t_case = $t_case;
|
||||
|
||||
$type = $this->t_case->getType();
|
||||
if (!in_array($type, array("web", "cli"))) {
|
||||
throw new Exception("Unknown training type '$type'.");
|
||||
}
|
||||
}
|
||||
|
||||
public function getCase() : TrainingCase
|
||||
{
|
||||
return $this->t_case;
|
||||
}
|
||||
|
||||
public function runWeb(int $max_runs, ?array &$stat = array()) : void
|
||||
{
|
||||
$url_list_fn = $this->t_case->getJobFilename();
|
||||
|
||||
if (!file_exists($url_list_fn)) {
|
||||
printf("\033[31m WARNING: Job file '$url_list_fn' not found!\033[0m\n");
|
||||
}
|
||||
|
||||
$a = file($url_list_fn, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
|
||||
$stat = array("http_code" => array(), "not_ok" => array());
|
||||
|
||||
for ($k = 0; $k < $max_runs; $k++) {
|
||||
echo ".";
|
||||
|
||||
$ch = array();
|
||||
|
||||
$mh = curl_multi_init();
|
||||
|
||||
foreach ($a as $i => $u) {
|
||||
|
||||
$ch[$i] = curl_init($u);
|
||||
|
||||
curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT_MS, 500000);
|
||||
curl_setopt($ch[$i], CURLOPT_TIMEOUT_MS, 500000);
|
||||
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch[$i], CURLOPT_USERAGENT, SDKConfig::getSdkUserAgentName());
|
||||
/* ??? */
|
||||
/*curl_setopt($ch[$i], CURLOPT_FOLLOWLOCATION, true);*/
|
||||
|
||||
curl_multi_add_handle($mh, $ch[$i]);
|
||||
}
|
||||
|
||||
$active = NULL;
|
||||
|
||||
do {
|
||||
$mrc = curl_multi_exec($mh, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
|
||||
while ($active && $mrc == CURLM_OK) {
|
||||
if (curl_multi_select($mh, 42.0) != -1) {
|
||||
do {
|
||||
$mrc = curl_multi_exec($mh, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ch as $h) {
|
||||
curl_multi_remove_handle($mh, $h);
|
||||
|
||||
/* Gather some stats */
|
||||
$info = curl_getinfo($h);
|
||||
$http_code = $info["http_code"];
|
||||
|
||||
if (isset($stat["http_code"][$http_code])) {
|
||||
$stat["http_code"][$http_code]++;
|
||||
} else {
|
||||
$stat["http_code"][$http_code] = 1;
|
||||
}
|
||||
|
||||
if (!$this->t_case->httpStatusOk((int)$http_code)) {
|
||||
$stat["not_ok"][] = $info;
|
||||
|
||||
//echo curl_multi_getcontent($h) ;
|
||||
}
|
||||
|
||||
curl_close($h);
|
||||
}
|
||||
|
||||
curl_multi_close($mh);
|
||||
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
}
|
||||
|
||||
/* TODO Extend with number runs. */
|
||||
public function run(int $max_runs = 1, ?array &$stat = array()) : void
|
||||
{
|
||||
$type = $this->t_case->getType();
|
||||
switch ($type) {
|
||||
case "web":
|
||||
$this->runWeb($max_runs, $stat);
|
||||
break;
|
||||
|
||||
case "cli":
|
||||
default:
|
||||
throw new Exception("Unknown training type '$type'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
99
lib/php/libsdk/SDK/Build/PGO/TrainingCaseIterator.php
Normal file
99
lib/php/libsdk/SDK/Build/PGO/TrainingCaseIterator.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace SDK\Build\PGO;
|
||||
|
||||
use SDK\Build\PGO\Config as PGOConfig;
|
||||
|
||||
|
||||
class TrainingCaseIterator implements \Iterator
|
||||
{
|
||||
protected $conf;
|
||||
protected $items = array();
|
||||
protected $idx;
|
||||
protected $el;
|
||||
|
||||
public function __construct(PGOConfig $conf)
|
||||
{
|
||||
$this->rewind();
|
||||
|
||||
$this->conf = $conf;
|
||||
|
||||
$items = glob($this->conf->getCasesTplDir() . DIRECTORY_SEPARATOR . "*");
|
||||
foreach ($items as $it) {
|
||||
if (!is_dir($it)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file_exists($this->getHandlerFilename($it))) {
|
||||
echo "Test case handler isn't present in '$it'.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isInactive($it)) {
|
||||
echo "The test case in '$it' is marked inactive.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->items[] = $it;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected function isInactive(string $base) : bool
|
||||
{
|
||||
return file_exists($base . DIRECTORY_SEPARATOR . "inactive");
|
||||
}
|
||||
|
||||
protected function getHandlerFilename(string $base) : string
|
||||
{
|
||||
return $base . DIRECTORY_SEPARATOR . "TrainingCaseHandler.php";
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
$base = $this->items[$this->idx];
|
||||
$ns = basename($base);
|
||||
|
||||
/* Don't overwrite generated config. */
|
||||
$it = $this->conf->getSectionItem($ns);
|
||||
if (!$it) {
|
||||
$this->conf->importSectionFromDir($ns, $base);
|
||||
}
|
||||
|
||||
require_once $this->getHandlerFilename($base);
|
||||
|
||||
$srv_http = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_http"));
|
||||
$srv_db = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_db"));
|
||||
|
||||
$class = "$ns\\TrainingCaseHandler";
|
||||
|
||||
$this->el = new $class($this->conf, $srv_http, $srv_db);
|
||||
|
||||
return $this->el;
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
$this->idx++;
|
||||
}
|
||||
|
||||
public function rewind()
|
||||
{
|
||||
$this->idx = 0;
|
||||
}
|
||||
|
||||
public function valid()
|
||||
{
|
||||
return $this->idx < count($this->items);
|
||||
}
|
||||
|
||||
public function key()
|
||||
{
|
||||
if (!is_object($this->el)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $this->el->getName();
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
namespace SDK;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Cache;
|
||||
use SDK\Exception;
|
||||
|
||||
class Cache
|
||||
{
|
||||
protected $id;
|
||||
@@ -36,6 +32,7 @@ class Cache
|
||||
return file_exists($this->getCacheablePath($path, $relative));
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO Sometimes a timestamp comparison might make sense. */
|
||||
public function cachedContentDiffers(string $path, string $content, bool $relative = false) : bool
|
||||
{/*{{{*/
|
||||
$p = $this->getCacheablePath($path, $relative);
|
||||
@@ -47,19 +44,38 @@ class Cache
|
||||
$old_sum = md5_file($p);
|
||||
$new_sum = md5($content);
|
||||
|
||||
return $old_sum != $new_sum;
|
||||
return $old_sum !== $new_sum;
|
||||
}/*}}}*/
|
||||
|
||||
public function cacheContent(string $path, string $content, bool $relative = false)
|
||||
public function cacheContent(string $path, string $content, bool $relative = false) : void
|
||||
{/*{{{*/
|
||||
$p = $this->getCacheablePath($path, $relative);
|
||||
|
||||
if (strlen($content) !== file_put_contents($p, $content)) {
|
||||
$to_write = strlen($content);
|
||||
$wrote = 0;
|
||||
|
||||
$fd = fopen($p, "wb");
|
||||
|
||||
flock($fd, LOCK_EX);
|
||||
|
||||
do {
|
||||
$got = fwrite($fd, substr($content, $wrote));
|
||||
if (false === $got) {
|
||||
break;
|
||||
}
|
||||
$wrote += $got;
|
||||
} while ($wrote < $to_write);
|
||||
|
||||
flock($fd, LOCK_UN);
|
||||
|
||||
fclose($fd);
|
||||
|
||||
if ($to_write !== $wrote) {
|
||||
throw new Exception("Couldn't cache '$p'");
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
public function getCachedContent(string $path, bool $relative = false)
|
||||
public function getCachedContent(string $path, bool $relative = false) : ?string
|
||||
{/*{{{*/
|
||||
$p = $this->getCacheablePath($path, $relative);
|
||||
|
||||
@@ -67,7 +83,7 @@ class Cache
|
||||
return file_get_contents($p);
|
||||
}
|
||||
|
||||
return "";
|
||||
return NULL;
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
|
||||
namespace SDK;
|
||||
|
||||
use SDK\Dependency\Fetcher;
|
||||
use SDK\Cache;
|
||||
use SDK\Exception;
|
||||
use SDK\Build\Dependency\Fetcher;
|
||||
|
||||
class Config
|
||||
{
|
||||
/* Config variables. */
|
||||
protected static $depsHost = 'windows.php.net';
|
||||
protected static $depsPort = 80;
|
||||
protected static $depsPort = 443;
|
||||
protected static $depsUriScheme = "https";
|
||||
protected static $depsBaseUri = "/downloads/php-sdk/deps";
|
||||
|
||||
/* protected static $sdkNugetFeedUrl = "http://127.0.0.1/sdk/nuget"; */
|
||||
@@ -34,38 +33,102 @@ class Config
|
||||
return self::$depsPort;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getDepsUriScheme() : string
|
||||
{/*{{{*/
|
||||
return self::$depsUriScheme;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getDepsBaseUri() : string
|
||||
{/*{{{*/
|
||||
return self::$depsBaseUri;
|
||||
}/*}}}*/
|
||||
|
||||
public static function setCurrentArchName(string $arch)
|
||||
public static function setCurrentArchName(string $arch) : void
|
||||
{/*{{{*/
|
||||
$arch = strtolower($arch);
|
||||
|
||||
if ("x64" != $arch && "x86" != $arch) {
|
||||
throw new Exception("Unknown arch keyword, either x86 or x64 is accepted");
|
||||
}
|
||||
|
||||
self::$currentArchName = $arch;
|
||||
} /*}}}*/
|
||||
|
||||
public static function getCurrentArchName()
|
||||
public static function getCurrentArchName() : string
|
||||
{/*{{{*/
|
||||
if (NULL === self::$currentArchName) {
|
||||
if (FALSE !== ($env = getenv('PHP_SDK_ARCH'))) {
|
||||
self::setCurrentArchName($env);
|
||||
} else {
|
||||
/* XXX this might be not true for other compilers! */
|
||||
passthru("where cl.exe >nul", $status);
|
||||
if ($status) {
|
||||
throw new Exception("Couldn't execute cl.exe.");
|
||||
}
|
||||
|
||||
exec("cl.exe /? 2>&1", $out);
|
||||
|
||||
if (preg_match(",x64,", $out[0])) {
|
||||
self::setCurrentArchName("x64");
|
||||
} elseif (preg_match(",x86,", $out[0])) {
|
||||
self::setCurrentArchName("x86");
|
||||
} else {
|
||||
throw new Exception("Couldn't determine Arch.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$currentArchName;
|
||||
} /*}}}*/
|
||||
|
||||
public static function setCurrentCrtName(string $crt)
|
||||
public static function setCurrentCrtName(string $crt) : void
|
||||
{/*{{{*/
|
||||
self::$currentCrtName = $crt;
|
||||
} /*}}}*/
|
||||
|
||||
public static function getCurrentCrtName()
|
||||
public static function getCurrentCrtName() : ?string
|
||||
{/*{{{*/
|
||||
if (NULL === self::$currentCrtName) {
|
||||
if (FALSE !== ($env = getenv('PHP_SDK_VS'))) {
|
||||
self::setCurrentCrtName($env);
|
||||
} else {
|
||||
$all_branches = Config::getKnownBranches();
|
||||
|
||||
if (!isset($all_branches[Config::getCurrentBranchName()])) {
|
||||
throw new Exception("Couldn't find any configuration for branch '" . Config::getCurrentBranchName() . "'");
|
||||
}
|
||||
|
||||
$branch = $all_branches[Config::getCurrentBranchName()];
|
||||
if (count($branch) > 1) {
|
||||
throw new Exception("Multiple CRTs are available for this branch, please choose one from " . implode(",", array_keys($branch)));
|
||||
}
|
||||
|
||||
self::setCurrentCrtName(array_keys($branch)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$currentCrtName;
|
||||
} /*}}}*/
|
||||
|
||||
public static function setCurrentStabilityName(string $stability)
|
||||
public static function setCurrentStabilityName(string $stability) : void
|
||||
{/*{{{*/
|
||||
if ("stable" != $stability && "staging" != $stability) {
|
||||
throw new Exception("Unknown stability keyword, either stable or staging is accepted");
|
||||
}
|
||||
|
||||
self::$currentStabilityName = $stability;
|
||||
} /*}}}*/
|
||||
|
||||
public static function getCurrentStabilityName()
|
||||
public static function getCurrentStabilityName() : ?string
|
||||
{/*{{{*/
|
||||
if (NULL === self::$currentStabilityName) {
|
||||
if ("master" == Config::getCurrentBranchName()) {
|
||||
Config::setCurrentStabilityName("staging");
|
||||
} else {
|
||||
Config::setCurrentStabilityName("stable");
|
||||
}
|
||||
}
|
||||
|
||||
return self::$currentStabilityName;
|
||||
} /*}}}*/
|
||||
|
||||
@@ -73,13 +136,17 @@ class Config
|
||||
{/*{{{*/
|
||||
if (empty(self::$knownBranches)) {
|
||||
$cache_file = "known_branches.txt";
|
||||
$cache = new Cache(self::getDepsLocalPath());
|
||||
$fetcher = new Fetcher(self::$depsHost, self::$depsPort);
|
||||
$deps_path = self::getDepsLocalPath();
|
||||
if (!$deps_path) {
|
||||
throw new Exception("Couldn't determine dependencies path. Please either switch to the PHP source root or use -d option.");
|
||||
}
|
||||
$cache = new Cache($deps_path);
|
||||
$fetcher = new Fetcher(self::$depsHost, self::$depsPort, self::$depsUriScheme);
|
||||
|
||||
$tmp = $fetcher->getByUri(self::$depsBaseUri . "/series/");
|
||||
if (false !== $tmp) {
|
||||
$data = array();
|
||||
if (preg_match_all(",/packages-(.+)-(vc\d+)-(x86|x64)-(stable|staging)\.txt,U", $tmp, $m, PREG_SET_ORDER)) {
|
||||
if (preg_match_all(",/packages-(.+)-(v[cs]\d+)-(x86|x64)-(stable|staging)\.txt,U", $tmp, $m, PREG_SET_ORDER)) {
|
||||
foreach ($m as $b) {
|
||||
if (!isset($data[$b[1]])) {
|
||||
$data[$b[1]] = array();
|
||||
@@ -93,6 +160,9 @@ class Config
|
||||
} else {
|
||||
/* It might be ok to use cached branches list, if a fetch failed. */
|
||||
$tmp = $cache->getCachedContent($cache_file, true);
|
||||
if (NULL == $tmp) {
|
||||
throw new Exception("No cached branches list found");
|
||||
}
|
||||
$data = json_decode($tmp, true);
|
||||
}
|
||||
|
||||
@@ -105,17 +175,80 @@ class Config
|
||||
return self::$knownBranches;
|
||||
}/*}}}*/
|
||||
|
||||
public static function setCurrentBranchName(string $name)
|
||||
public static function setCurrentBranchName(string $name) : void
|
||||
{/*{{{*/
|
||||
if (!array_key_exists($name, self::getKnownBranches())) {
|
||||
// throw new Exception("Unsupported branch '$name'");
|
||||
throw new Exception("Unsupported branch '$name'");
|
||||
}
|
||||
|
||||
self::$currentBranchName = $name;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getCurrentBranchName()
|
||||
public static function guessCurrentBranchName() : ?string
|
||||
{/*{{{*/
|
||||
$branch = NULL;
|
||||
$found = false;
|
||||
|
||||
$rmtools_branch = getenv("PHP_RMTOOLS_PHP_BUILD_BRANCH");
|
||||
if ("master" == $rmtools_branch) {
|
||||
return "master";
|
||||
}
|
||||
|
||||
/* Try to figure out the branch. The worky scenarios are
|
||||
- CWD is in php-src
|
||||
- phpize is on the path
|
||||
FIXME for the dev package, there should be a php-config utility
|
||||
*/
|
||||
$fl = "main/php_version.h";
|
||||
$found = file_exists($fl);
|
||||
|
||||
if (!$found) {
|
||||
exec("where phpize", $out, $status);
|
||||
if (!$status) {
|
||||
$fl = dirname($out[0]) . DIRECTORY_SEPARATOR . "include" . DIRECTORY_SEPARATOR . $fl;
|
||||
$found = file_exists($fl);
|
||||
}
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
$s = file_get_contents($fl);
|
||||
$major = $minor = NULL;
|
||||
|
||||
if (preg_match(",PHP_MAJOR_VERSION (\d+),", $s, $m)) {
|
||||
$major = $m[1];
|
||||
}
|
||||
if (preg_match(",PHP_MINOR_VERSION (\d+),", $s, $m)) {
|
||||
$minor = $m[1];
|
||||
}
|
||||
|
||||
if (is_numeric($major) && is_numeric($minor)) {
|
||||
$branch = "$major.$minor";
|
||||
}
|
||||
|
||||
/* Verify that we use an available branch name. Master has some
|
||||
version, but no dedicated series. For master, it rather
|
||||
makes sense to use master as branch name. */
|
||||
$git = trim(shell_exec("where git.exe"));
|
||||
if ($git && is_dir(".git")) {
|
||||
$cmd = "\"$git\" branch";
|
||||
|
||||
$ret = trim(shell_exec($cmd));
|
||||
if (preg_match_all(",\*\s+master,", $ret) > 0) {
|
||||
$branch = "master";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $branch;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getCurrentBranchName() : string
|
||||
{/*{{{*/
|
||||
if (NULL == self::$currentBranchName) {
|
||||
$branch = self::guessCurrentBranchName();
|
||||
self::setCurrentBranchName($branch);
|
||||
}
|
||||
|
||||
return self::$currentBranchName;
|
||||
}/*}}}*/
|
||||
|
||||
@@ -124,30 +257,38 @@ class Config
|
||||
$ret = array();
|
||||
$branches = self::getKnownBranches();
|
||||
|
||||
if (!array_key_exists(self::$currentBranchName, $branches)) {
|
||||
throw new Exception("Unknown branch '" . self::$currentBranchName . "'");
|
||||
$current_branch_name = self::getCurrentBranchName();
|
||||
if (!array_key_exists($current_branch_name, $branches)) {
|
||||
throw new Exception("Unknown branch '$current_branch_name'");
|
||||
}
|
||||
|
||||
$cur_crt = Config::getCurrentCrtName();
|
||||
if (count($branches[self::$currentBranchName]) > 1) {
|
||||
if (count($branches[$current_branch_name]) > 1) {
|
||||
if (NULL === $cur_crt) {
|
||||
throw new Exception("More than one CRT is available for branch '" . self::$currentBranchName . "', pass one explicitly.");
|
||||
throw new Exception("More than one CRT is available for branch '$current_branch_name', pass one explicitly.");
|
||||
}
|
||||
|
||||
$crt = array_keys($branches[self::$currentBranchName])[0];
|
||||
if ($cur_crt != $crt) {
|
||||
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '" . self::$currentBranchName . "'");
|
||||
$cur_crt_usable = false;
|
||||
foreach (array_keys($branches[$current_branch_name]) as $crt) {
|
||||
if ($cur_crt == $crt) {
|
||||
$cur_crt_usable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data = $branches[self::$currentBranchName][$cur_crt];
|
||||
if (!$cur_crt_usable) {
|
||||
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '$current_branch_name'");
|
||||
}
|
||||
$data = $branches[$current_branch_name][$cur_crt];
|
||||
} else {
|
||||
/* Evaluate CRTs, to avoid ambiquity. */
|
||||
list($crt, $data) = each($branches[self::$currentBranchName]);
|
||||
$crt = key($branches[$current_branch_name]);
|
||||
$data = $branches[$current_branch_name][$crt];
|
||||
if ($crt != $cur_crt) {
|
||||
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '" . self::$currentBranchName . "'");
|
||||
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '$current_branch_name'");
|
||||
}
|
||||
}
|
||||
|
||||
$ret["name"] = self::$currentBranchName;
|
||||
$ret["name"] = $current_branch_name;
|
||||
$ret["crt"] = $crt;
|
||||
|
||||
/* Last step, filter by arch and stability. */
|
||||
@@ -160,10 +301,13 @@ class Config
|
||||
}
|
||||
}
|
||||
|
||||
if (!$ret["stability"]) {
|
||||
if (!isset($ret["arch"]) || !$ret["arch"]) {
|
||||
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
|
||||
}
|
||||
if (!isset($ret["stability"]) || !$ret["stability"]) {
|
||||
throw new Exception("Failed to find config with stability '" . self::getCurrentStabilityName() . "'");
|
||||
}
|
||||
if (!$ret["crt"]) {
|
||||
if (!isset($ret["crt"]) || !$ret["crt"]) {
|
||||
throw new Exception("Failed to find config with arch '" . self::getCurrentArchName() . "'");
|
||||
}
|
||||
|
||||
@@ -175,7 +319,7 @@ class Config
|
||||
return self::$sdkNugetFeedUrl;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getSdkPath()
|
||||
public static function getSdkPath() : string
|
||||
{/*{{{*/
|
||||
$path = getenv("PHP_SDK_ROOT_PATH");
|
||||
|
||||
@@ -202,12 +346,45 @@ class Config
|
||||
return file_get_contents($path);
|
||||
}/*}}}*/
|
||||
|
||||
public static function getDepsLocalPath()
|
||||
public static function getDepsLocalPath() : ?string
|
||||
{/*{{{*/
|
||||
if (NULL == self::$depsLocalPath) {
|
||||
if (file_exists("Makefile")) {
|
||||
$s = file_get_contents("Makefile");
|
||||
|
||||
if (preg_match(",PHP_BUILD=(.+),", $s, $m)) {
|
||||
if (isset($m[1])) {
|
||||
self::setDepsLocalPath(trim($m[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == self::$depsLocalPath) {
|
||||
$tmp = dirname(getcwd()) . DIRECTORY_SEPARATOR . "deps";
|
||||
if (is_dir($tmp)) {
|
||||
self::setDepsLocalPath($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == self::$depsLocalPath) {
|
||||
$tmp = realpath("../deps");
|
||||
if (is_dir($tmp)) {
|
||||
self::setDepsLocalPath($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == self::$depsLocalPath) {
|
||||
if (file_exists("main/php_version.h")) {
|
||||
/* Deps dir might not exist. */
|
||||
self::setDepsLocalPath(realpath("..") . DIRECTORY_SEPARATOR . "deps");
|
||||
}
|
||||
}
|
||||
|
||||
return self::$depsLocalPath;
|
||||
}/*}}}*/
|
||||
|
||||
public static function setDepsLocalPath(string $path)
|
||||
public static function setDepsLocalPath(string $path) : void
|
||||
{/*{{{*/
|
||||
self::$depsLocalPath = $path;
|
||||
}/*}}}*/
|
||||
@@ -237,6 +414,11 @@ class Config
|
||||
|
||||
return $path;
|
||||
}/*}}}*/
|
||||
|
||||
public static function getSdkUserAgentName() : string
|
||||
{/*{{{*/
|
||||
return "PHP-SDK-BINARY-TOOLS/" . self::getSdkVersion();
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,127 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace SDK;
|
||||
|
||||
use SDK\Config;
|
||||
use SDK\Exception;
|
||||
|
||||
trait FileOps
|
||||
{
|
||||
protected function md(string $name = "", bool $tmp = false) : string
|
||||
{/*{{{*/
|
||||
$ret = $name;
|
||||
|
||||
if (!$name) {
|
||||
if ($tmp) {
|
||||
$pre = Config::getTmpDir();
|
||||
$ret = $pre . DIRECTORY_SEPARATOR . md5(uniqid());
|
||||
} else {
|
||||
throw new Exception("Dir name is empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!is_dir($ret)) {
|
||||
if (!mkdir($ret, 0755, true)) {
|
||||
throw new Exception("Unable to create '$ret'");
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO is link and more checks. */
|
||||
protected function rm(string $path) : bool
|
||||
{/*{{{*/
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
} else if (is_file($path)) {
|
||||
return unlink($path);
|
||||
}
|
||||
|
||||
$ret = true;
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$path,
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
foreach ($iterator as $item) {
|
||||
if ($item->isDir()) {
|
||||
$ret = $ret && rmdir($item->getPathname());
|
||||
} else {
|
||||
$ret = $ret && unlink($item->getPathname());
|
||||
}
|
||||
}
|
||||
return $ret && rmdir($path);
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO islink and more checks */
|
||||
protected function cp_or_mv(string $src, string $dst, callable $cb) : bool
|
||||
{/*{{{*/
|
||||
if (!file_exists($src)) {
|
||||
return false;
|
||||
} else if (is_file($src)) {
|
||||
return call_user_func($cb, $src, $dst);
|
||||
}
|
||||
|
||||
if (!file_exists($dst)) {
|
||||
$this->md($dst);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$src,
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
$cut_len = strlen($src)+1;
|
||||
foreach ($iterator as $item) {
|
||||
$src_path = $item->getPathname();
|
||||
$sub = substr($src_path, $cut_len);
|
||||
$dst_path = $dst . DIRECTORY_SEPARATOR . $sub;
|
||||
$dst_parent = dirname($dst_path);
|
||||
|
||||
if (!is_dir($dst_parent)) {
|
||||
if (!$this->md($dst_parent)) {
|
||||
throw new Exception("Unable to create '$dst_parent'");
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->isFile()) {
|
||||
if (!call_user_func($cb, $src_path, $dst_path)) {
|
||||
throw new Exception("Unable to $cb '$src_path' to '$dst_path'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}/*}}}*/
|
||||
|
||||
protected function cp(string $src, string $dst) : bool
|
||||
{/*{{{*/
|
||||
return $this->cp_or_mv($src, $dst, "copy");
|
||||
}/*}}}*/
|
||||
|
||||
protected function mv(string $src, string $dst) : bool
|
||||
{/*{{{*/
|
||||
$ret = $this->cp_or_mv($src, $dst, "rename");
|
||||
|
||||
$ret = $ret && $this->rm($src);
|
||||
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
<?php
|
||||
|
||||
namespace SDK;
|
||||
|
||||
trait FileOps
|
||||
{
|
||||
protected function md(string $name = "", bool $tmp = false) : string
|
||||
{/*{{{*/
|
||||
$ret = $name;
|
||||
|
||||
if (!$name) {
|
||||
if ($tmp) {
|
||||
$pre = Config::getTmpDir();
|
||||
$ret = $pre . DIRECTORY_SEPARATOR . md5(uniqid());
|
||||
} else {
|
||||
throw new Exception("Dir name is empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!is_dir($ret)) {
|
||||
if (!mkdir($ret, 0755, true)) {
|
||||
throw new Exception("Unable to create '$ret'");
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO is link and more checks. */
|
||||
protected function rm(string $path) : bool
|
||||
{/*{{{*/
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
} else if (is_file($path)) {
|
||||
return unlink($path);
|
||||
}
|
||||
|
||||
$ret = true;
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$path,
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
foreach ($iterator as $item) {
|
||||
if ($item->isDir()) {
|
||||
$ret = $ret && rmdir($item->getPathname());
|
||||
} else {
|
||||
$ret = $ret && unlink($item->getPathname());
|
||||
}
|
||||
}
|
||||
return $ret && rmdir($path);
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO islink and more checks */
|
||||
protected function cp_or_mv(string $src, string $dst, callable $cb) : bool
|
||||
{/*{{{*/
|
||||
if (!file_exists($src)) {
|
||||
return false;
|
||||
} else if (is_file($src)) {
|
||||
return call_user_func($cb, $src, $dst);
|
||||
}
|
||||
|
||||
if (!file_exists($dst)) {
|
||||
$this->md($dst);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$src,
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
$cut_len = strlen($src)+1;
|
||||
foreach ($iterator as $item) {
|
||||
$src_path = $item->getPathname();
|
||||
$sub = substr($src_path, $cut_len);
|
||||
$dst_path = $dst . DIRECTORY_SEPARATOR . $sub;
|
||||
$dst_parent = dirname($dst_path);
|
||||
|
||||
if (!is_dir($dst_parent)) {
|
||||
if (!$this->md($dst_parent)) {
|
||||
throw new Exception("Unable to create '$dst_parent'");
|
||||
}
|
||||
}
|
||||
|
||||
if ($item->isFile()) {
|
||||
if (!call_user_func($cb, $src_path, $dst_path)) {
|
||||
throw new Exception("Unable to $cb '$src_path' to '$dst_path'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}/*}}}*/
|
||||
|
||||
protected function cp(string $src, string $dst) : bool
|
||||
{/*{{{*/
|
||||
return $this->cp_or_mv($src, $dst, "copy");
|
||||
}/*}}}*/
|
||||
|
||||
protected function mv(string $src, string $dst) : bool
|
||||
{/*{{{*/
|
||||
$ret = $this->cp_or_mv($src, $dst, "rename");
|
||||
|
||||
$ret = $ret && $this->rm($src);
|
||||
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
protected function download(string $url, string $dest_fn = NULL) : ?string
|
||||
{/*{{{*/
|
||||
$fd = NULL;
|
||||
$retry = 0;
|
||||
|
||||
retry:
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
if ($dest_fn) {
|
||||
$fd = fopen($dest_fn, "w+");
|
||||
curl_setopt($ch, CURLOPT_FILE, $fd);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, Config::getSdkUserAgentName());
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
|
||||
$ret = curl_exec($ch);
|
||||
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if (false === $ret || 200 !== $code) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
if ($dest_fn) {
|
||||
fclose($fd);
|
||||
}
|
||||
if ($retry++ < 3) {
|
||||
goto retry;
|
||||
}
|
||||
throw new Exception($err);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($dest_fn) {
|
||||
fclose($fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}/*}}}*/
|
||||
|
||||
/* TODO More detailed zip errors. */
|
||||
protected function unzip(string $zip_fn, string $dest_fn, string $dest_dn = NULL) : void
|
||||
{/*{{{*/
|
||||
$zip = new \ZipArchive;
|
||||
|
||||
$res = $zip->open($zip_fn);
|
||||
if (true !== $res) {
|
||||
throw new Exception("Failed to open '$zip_fn'.");
|
||||
}
|
||||
|
||||
$res = $zip->extractTo($dest_fn);
|
||||
if (true !== $res) {
|
||||
$zip->close();
|
||||
throw new Exception("Failed to unzip '$zip_fn'.");
|
||||
}
|
||||
|
||||
/* Not robust, useful for zips containing one dir sibling only in the root. */
|
||||
if ($dest_dn) {
|
||||
$stat = $zip->statIndex(0);
|
||||
if (false === $stat) {
|
||||
$zip->close();
|
||||
throw new Exception("Failed to stat first index in '$zip_fn'.");
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
/* Index of zero might be not the zipped folder, unusual but true. */
|
||||
/*$name = $stat["name"];
|
||||
if ("/" != substr($name, -1)) {
|
||||
throw new Exception("'$name' is not a directory.");
|
||||
}
|
||||
$name = substr($name, 0, -1);*/
|
||||
|
||||
$name = rtrim($stat["name"], "/");
|
||||
while (strstr($name, '/') !== false) {
|
||||
$name = dirname($name);
|
||||
}
|
||||
|
||||
$old_dir = $dest_fn . DIRECTORY_SEPARATOR . $name;
|
||||
$new_dir = $dest_fn . DIRECTORY_SEPARATOR . $dest_dn;
|
||||
if (file_exists($new_dir)) {
|
||||
if (!$this->rm($new_dir)) {
|
||||
throw new Exception("Failed to remove '$new_dir'.");
|
||||
}
|
||||
}
|
||||
/* if (!$this->mv($old_dir, $new_dir)) { */
|
||||
if (!rename($old_dir, $new_dir)) {
|
||||
throw new Exception("Failed to rename '$old_dir' to '$new_dir'.");
|
||||
}
|
||||
} else {
|
||||
$zip->close();
|
||||
}
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
|
||||
108
lib/php/libsdk/SDK/Lock.php
Normal file
108
lib/php/libsdk/SDK/Lock.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace SDK;
|
||||
|
||||
class Lock
|
||||
{
|
||||
protected $fd;
|
||||
protected $fn;
|
||||
protected $locked = false;
|
||||
protected $wouldBlock = false;
|
||||
protected $shared = false;
|
||||
|
||||
public function __construct(string $tag, bool $auto = true, bool $autoShared = false)
|
||||
{/*{{{*/
|
||||
$hash = hash("sha256", $tag);
|
||||
$this->fn = Config::getTmpDir() . DIRECTORY_SEPARATOR . $hash . ".lock";
|
||||
|
||||
if ($auto) {
|
||||
if ($autoShared) {
|
||||
$this->shared();
|
||||
} else {
|
||||
$this->exclusive();
|
||||
}
|
||||
}
|
||||
}/*}}}*/
|
||||
|
||||
public function __destruct()
|
||||
{/*{{{*/
|
||||
$this->unlock();
|
||||
/* We don't really know no one else waits on the same lock yet.*/
|
||||
/*if (file_exists($this->fn) && !$this->shared) {
|
||||
@unlink($this->fn);
|
||||
}*/
|
||||
}/*}}}*/
|
||||
|
||||
public function shared(bool $block = false) : bool
|
||||
{/*{{{*/
|
||||
$flags = LOCK_SH;
|
||||
if (!$block) {
|
||||
$flags |= LOCK_NB;
|
||||
}
|
||||
|
||||
return $this->doLock($flags);
|
||||
}/*}}}*/
|
||||
|
||||
public function exclusive(bool $block = false) : bool
|
||||
{/*{{{*/
|
||||
$flags = LOCK_EX;
|
||||
if (!$block) {
|
||||
$flags |= LOCK_NB;
|
||||
}
|
||||
|
||||
return $this->doLock($flags);
|
||||
}/*}}}*/
|
||||
|
||||
protected function doLock(int $flags = LOCK_EX) : bool
|
||||
{/*{{{*/
|
||||
if ($this->locked) {
|
||||
/* Or throw an exception, as we don't know which lock type the outta world expected. */
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->shared = $flags & LOCK_SH;
|
||||
if ($this->shared) {
|
||||
$this->fd = fopen($this->fn, "rb");
|
||||
} else {
|
||||
$this->fd = fopen($this->fn, "wb");
|
||||
}
|
||||
if (false === $this->fd) {
|
||||
throw new Exception("Failed to open lock under '$this->fn'");
|
||||
}
|
||||
$this->locked = flock($this->fd, $flags, $this->wouldBlock);
|
||||
return $this->locked;
|
||||
}/*}}}*/
|
||||
|
||||
public function unlock() : bool
|
||||
{/*{{{*/
|
||||
if (!$this->locked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->doLock(LOCK_UN);
|
||||
|
||||
fclose($this->fd);
|
||||
$this->fd = NULL;
|
||||
|
||||
return $this->locked;
|
||||
}/*}}}*/
|
||||
|
||||
public function locked() : bool
|
||||
{/*{{{*/
|
||||
return $this->locked;
|
||||
}/*}}}*/
|
||||
|
||||
public function wouldBlock() : bool
|
||||
{/*{{{*/
|
||||
return 1 === $this->wouldBlock;
|
||||
}/*}}}*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
function __autoload($name)
|
||||
{
|
||||
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $name . ".php";
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
msys2/usr/bin/msys-gcc_s-seh-1.dll
Executable file
BIN
msys2/usr/bin/msys-gcc_s-seh-1.dll
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
msys2/usr/bin/msys-icudata62.dll
Normal file
BIN
msys2/usr/bin/msys-icudata62.dll
Normal file
Binary file not shown.
BIN
msys2/usr/bin/msys-icuuc62.dll
Normal file
BIN
msys2/usr/bin/msys-icuuc62.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
msys2/usr/bin/msys-idn-12.dll
Normal file
BIN
msys2/usr/bin/msys-idn-12.dll
Normal file
Binary file not shown.
BIN
msys2/usr/bin/msys-idn2-0.dll
Normal file
BIN
msys2/usr/bin/msys-idn2-0.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user