Skip to content

Commit 27a5b97

Browse files
authored
Merge pull request #76 from asgrim/parallel-jobs-with-make
Parallel jobs with make
2 parents c80f425 + 2f4ca87 commit 27a5b97

17 files changed

+130
-14
lines changed

src/Building/UnixBuild.php

+13-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class UnixBuild implements Build
2020
{
2121
private const PHPIZE_TIMEOUT_SECS = 60; // 1 minute
2222
private const CONFIGURE_TIMEOUT_SECS = 120; // 2 minutes
23-
private const MAKE_TIMEOUT_SECS = 600; // 10 minutes
23+
private const MAKE_TIMEOUT_SECS = null; // unlimited
2424

2525
/** {@inheritDoc} */
2626
public function __invoke(
@@ -52,7 +52,7 @@ public function __invoke(
5252
$optionsOutput = count($configureOptions) ? ' with options: ' . implode(' ', $configureOptions) : '.';
5353
$output->writeln('<info>Configure complete</info>' . $optionsOutput);
5454

55-
$makeOutput = $this->make($downloadedPackage);
55+
$makeOutput = $this->make($targetPlatform, $downloadedPackage, $output);
5656
if ($output->isVeryVerbose()) {
5757
$output->writeln($makeOutput);
5858
}
@@ -93,10 +93,19 @@ private function configure(DownloadedPackage $downloadedPackage, array $configur
9393
);
9494
}
9595

96-
private function make(DownloadedPackage $downloadedPackage): string
96+
private function make(TargetPlatform $targetPlatform, DownloadedPackage $downloadedPackage, OutputInterface $output): string
9797
{
98+
$makeCommand = ['make'];
99+
100+
if ($targetPlatform->makeParallelJobs === 1) {
101+
$output->writeln('Running make without parallelization - try providing -jN to PIE where N is the number of cores you have.');
102+
} else {
103+
$makeCommand[] = '--jobs';
104+
$makeCommand[] = (string) $targetPlatform->makeParallelJobs;
105+
}
106+
98107
return Process::run(
99-
['make'],
108+
$makeCommand,
100109
$downloadedPackage->extractedSourcePath,
101110
self::MAKE_TIMEOUT_SECS,
102111
);

src/Command/CommandHelper.php

+18-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ final class CommandHelper
4141
private const ARG_REQUESTED_PACKAGE_AND_VERSION = 'requested-package-and-version';
4242
private const OPTION_WITH_PHP_CONFIG = 'with-php-config';
4343
private const OPTION_WITH_PHP_PATH = 'with-php-path';
44+
private const OPTION_MAKE_PARALLEL_JOBS = 'make-parallel-jobs';
4445

4546
/** @psalm-suppress UnusedConstructor */
4647
private function __construct()
@@ -52,13 +53,13 @@ public static function configurePhpConfigOptions(Command $command): void
5253
$command->addOption(
5354
self::OPTION_WITH_PHP_CONFIG,
5455
null,
55-
InputOption::VALUE_OPTIONAL,
56+
InputOption::VALUE_REQUIRED,
5657
'The path to the `php-config` binary to find the target PHP platform on ' . OperatingSystem::NonWindows->asFriendlyName() . ', e.g. --' . self::OPTION_WITH_PHP_CONFIG . '=/usr/bin/php-config7.4',
5758
);
5859
$command->addOption(
5960
self::OPTION_WITH_PHP_PATH,
6061
null,
61-
InputOption::VALUE_OPTIONAL,
62+
InputOption::VALUE_REQUIRED,
6263
'The path to the `php` binary to use as the target PHP platform on ' . OperatingSystem::Windows->asFriendlyName() . ', e.g. --' . self::OPTION_WITH_PHP_PATH . '=C:\usr\php7.4.33\php.exe',
6364
);
6465
}
@@ -70,6 +71,12 @@ public static function configureDownloadBuildInstallOptions(Command $command): v
7071
InputArgument::REQUIRED,
7172
'The extension name and version constraint to use, in the format {ext-name}{?:{?version-constraint}{?@stability}}, for example `xdebug/xdebug:^3.4@alpha`, `xdebug/xdebug:@alpha`, `xdebug/xdebug:^3.4`, etc.',
7273
);
74+
$command->addOption(
75+
self::OPTION_MAKE_PARALLEL_JOBS,
76+
'j',
77+
InputOption::VALUE_REQUIRED,
78+
'Override many jobs to run in parallel when running compiling (this is passed to "make -jN" during build). PIE will try to detect this by default.',
79+
);
7380

7481
self::configurePhpConfigOptions($command);
7582

@@ -112,7 +119,15 @@ public static function determineTargetPlatformFromInputs(InputInterface $input,
112119
$phpBinaryPath = PhpBinaryPath::fromPhpBinaryPath($withPhpPath);
113120
}
114121

115-
$targetPlatform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath);
122+
$makeParallelJobs = null; /** `null` means {@see TargetPlatform} will try to auto-detect */
123+
if ($input->hasOption(self::OPTION_MAKE_PARALLEL_JOBS)) {
124+
$makeParallelJobsOptions = (int) $input->getOption(self::OPTION_MAKE_PARALLEL_JOBS);
125+
if ($makeParallelJobsOptions > 0) {
126+
$makeParallelJobs = $makeParallelJobsOptions;
127+
}
128+
}
129+
130+
$targetPlatform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, $makeParallelJobs);
116131

117132
$output->writeln(sprintf('<info>You are running PHP %s</info>', PHP_VERSION));
118133
$output->writeln(sprintf(

src/Platform/TargetPlatform.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Php\Pie\Platform;
66

77
use Php\Pie\Platform\TargetPhp\PhpBinaryPath;
8+
use Php\Pie\Util\NumberOfCores;
89

910
use function array_key_exists;
1011
use function curl_version;
@@ -27,6 +28,7 @@ public function __construct(
2728
public readonly PhpBinaryPath $phpBinaryPath,
2829
public readonly Architecture $architecture,
2930
public readonly ThreadSafetyMode $threadSafety,
31+
public readonly int $makeParallelJobs,
3032
public readonly WindowsCompiler|null $windowsCompiler,
3133
) {
3234
}
@@ -50,7 +52,7 @@ public static function isRunningAsRoot(): bool
5052
return function_exists('posix_getuid') && posix_getuid() === 0;
5153
}
5254

53-
public static function fromPhpBinaryPath(PhpBinaryPath $phpBinaryPath): self
55+
public static function fromPhpBinaryPath(PhpBinaryPath $phpBinaryPath, int|null $makeParallelJobs): self
5456
{
5557
$os = $phpBinaryPath->operatingSystem();
5658

@@ -122,11 +124,16 @@ public static function fromPhpBinaryPath(PhpBinaryPath $phpBinaryPath): self
122124
}
123125
}
124126

127+
if ($makeParallelJobs === null) {
128+
$makeParallelJobs = NumberOfCores::determine();
129+
}
130+
125131
return new self(
126132
$os,
127133
$phpBinaryPath,
128134
$architecture,
129135
$threadSafety,
136+
$makeParallelJobs,
130137
$windowsCompiler,
131138
);
132139
}

src/Util/NumberOfCores.php

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Pie\Util;
6+
7+
use Symfony\Component\Process\Process;
8+
9+
use function is_numeric;
10+
use function trim;
11+
12+
final class NumberOfCores
13+
{
14+
/** @psalm-suppress UnusedConstructor */
15+
private function __construct()
16+
{
17+
}
18+
19+
/**
20+
* @param list<string> $params
21+
*
22+
* @return positive-int
23+
*/
24+
private static function tryCommand(string $command, array $params): int|null
25+
{
26+
$whichProcess = new Process(['which', $command]);
27+
if ($whichProcess->run() === 0) {
28+
$commandPath = trim($whichProcess->getOutput());
29+
30+
$commandProcess = new Process([$commandPath, ...$params]);
31+
if ($commandProcess->run() === 0) {
32+
$commandResult = trim($commandProcess->getOutput());
33+
if (is_numeric($commandResult)) {
34+
$commandNumericResult = (int) $commandResult;
35+
36+
if ($commandNumericResult > 0) {
37+
return $commandNumericResult;
38+
}
39+
}
40+
}
41+
}
42+
43+
return null;
44+
}
45+
46+
/**
47+
* Try a few different ways of determining number of CPUs. If we can't guess
48+
* how many CPUs someone has, then default to 1 for safety.
49+
*
50+
* @return positive-int
51+
*/
52+
public static function determine(): int
53+
{
54+
$nproc = self::tryCommand('nproc', ['--all']);
55+
if ($nproc !== null) {
56+
return $nproc;
57+
}
58+
59+
$getconf = self::tryCommand('getconf', ['_NPROCESSORS_ONLN']);
60+
if ($getconf !== null) {
61+
return $getconf;
62+
}
63+
64+
$sysctl = self::tryCommand('sysctl', ['-n', 'hw.ncpu']);
65+
if ($sysctl !== null) {
66+
return $sysctl;
67+
}
68+
69+
// Default to 1 for safety
70+
return 1;
71+
}
72+
}

test/integration/Building/UnixBuildTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function testUnixBuildCanBuildExtension(): void
5050
$unixBuilder = new UnixBuild();
5151
$unixBuilder->__invoke(
5252
$downloadedPackage,
53-
TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess()),
53+
TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess(), null),
5454
['--enable-pie_test_ext'],
5555
$output,
5656
);

test/integration/DependencyResolver/ResolveDependencyWithComposerTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function testDependenciesAreResolvedToExpectedVersions(
6969
$resolve = $container->get(DependencyResolver::class);
7070

7171
$package = $resolve->__invoke(
72-
TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess()),
72+
TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess(), null),
7373
'asgrim/example-pie-extension',
7474
$requestedVersion,
7575
);

test/integration/Installing/UnixInstallTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function testUnixInstallCanInstallExtension(string $phpConfig): void
7575
}
7676

7777
$output = new BufferedOutput();
78-
$targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromPhpConfigExecutable($phpConfig));
78+
$targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromPhpConfigExecutable($phpConfig), null);
7979
$extensionPath = $targetPlatform->phpBinaryPath->extensionPath();
8080

8181
$downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath(

test/integration/Installing/WindowsInstallTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public function testWindowsInstallCanInstallExtension(): void
6565
PhpBinaryPath::fromCurrentProcess(),
6666
Architecture::x86_64,
6767
ThreadSafetyMode::ThreadSafe,
68+
1,
6869
WindowsCompiler::VS16,
6970
);
7071
$phpPath = dirname($targetPlatform->phpBinaryPath->phpBinaryPath);

test/unit/Command/CommandHelperTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function testInvalidRequestedNameAndVersionPairThrowsExceptionWhenNoPacka
9292
public function testDownloadPackage(): void
9393
{
9494
$dependencyResolver = $this->createMock(DependencyResolver::class);
95-
$targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess());
95+
$targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess(), null);
9696
$requestedNameAndVersionPair = ['name' => 'php/test-pie-ext', 'version' => '^1.2'];
9797
$downloadAndExtract = $this->createMock(DownloadAndExtract::class);
9898
$output = $this->createMock(OutputInterface::class);

test/unit/DependencyResolver/ResolveDependencyWithComposerTest.php

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public function testPackageThatCanBeResolved(): void
5757
$phpBinaryPath,
5858
Architecture::x86_64,
5959
ThreadSafetyMode::ThreadSafe,
60+
1,
6061
null,
6162
);
6263

@@ -97,6 +98,7 @@ public function testPackageThatCannotBeResolvedThrowsException(array $platformOv
9798
$phpBinaryPath,
9899
Architecture::x86_64,
99100
ThreadSafetyMode::ThreadSafe,
101+
1,
100102
null,
101103
);
102104

@@ -139,6 +141,7 @@ public function testZtsOnlyPackageCannotBeInstalledOnNtsSystem(): void
139141
$phpBinaryPath,
140142
Architecture::x86_64,
141143
ThreadSafetyMode::NonThreadSafe,
144+
1,
142145
null,
143146
);
144147

@@ -181,6 +184,7 @@ public function testNtsOnlyPackageCannotBeInstalledOnZtsSystem(): void
181184
$phpBinaryPath,
182185
Architecture::x86_64,
183186
ThreadSafetyMode::ThreadSafe,
187+
1,
184188
null,
185189
);
186190

test/unit/Downloading/Exception/CouldNotFindReleaseAssetTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function testForMissingWindowsCompiler(): void
6767
$phpBinary,
6868
Architecture::x86,
6969
ThreadSafetyMode::NonThreadSafe,
70+
1,
7071
null,
7172
));
7273

test/unit/Downloading/GithubPackageReleaseAssetsTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void
4141
$phpBinaryPath,
4242
Architecture::x86,
4343
ThreadSafetyMode::ThreadSafe,
44+
1,
4445
WindowsCompiler::VC14,
4546
);
4647

@@ -97,6 +98,7 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr
9798
$phpBinaryPath,
9899
Architecture::x86,
99100
ThreadSafetyMode::ThreadSafe,
101+
1,
100102
WindowsCompiler::VC14,
101103
);
102104

@@ -148,6 +150,7 @@ public function testFindWindowsDownloadUrlForPackageThrowsExceptionWhenAssetNotF
148150
PhpBinaryPath::fromCurrentProcess(),
149151
Architecture::x86,
150152
ThreadSafetyMode::ThreadSafe,
153+
1,
151154
WindowsCompiler::VC14,
152155
);
153156

test/unit/Downloading/UnixDownloadAndExtractTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public function testInvoke(): void
3232
PhpBinaryPath::fromCurrentProcess(),
3333
Architecture::x86,
3434
ThreadSafetyMode::NonThreadSafe,
35+
1,
3536
null,
3637
);
3738

test/unit/Downloading/WindowsDownloadAndExtractTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function testInvoke(): void
3737
PhpBinaryPath::fromCurrentProcess(),
3838
Architecture::x86,
3939
ThreadSafetyMode::ThreadSafe,
40+
1,
4041
WindowsCompiler::VC14,
4142
);
4243

test/unit/Installing/InstallNotification/SendInstallNotificationUsingGuzzleTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public function setUp(): void
5353
$phpBinaryPath,
5454
Architecture::x86,
5555
ThreadSafetyMode::ThreadSafe,
56+
1,
5657
WindowsCompiler::VC14,
5758
);
5859
}

test/unit/Platform/TargetPlatformTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function testWindowsPlatformFromPhpInfo(): void
5050
PHP Extension Build => API20230831,TS,VS16
5151
TEXT);
5252

53-
$platform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath);
53+
$platform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, null);
5454

5555
self::assertSame(OperatingSystem::Windows, $platform->operatingSystem);
5656
self::assertSame(WindowsCompiler::VS16, $platform->windowsCompiler);
@@ -91,7 +91,7 @@ public function testLinuxPlatform(): void
9191
Thread Safety => disabled
9292
TEXT);
9393

94-
$platform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath);
94+
$platform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, null);
9595

9696
self::assertSame(OperatingSystem::NonWindows, $platform->operatingSystem);
9797
self::assertSame(null, $platform->windowsCompiler);

test/unit/Platform/WindowsExtensionAssetNameTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public function setUp(): void
3333
PhpBinaryPath::fromCurrentProcess(),
3434
Architecture::x86_64,
3535
ThreadSafetyMode::ThreadSafe,
36+
1,
3637
WindowsCompiler::VC14,
3738
);
3839

0 commit comments

Comments
 (0)