TypePHP 编译器 https://swoole.com/aot/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

224 lines
8.7 KiB

<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace TypePhp\Build;
use TypePhp\Metadata\Constants;
trait NativeCommandOptionsTrait
{
/** @var null|array{header: string, artifact: string} */
protected ?array $precompiledHeader = null;
protected function getCommonCompileCommandOptions(): CompileOptions
{
$includePaths = $this->getIncludePaths();
if (!empty($this->userIncludePaths)) {
$includePaths = array_merge($includePaths, $this->userIncludePaths);
}
$userDefines = $this->userDefines;
if ($this->isIosTarget()) {
$userDefines[] = 'PHPX_IOS=1';
}
if ($this->isAndroidTarget()) {
$userDefines[] = 'PHPX_ANDROID=1';
}
if ($this->isBuildModeLib()) {
$userDefines[] = 'TYPEPHP_NO_MAIN=1';
$userDefines[] = $this->getLibraryExportsMacroName() . '=1';
}
if ($this->isNanoMode()) {
array_push(
$userDefines,
'TYPEPHP_NATIVE=1',
'PHP_NANO=1',
'PHPX_NANO=1',
'_POSIX_C_SOURCE=200809L',
);
if ($this->isMacos() || $this->isIosTarget()) {
// A strict POSIX feature profile hides Darwin's BSD integer
// aliases (u_int/u_char/u_short), which are still used by
// public macOS and iOS SDK headers such as sys/sysctl.h.
$userDefines[] = '_DARWIN_C_SOURCE=1';
}
array_push($userDefines, ...$this->nanoRuntimeDefines);
if ($this->isWasiTarget()) {
$userDefines[] = 'ZEND_MM_ERROR=0';
}
}
$values = [
'include_paths' => $includePaths,
'optimize' => $this->optimizeLevel,
'debug' => $this->debug,
'sanitize' => $this->sanitize,
'march' => $this->march,
'target_platform' => $this->targetPlatform,
'is_zts' => $this->isPhpZts,
'build_mode' => $this->buildMode,
'enable_profiler' => $this->enableProfiler,
'prof_output' => $this->targetName . '.prof',
'user_defines' => $userDefines,
'lto' => $this->enableLto,
'section_gc' => $this->isNanoMode(),
'wasi_exceptions' => $this->isNanoMode() && $this->isWasiTarget(),
];
if ($this->debug && $this->isWindows()) {
$values['compiler_pdb'] = $this->getMsvcCompilerPdbFile();
}
return new CompileOptions($values);
}
protected function getMsvcCompilerPdbFile(): string
{
$directory = $this->getBuildDir() . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'msvc';
if (!is_dir($directory) && !mkdir($directory, 0777, true) && !is_dir($directory)) {
throw new \RuntimeException('Cannot create MSVC PDB directory: ' . $directory);
}
return $directory . DIRECTORY_SEPARATOR . $this->targetName . '.compile.pdb';
}
protected function getCompileCommandOptions(): CompileOptions
{
$options = $this->getCommonCompileCommandOptions();
$options = $options
->with('cpp_std', $this->cxxStd)
->with('cxxflags', $this->cxxFlags)
->with('suppressed_warnings', Constants::MSVC_SUPPRESSED_WARNINGS ?? []);
if ($this->isBuildModeLib()) {
$options = $options->with(
'forced_include',
$this->getIncludeDir() . '/php_' . $this->targetName . '_all_decl.h'
);
}
if ($this->precompiledHeader !== null) {
$options = $options->with('precompiled_header', $this->precompiledHeader);
}
return $options;
}
protected function getCCompileCommandOptions(): CompileOptions
{
$options = $this->getCommonCompileCommandOptions();
$options = $options
->with('cflags', $this->cFlags)
->with('suppressed_warnings', ['4244', '4146']);
return $this->isNanoMode() ? $options->with('c_std', 'c11') : $options;
}
protected function getPrecompiledHeaderCompileCommandOptions(): CompileOptions
{
$values = $this->getCompileCommandOptions()->toArray();
unset($values['forced_include'], $values['precompiled_header']);
return new CompileOptions($values);
}
protected function getNativeCompileCommandOptions(string $language = ''): CompileOptions
{
$options = $this->getCommonCompileCommandOptions();
$options = $options->with('suppressed_warnings', Constants::MSVC_SUPPRESSED_WARNINGS ?? []);
if ($language === 'objective-c++') {
$options = $options->with('cpp_std', $this->cxxStd)->with('cxxflags', $this->cxxFlags);
} elseif ($language === 'assembler') {
$options = $options->with('nativeflags', $this->asmFlags);
} elseif ($language === 'objective-c') {
$options = $options->with('nativeflags', $this->cFlags);
}
return $options;
}
protected function getProjectRuntimeEntryCompileCommandOptions(): CompileOptions
{
$values = $this->getCompileCommandOptions()->toArray();
// TYPEPHP_PROJECT_NAME is deliberately confined to the small,
// project-specific entry translation unit. Defining it while loading
// the common PCH would make every output target require a distinct PCH.
unset($values['forced_include'], $values['precompiled_header']);
$values['user_defines'][] = 'TYPEPHP_RUNTIME_EXPORTS=1';
$values['user_defines'][] = 'TYPEPHP_PROJECT_NAME=' . $this->targetName;
return new CompileOptions($values);
}
protected function getLinkCommandOptions(): LinkOptions
{
$libraryPaths = array_merge($this->getLibraryPaths(), $this->linkPaths);
$libraries = $this->getLibraries();
if ($this->enableProfiler) {
$libraries[] = 'profiler';
}
$libraries = array_merge($libraries, $this->linkLibs);
$ldflags = $this->ldflags;
$postLdflags = '';
if ($this->isPhpBuilderBuild()
&& $this->hasSapi('embed')
&& $this->sapiPhpBuildDirectory !== null
) {
$makefile = $this->sapiPhpBuildDirectory . '/Makefile';
$contents = is_file($makefile) ? (string) file_get_contents($makefile) : '';
if (preg_match('/^EXTRA_LIBS[ \t]*=[ \t]*(.*)$/m', $contents, $match) === 1) {
// Static libphp references these system libraries, so they must
// appear after -lphp on linkers that resolve archives left-to-right.
$postLdflags = trim($match[1]);
}
}
$targetPlatform = $this->targetPlatform;
if ($this->fullStatic) {
// The bundled libphp.a carries musl libc, so the link must use musl's
// C runtime instead of glibc's. -B points the driver at the musl
// startup files; -static keeps the result free of NEEDED entries.
// Only the link step switches target: the translation units are still
// compiled against the host libstdc++ headers, which is fine because
// TLS relocations are resolved here rather than at compile time.
$targetPlatform = $this->getFullStaticTargetTriple();
$ldflags = trim('-static -B ' . escapeshellarg($this->getFullStaticMuslDir()) . ' ' . $ldflags);
}
if ($this->isNanoMode()) {
$gcSections = $this->isMacos() ? '-Wl,-dead_strip' : '-Wl,--gc-sections';
$ldflags = trim($gcSections . ' ' . $ldflags);
if ($this->isWasiTarget()) {
$ldflags = trim(
'-fwasm-exceptions -lsetjmp -lunwind ' . $ldflags,
);
}
}
$options = [
'library_paths' => $libraryPaths,
'libraries' => $libraries,
'ldflags' => $ldflags,
'post_ldflags' => $postLdflags,
'debug' => $this->debug,
'no_console' => $this->noConsole,
'build_mode' => $this->buildMode,
'sanitize' => $this->sanitize,
'lto' => $this->enableLto,
'target_platform' => $targetPlatform,
'response_file' => $this->getBuildDir() . DIRECTORY_SEPARATOR . 'cache'
. DIRECTORY_SEPARATOR . 'link' . DIRECTORY_SEPARATOR
. basename($this->getTargetFileName()) . '.rsp',
];
$rpaths = $this->isNanoMode()
? []
: $this->getPlatform()->getDefaultRpaths($this->getPhpxDir(), $this->getPhpDir());
if (!empty($rpaths)) {
$options['rpath'] = $rpaths;
}
return new LinkOptions($options);
}
}