diff --git a/src/Building/UnixBuild.php b/src/Building/UnixBuild.php index 384c547..6e7c994 100644 --- a/src/Building/UnixBuild.php +++ b/src/Building/UnixBuild.php @@ -45,8 +45,18 @@ public function __invoke( }; } + $phpizePath ??= PhpizePath::guessFrom($targetPlatform->phpBinaryPath); + + /** + * Call a cleanup first; most of the time, we expect to be changing a + * version (e.g. upgrade, downgrade), in which case the source is + * already clean anyway; however, sometimes we want to rebuild the + * current ext, so this will perform a clean first + */ + $this->cleanup($phpizePath, $downloadedPackage, $output, $outputCallback); + $this->phpize( - $phpizePath ?? PhpizePath::guessFrom($targetPlatform->phpBinaryPath), + $phpizePath, $downloadedPackage, $output, $outputCallback, @@ -151,4 +161,40 @@ private function make( $outputCallback, ); } + + /** @param callable(SymfonyProcess::ERR|SymfonyProcess::OUT, string): void|null $outputCallback */ + private function cleanup( + PhpizePath $phpize, + DownloadedPackage $downloadedPackage, + OutputInterface $output, + callable|null $outputCallback, + ): void { + /** + * A basic, but fallible check to see if we should clean first. This + * should work "most" of the time, unless someone has removed the + * configure script manually... + */ + if (! file_exists($downloadedPackage->extractedSourcePath . '/configure')) { + if ($output->isVerbose()) { + $output->writeln('Skipping phpize --clean, configure does not exist'); + } + + return; + } + + $phpizeCleanCommand = [$phpize->phpizeBinaryPath, '--clean']; + + if ($output->isVerbose()) { + $output->writeln('Running phpize --clean step using: ' . implode(' ', $phpizeCleanCommand) . ''); + } + + Process::run( + $phpizeCleanCommand, + $downloadedPackage->extractedSourcePath, + self::PHPIZE_TIMEOUT_SECS, + $outputCallback, + ); + + $output->writeln('Build files cleaned up.'); + } } diff --git a/test/integration/Building/UnixBuildTest.php b/test/integration/Building/UnixBuildTest.php index ce82c94..41bffb7 100644 --- a/test/integration/Building/UnixBuildTest.php +++ b/test/integration/Building/UnixBuildTest.php @@ -18,6 +18,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Process; use function dirname; @@ -173,4 +174,88 @@ public function testUnixBuildCanBuildExtensionWithBuildPath(): void (new Process(['make', 'clean'], $downloadedPackage->extractedSourcePath))->mustRun(); (new Process(['phpize', '--clean'], $downloadedPackage->extractedSourcePath))->mustRun(); } + + public function testCleanupDoesNotCleanWhenConfigureIsMissing(): void + { + if (Platform::isWindows()) { + self::markTestSkipped('Unix build test cannot be run on Windows'); + } + + (new Process(['phpize', '--clean'], self::TEST_EXTENSION_PATH))->mustRun(); + self::assertFileDoesNotExist(self::TEST_EXTENSION_PATH . '/configure'); + + $output = new BufferedOutput(); + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + + $downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath( + new Package( + $this->createMock(CompletePackage::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('pie_test_ext'), + 'pie_test_ext', + '0.1.0', + null, + [], + true, + true, + null, + ), + self::TEST_EXTENSION_PATH, + ); + + $unixBuilder = new UnixBuild(); + $unixBuilder->__invoke( + $downloadedPackage, + TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess(), null), + ['--enable-pie_test_ext'], + $output, + null, + ); + + $outputString = $output->fetch(); + self::assertStringContainsString('Skipping phpize --clean, configure does not exist', $outputString); + self::assertStringNotContainsString('Build files cleaned up', $outputString); + } + + public function testVerboseOutputShowsCleanupMessages(): void + { + if (Platform::isWindows()) { + self::markTestSkipped('Unix build test cannot be run on Windows'); + } + + (new Process(['phpize'], self::TEST_EXTENSION_PATH))->mustRun(); + self::assertFileExists(self::TEST_EXTENSION_PATH . '/configure'); + + $output = new BufferedOutput(); + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + + $downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath( + new Package( + $this->createMock(CompletePackage::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('pie_test_ext'), + 'pie_test_ext', + '0.1.0', + null, + [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], + true, + true, + null, + ), + self::TEST_EXTENSION_PATH, + ); + + $unixBuilder = new UnixBuild(); + $unixBuilder->__invoke( + $downloadedPackage, + TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromCurrentProcess(), null), + ['--enable-pie_test_ext'], + $output, + null, + ); + + $outputString = $output->fetch(); + self::assertStringContainsString('Running phpize --clean step', $outputString); + self::assertStringContainsString('Build files cleaned up', $outputString); + } }