static function run_build_dependencies( $task=null, $args=array(), $cliopts=array() )
    {
        $opts = self::getOpts( @$args[0], @$args[1], $cliopts );
        $current = $opts['extension']['name'];
        foreach( $opts['dependencies']['extensions'] as $ext => $source )
        {
            // avoid loops
            if ( $ext != $current )
            {
                // create a temporary config file to drive the init task
                // this could be done better in memory...
                foreach( $source as $type => $def )
                {
                    break;
                }
                $tempconf = array( 'extension' => array( 'name' => $ext ),  'version' => array( 'major' => 0, 'minor' => 0, 'release' => 0 ), $type => $def );
                $tempconffile = self::getOptionsDir() . "/options-tmp_$ext.yaml";
                pakeYaml::emitfile( $tempconf, $tempconffile );

                // download remote extension
                // nb: we can not run the init task here via invoke() because of already_invoked status,
                // so we use execute(). NB: this is fine as long as init has no prerequisites
                $task = pakeTask::get( 'init' );
                $task->execute( array( "tmp_$ext" ), array_merge( $cliopts, array( 'skip-init' => false, 'skip-init-fetch' => false, 'skip-init-clean' => true ) ) );

                // copy config file from ext dir to current config dir
                if ( is_file( self::getBuildDir( $opts ) . "/$ext/pake/options-$ext.yaml" ) )
                {
                    pake_copy( self::getBuildDir( $opts ) . "/$ext/pake/options-$ext.yaml", self::getOptionsDir() . "/options-$ext.yaml" );
                }
                else
                {
                    throw new pakeException( "Missing pake/options.yaml extension in dependent extension $ext" );
                }

                // finish the init-task
                $task->execute( array( "tmp_$ext" ), array_merge( $cliopts, array( 'skip-init' => false, 'skip-init-fetch' => true, 'skip-init-clean' => false ) ) );
                pake_remove( $tempconffile, '' );

                // and build it. Here again we cannot use 'invoke', but we know 'build' has prerequisites
                // so we execute them one by one
                $task = pakeTask::get( 'build' );
                foreach( $task->get_prerequisites() as $pretask )
                {
                    $pretask = pakeTask::get( $pretask );
                    $pretask->execute( array( $ext ), array_merge( $opts, array( 'skip-init' => true ) ) );
                }
                $task->execute( array( $ext ), array_merge( $opts, array( 'skip-init' => true ) ) );
            }
        }
    }