С каждым релизом PHP становится всё быстрее, а при включении JIT (Just-In-Time) компиляции, достигает почти отметок того же C.

image

У многих в своё время, наверное, было желание легкого написание консольных и оконных приложений. Ребята рунета иногда писали незаменимые приложения для решения мелких задач и делились на форумах, хотя некоторые из них и содержали костыли.

Однако времена меняются, и люди начали осознавать свои ошибки, переходя, скажем, на ООП.

Чтобы поностальгировать и продемонстрировать нового Франкенштейна, мы соберем полноценное консольное exe-приложение на PHP.

PHP — интерпретируемый язык, поэтому для работы нам просто необходимо иметь его бинарные файлы.

Для создания приложения нам понадобятся основной exe-файл и dll-библиотека движка. 32-битная версия PHP 8.1 занимает 7 Мб! Hello World с размером в 7 метров нам не подходит, согласитесь.

Следуя инструкции, мне удалось скомпилировать PHP без каких-либо дополнительных модулей, оставив только JIT и FFI (есть причина).

Размер получившихся файлов составил 5 Мб (x64), что уже не плохо, но недостаточно. Мы продолжим работать с x64, так как разница между ним и x86 составляет всего 100кб.

php.exe + php8.dll:


image


Теперь нам нужен PHP-код для нашего приложения.

Ради примера возьмём скрипт Zend Benchmark и добавим несколько аргументов командной строки для тестов.

Чтобы упаковать наше приложение в один файл, мы будем использовать бесплатную утилиту Enigma Virtual Box.

Но для этого Энигме нужен главный обработчик, который вызовет интерпретатор, но программировать на другом языке мы не будем, так как полагаемся только на PHP. :)

Используя BatToExe, мы вызываем интерпретатор из каталога %TEMP%. Позже Энигма позаботится, чтобы он оказался там.

image

%1 %2 — это количество аргументов, которые мы собираемся передать.

Выбираем обработчик, забрасываем наши бинарники с исходниками в окно Энигмы, используем папку %Temp Folder%. В Files Option кликаем на галочку компрессии.

В свойствах файлов по Методу Виртуализации ставим на -Запись если не существует-, сам скрипт советую ставить на -Запись всегда-, чтобы легче было дебажить код. Бинарником PHP является файл render.exe, скрипт exe.c.

image

Скомпилировав приложение мы получаем портативный файл, который весит 2.9 Мб!

Если бы мы пошли дальше и убрали все ненужные встроенные зависимости, а также написали бы легкий обработчик, который самостоятельно распаковывает архив, то, возможно, размер приложения уменьшился бы до сотен килобайтов (отпишитесь, если знаете такой).

Сжатый .7z архив с нынешними бинарниками весит всего 1.5 Мб.

Для сравнения, скомпилированный Hello World бинарник Go приложения, весит 1.2 Мб.

Тестируем:

image

Работает как часы, чтобы вы понимали про заявленную скорость ассемблер кода генерируемым JIT, моя машина проходит бенчмарк за 0.7с, при выключенном же JIT, она просядает до 2.4с.
Реализовать параллельность для ресурсоёмких вычислительных операций не проблема (функции popen() / proc_open), можно также воспользоваться готовыми библиотеками, как amphp/parallel.

Запуск самих приложений быстрый и составляет менее секунды.

Вычислим ещё корневой Merkle хеш большого файла:

image


Вы не забыли про FFI?

Благодаря этому расширению мы можем писать C код прямо в PHP, подключать dll библиотеки, создавать WinAPI приложения, вот пример кода MessageBox:

<?php
$ffi = FFI::cdef("
    int MessageBoxA(void*, const char*, const char*, int);
", "user32.dll");

$ffi->MessageBoxA(null, "Hello!", "Habr", 0);
?>

А вот результат:
image


Вывод:


Писать простые исполняемые приложения на PHP можно. Они могут выступать бэкенд утилитами для графических обёрток, но не следует этого делать, поскольку PHP отлично проявил себя в web-разработке, а не в десктоп-решениях.

Эксперименты на сырой платформе могут привести к проблемам.

Комментарии (11)


  1. FanatPHP
    00.00.0000 00:00
    +1

    Скажите, а можно узнать у автора, нет ли англоязычной версии?


    1. penetration Автор
      00.00.0000 00:00
      +4

      Будет, напишу через несколько дней


  1. sden77
    00.00.0000 00:00
    +2

    Немного странный вывод. Консольные приложения на php пишут давно и достаточно массово, просто их не упаковывают в исполняемый файл, а используют установленный в системе интерпретатор


    1. penetration Автор
      00.00.0000 00:00

      Спасибо, уточнил


  1. rsmike
    00.00.0000 00:00
    +15

    Hello World с размером в 7 метров нам не подходит, согласитесь.

    на этой фразе засмеялись писатели полугигабайтных "десктопных приложений" на электроне


  1. SerafimArts
    00.00.0000 00:00
    +2

    А почему бы просто не собрать пых с embed-like SAPI? Там даже ридмишка красивая есть с описанием: https://github.com/php/php-src/tree/master/sapi/embed


    На вход ему можно выдать, например phar и получится в результате 3 файла: php8.dll, php.exe и app.phar.


    Тыкаешь на php.exe, а оно просто дёргает мэин из phar и запускается, всё. И без всяких энигм и прочих костылей =)))


    1. penetration Автор
      00.00.0000 00:00

      Весьма, даже с .bat файлом можно, но пока, как по мне, нужно найти способ спрять все эти файлы в один исполняемый файл (ненадобно пользователю видеть библиотеки) и вернуть ответ вызова.

      Даже в sfx архив можно, проблема в том, что sfx выполняет команды и не дожидается их ответа, программы открываются в новом командном окне, а это выглядит не очень.


      1. SerafimArts
        00.00.0000 00:00

        Ну так изначально там просто внутрь main() подставляется php код как есть. Phar просто как пример, чтоб не пересобирать всё каждый раз.


        1. penetration Автор
          00.00.0000 00:00

          Поэкспериментируем


  1. roxblnfk
    00.00.0000 00:00

    Компилил PHP 4.4.4 с помощью bcompiller . С добавлением UPX получалось 650кб (все файлы остались, могу зашарить). Но там и php.dll весил немного. Зато и FFI есть и окошки из коробки за счёт WinBinder.

    Был ещё в те времена какой-то phpack, но профита с него не помню. Возможно, из него можно вытащить уменьшенные dll-ки пыхи пятой (типа такого: https://github.com/alecgorge/phpack/tree/master/stubs/tiny)

    Увы, во времена php7 уже на другие извращенства перелез


    1. penetration Автор
      00.00.0000 00:00

      Да, помню.

      Был ещё phc-win, exeoutput, rapidEXE (файл получался на 5мб), PHP 5-ой версии весил мало. Но все они навешаны на собственные наработки, а здесь стандартный вывод с любой версией PHP.
      А что за извращенства на PHP 7 у вас?)