PHP Extension written with C++. Build and check with GitHub Actions.

yaroslavche

Yaroslav

Posted on November 10, 2021

PHP Extension written with C++. Build and check with GitHub Actions.
My Workflow

Small description about repository: phptdlib is a PHP extension for the Telegram Database library, which allows to create Telegram clients. This is a CMake based C++ project with dependencies (tdlib/td, CopernicaMarketingSoftware/PHP-CPP and nlohmann/json), which produces a PHP extension.

First of all, need to prepare environment for building CMake project

jobs:
    build:
        name: ${{ matrix.config.name }}
        runs-on: ${{ matrix.config.os }}
        env: # custom ENV variables
            CONFIG: gcc
            CC: gcc
            CXX: g++
        strategy:
            fail-fast: false
            matrix:
                config:
                    - {
                        name: "Ubuntu Latest GCC (Release)",
                        os: ubuntu-latest,
                        build_type: "Release",
                        cc: "gcc",
                        cxx: "g++",
                        generators: "Ninja"
                    }
Enter fullscreen mode Exit fullscreen mode

And in steps right after repo checkout need to add PHP headers and capability for running PHP code. Thanks to shivammathur/setup-php@v2 it's pretty easy to achieve:

        steps:
            -   uses: actions/checkout@v2
            -   name: Setup PHP 7.4 with PECL extension
                uses: shivammathur/setup-php@v2
                with:
                    php-version: '7.4'
Enter fullscreen mode Exit fullscreen mode

After that we're ready to install development tools and check their versions:

            -   name: Install main dependencies (Ubuntu)
                if: startsWith(matrix.config.name, 'Ubuntu Latest GCC')
                run: |
                    sudo apt-get update
                    sudo apt-get install ninja-build cmake gperf build-essential zlib1g-dev
                    ninja --version
                    cmake --version
                    gcc --version
                    php --version
Enter fullscreen mode Exit fullscreen mode

Here you can note that we're able to extend the matrix and configure for each environment its own workflow.

In the build process there is one huge disadvantage - it takes a lot of resources and plenty of time. It's bad to occupy resources, when they aren't needed. That's why it's worth it to cache compiled object files.

            -   name: Cache extension dependencies
                id: cahce-ext-deps
                uses: actions/cache@v2
                with:
                    path: ~/cached_builds
                    key: ${{ runner.os }}-ext-deps
Enter fullscreen mode Exit fullscreen mode

But, honestly, I think this config isn't really correctly configured for my case. The idea was in caching compiled object files and later just use that directory and linker would use that object files (in the install script from the next step). But looks like it doesn't work as I've expected and the compiler compiles object files even when no changes are made in dependencies. I'll be very appreciated for an advice.

I've created an install script for updating dependencies for shared lib builds. It takes the build path as the first argument, pulls the latest code from tdlib/td, CopernicaMarketingSoftware/PHP-CPP and nlohmann/json repositories and builds separately as shared libraries.

            -   name: Install extension dependencies
                shell: bash
                run: |
                    ./scripts/install.sh ~/cached_builds
                    cd ~/cached_builds
                    sudo ldconfig
Enter fullscreen mode Exit fullscreen mode

This process takes around 10 minutes.

When dependencies are built and installed, we're ready to install extension itself:

            -   name: Build and install
                shell: bash
                run: |
                    mkdir build
                    cd build
                    cmake -D USE_SHARED_TD:BOOL=ON -D USE_SHARED_JSON:BOOL=ON -D USE_SHARED_PHPCPP:BOOL=ON ..
                    make
                    sudo make install
Enter fullscreen mode Exit fullscreen mode

And if all above steps are fine, then we can check if it is installed and works. Need to check installed modules and try to run example scripts.

            -   name: Test
                shell: bash
                run: |
                    pwd
                    php -m | grep tdlib
                    php php_examples/func.php
Enter fullscreen mode Exit fullscreen mode

And need to specify when it is needed to trigger actions. In my case I also want to configure scheduled runs more often (twice in a month) because build fails would notify me that need to update dependencies.

on:
    push:
    pull_request:
    release:
    schedule:
        -   cron: "0 0 1,15 * *"
Enter fullscreen mode Exit fullscreen mode

Before I used travis, but it accidentally stopped working for me at some point, and I've decided to migrate to GitHub Actions. Right now it's not ideal and uses just one config and one entry in the matrix, but it's doing its job and can be configured better in future.
Thanks for reading =)

Submission Category:

Wacky Wildcards

Yaml File or Link to Code

GitHub logo yaroslavche / phptdlib

PHP Extension for tdlib/td written with PHP-CPP

Cmake workflow

The PHP extension tdlib allows you to work with the Telegram database library If simple, this is the usual functions wrapper for working with the tdlib/td json client. You can:

  • create a JSON client $client = td_json_client_create()
  • execute the synchronous request $result = td_json_client_execute($client, $json);
  • perform an asynchronous request td_json_client_send($client, $json); *
  • get all the responses at the moment $response = td_json_client_receive($client, $timeout);
  • and destroy client td_json_client_destroy($client);

* you must use td_json_client_receive to get a response from an asynchronous request.

Getting started with TDLib

td_json_client.h File Reference

Video tutorial how to install and simple usage

phptdlib Documentation

Example

https://github.com/tdlib/td/blob/master/example/cpp/tdjson_example.cpp

<?php
$client = td_json_client_create()
td_json_client_execute($client, json_encode(['@type' => 'setLogVerbosityLevel', 'new_verbosity_level' => '0']));
$waitTimeout = 10;
while(true)
{
    $result = td_json_client_receive($client, $waitTimeout);
    if(!empty($result)) {
        
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
yaroslavche
Yaroslav

Posted on November 10, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related