/pmake
PHP | 1409 lines | 981 code | 148 blank | 280 comment | 159 complexity | fdee844ae21eb9ec75f73001641da8c7 MD5 | raw file
- #!/usr/bin/php5
- <?php
- /*******************************************************************************
- * pmake config
- *
- * Liste des variables:
- * OBJ_DIR {String} Dossier des objets
- * BIN_DIR {String} Dossier de l'executable
- * EXEC_NAME {String} Nom de l'executable
- * SRC {String} Sources (Peut être: une suite fichiers / dossiers, un masque. ( 'file1.cpp file2.cpp file\ 3.cpp directory/*.cpp' ))
- * SRC_RECURSIV {Bool} If there is a directory in SRC => recurse ?
- * INCLUDE_DIR {String} Dossier a inclure pour la recherche
- * LIBS {String} Librairie a link
- * CONSOLE {Bool} Afficher la console ? ( Aucun effet sous UNIX )
- * CFLAGS {String} Flags a passer a gcc/g++
- * LDFLAGS {String} Flags a passer au linker (ld)
- * CMD_AFTER {Array} Commandes a executer après une compilation réussi. ( PAS DE PRISE EN CHARGE POUR '+' ( concat ) )
- * Il est aussi a noter que l'on peut utiliser les variables de cette liste. ($LIBS sera remplacé)
- *
- * Le parser analyse les options dans l'odre suivant:
- * 1) $_CONFIG['global'][OPTION]
- * 2) $_CONFIG['global'][release|debug][OPTION]
- * 3) $_CONFIG[win|unix][OPTION]
- * 4) $_CONFIG[win|unix][release|debug][OPTION]
- * Les étapes remplaces la valeur précédante. ( Donc si vous avez def LIBS dans 1,2,3,4 alors on ne vera que la LIB de l'etape 4 )
- * Pour concaténer les valeurs, ajouter +
- * ex:
- * $_CONFIG['global']['OBJ_DIR'] = 'obj/';
- * $_CONFIG['global']['release']['OBJ_DIR'] = '+release/';
- * $_CONFIG['global']['debug']['OBJ_DIR'] = '+debug/';
- * // Ainsi, avec cette exemple en mode release, on aura OBJ_DIR = obj/release/
- * // NOTE: si on ajoute un espace '+ release/' => obj/ release/
- */
- $_CONFIG = array(
- 'global' => array(
- 'OBJ_DIR' => 'obj/'
- ,'BIN_DIR' => 'bin/'
- ,'EXEC_NAME' => 'mturing'
- ,'SRC' => 'src/*.c'
- ,'SRC_RECURSIV' => true
- ,'INCLUDE_DIR' => 'src'
- ,'LIBS' => ''
- ,'CONSOLE' => true
- ,'CFLAGS' => '-W -Wall -Wextra -Wdeprecated -Wuninitialized -Wunused-variable -Wvariadic-macros -Wredundant-decls -Wunused-macros -Wundef'
- //.' -Wlogical-op -Wdouble-promotion'
- .' -Wfloat-equal'//avertit si l'on teste l'égalité de deux nombres à virgule.
- .' -Wwrite-strings'
- .' -Wredundant-decls -Winit-self'
- //.' -Winline'// Avertis si une fonction demandé inline n'a pas été inline
- .' -Wpointer-arith'//qui affiche des messages si l'on fait des calculs du type pointeur + nombre
- //.' -Wcast-qual'//qui affiche des messages si l'on convertit un pointeur sur une constante en un pointeur sur une variable non constante
- .' -Wcast-align'// qui affiche des messages si l'on convertit des pointeurs d'un type à l'autre alors que leur taille en mémoire est différente (par exemple de char* vers int*).
- //.' -Wshadow'// affiche un message s'il y a deux variables de même nom dans la même portion de code.
- ,'release' => array(
- 'OBJ_DIR' => '+release/'
- ,'CFLAGS' => '+ -Os -fdata-sections -ffunction-sections'// Ligne d'optimisation
- ,'LDFLAGS' => '+ -s -Wl,--gc-sections -Wl,-O1'// Ligne d'optimisation: -s <=> strip --strip-unneeded
- //,'CMD_AFTER'=> array('strip --strip-unneeded $BIN_DIR$EXEC_NAME')// On remove tout les symboles
- )
- ,'debug' => array(
- 'OBJ_DIR' => '+debug/'
- ,'CFLAGS' => '+ -ggdb3'// -D_GLIBCXX_DEBUG pour le debug de la std lib (NON compactible avec OIS)
- ,'EXEC_NAME'=> '+_debug'
- )
- ),
- 'win' => array(
- 'INCLUDE_DIR' => ''
- ,'EXEC_NAME' => '+.exe'
- ,'LDFLAGS' => ''
- ,'release' => array(
- 'CONSOLE' => false
- )
- ,'debug' => array(
- 'LDFLAGS' => '+ -rdynamic -Wl,--export-all-symbols'
- ,'CONSOLE' => true
- )
- ),
- 'unix' => array(
- 'INCLUDE_DIR' => ''// /usr/include
- //'INCLUDE_DIR' => '+ /usr/i586-mingw32msvc/include/OGRE/ /usr/i586-mingw32msvc/include/OIS/'// /usr/include
- //,'LDFLAGS' => '+ -Wl,--enable-auto-image-base -Wl,--add-stdcall-alias -Wl,--enable-auto-import'
- ,'release' => array()
- ,'debug' => array(
- 'LDFLAGS' => '+ -rdynamic'
- )
- )
- );
- // If TRUE => the project will always be compiled in debug mode
- define('FORCE_DEBUG_MODE', false);
- // Compil
- define('CXX', '/usr/bin/g++');
- //define('CXX', 'i586-mingw32msvc-c++');
- define('USE_THREAD', 2);// Forcer N thread pour la compilation
- // Inclure tout les includes ( même systeme ) lors de la génération des dépendances ?
- // Cela peut prendre beaucoup de temps !
- // OBLIGATOIRE aver clang++
- define('GEN_DEP_WITH_ALL_INCLUDE', false);
- // Compiler en 64bits ?
- // Cette fonction ne marche que si le système est en 64bits
- define('BUILD_64BYTES', false);
- /*******************************************************************************
- * DO NOT TOUCH
- */
- define('OS_UNIX', 0);
- define('OS_WINDOWS', 1);
- define('OS_RUNNING', (PHP_SHLIB_SUFFIX === 'dll')?1:0);// Permet de savoir quel OS TOURNE
- define('CONSOLE_WIDTH', 80);
- define('MAKEFILE_TIME', filemtime(__FILE__));//!< Dernière modification du makefile
- define('ENABLED_COLOR', OS_RUNNING === OS_UNIX && !in_array('noColor', $argv));
- // Mode debug ?
- define('IS_DEBUG_MODE', in_array('debug', $argv) || FORCE_DEBUG_MODE);
- define('IS_VERBOSE_MODE', in_array('verbose', $argv) || in_array('v', $argv));
- if( function_exists('pcntl_fork') && OS_RUNNING !== OS_WINDOWS ){
- // On détermine le nombre de thread a utiliser
- foreach( $argv as $val )
- {
- if( substr($val, 0, 2) === '-j' ){
- $val = intval(substr($val, 2));
- if( $val <= 0 ){
- define('NB_THREAD', 1);
- }else{
- define('NB_THREAD', $val);
- }
- break;
- }
- }
- if( !defined('NB_THREAD') ){
- if( defined('USE_THREAD') ){
- define('NB_THREAD', USE_THREAD);
- }else{
- define('NB_THREAD', 1);
- }
- }
- }else{
- define('NB_THREAD', 1);
- }
- if( NB_THREAD > 1 )
- Thread::init();
- $_CMD_AFTER = array();//!< Liste des commandes a exec après une compilation
- if( OS_RUNNING === OS_WINDOWS )
- execute('@chcp 1252 > nul');// On permet a la console de window de prendre en compte les accents
- if( BUILD_64BYTES && is_64bit() ){
- if( !IsSet($_CONFIG['global']) )
- $_CONFIG['global'] = array();
- if( !IsSet($_CONFIG['global']) )
- $_CONFIG['global']['CFLAGS'] = '';
- $_CONFIG['global']['CFLAGS'] .= ' -m64';
- if( !IsSet($_CONFIG['global']) )
- $_CONFIG['global']['LDFLAGS'] = '';
- $_CONFIG['global']['LDFLAGS'] .= ' -m64';
- }
- /*******************************************************************************
- * Color list
- */
- if( OS_RUNNING === OS_UNIX ){
- define('COLOR_BLACK', 0);
- define('COLOR_RED', 1);
- define('COLOR_GREEN', 2);
- define('COLOR_YELLOW', 3);
- define('COLOR_BLUE', 4);
- define('COLOR_MAGENTA', 5);
- define('COLOR_CYAN', 6);
- define('COLOR_WHITE', 7);
- }else{
- define('COLOR_BLACK', '0F');
- define('COLOR_RED', 'C0');
- define('COLOR_GREEN', '20');
- define('COLOR_YELLOW', 'E0');
- define('COLOR_BLUE', '10');
- define('COLOR_MAGENTA', '90');
- define('COLOR_CYAN', 'B0');
- define('COLOR_WHITE', 'F0');
- /*
- 0 = Noir 8 = Gris
- 1 = Bleu fonc‚ 9 = Bleu clair
- 2 = Vert A = Vert clair
- 3 = Bleu-gris B = Cyan
- 4 = Marron C = Rouge
- 5 = Pourpre D = Rose
- 6 = Kaki E = Jaune
- 7 = Gris clair F = Blanc
- */
- }
- // On parse les options
- parseOptions();
- /*******************************************************************************
- * Affichage de l'aide
- */
- if( in_array('help', $argv) || in_array('-help', $argv) || in_array('--help', $argv) || in_array('-h', $argv) || in_array('/?', $argv) )
- showHelp();
- /*******************************************************************************
- * Re build
- */
- if( in_array('re', $argv) || in_array('rebuild', $argv) )
- execute(__FILE__.' clean '.(IS_DEBUG_MODE?'debug':''));
- /*******************************************************************************
- * Nétoyage
- */
- if( in_array('clean', $argv) || in_array('clear', $argv) || in_array('ca', $argv) || in_array('cleanall', $argv) ){
- rrmdir(OBJ_DIR);
- if( in_array('all', $argv) || in_array('ca', $argv) || in_array('cleanall', $argv) ){
- $OS = (OS_RUNNING === OS_UNIX)?'unix':'win';
- $MODE = (!IS_DEBUG_MODE)?'debug':'release';
- if( IsSet($_CONFIG['global']) ){
- if( IsSet($_CONFIG['global']['OBJ_DIR']) )
- $OBJ = $_CONFIG['global']['OBJ_DIR'];
- if( IsSet($_CONFIG['global'][$MODE],$_CONFIG['global'][$MODE]['OBJ_DIR']) )
- appendOrReset($OBJ, $_CONFIG['global'][$MODE]['OBJ_DIR']);
- }
- if( IsSet($_CONFIG[$OS]) ){
- if( IsSet($_CONFIG[$OS]['OBJ_DIR']) )
- appendOrReset($OBJ, $_CONFIG[$OS]['OBJ_DIR']);
- if( IsSet($_CONFIG[$OS][$MODE],$_CONFIG[$OS][$MODE]['OBJ_DIR']) )
- appendOrReset($OBJ, $_CONFIG[$OS][$MODE]['OBJ_DIR']);
- }
- rrmdir($OBJ);
- }
- exit;
- }
- /*******************************************************************************
- * On génère les dépendances
- */
- $INCLUDE_DIR = array('local'=>'', 'system'=>'');
- // On détermine les dossiers a inclure
- if( strlen(INCLUDE_DIR) ){
- foreach( split_RespectEscape(INCLUDE_DIR) as $val )
- {
- if( substr($val, 0, 1) === '/' || (OS_RUNNING === OS_WINDOWS && substr($val, 1, 2) === ':/') ){
- $INCLUDE_DIR['system'] .= ' -isystem '.$val;// Les lib externes sont considérés comme fiables => no warning
- }else{
- $INCLUDE_DIR['local'] .= ' -I'.$val;
- }
- }
- }
- $INCLUDE_DIR['system'] = trim($INCLUDE_DIR['system']);
- $INCLUDE_DIR['local'] = trim($INCLUDE_DIR['local']);
- /*******************************************************************************
- * Création des dossiers manquant
- */
- makeDir(OBJ_DIR);
- makeDir(BIN_DIR);
- // Contient la liste des fichiers a traiter
- $fileList = getListOfFile(SRC);
- $time = time();
- /*******************************************************************************
- * On génère les dépendances
- */
- $returned = null;
- $cmd = '';
- $stdout = '';
- $stderr = '';
- echo cutOrFill('Génération des dépendances', CONSOLE_WIDTH-3),(IS_VERBOSE_MODE?"\r\n":'[');
- if( GEN_DEP_WITH_ALL_INCLUDE ){
- $cmd = CXX.' '.implode(' ',$INCLUDE_DIR).' -MM '.implode(' ', array_keys($fileList));
- }else{
- $cmd = CXX.' '.$INCLUDE_DIR['local'].' -MM '.implode(' ', array_keys($fileList));
- }
- if( IS_VERBOSE_MODE )//implode(' ',$INCLUDE_DIR)
- echo $cmd,"\r\n";
- // Version remplacant la version commenté qui suit. Cette version ne provoque pas de "Broken pipe"
- $stderrFile = tempnam(sys_get_temp_dir(), 'pmake');// Création d'un recepteur temporaire
- exec($cmd.' 2> '.$stderrFile, $stdout, $returned);// Génération des dépendances
- $stderr = file_get_contents($stderrFile);// On lit le "flux" d'erreur
- unlink($stderrFile);// Fermeture du "flux" d'erreur
- if( $returned !== 0 || !empty($stderr) ){
- if( $returned !== 0 ){
- echo (IS_VERBOSE_MODE?'[':''),color('FAIL', COLOR_RED),"]\r\n";
- }else{
- echo (IS_VERBOSE_MODE?'[':''),color('WARNING', COLOR_YELLOW),"]\r\n";
- }
- echo str_replace(array('fatal error','^','not found'), array(color('fatal error', COLOR_RED),color('^', COLOR_GREEN),color('not found', COLOR_RED, true)), $stderr);
- if( $returned !== 0 )
- exit($returned);
- }
- unset($stderr,$returned,$stderrFile,$cmd);
- /*// Ne pas utiliser cette version. Provoque un "Broken pipe" avec clang++
- // On lance la commande de génération des dépendances. Si elle plante => on arrête tout
- if( ($returned=execute($cmd, null, $stdout, $stderr)) !== 0 || !empty($stderr) ){
- echo (IS_VERBOSE_MODE?'[':''),color('FAIL', COLOR_RED),"]\r\n",str_replace(array('fatal error','^','not found'), array(color('fatal error', COLOR_RED),color('^', COLOR_GREEN),color('not found', COLOR_RED, true)), $stderr);
- exit($returned);
- }
- $stdout = explode("\n", trim($stdout));
- //*/
- for( $i=0; $i<count($stdout); $i++ )
- {
- if( substr(trim($stdout[$i]), -1, 1) === '\\' ){
- $stdout[$i] = trim(substr($stdout[$i], 0, -2)).' '.trim($stdout[$i+1]);
- array_splice($stdout, $i+1, 1);
- $i--;
- }
- }
- unset($i);
- /*******************************************************************************
- * Traitement des dépendances
- */
- $EXEC_DEP = array();
- foreach( $stdout as $key => &$val )
- {
- $tmp = explode(':', $val);
- $tmp[1] = split_RespectEscape(trim($tmp[1]));
- // On cherche a supprimer les redondances. Ex: src/../Block.h et src/Block.h
- $simplify = array();
- foreach( $tmp[1] as &$path )
- $simplify[relativePath($path)] = true;
- $fileList[$tmp[1][0]] = array_keys($simplify);
- $fileList[$tmp[1][0]]['obj'] = OBJ_DIR.$tmp[0];
- $EXEC_DEP[] = OBJ_DIR.$tmp[0];
- unset($simplify, $tmp);
- }
- unset($tmp,$stdout,$key,$val);
- echo color(time()-$time, COLOR_GREEN)," sec]\r\n";
- /*******************************************************************************
- * Word Count
- */
- if( in_array('wc', $argv) ){
- echo center('Number of lines for the project '.EXEC_NAME, COLOR_MAGENTA, true),"\r\n";
- $nbLine = 0;
- $n = 0;
- $READ = array();
- foreach( $fileList as $file => $val )
- {
- for( $i=0,$size=count($val)-1; $i<$size; $i++ )
- {
- $val[$i] = relativePath($val[$i]);
- if( !IsSet($READ[$val[$i]]) ){
- $READ[$val[$i]] = count(file($val[$i]));
- echo cutOrFill($val[$i], CONSOLE_WIDTH-3),$READ[$val[$i]],"\r\n";
- $nbLine += $READ[$val[$i]];
- }
- }
- }
- echo cutOrFill('Total', CONSOLE_WIDTH-3),color($nbLine, COLOR_GREEN, true),"\r\n";
- exit;
- }
- /*******************************************************************************
- * Lancement de CppCheck
- */
- if( in_array('cppcheck', $argv) ){
- echo 'Running CppCheck',"\r\n";
- // Génération des fichiers a analyser
- $tmp = array();
- foreach( $fileList as $key => $list )
- for( $i=0, $size=count($list)-1; $i<$size; $i++ )
- $tmp[$list[$i]] = true;
- $tmp = implode(' ', array_keys($tmp));
- if( IS_VERBOSE_MODE )
- echo 'cppcheck --enable=all -q ',$tmp,"\r\n";
- execute('cppcheck --enable=all -q '.$tmp);
- exit;
- }
- // Compilation des objets
- $incl = implode(' ', $INCLUDE_DIR);
- /*******************************************************************************
- * Lancement du générateur de makefile
- */
- if( in_array('makefile', $argv) ){
- echo 'Running makefile generator',"\r\n";
- $EXEC_DEP = implode(' ', $EXEC_DEP);
- $makefile = 'ifeq ($(SHELL), sh.exe)'."\r\n"
- ."\t".'CMD_DEL = del /F /Q'."\r\n"
- .'else'."\r\n"
- ."\t".'CMD_DEL = rm -f'."\r\n"
- .'endif'."\r\n"
- .'all: '.BIN_DIR.EXEC_NAME."\r\n"
- ."\t".'@echo Done'."\r\n"
- .BIN_DIR.EXEC_NAME.': '.BIN_DIR.' '.OBJ_DIR.' '.$EXEC_DEP."\r\n"
- ."\t".'@echo Compilation de '.BIN_DIR.EXEC_NAME."\r\n"
- ."\t".CXX.' '.LDFLAGS.' -o '.BIN_DIR.EXEC_NAME.' '.$EXEC_DEP.' '.LIBS."\r\n"
- .rtrim(BIN_DIR,'/ ').':'."\r\n"
- ."\t".'@echo Création du dossier: '.BIN_DIR."\r\n";
- $fullPath = '';
- foreach( explode('/', rtrim(BIN_DIR,'/ ')) as $dir )
- {
- $makefile .= "\t".'@mkdir '.$fullPath.$dir."\r\n";
- $fullPath .= $dir.'/';
- }
- $makefile .= rtrim(OBJ_DIR,'/ ').':'."\r\n"
- ."\t".'@echo Création du dossier: '.OBJ_DIR."\r\n";
- $fullPath = '';
- foreach( explode('/', rtrim(OBJ_DIR,'/ ')) as $dir )
- {
- $makefile .= "\t".'@mkdir '.$fullPath.$dir."\r\n";
- $fullPath .= $dir.'/';
- }
- $tmp = null;
- $obj = null;
- foreach( $fileList as $file => $list )
- {
- $obj = $list['obj'];
- unset($list['obj']);
- $makefile .= $obj.': '.implode(' ', $list)."\r\n"
- ."\t".'@echo Compilation de '.$file."\r\n"
- ."\t".CXX.' '.$incl.' '.CFLAGS.' -c -pipe '.$file.' -o '.$obj."\r\n";
- }
- // Création de la règle make clean
- $makefile .= 'clean:'."\r\n"
- ."\t".'@echo Suppression des fichiers temporaires'."\r\n"
- ."\t".'$(CMD_DEL) '.$EXEC_DEP."\r\n";
- // Création de la règle make exec
- $makefile .= 'exec: '.BIN_DIR.EXEC_NAME."\r\n"
- ."\t".'cd '.BIN_DIR.' && '.((OS_RUNNING === OS_UNIX)?'./':'').EXEC_NAME."\r\n";
- file_put_contents('Makefile', $makefile);
- exit('Done'."\r\n");
- }
- $time = time();
- /*******************************************************************************
- * Compilation
- */
- foreach( $fileList as $file => $dep )
- {
- if( isMakeNeeded($dep['obj'], $dep) ){
- if( NB_THREAD === 1 ){
- compile(CXX.' '.$incl.' '.CFLAGS.' -c -pipe '.$file.' -o '.$dep['obj'], $file, $dep['obj']);
- }else{
- echo '* Processing for : ',$file,"\r\n";
- Thread::start('compile', array('cmd'=>CXX.' '.$incl.' '.CFLAGS.' -c -pipe '.$file.' -o '.$dep['obj'], 'file'=>$file, 'target'=>$dep['obj'], 'waitForPrint'=>true));
- }
- }
- if( NB_THREAD > 1 )
- Thread::wait();
- }
- unset($INCLUDE_DIR, $file, $dep);
- // On wait tout les thread
- if( NB_THREAD > 1 )
- Thread::wait(true);
- // Compilation du fichier final
- $EXEC_DEP[] = '';// Pour compenser le -1
- if( isMakeNeeded(BIN_DIR.EXEC_NAME, $EXEC_DEP) ){
- compile(CXX.' '.LDFLAGS.' -o '.BIN_DIR.EXEC_NAME.' '.implode(' ', $EXEC_DEP).' '.LIBS, BIN_DIR.EXEC_NAME, BIN_DIR.EXEC_NAME);
- }else{
- echo cutOrFill(BIN_DIR.EXEC_NAME, CONSOLE_WIDTH-3),'[',color('ALL READY DONE', COLOR_YELLOW),"]\r\n";
- }
- unset($EXEC_DEP);
- echo 'Done in ',(time()-$time),'secs',"\r\n";
- /*******************************************************************************
- * Lancement des commandes suplémentaires
- */
- $SRC = trim(implode(' ', array_keys($fileList)));
- unset($fileList, $key, $val);
- foreach( $_CMD_AFTER as $key => $val )
- {
- $stdout='';
- $stderr='';
- $val = str_replace('$SRC', $SRC, $val);
- echo cutOrFill('Running '.$val, CONSOLE_WIDTH-3),'[';
- if( execute($val, $stdout, $stderr) === 0 ){
- echo color('OK', COLOR_GREEN),"]\r\n";
- }else{
- echo color('FAILL', COLOR_RED),"]\r\n";
- }
- }
- /*******************************************************************************
- * Lancement de valgrind
- */
- if( in_array('valgrind', $argv) ){
- echo 'Running Valgrind on ',BIN_DIR.EXEC_NAME,"\r\n";
- execute('valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=valgrind.log ./'.EXEC_NAME, BIN_DIR);
- echo file_get_contents(BIN_DIR.'valgrind.log');
- exit;
- }
- else
- /*******************************************************************************
- * Lancement du fichier obtenu
- */
- if( in_array('exec', $argv) ){
- echo 'Running ',BIN_DIR.EXEC_NAME,"\r\n";
- if( IS_DEBUG_MODE ){
- execute('echo 0 | gdb -batch-silent -ex "run" -ex "set logging overwrite on" -ex "set logging file gdb.bt" -ex "set logging on" -ex "set pagination off" -ex "handle SIG33 pass nostop noprint" -ex "echo backtrace:\n" -ex "backtrace full" -ex "echo \n\nregisters:\n" -ex "info registers" -ex "echo \n\ncurrent instructions:\n" -ex "x/16i \$pc" -ex "echo \n\nthreads backtrace:\n" -ex "thread apply all backtrace" -ex "set logging off" -ex "quit" --args '.EXEC_NAME, BIN_DIR);
- if( is_file(BIN_DIR.'gdb.bt') )
- echo file_get_contents(BIN_DIR.'gdb.bt');
- }else{
- execute('./'.EXEC_NAME, BIN_DIR);
- }
- }
- exit();
- /******************************************************************************/
- /***************************************************************************//*!
- * @brief Permet de compiler un fichier. (.cpp => .o)
- * @param[in] $cmd {String} La commande a executer
- * @param[in] $file {String} L'adresse vers le fichier a compiler
- * @param[in] $target {String} La cible a obtenir
- * @return[NONE]
- */
- function compile( $cmd, $file='', $target='', $waitForPrint=false )
- {
- if( is_array($cmd) ){
- $file = $cmd['file'];
- $target = $cmd['target'];
- $waitForPrint = $cmd['waitForPrint'];
- $cmd = $cmd['cmd'];
- }
- $printInfo = '';
- if( $waitForPrint ){
- if( IS_VERBOSE_MODE )
- $printInfo = $cmd."\r\n";
- $printInfo .= cutOrFill($file, CONSOLE_WIDTH-3).'[';
- }else{
- if( IS_VERBOSE_MODE )
- echo $cmd,"\r\n";
- echo cutOrFill($file, CONSOLE_WIDTH-3),'[';
- }
- $descriptorspec = array(
- 0 => array('pipe', 'r'),// stdin est un pipe où le processus va lire
- 1 => array('pipe', 'w'),// stdout est un pipe où le processus va écrire
- 2 => array('pipe', 'w')// stderr est un fichier
- );
- $pipes = null;// On récup les pointeurs de lecture via cet variable
- // On supprime l'ancien fichier objet
- if( is_file($target) )
- unlink($target);
- $stdout = '';
- $stderr = '';
- $return_value = 0;
- if( ($return_value=execute($cmd, null, $stdout, $stderr)) || !empty($stderr) ){
- if( $waitForPrint )
- echo $printInfo;
- if( is_file($target) ){
- echo color('WARNING', COLOR_YELLOW),"]\r\n";
- fwrite(STDERR, parse_gcc_error($stderr));
- return ;
- }else{
- echo color('FAIL', COLOR_RED),"]\r\n";
- fwrite(STDERR, parse_gcc_error($stderr));
- exit($return_value);
- }
- }
- if( $waitForPrint )
- echo $printInfo;
- echo color('OK', COLOR_GREEN),"]\r\n";
- }
- /***************************************************************************//*!
- * @brief Permet de déterminer si un objet a besoin d'être recompilé
- * @param[in] $target {String} Fichier a obtenir
- * @param[in] $dep {Array} Les dépendances de $file. ( Doit contenir $dep['obj'] )
- * @return {Bool} TRUE si l'objet doit être recompilé
- */
- function isMakeNeeded( $target, &$dep )
- {
- if( !is_file($target) )
- return true;
- $objFiletime = filemtime($target);
- if( MAKEFILE_TIME > $objFiletime )
- return true;
- for( $i=0,$size=count($dep)-1; $i<$size; $i++ )
- if( filemtime($dep[$i]) > $objFiletime )
- return true;
- return false;
- }
- /***************************************************************************//*!
- * @brief Permet d'obtenir la liste des fichiers a traiter
- * @param[in] $src {String}
- * @return {Array} La liste des fichiers a traiter
- */
- function getListOfFile( $src )
- {
- // Fichier
- if( is_file($src) )
- return array(relativePath($src)=>'');
- // Dossier
- if( is_dir($src) )
- return getListOfFile($src.((substr($src, -1, 1) === '/')?'*':'/*'));
- // Liste ?
- // file1.cpp file2.cpp file\ 3.cpp directory/*.cpp
- $array_src = split_RespectEscape($src);
- if( count($array_src) > 1 ){
- $return = array();
- foreach( $array_src as $key => $file )
- $return = array_merge($return, getListOfFile($file));
- return $return;
- }
- unset($array_src);
- // Masque ?
- if( strpos($src, '*') ){
- $return = array();
- foreach( glob($src) as $key => $file )
- $return = array_merge($return, getListOfFile($file));
- if( SRC_RECURSIV ){
- $match = null;
- if( preg_match_all('`(.+)(\*.*)`', $src, $match) ){
- $folders = glob($match[1][0].'*', GLOB_ONLYDIR);
- if( $folders ){
- foreach($folders as $key => $dir)
- $return = array_merge($return, getListOfFile($dir.'/'.$match[2][0]));
- }
- }
- }
- return $return;
- }
- throw new Exception('file or folder not found for '.$src."\r\n");
- }
- /***************************************************************************//*!
- * @brief Permet d'afficher l'aide
- * @return[NONE]
- * @warning Cette fonction appel exit
- */
- function showHelp()
- {
- exit(
- color('Assistance for the Project '.EXEC_NAME, COLOR_MAGENTA, true)."\r\n"
- .' help Show this manual.'."\r\n"
- .' exec Build and run.'."\r\n"
- .' debug Build in debug mode.'."\r\n"
- .' re|rebuild Clean & build (current mode).'."\r\n"
- .' valgrind Build and run with Valgrind.'."\r\n"
- .' cppcheck Run an analysis on source code with CppCheck.'."\r\n"
- .' clean Remove all .o for the current mode (release or debug).'."\r\n"
- .' cleanall|ca Remove all .o for all mode (release & debug).'."\r\n"
- .' wc Show how many line there is in this project.'."\r\n"
- .' v|verbose Show variables info.'."\r\n"
- .' noColor Disable color.'."\r\n"
- .' makefile Generate a makefile.'."\r\n"
- .' -jX Build with X thread.'."\r\n"
- );
- }
- /***************************************************************************//*!
- * @brief Permet de parser correctement une chaine contenant des fichiers.
- * Exemple: file1.cpp file2.cpp file\ 3.cpp dossier/*.cpp
- * Va retourner: array('file1.cpp', 'file2.cpp', 'file\ 3.cpp', 'dossier/*.cpp')
- * @return {Array} Liste des fichiers séparé par un espace.
- */
- function split_RespectEscape( $str )
- {
- return str_replace(':/:', '\ ', explode(' ', str_replace('\ ', ':/:', $str)));
- }
- /***************************************************************************//*!
- * @brief Permet de coloriser le texte {$txt} avec la couleur {$color}.
- * De plus, le texte peut être souligné {$underline}
- * @param[in] $txt {String} Le texte a coloriser
- * @param[in] $color {int} Couleur du texte. VOIR les define commencant par COLOR_
- * @param[in,opt] $underline {bool} Activer le soulignement ?
- * @return Le texte colorisé.
- *
- * @warning Cette fonction utilise les caractères d'échapement des consoles UNIX pour coloriser le texte.
- * Cela implique donc que ça ne marchera pas sous Windows.
- */
- function color( $txt, $color, $underline=false )
- {
- if( !ENABLED_COLOR )
- return $txt;
- if( $underline )
- return "\033[3".$color.";4m"."\033[3".$color.";1m".$txt."\033[0m";
- return "\033[3".$color.";1m".$txt."\033[0m";
- }
- /***************************************************************************//*!
- * @brief Permet de couper ou d'allonger un texte en fonction de $max
- * @param[in] $str {String} La chaine a ajuster
- * @param[in] $max {uint} La taille max a retourner
- * @return {String} Exemple:
- * cutOrFill("j'aime les fleurs", 10) => "j'aime ..."
- * cutOrFill("j'aime les fleurs", 20) => "j'aime les fleurs "
- */
- function cutOrFill( $str, $max )
- {
- if( $max < 0 )
- return $str.' ';
- if( count($str) > $max )
- return substr($str, 0, $max-3).'...';
- return str_pad($str, $max-count($str), ' ');
- }
- /***************************************************************************//*!
- * @brief Permet de center le texte
- * @param[in] $text {String} Le texte a centrer
- * @param[in] $color {int} Couleur du texte. VOIR les define commencant par COLOR_
- * @param[in,opt] $underline {bool} Activer le soulignement ?
- * @return {String} Le texte centré
- */
- function center( $text, $color=-1, $underline=false )
- {
- $rest = CONSOLE_WIDTH - strlen($text);
- if( $rest < 0 ){
- if( $color !== -1 )
- return color($text, $color, $underline);
- return $text;
- }
- if( $color !== -1 )
- return str_pad('', $rest/2).color($text, $color, $underline);
- return str_pad('', $rest/2).$text;
- }
- /***************************************************************************//*!
- * @brief Permet de créer un dossier avec gestion des erreurs
- * @param[in] $dir {String} Le dossier a créer
- * @return[NONE]
- *
- * @warning Cette fonction appel EXIT en cas d'echec
- */
- function makeDir( $dir )
- {
- if( is_dir($dir) )
- return ;
- echo 'Création du dossier ',cutOrFill($dir, 56),' [';
- if( !mkdir($dir, 0755, true) )
- exit(color('FAIL', COLOR_RED)."]\r\n");
- echo color('OK', COLOR_GREEN),"]\r\n";
- }
- /***************************************************************************//*!
- * @brief Mini parser. Permet d'afficher la ligne qui contient l'erreur.
- * @param[in] $err {String} L'erreur gcc
- * @return {String} L'erreur GCC modifiée
- */
- function parse_gcc_error( $err )
- {
- $match = null;
- if( preg_match_all('`([^:\r\n]+):([0-9]+):([0-9]+):([^\r\n]+)`i', $err, $match) ){
- for( $i=0,$size=count($match[1]); $i<$size; $i++ )
- {
- $tmp = file($match[1][$i]);
- $err = str_replace($match[0][$i], $match[0][$i]."\r\n ".cpp(trim($tmp[$match[2][$i]-1])), $err);
- }
- }
- return $err;
- }
- /***************************************************************************//*!
- * @brief Colorateur syntaxique pour C++
- * @param[in] $code {String} Le code a coloriser
- * @return {String} Le code colorisé
- */
- function cpp( $code )
- {
- static $keyWord = array(
- 'return', 'if', 'else', 'false', 'true',
- 'double', 'int', 'float', 'char', 'void', 'bool',
- 'for', 'while',
- 'const', 'static', 'inline',
- 'new', 'delete',
- 'class', 'struct', 'typedef', 'enum'
- );
- if( !ENABLED_COLOR )
- return $code;
- if( is_file('/usr/bin/source-highlight') ){
- $stdout = '';
- $stderr = '';
- execute('/usr/bin/source-highlight --src-lang=cc --out-format=esc', null, $stdout, $stderr, $code);
- if( $stderr ){
- echo $stderr;
- return $code;
- }
- return $stdout;
- }
- // Permet de parser les erreurs du type
- // Block* World::getBlock( double x, double y, double z )
- if( preg_match_all('`^([ \t\r\n]*)([^ ]+)([ \t\r\n]*)([^\:]+)\:\:([^\(]+)\(([^\)]+)\)`', $code, $match) ){
- $hasStar = (substr($match[2][0], -1, 1) === '*')?'*':'';
- // Analyse des arguments
- $arg = explode(',', $match[6][0]);
- foreach( $arg as $key => &$val )
- {
- $tmp = explode(' ', trim($val));
- $star = (substr($tmp[0], -1, 1) === '*')?'*':'';
- $tmp[0] = str_replace('*', '', $tmp[0]);
- if( in_array($tmp[0], $keyWord) ){
- $tmp[0] = color($tmp[0], COLOR_YELLOW).$star;
- }else{
- $tmp[0] = color($tmp[0], COLOR_GREEN).$star;
- }
- $val = implode(' ', $tmp);
- }
- if( count($arg) ){
- $arg = ' '.implode(', ', $arg).' ';
- }else{
- $arg = ' ';
- }
- return
- // Block*
- color(str_replace('*', '', $match[2][0]), COLOR_GREEN).$hasStar
- // Wolrd
- .' '.color($match[4][0], COLOR_GREEN)
- // ::getBlock
- .'::'.color($match[5][0], COLOR_BLUE)
- .'('.$arg.')';
- }
- // static Chunk* chk = new Chunk(0,0,0,0);
- if( preg_match_all('`^[ \r\n\t]*(static|const)?[ \t]*([^ ]+)[ \t]+([^ ]+)([ \t]=[ \t]([^;]+))?;`', $code, $match) ){
- $star = (substr($match[2][0], -1, 1) === '*')?'*':'';
- $match[2][0] = str_replace('*', '', $match[2][0]);
- if( in_array($match[2][0], $keyWord) ){
- $match[2][0] = color($match[2][0], COLOR_YELLOW).$star;
- }else{
- $match[2][0] = color($match[2][0], COLOR_GREEN).$star;
- }
- $equal = '';
- if( IsSet($match[5]) && $match[5][0] ){
- $equal = ' = ';
- $match[5][0] = trim($match[5][0]);
- if( substr($match[5][0], 0, 3) === 'new' ){
- $equal .= color('new', COLOR_YELLOW);
- if( preg_match_all('`new[ \t]([^(;]+)[ \t]*([^;]*)`', $match[5][0], $match2) ){
- $star = (substr($match2[1][0], -1, 1) === '*')?'*':'';
- $match2[1][0] = str_replace('*', '', $match2[1][0]);
- if( in_array($match2[1][0], $keyWord) ){
- $equal .= ' '.color($match2[1][0], COLOR_YELLOW).$star;
- }else{
- $equal .= ' '.color($match2[1][0], COLOR_GREEN).$star;
- }
- $equal .= $match2[2][0];
- }
- }else{
- $equal .= $match[5][0];
- }
- }
- return trim(
- // Static|const
- ($match[1][0]?color($match[1][0], COLOR_YELLOW).' ':'')
- // Chunk*
- .$match[2][0].' '
- // chk
- .($match[3][0]?trim($match[3][0]):'')
- .$equal.';'
- );
- }
- // inline Real normalise()
- if( preg_match_all('`^[ \r\n\t]*(static|const|inline)?[ \t]*([^ ]+)[ \t]+([^ ]+)([ \t]([^;]+));`', $code, $match) ){
- $star = (substr($match[2][0], -1, 1) === '*')?'*':'';
- $match[2][0] = str_replace('*', '', $match[2][0]);
- if( in_array($match[2][0], $keyWord) ){
- $match[2][0] = color($match[2][0], COLOR_YELLOW).$star;
- }else{
- $match[2][0] = color($match[2][0], COLOR_GREEN).$star;
- }
- $equal = '';
- if( IsSet($match[5]) && $match[5][0] ){
- $equal = ' = ';
- $match[5][0] = trim($match[5][0]);
- if( substr($match[5][0], 0, 3) === 'new' ){
- $equal .= color('new', COLOR_YELLOW);
- if( preg_match_all('`new[ \t]([^(;]+)[ \t]*([^;]*)`', $match[5][0], $match2) ){
- $star = (substr($match2[1][0], -1, 1) === '*')?'*':'';
- $match2[1][0] = str_replace('*', '', $match2[1][0]);
- if( in_array($match2[1][0], $keyWord) ){
- $equal .= ' '.color($match2[1][0], COLOR_YELLOW).$star;
- }else{
- $equal .= ' '.color($match2[1][0], COLOR_GREEN).$star;
- }
- $equal .= $match2[2][0];
- }
- }else{
- $equal .= $match[5][0];
- }
- }
- return trim(
- // Static|const
- ($match[1][0]?color($match[1][0], COLOR_YELLOW).' ':'')
- // Chunk*
- .$match[2][0].' '
- // chk
- .($match[3][0]?trim($match[3][0]):'')
- .$equal.';'
- );
- }
- // #if OGRE_WCHAR_T_STRINGS
- if( preg_match_all('`^[ \r\n\t]*#if[ \t]+(.+)`', $code, $match) ){
- return trim(
- // #if
- color('#if', COLOR_BLUE).' '
- // OGRE_WCHAR_T_STRINGS
- .$match[1][0]
- );
- }
- return $code;
- }
- /***************************************************************************//*!
- * @brief Permet de supprimer un dossier de façon récusive
- * @param[in] $dir {String} Le dossier a supprimer
- * @return[NONE]
- */
- function rrmdir( $dir )
- {
- if( substr($dir, -1, 1) !== '/' )
- $dir .= '/';
- if( !is_dir($dir) ){
- echo 'Suppression dossier ',cutOrFill($dir, 56),' [',color('ALL READY DONE', COLOR_YELLOW),"]\r\n";
- return ;
- }
- foreach( glob($dir.'*') as $file )
- {
- if( is_dir($file) ){
- rrmdir($file);
- }else{
- echo 'Suppression du fichier ',cutOrFill($file, 53),' [';
- if( unlink($file) ){
- echo color('OK', COLOR_GREEN),"]\r\n";
- }else{
- echo color('FAIL', COLOR_RED),"]\r\n";
- }
- }
- }
- echo 'Suppression du dossier ',cutOrFill($dir, 53),' [';
- if( rmdir($dir) ){
- echo color('OK', COLOR_GREEN),"]\r\n";
- }else{
- echo color('FAIL', COLOR_RED),"]\r\n";
- }
- }
- /***************************************************************************//*!
- * @brief Permet de résoudre les ./ et les ../
- * @param[in] $path {String} Une adresse
- * @return {String} L'adresse résolue
- */
- function relativePath( $path )
- {
- $relativePath = $path;
- $pattern = '/\w+\/\.\.\//';
- while( preg_match($pattern, $relativePath) )
- $relativePath = preg_replace($pattern, '', $relativePath);
- return preg_replace('`^./`', '', str_replace('/./', '/', $relativePath));
- }
- /***************************************************************************//*!
- * @brief Permet d'executer la commande $cmd
- * @param[in] $cmd {String} Commande a executer
- * @param[in,opt] $path {String} Dossier d'execution
- * @return Le code de retour. (-1 En cas d'erreur d'execution)
- */
- function execute( $cmd, $path=null, &$stdout=null, &$stderr=null, $stdin=null )
- {
- $descriptorspec = array(
- 0 => array('pipe', 'r'),// stdin est un pipe où le processus va lire
- 1 => array('pipe', 'w'),// stdout est un pipe où le processus va écrire
- 2 => array('pipe', 'w')// stderr est un fichier
- );
- $pipes = null;// On récup les pointeurs de lecture via cet variable
- $process = proc_open($cmd, $descriptorspec, $pipes, $path, null);
- if( is_resource($process) ){
- // $pipes ressemble à :
- // 0 => fichier accessible en écriture, connecté à l'entrée standard du processus fils
- // 1 => fichier accessible en lecture, connecté à la sortie standard du processus fils
- // 2 => fichier accessible en lecture, connecté à la sortie stderr du processus fils
- if( $stdin !== null )
- fwrite($pipes[0], $stdin);
- fclose($pipes[0]);
- $timeout = time()+5;
- stream_set_blocking($pipes[1], 0);
- while( !feof($pipes[1]) && ($read = fread($pipes[1], 1000)) !== false )
- {
- if( !empty($read) ){
- if( $stdout === null ){
- echo $read;
- }else{
- $stdout .= $read;
- }
- }
- usleep(500);
- if( time() >= $timeout )
- break;
- }
- fclose($pipes[1]);
- $timeout = time()+5;
- stream_set_blocking($pipes[2], 0);
- while( !feof($pipes[2]) && ($read = fread($pipes[2], 1000)) !== false )
- {
- if( !empty($read) ){
- if( $stderr === null ){
- echo $read;
- }else{
- $stderr .= $read;
- }
- }
- usleep(500);
- if( time() >= $timeout )
- break;
- }
- fclose($pipes[2]);
- // Il est important que vous fermiez les pipes avant d'appeler
- // proc_close afin d'éviter un verrouillage.
- return proc_close($process);
- }
- return -1;
- }
- /***************************************************************************//*!
- * @brief Fonction de concatenation.
- * Ex:
- * $def = 'obj/' et $val = '+release/' => $def = 'obj/release/'
- * $def = 'obj/' et $val = 'release/' => $def = 'release/'
- * @param[in,out] $def {String}
- * @param[in] $val {String}
- * @return[NONE]
- */
- function appendOrReset( &$def, $val )
- {
- if( is_string($val) && substr($val, 0, 1) === '+' ){
- $def .= substr($val, 1);
- return ;
- }
- $def = $val;
- }
- /***************************************************************************//*!
- * @brief Permet de parser les options dans $_CONFIG
- * @return[NONE]
- *
- * @warning NE PAS APPELER 2 FOIS CETTE FONCTION
- * @note Cette fonction fait appel a $_CONFIG
- */
- function parseOptions()
- {
- global $_CONFIG, $_CMD_AFTER;
- $OS = (OS_RUNNING === OS_UNIX)?'unix':'win';
- $MODE = IS_DEBUG_MODE?'debug':'release';
- $defines = array(
- 'CONSOLE',
- 'OBJ_DIR',
- 'BIN_DIR',
- 'EXEC_NAME',
- 'SRC',
- 'SRC_RECURSIV',
- 'INCLUDE_DIR',
- 'LIBS',
- 'CFLAGS',
- 'LDFLAGS'
- );
- $def = null;
- $var = array();
- $LIB = '';
- foreach( $defines as $key => $val )
- {
- $def = '';
- if( IsSet($_CONFIG['global']) ){
- if( IsSet($_CONFIG['global'][$val]) )
- $def = $_CONFIG['global'][$val];
- if( IsSet($_CONFIG['global'][$MODE],$_CONFIG['global'][$MODE][$val]) )
- appendOrReset($def, $_CONFIG['global'][$MODE][$val]);
- }
- if( IsSet($_CONFIG[$OS]) ){
- if( IsSet($_CONFIG[$OS][$val]) )
- appendOrReset($def, $_CONFIG[$OS][$val]);
- if( IsSet($_CONFIG[$OS][$MODE],$_CONFIG[$OS][$MODE][$val]) )
- appendOrReset($def, $_CONFIG[$OS][$MODE][$val]);
- }
- if( IS_VERBOSE_MODE )
- echo cutOrFill($val, CONSOLE_WIDTH-strlen($def)),color($def, COLOR_GREEN),"\r\n";
- // Règle spécial pour désactier la console sous windows
- if( defined('CONSOLE') && CONSOLE && OS_RUNNING === OS_WINDOWS && $val === 'LIBS' )
- $def .= ' -mwindows';
- define($val, $def);
- }
- if( IsSet($_CONFIG['global']) ){
- if( IsSet($_CONFIG['global']['CMD_AFTER']) )
- $_CMD_AFTER = array_merge($_CMD_AFTER, $_CONFIG['global']['CMD_AFTER']);
- if( IsSet($_CONFIG['global'][$MODE],$_CONFIG['global'][$MODE]['CMD_AFTER']) )
- $_CMD_AFTER = array_merge($_CMD_AFTER, $_CONFIG['global'][$MODE]['CMD_AFTER']);
- }
- if( IsSet($_CONFIG[$OS]) ){
- if( IsSet($_CONFIG[$OS]['CMD_AFTER']) )
- $_CMD_AFTER = array_merge($_CMD_AFTER, $_CONFIG[$OS]['CMD_AFTER']);
- if( IsSet($_CONFIG[$OS][$MODE],$_CONFIG[$OS][$MODE]['CMD_AFTER']) )
- $_CMD_AFTER = array_merge($_CMD_AFTER, $_CONFIG[$OS][$MODE]['CMD_AFTER']);
- }
- if( IS_VERBOSE_MODE ){
- $def = count($_CMD_AFTER)?count($_CMD_AFTER):'[NONE]';
- echo cutOrFill('CMD_AFTER', CONSOLE_WIDTH-strlen($def)),color($def, COLOR_GREEN),"\r\n";
- }
- $res = array(
- '$CONSOLE' => CONSOLE,
- '$OBJ_DIR' => OBJ_DIR,
- '$BIN_DIR' => BIN_DIR,
- '$EXEC_NAME' => EXEC_NAME,
- //'$SRC' => SRC, //<! Les Sources sont mise après
- '$SRC_RECURSIV' => SRC_RECURSIV,
- '$INCLUDE_DIR' => INCLUDE_DIR,
- '$LIBS' => LIBS,
- '$CFLAGS' => CFLAGS,
- '$LDFLAGS' => LDFLAGS
- );
- foreach( $_CMD_AFTER as $key => &$val )
- {
- $val = str_replace(array_keys($res), array_values($res), $val);
- if( IS_VERBOSE_MODE )
- echo cutOrFill(' '.$val, CONSOLE_WIDTH),"\r\n";
- }
- if( IS_VERBOSE_MODE )
- echo "\r\n";
- }
- /***************************************************************************//*!
- * @brief Permet de gérer une file de thread
- *
- * Utilisation:
- * @code
- * define('NB_THREAD', 5);// On veux 5 thread
- *
- * Thread::start(function($arg){
- * echo $arg;// Va afficher 'argument'
- * }, 'argument');
- *
- * Thread::start(function($arg){
- * echo $arg;// Va afficher 'argument'
- * return 'lol';
- * }, 'argument', function($ret){
- * echo $ret;// Va afficher 'lol'
- * });
- * @endcode
- */
- class Thread
- {
- private static $m_thread = array();
- private static $m_parentPid = -1;
- private function __construct() {}//!< Constructeur interdit. Class Static
- /***********************************************************************//*!
- * @brief Permet d'init le système de communication
- * @return[NONE]
- */
- public static function init()
- {
- if( defined('MSG_QUEUE') )
- return ;
- self::$m_parentPid = posix_getpid();
- register_shutdown_function('Thread::killAll');
- // Création d'un canal de communication pour les thread
- define('MSG_QUEUE', rand());
- // On clean le canal de communication
- if( msg_queue_exists(MSG_QUEUE) )
- msg_remove_queue(msg_get_queue(MSG_QUEUE));
- // Création d'un canal de communication
- define('MSG_HANDLER', msg_get_queue(MSG_QUEUE));
- }
- /***********************************************************************//*!
- * @brief Permet de lancer un thread
- * @param[in] $function {Function} La fonction a appeler
- * @param[in] $arg {Mixed} Les données a passer à $function
- * @param[in,opt] $communication {Function} La fonction a executer lors de
- * la fin du thread. ( Un argument est passé à
- * celle-ci. La var contient le return de $function )
- * @return[NONE]
- */
- public static function start( $function, $arg )
- {
- $pid = pcntl_fork();
- if( $pid === -1 ){
- $function($arg);
- // Error
- fclose($fp);
- }elseif( $pid ){
- // Parent
- self::$m_thread['p'.$pid] = true;
- return ;
- }else{
- register_shutdown_function(function(){
- msg_send(MSG_HANDLER, 1/*msg type*/, posix_getpid(), true, true, $err);
- if( $err )
- echo $err;
- });
- // Child
- $function($arg);
- exit(0);
- }
- }
- /***********************************************************************//*!
- * @brief Permet d'attendre NB_THREAD ou si $all => tout les thread
- * @param[in,opt] $all {Bool} Si true => la fonction wait tout les thread
- * @return[NONE]
- */
- public static function wait( $all=false )
- {
- if( $all ){
- while( count(self::$m_thread) > 0 )
- {
- self::getMessage();
- usleep(500);
- }
- return ;
- }
- if( count(self::$m_thread) >= NB_THREAD ){
- while( count(self::$m_thread) >= NB_THREAD )
- {
- self::getMessage();
- usleep(500);
- }
- return ;
- }
- self::getMessage();
- }
- /***********************************************************************//*!
- * @brief Permet de kill tout les thread lancé
- * @return[NONE]
- */
- public static function killAll()
- {
- if( self::$m_parentPid !== posix_getpid() )
- return ;
- foreach( self::$m_thread as $key => $data )
- posix_kill(substr($key, 1), SIGINT);
- }
- /***********************************************************************//*!
- * @brief La fonction va traiter tout les messages de fin de thread et va se charger
- * de transmettre le résultat à la fonction final si elle a été défini dans
- * start( ..., ..., $communication=function(){....})
- * @return[NONE]
- */
- private static function getMessage()
- {
- $queue_status = msg_stat_queue(MSG_HANDLER);
- if( $queue_status['msg_qnum'] == 0 )
- return ;
- for( $i=0; $i<$queue_status['msg_qnum']; $i++ )
- {
- msg_receive(MSG_HANDLER, 0, $msgtype, 8, $data, true, null, $err);
- if( IsSet(self::$m_thread['p'.$data]) ){
- $status = 0;
- pcntl_waitpid($data, $status);
- if( $status !== 0 )
- exit(pcntl_wexitstatus($status));
- }
- unset(self::$m_thread['p'.$data]);
- }
- }
- }
- /***********************************************************************//*!
- * @brief Permet de déterminer l'architecture: 32 ou 64bits
- * @return TRUE si 64bits
- */
- function is_64bit()
- {
- if( PHP_INT_SIZE === 8 )
- return true;
- if( PHP_INT_SIZE === 4 )
- return false;
- $int = intval("9223372036854775807");
- if( $int === 9223372036854775807 )
- return true;
- if( $int == 2147483647 )
- return false;
- throw new Exception('Error ! Systeme has returned an incorrect value: '.$int);
- }
- ?>