Windows::prepareConfigOpts()   B
last analyzed

Complexity

Conditions 7
Paths 11

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 22
rs 8.8333
cc 7
nc 11
nop 0
1
<?php
2
3
/*
4
 * Pickle
5
 *
6
 *
7
 * @license
8
 *
9
 * New BSD License
10
 *
11
 * Copyright © 2015-2015, Pickle community. All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *     * Redistributions of source code must retain the above copyright
16
 *       notice, this list of conditions and the following disclaimer.
17
 *     * Redistributions in binary form must reproduce the above copyright
18
 *       notice, this list of conditions and the following disclaimer in the
19
 *       documentation and/or other materials provided with the distribution.
20
 *     * Neither the name of the Hoa nor the names of its contributors may be
21
 *       used to endorse or promote products derived from this software without
22
 *       specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
37
namespace Pickle\Package\PHP\Command\Build;
38
39
use Exception;
40
use Pickle\Base\Abstracts;
41
use Pickle\Base\Interfaces;
42
use Pickle\Engine;
43
44
class Windows extends Abstracts\Package\Build implements Interfaces\Package\Build
45
{
46
    public function prepare()
47
    {
48
        if (!file_exists('c:\\php-sdk\\bin')) {
49
            throw new Exception('PHP SDK not found');
50
        }
51
        putenv('path=c:\\php-sdk\\bin;' . getenv('path'));
52
53
        if (!$this->runCommand('phpsdk_setvars')) {
54
            throw new Exception('phpsdk_setvars failed');
55
        }
56
57
        $this->phpize();
58
    }
59
60
    public function phpize()
61
    {
62
        $backCwd = getcwd();
63
        chdir($this->pkg->getSourceDir());
64
65
        $res = $this->runCommand('phpize');
66
        chdir($backCwd);
67
        if (!$res) {
68
            throw new Exception('phpize failed');
69
        }
70
    }
71
72
    public function configure($opts = null)
73
    {
74
        /* duplicate src tree to do not pollute repo or src dir */
75
        $this->copySrcDir($this->pkg->getSourceDir(), $this->tempDir);
76
        $backCwd = getcwd();
77
        chdir($this->tempDir);
78
79
        $configureOptions = $opts ?: $this->prepareConfigOpts();
80
81
        $res = $this->runCommand($this->pkg->getSourceDir() . '/configure ' . $configureOptions);
82
        chdir($backCwd);
83
        if (!$res) {
84
            throw new Exception('configure failed, see log at ' . $this->tempDir . '\config.log');
85
        }
86
87
        /* This post check is required for the case when config.w32 doesn't
88
           bail out on error but silently disables an extension. In this
89
           case we won't see any bad exit status. */
90
        $opts = $this->pkg->getConfigureOptions();
91
        $ext = key($opts);
92
        if (preg_match(',\|\s+' . preg_quote($ext) . '\s+\|\s+shared\s+\|,Sm', $this->getlog('configure')) < 1) {
93
            throw new Exception("failed to configure the '{$ext}' extension");
94
        }
95
    }
96
97
    public function make()
98
    {
99
        $backCwd = getcwd();
100
        chdir($this->tempDir);
101
        $res = $this->runCommand('nmake');
102
        chdir($backCwd);
103
104
        if (!$res) {
105
            throw new Exception('nmake failed');
106
        }
107
    }
108
109
    public function install()
110
    {
111
        $backCwd = getcwd();
112
        chdir($this->tempDir);
113
114
        /* Record the produced DLL filenames. */
115
        $files = (array) glob('*/*/php_*.dll');
116
        $files = array_merge($files, glob('*/php_*.dll'));
117
        $dlls = [];
118
        foreach ($files as $file) {
119
            $dlls[] = basename($file);
120
        }
121
122
        $res = $this->runCommand('nmake install');
123
        chdir($backCwd);
124
        if (!$res) {
125
            throw new Exception('nmake install failed');
126
        }
127
128
        $ini = \Pickle\Engine\Ini::factory(Engine::factory());
129
        $ini->updatePickleSection($dlls);
130
    }
131
132
    public function getInfo()
133
    {
134
        $info = [];
135
        $info = array_merge($info, $this->getInfoFromPhpizeLog());
136
        $info = array_merge($info, $this->getInfoFromConfigureLog());
137
        $m = null;
138
        if (!preg_match(',(.+)/(.+),', $info['name'], $m)) {
139
            $info['vendor'] = null;
140
        } else {
141
            $info['name'] = $m[2];
142
            $info['vendor'] = $m[1];
143
        }
144
145
        return $info;
146
    }
147
148
    protected function prepareConfigOpts()
149
    {
150
        $configureOptions = '--enable-debug-pack';
151
        foreach ($this->options as $name => $option) {
152
            $decision = null;
153
            if ($option->type === 'enable') {
154
                $decision = $option->input === true ? 'enable' : 'disable';
155
            } elseif ($option->type == 'disable') {
156
                $decision = $option->input === false ? 'enable' : 'disable';
157
            }
158
159
            if ($decision !== null) {
160
                $configureOptions .= ' --' . $decision . '-' . $name;
161
            }
162
        }
163
164
        $php_prefix = dirname(Engine::factory()->getPath());
165
        $configureOptions .= " --with-prefix={$php_prefix}";
166
167
        $this->appendPkgConfigureOptions($configureOptions);
168
169
        return $configureOptions;
170
    }
171
172
    protected function getInfoFromPhpizeLog()
173
    {
174
        $ret = [
175
            'php_major' => null,
176
            'php_minor' => null,
177
            'php_patch' => null,
178
        ];
179
180
        $tmp = $this->getLog('phpize');
181
        $m = null;
182
        if (!preg_match(",Rebuilding configure.js[\n\r\\d:]+\\s+(.+)[\n\r]+,", $tmp, $m)) {
183
            throw new Exception("Couldn't determine PHP development SDK path");
184
        }
185
        $sdk = $m[1];
186
187
        $ver_header = file_get_contents("{$sdk}/include/main/php_version.h");
188
189
        if (!preg_match(',PHP_MAJOR_VERSION\\s+(\\d+),', $ver_header, $m)) {
190
            throw new Exception("Couldn't determine PHP_MAJOR_VERSION");
191
        }
192
        $ret['php_major'] = $m[1];
193
194
        if (!preg_match(',PHP_MINOR_VERSION\\s+(\\d+),', $ver_header, $m)) {
195
            throw new Exception("Couldn't determine PHP_MINOR_VERSION");
196
        }
197
        $ret['php_minor'] = $m[1];
198
199
        if (!preg_match(',PHP_RELEASE_VERSION\\s+(\\d+),', $ver_header, $m)) {
200
            throw new Exception("Couldn't determine PHP_RELEASE_VERSION");
201
        }
202
        $ret['php_patch'] = $m[1];
203
204
        return $ret;
205
    }
206
207
    protected function getInfoFromConfigureLog()
208
    {
209
        $info = [
210
            'thread_safe' => null,
211
            'compiler' => null,
212
            'arch' => null,
213
            'version' => null,
214
            'name' => null,
215
            'is_release' => null,
216
        ];
217
218
        $tmp = $this->getLog('configure');
219
        $m = null;
220
        if (!preg_match(',Build type\\s+\\|\\s+([a-zA-Z]+),', $tmp, $m)) {
221
            throw new Exception("Couldn't determine the build thread safety");
222
        }
223
        $info['is_release'] = $m[1] === 'Release';
224
225
        if (!preg_match(',Thread Safety\\s+\\|\\s+([a-zA-Z]+),', $tmp, $m)) {
226
            throw new Exception("Couldn't determine the build thread safety");
227
        }
228
        $info['thread_safe'] = strtolower($m[1]) == 'yes';
229
230
        if (!preg_match(',Compiler\\s+\\|\\s+MSVC(\\d+),', $tmp, $m)) {
231
            throw new Exception('Currently only MSVC is supported');
232
        }
233
        $info['compiler'] = 'vc' . $m[1];
234
235
        if (!preg_match(',Architecture\\s+\\|\\s+([a-zA-Z0-9]+),', $tmp, $m)) {
236
            throw new Exception("Couldn't determine the build architecture");
237
        }
238
        $info['arch'] = $m[1];
239
240
        $info['version'] = $this->getPackage()->getPrettyVersion();
241
        $info['name'] = $this->getPackage()->getName();
242
243
        return $info;
244
    }
245
246
    /**
247
     * @param string $src
248
     */
249
    private function copySrcDir($src, $dest)
250
    {
251
        foreach (scandir($src) as $file) {
252
            $srcfile = rtrim($src, '/') . '/' . $file;
253
            $destfile = rtrim($dest, '/') . '/' . $file;
254
            if (!is_readable($srcfile)) {
255
                continue;
256
            }
257
            if ($file != '.' && $file != '..') {
258
                if (is_dir($srcfile)) {
259
                    if (!is_dir($destfile)) {
260
                        mkdir($destfile);
261
                    }
262
                    $this->copySrcDir($srcfile, $destfile);
263
                } else {
264
                    copy($srcfile, $destfile);
265
                }
266
            }
267
        }
268
    }
269
}
270
271
/* vim: set tabstop=4 shiftwidth=4 expandtab: fdm=marker */
272