Skip to content

Instantly share code, notes, and snippets.

@guillemcanal
Created August 9, 2016 13:03
Show Gist options
  • Save guillemcanal/be3db96d3caa315b4e2b8259cab7d07e to your computer and use it in GitHub Desktop.
Save guillemcanal/be3db96d3caa315b4e2b8259cab7d07e to your computer and use it in GitHub Desktop.
Build the PHP 5 iconv extension from source for Alpine

Build PHP5 iconv extension from source for Alpine

If you plan to use iconv() to transliterate string in you PHP project, please, take this:

FROM alpine:3.4

RUN apk add --update php5-cli wget build-base php5-dev autoconf re2c libtool \

    # Install GNU libiconv

    && mkdir -p /opt \
    && cd /opt \
    && wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz \
    && tar xzf libiconv-1.14.tar.gz \
    && cd libiconv-1.14 \
    && sed -i 's/_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");/#if HAVE_RAW_DECL_GETS\n_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");\n#endif/g' srclib/stdio.in.h \
    && ./configure --prefix=/usr/local \
    && make \
    && make install \
    
    # Install PHP iconv from source

    && cd /opt \
    && wget http://php.net/distributions/php-5.6.24.tar.gz \
    && tar xzf php-5.6.24.tar.gz \
    && cd php-5.6.24/ext/iconv \
    && phpize \
    && ./configure --with-iconv=/usr/local \
    && make \
    && make install \
    && mkdir -p /etc/php5/conf.d \
    && echo "extension=iconv.so" >> /etc/php5/conf.d/iconv.ini \

    # Cleanup

    && apk del wget build-base php5-dev autoconf re2c libtool \
    && rm /opt \
    && rm -rf /var/cache/apk/* \
    && rm -rf /usr/share/*

Sample PHP example file:

<?php
setlocale(LC_ALL,'en_US.UTF-8');

// your horrible slugify function
function slugify($text) {
    $text = preg_replace('~[^\\pL\d]+~u', '-', $text);
    $text = trim($text, '-');
    $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
    $text = strtolower($text);
    $text = preg_replace('~[^-\w]+~', '', $text);

    if (empty($text)) {
        return 'n-a';
    }

    return $text;
}

print slugify('héhéhé') . PHP_EOL;
@alexanderilyin
Copy link

Shorter hack:

RUN apk add --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php

@JanGalek
Copy link

@alexanderilyin It not work at the moment, package was removed.

@chrisneal
Copy link

chrisneal commented Mar 22, 2019

RUN apk add --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php

@fuel-wlightning
Copy link

The package no longer provides /usr/lib/preloadable_libiconv.so

@doublesharp
Copy link

@fuel-wlightning you can get the lib by specifying an older alpine repo.

RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.13/community/ --allow-untrusted gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php

@fuel-wlightning
Copy link

fuel-wlightning commented Apr 29, 2021

I ended up with this:

RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.12/community/ gnu-libiconv=1.15-r2
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so

Then I run this within the container to ensure it's working. (exit code is non-zero on failure)

<?php
$string = 'Umlaut: ö';
$targetString = 'Umlaut: "o';
$converted = convertIngnoreTranslit($string);
if ($converted !== $targetString) {
    displayResult($string, $converted);
    exit(1);
}

$string = 'Regular: o';
$targetString = 'Regular: o';
$converted = convertIngnoreTranslit($string);
if ($converted !== $targetString) {
    displayResult($string, $converted);
    echo "iconv test failed.". PHP_EOL;
    exit(1);
}

$string = 'Umlaut: ö';
$targetString = 'Umlaut: "o';
$converted = convertIngnoreTranslit($string);
if ($converted !== $targetString) {
    displayResult($string, $converted);
    echo "iconv test failed.". PHP_EOL;
    exit(1);
}

$string = 'Regular: o';
$targetString = 'Regular: o';
$converted = convertIngnoreTranslit($string);
if ($converted !== $targetString) {
    displayResult($string, $converted);
    echo "iconv test failed.". PHP_EOL;
    exit(1);
}

echo "iconv test passed.". PHP_EOL;

function convertTranslit($string)
{
    $result = iconv('UTF-8', 'ASCII//TRANSLIT', $string);
    return $result;
}

function convertIngnoreTranslit($string)
{
    $result = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $string);
    return $result;
}

function displayResult($string, $result)
{
    echo $string;
    echo "\n";
    echo 'Result: '. $result;
    echo "\n";
    if (gettype($result) === boolean && $result === false) {
        echo 'Result is false';
        echo "\n";
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment