[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Building for Android


After several attempts, I could get a successful build.
However, when I test it, it segfaults.

In the following, I will try to explain what I did.
I will try to be brief but, if there is any interest, I can provide more
detailed instructions (or even a script that automates the whole process).

0) The build environment is as follows:
- Ubuntu 15.04 64 bit with 3.19.0-33 kernel
- cmake 3.0.2 and gcc 4.9.2 (both from repos)
- Android NDK r9d
- OpenSSL 1.0.2d
- libSSH 0.7.2
- Qt 5.4 and QtCreator 3.3.0
- Target platform arm-linux-androideabi-4.8 API 19
- Target device Samsung Galaxy S5 klte

1) First, we need to build the dependencies.
zlib is already part of the NDK, so we only need to cross-compile OpenSSL.
This is easily accomplished by following the instructions found here:
https://wiki.openssl.org/index.php/Android
After installation I symlinked libcrypto.so, libssl.so and the include
files inside the NDK "usr" folder (so that they can easily be linked
against).

2) Following Daniel Kroker's advice, I added the taka-no-me toolchain
into the libSSH folder.
Before I could complete the build, however, I had to solve following
problems.

3) My version of cmake has a bug that was fixed in 3.1 an later versions.
This prevents it to correctly detect OpenSSL 1.0.2 (it is reported to
work with earlier versions, though).
To fix it, I manually applied this patch:
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c5d9a8283cfac15b4a5a07f18d5eb10c1f388505

4) The cmake configuration of libSSH contains a TRY_RUN() step.
As far as I could understand, this is supposed to run a dummy test to
check if a certain feature works correctly.
This is obviously not possible in cross-compilation mode: fortunately,
the error issued by cmake contains an explanation on how to fix it.
In the libSSH folder one needs to create a file (named e.g.
"TryRunResults.cmake") with following content:
        set( THREADS_PTHREAD_ARG 0
             CACHE STRING "Result from TRY_RUN" FORCE)

5) The build still fails with error "implicit declaration of function
'getpwuid_r'"
This function is supposed to return informations about the current user,
like username and home directory.
This has no equivalent on android, so I needed to change these two
functions in the file "misc.c":
   char *ssh_get_user_home_dir(void)
   char *ssh_get_local_username(void)
For my tests, I resigned to return hard-coded values, but more work is
required for a general solution.

6) Now the build completes successfully. These are the command issued:
cd /path/to/downloaded/libSSH/
mkdir build
cd build
        cmake \
            -C ../TryRunResults.cmake \
            -DCMAKE_INSTALL_PREFIX=/opt/libssh-android \
            -DWITH_INTERNAL_DOC=OFF \
            -DWITH_STATIC_LIB=ON \
            -DWITH_TESTING=OFF \
            -DWITH_SERVER=OFF \
            -DWITH_EXAMPLES=OFF \
            -DCMAKE_BUILD_TYPE=Release \
            -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake \
            -DANDROID_NDK="$ANDROID_NDK_ROOT" \
            -DANDROID_NATIVE_API_LEVEL=android-19 \
            -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.8 \
            -DANDROID_ABI="armeabi-v7a with NEON" \
        ..
        cmake --build .

7) Before deployment, there are two more obstacles.
First, the Android NDK doesnt provide OpenSSL, but the library is
installed in Android and loaded by default (taking precedence over
libraries packaged in the APK).
This means that we have to rename the libcrypto.so and libssl.so to
something else, and repeat the linking step. However, see below.
(this problem is documented here:
https://mta.openssl.org/pipermail/openssl-users/2015-April/001183.html)
Second, Android does not support loading of versioned libraries (meaning
that e.g. libssh.so is a symlink to libssh.so.4.4.0).
This means that we have to configure OpenSSL and libSSH to produce
non-versioned files, and relink. However, see below.
(this problem is documented here:
https://bugreports.qt.io/browse/QTCREATORBUG-11062)
The link above also provided a solution (hack?) for both problems, which
I implemented with following BASH code:
    local subs=()
    subs+=(-e 's/libcrypto.so.1.0.0/libcryptm.so\x00\x00\x00\x00\x00\x00/g')
    subs+=(-e 's/libcrypto.so/libcryptm.so/g')
    subs+=(-e 's/libssl.so.1.0.0/libssm.so\x00\x00\x00\x00\x00\x00/g')
    subs+=(-e 's/libssl.so/libssm.so/g')
    subs+=(-e 's/libssh.so.4.4.0/libssh.so\x00\x00\x00\x00\x00\x00/g')
    subs+=(-e 's/libssh.so.4/libssh.so\x00\x00/g')
    sed "${subs[@]}" "/opt/openssl/android-19/lib/libcrypto.so" >
"/home/matteo/deploy/libcryptm.so"
    sed "${subs[@]}" "/opt/openssl/android-19/lib/libssl.so" >
"/home/matteo/deploy/libssm.so"
    sed "${subs[@]}" "/opt/libssh-android/lib/libssh.so" >
"/home/matteo/deploy/libssh.so"
    chmod a+x /home/matteo/deploy/*

8) I prepared a very simple test project in Qt.
Starting from the widget-based template for android, I added a function
that, when clicking on a QPushButton, attempts to connect to a ssh
server in my LAN.
void MainWindow::test()
{
    ssh::Session session;
    session.setOption(SSH_OPTIONS_TIMEOUT, 20);
    session.setOption(SSH_OPTIONS_HOST, "192.168.0.13");
    session.setOption(SSH_OPTIONS_USER, "root");
    session.setOption(SSH_OPTIONS_PORT, 2222);

    session.connect();
}

This works if "session.connect();" is commented out, but the program
crashes otherwise, with error:
F/libc    (22871): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10100
in tid 23039 (QtThread)
Note that the very same code works in "desktop mode".

Right now I am out of ideas on how to debug this, so if someone can give
an hint, I would much appreciate it.
As I said above, I can provide more details and code upon request.

Thanks in advance
Matteo

On 11/19/2015 09:28 AM, Daniel Kroker wrote:
> Hi,
>
> its not so easy to build libssh for android. you need the android
> toolchain look at
> https://github.com/taka-no-me/android-cmake/blob/master/android.toolchain.cmake
>
> Am 19.11.2015 um 02:35 schrieb Matteo:
>> Hi all,
>>
>> My project depends on libssh and I am trying to port it to Android.
>>
>> After some research in the Internet, it appears that I have to
>> cross-compile libssh by using the Android NDK.
>> However, I could not find any good sources of information about the
>> topic.
>>
>> Could somebody please provide a starting point for me?
>>
>> Thank you in advance.
>> Mat
>>
>>
>


Follow-Ups:
Re: Building for AndroidAris Adamantiadis <aris@xxxxxxxxxxxx>
References:
Building for AndroidMatteo <matpen@xxxxxxx>
Re: Building for AndroidDaniel Kroker <dk@xxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org