genFcallCode() public method

public genFcallCode ( )
示例#1
0
 /**
  * Generates the C sources from Zephir without compiling them
  *
  * @param CommandInterface $command
  * @return bool
  * @throws Exception
  */
 public function generate(CommandInterface $command)
 {
     /**
      * Get global namespace
      */
     $namespace = $this->checkDirectory();
     /**
      * Check whether there are external dependencies
      */
     $externalDependencies = $this->config->get('external-dependencies');
     if (is_array($externalDependencies)) {
         foreach ($externalDependencies as $dependencyNs => $location) {
             if (!file_exists($location)) {
                 throw new CompilerException('Location of dependency "' . $dependencyNs . '" does not exist. Check the config.json for more information');
             }
             $this->addExternalDependency($dependencyNs, $location);
         }
     }
     /**
      * Check if there are module/request/global destructors
      */
     $destructors = $this->config->get('destructors');
     if (is_array($destructors)) {
         $invokeDestructors = $this->processCodeInjection($destructors);
         $includes = $invokeDestructors[0];
         $destructors = $invokeDestructors[1];
     }
     /**
      * Check if there are module/request/global initializers
      */
     $initializers = $this->config->get('initializers');
     if (is_array($initializers)) {
         $invokeInitializers = $this->processCodeInjection($initializers);
         $includes = $invokeInitializers[0];
         $initializers = $invokeInitializers[1];
     }
     /**
      * Round 1. pre-compile all files in memory
      */
     $this->recursivePreCompile(str_replace('\\', DIRECTORY_SEPARATOR, $namespace));
     if (!count($this->files)) {
         throw new Exception("Zephir files to compile couldn't be found. Did you add a first class to the extension?");
     }
     /**
      * Round 2. Check 'extends' and 'implements' dependencies
      */
     foreach ($this->files as $compileFile) {
         $compileFile->checkDependencies($this);
     }
     /**
      * Sort the files by dependency ranking
      */
     $files = array();
     $rankedFiles = array();
     $this->calculateDependencies($this->files);
     foreach ($this->files as $rankFile) {
         $rank = $rankFile->getClassDefinition()->getDependencyRank();
         $rankedFiles[$rank][] = $rankFile;
     }
     krsort($rankedFiles);
     foreach ($rankedFiles as $rank => $rankFiles) {
         $files = array_merge($files, $rankFiles);
     }
     $this->files = $files;
     /**
      * Convert C-constants into PHP constants
      */
     $constantsSources = $this->config->get('constants-sources');
     if (is_array($constantsSources)) {
         $this->loadConstantsSources($constantsSources);
     }
     /**
      * Set extension globals
      */
     $globals = $this->config->get('globals');
     if (is_array($globals)) {
         $this->setExtensionGlobals($globals);
     }
     /**
      * Load function optimizers
      */
     if (self::$loadedPrototypes === false) {
         FunctionCall::addOptimizerDir(ZEPHIRPATH . 'Library/Optimizers/FunctionCall');
         $optimizerDirs = $this->config->get('optimizer-dirs');
         if (is_array($optimizerDirs)) {
             foreach ($optimizerDirs as $directory) {
                 FunctionCall::addOptimizerDir(realpath($directory));
             }
         }
         if (is_dir(ZEPHIRPATH . 'prototypes') && is_readable(ZEPHIRPATH . 'prototypes')) {
             /**
              * Load additional extension prototypes
              * @var $file \DirectoryIterator
              */
             foreach (new \DirectoryIterator(ZEPHIRPATH . 'prototypes') as $file) {
                 if (!$file->isDir()) {
                     $extension = str_replace('.php', '', $file);
                     if (!extension_loaded($extension)) {
                         require $file->getRealPath();
                     }
                 }
             }
         }
         /**
          * Load customer additional extension prototypes
          */
         $prototypeDirs = $this->config->get('prototype-dir');
         if (is_array($prototypeDirs)) {
             foreach ($prototypeDirs as $prototype => $prototypeDir) {
                 /**
                  * Check if the extension is installed
                  */
                 if (!extension_loaded($prototype)) {
                     $prototypeRealpath = realpath($prototypeDir);
                     if ($prototypeRealpath) {
                         foreach (new \DirectoryIterator($prototypeRealpath) as $file) {
                             if (!$file->isDir()) {
                                 require $file->getRealPath();
                             }
                         }
                     }
                 }
             }
         }
         self::$loadedPrototypes = true;
     }
     /**
      * Round 3. Compile all files to C sources
      */
     $files = array();
     $hash = "";
     foreach ($this->files as $compileFile) {
         /**
          * Only compile classes in the local extension, ignore external classes
          */
         if (!$compileFile->isExternal()) {
             $compileFile->compile($this, $this->stringManager);
             $compiledFile = $compileFile->getCompiledFile();
             $methods = array();
             $classDefinition = $compileFile->getClassDefinition();
             foreach ($classDefinition->getMethods() as $method) {
                 $methods[] = '[' . $method->getName() . ':' . join('-', $method->getVisibility()) . ']';
                 if ($method->isInitializer() && $method->isStatic()) {
                     $this->internalInitializers[] = "\t" . $method->getName() . '(TSRMLS_C);';
                 }
             }
             $files[] = $compiledFile;
             $hash .= '|' . $compiledFile . ':' . $classDefinition->getClassEntry() . '[' . join('|', $methods) . ']';
         }
     }
     /**
      * Round 3.2. Compile anonymous classes
      */
     foreach ($this->anonymousFiles as $compileFile) {
         $compileFile->compile($this, $this->stringManager);
         $compiledFile = $compileFile->getCompiledFile();
         $methods = array();
         $classDefinition = $compileFile->getClassDefinition();
         foreach ($classDefinition->getMethods() as $method) {
             $methods[] = '[' . $method->getName() . ':' . join('-', $method->getVisibility()) . ']';
         }
         $files[] = $compiledFile;
         $hash .= '|' . $compiledFile . ':' . $classDefinition->getClassEntry() . '[' . join('|', $methods) . ']';
     }
     $hash = md5($hash);
     $this->compiledFiles = $files;
     /**
      * Round 3.3. Load extra C-sources
      */
     $extraSources = $this->config->get('extra-sources');
     if (is_array($extraSources)) {
         $this->extraFiles = $extraSources;
     } else {
         $this->extraFiles = array();
     }
     /**
      * Round 3.4. Load extra classes sources
      */
     $extraClasses = $this->config->get('extra-classes');
     if (is_array($extraClasses)) {
         foreach ($extraClasses as $value) {
             if (isset($value['source'])) {
                 $this->extraFiles[] = $value['source'];
             }
         }
     }
     /**
      * Round 4. Create config.m4 and config.w32 files / Create project.c and project.h files
      */
     $namespace = str_replace('\\', '_', $namespace);
     $extensionName = $this->config->get('extension-name');
     if (empty($extensionName) || !is_string($extensionName)) {
         $extensionName = $namespace;
     }
     $needConfigure = $this->createConfigFiles($extensionName);
     $needConfigure |= $this->createProjectFiles($extensionName);
     $needConfigure |= $this->checkIfPhpized();
     $version = self::getCurrentVersion();
     /**
      * When a new file is added or removed we need to run configure again
      */
     if (!$command instanceof CommandGenerate) {
         if (!$this->fileSystem->exists($version . '/compiled-files-sum')) {
             $needConfigure = true;
             $this->fileSystem->write($version . '/compiled-files-sum', $hash);
         } else {
             if ($this->fileSystem->read($version . '/compiled-files-sum') != $hash) {
                 $needConfigure = true;
                 $this->fileSystem->write($version . '/compiled-files-sum', $hash);
             }
         }
     }
     /**
      * Round 5. Generate concatenation functions
      */
     $this->stringManager->genConcatCode();
     $this->fcallManager->genFcallCode();
     if ($this->config->get('stubs-run-after-generate', 'stubs')) {
         $this->stubs($command, true);
     }
     return $needConfigure;
 }