static function run_coding_style_report( $task=null, $args=array(), $cliopts=array() )
    {
        $opts = self::getOpts( @$args[0], @$args[1], $cliopts );
        if ( !SharedLock::acquire( $opts['extension']['name'], LOCK_SH, $opts ) )
            throw new PakeException( "Source code locked by another process" );

        $destdir = self::getReportDir( $opts ) . '/' . $opts['extension']['name'];
        $phpcs = self::getTool( 'phpcs', $opts, true );

        // in case we use the standard rule set, try to install it (after composer has downloaded it)
        // nb: this could become a task of its own...
        $rulesDir = self::getVendorDir() . '/squizlabs/php_codesniffer/Codesniffer/Standards/' . $opts['tools']['phpcs']['rules'] ;
        if ( !is_dir( $rulesDir ) )
        {
            if ( $opts['tools']['phpcs']['rules'] == 'ezcs' )
            {
                $sourceDir = self::getVendorDir() . '/ezsystems/ezcs/php/ezcs';
                if ( is_dir( $sourceDir ) )
                {
                    pake_symlink( $sourceDir, $rulesDir );
                }
            }
        }

        // phpcs will exit with a non-0 value as soon as there is any violation (which generates an exception in pake_sh),
        // but we do not consider this a fatal error, as we are only generating reports
        try
        {
            $out = pake_sh( "$phpcs --standard=" . escapeshellarg( $opts['tools']['phpcs']['rules'] ) . " " .
                "--report=" . escapeshellarg( $opts['tools']['phpcs']['format'] ) . " " .
                // if we do not filter on php files, phpcs can go in a loop trying to parse tpl files
                "--extensions=php " . /*"--encoding=utf8 " .*/
                escapeshellarg( self::getBuildDir( $opts ) . '/' . $opts['extension']['name'] ) );
        }
        catch ( pakeException $e )
        {
            $out = preg_replace( '/^Problem executing command/', '', $e->getMessage() );
        }
        pake_mkdirs( $destdir );
        pake_write_file( $destdir . '/phpcs.txt', $out, true );

        SharedLock::release( $opts['extension']['name'], LOCK_SH, $opts );
    }