How to use pthread in Native App



  • Is it possible to use pthread with a native Ubuntu Touch app built using clickable and cmake? I'm trying to link to a C library I've already written that depends on pthread but adding pthread as a dependency in CMakeLists.txt doesn't link (either that or the library is missing?). Building for desktop with clickable desktop compiles successfully but then the module fails to load with the error message:

    file:///path/to/project/build/tmp/qml/Main.qml:29 Type ChatView unavailable
    file:///path/to/project/build/tmp/qml/ChatView.qml:19 plugin cannot be loaded for module "SockTalkFrontend": Cannot load library /path/to/project/build/tmp/lib/x86_64-linux-gnu/SockTalkFrontend/libSockTalkFrontend.so: (/path/to/project/build/tmp/lib/x86_64-linux-gnu/SockTalkFrontend/libSockTalkFrontend.so: undefined symbol: _ZTINSt6thread6_StateE)
    

    If I recompile the library on the device and then build for mobile (armhf) it yields the following error:

    -- Looking for pthread.h
    -- Looking for pthread.h - found
    -- Looking for pthread_create
    -- Looking for pthread_create - not found
    -- Check if compiler accepts -pthread
    CMake Error: TRY_RUN() invoked in cross-compiling mode, please set the following cache variables appropriately:
       THREADS_PTHREAD_ARG (advanced)
    For details see /path/to/project//build/TryRunResults.cmake
    -- Check if compiler accepts -pthread - no
    -- Found Threads: TRUE  
    -- Configuring incomplete, errors occurred!
    

    Build logs (CMakeError.log) :

    Determining if the pthread_create exist failed with the following output:
    Change Dir: /path/to/project/build/CMakeFiles/CMakeTmp
    
    Run Build Command:"/usr/bin/make" "cmTC_802c3/fast"
    /usr/bin/make -f CMakeFiles/cmTC_802c3.dir/build.make CMakeFiles/cmTC_802c3.dir/build
    make[1]: Entering directory '/path/to/project/build/CMakeFiles/CMakeTmp'
    Building C object CMakeFiles/cmTC_802c3.dir/CheckSymbolExists.c.o
    /usr/bin/arm-linux-gnueabihf-gcc     -o CMakeFiles/cmTC_802c3.dir/CheckSymbolExists.c.o   -c /path/to/project/build/CMakeFiles/CMakeTmp/CheckSymbolExists.c
    Linking C executable cmTC_802c3
    /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_802c3.dir/link.txt --verbose=1
    /usr/bin/arm-linux-gnueabihf-gcc       CMakeFiles/cmTC_802c3.dir/CheckSymbolExists.c.o  -o cmTC_802c3 -rdynamic 
    CMakeFiles/cmTC_802c3.dir/CheckSymbolExists.c.o: In function `main':
    CheckSymbolExists.c:(.text+0xe): undefined reference to `pthread_create'
    CheckSymbolExists.c:(.text+0x12): undefined reference to `pthread_create'
    collect2: error: ld returned 1 exit status
    CMakeFiles/cmTC_802c3.dir/build.make:97: recipe for target 'cmTC_802c3' failed
    make[1]: *** [cmTC_802c3] Error 1
    make[1]: Leaving directory '/path/to/project/build/CMakeFiles/CMakeTmp'
    Makefile:126: recipe for target 'cmTC_802c3/fast' failed
    make: *** [cmTC_802c3/fast] Error 2
    
    File /path/to/project/build/CMakeFiles/CMakeTmp/CheckSymbolExists.c:
    /* */
    #include <pthread.h>
    
    int main(int argc, char** argv)
    {
      (void)argv;
    #ifndef pthread_create
      return ((int*)(&pthread_create))[argc];
    #else
      (void)argc;
      return 0;
    #endif
    }
    
    Determining if compiler accepts -pthread returned PLEASE_FILL_OUT-FAILED_TO_RUN instead of 2. The compiler had the following output:
    Change Dir: /path/to/project/build/CMakeFiles/CMakeTmp
    
    Run Build Command:"/usr/bin/make" "cmTC_1d99c/fast"
    /usr/bin/make -f CMakeFiles/cmTC_1d99c.dir/build.make CMakeFiles/cmTC_1d99c.dir/build
    make[1]: Entering directory '/path/to/project/build/CMakeFiles/CMakeTmp'
    Building C object CMakeFiles/cmTC_1d99c.dir/CheckForPthreads.c.o
    /usr/bin/arm-linux-gnueabihf-gcc     -o CMakeFiles/cmTC_1d99c.dir/CheckForPthreads.c.o   -c /usr/share/cmake-3.5/Modules/CheckForPthreads.c
    Linking C executable cmTC_1d99c
    /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_1d99c.dir/link.txt --verbose=1
    /usr/bin/arm-linux-gnueabihf-gcc       CMakeFiles/cmTC_1d99c.dir/CheckForPthreads.c.o  -o cmTC_1d99c -rdynamic -pthread 
    make[1]: Leaving directory '/path/to/project/build/CMakeFiles/CMakeTmp'
    

    I would prefer not to have to rewrite the library, but I'm open to adapting the thread type if necessary. Thanks!



  • I would need to see the source and cmake files to give you an accurate answer, but first thing I would say is that you shouldn't just put pthread in the compiler flags or target libraries commands in cmake. Instead you should use find_package(Threads REQUIRED) and then use ${CMAKE_THREAD_LIBS_INIT} variable in the target_link_libraries() call as an additional library.



  • The source code can be found on GitLab or GitHub.

    Where exactly should ${CMAKE_THREAD_LIBS_INIT} go?



  • @Arc676 OK. It looks like you have the find_package() and are using Threads::Threads there already, so that should work.

    But it looks like you're using a static binary which you've included in the git repo? And you're calling target_link_libraries() multiple times. You should only call it once for each target, and list all the libraries you're linking against in the arguments, I think (you can place each argument on a separate line so it's easier to read).



  • Yes, the library is a static library included in the repository (compiled with -fPIC). The README in the linked repository includes a link to the repository for just the library.

    I changed the Makefile to have

    set(CMAKE_AUTOMOC ON)
    
    set(THREADS_PREFER_PTHREAD_FLAG ON)
    find_package(Threads REQUIRED)
    
    include_directories(${CMAKE_SOURCE_DIR}/plugins/SockTalkFrontend/lib)
    link_directories(${CMAKE_SOURCE_DIR}/plugins/SockTalkFrontend/lib)
    
    add_library(${PLUGIN} MODULE ${SRC})
    target_link_libraries(${PLUGIN} ${CMAKE_SOURCE_DIR}/plugins/SockTalkFrontend/lib/libsocktalk.a Threads::Threads)
    set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
    qt5_use_modules(${PLUGIN} Qml Quick DBus)
    

    But it didn't change the outcome. Thanks for the tip of linking multiple libraries in the same call though.