How to statically link external library by target_link_libraries()?

I am trying to achieve the equivalent of following command by CMake.

gcc -static -O0 -g main.c /usr/lib/x86_64-linux-gnu/libpthread.a

My cmake script successfully built executable file, but gave segmentation fault at run.
Can anybody point me what should I fix ? The command line above built and ran normally, and if I linked libpthtread.so by my cmake script it also terminated without issue.

  • main.c

    #include <pthread.h>
    #include <stdio.h>

    void work(void parg){
    int val = (int)parg;
    printf(“worker tid=%d\n”, *val);
    *val = 100;
    }

    int main (){
    pthread_t handle;
    int data = 0;

      pthread_create(&handle, NULL, work, &data);    
      pthread_join(handle, NULL);
      printf("final = %d\n", data);
    
      return 0;
    

    }

  • CMakeLists.txt

    cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
    project(pthread_task)
    add_executable(pthread_task main.c)
    target_link_libraries(pthread_task pthread.a libc.a)
    install(TARGETS pthread_task DESTINATION ${CMAKE_INSTALL_PREFIX})

  • cmake command
    mkdir build
    cd build
    cmake -DCMAKE_BUILD_TYPE=“DEBUG” -DCMAKE_C_FLAGS_DEBUG="-O0 -g -static" …/

  • env
    $ dpkg -l | grep cmake
    ii cmake 3.13.4-1 amd64 cross-platform, open-source make system

    $ uname -a
    Linux x250 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) x86_64 GNU/Linux

Self solved. If there is more efficient way please reply.

cmake_minimum_required(VERSION 3.13 FATAL_ERROR)

project(pthread_task)
add_executable(pthread_task main.c)

add_library(libpthread STATIC IMPORTED)
set_target_properties(libpthread PROPERTIES IMPORTED_LOCATION /usr/lib/x86_64-linux-gnu/libpthread.a)
set_target_properties(libpthread PROPERTIES INTERFACE_INCLUDE_DIRECTORIES /usr/include)

target_link_libraries(pthread_task libpthread)
install(TARGETS pthread_task DESTINATION ${CMAKE_INSTALL_PREFIX})
  • Just for check

    $ readelf -s ./pthread_task | grep pthread
    34: 0000000000000000 0 FILE LOCAL DEFAULT ABS pthread_create.c
    58: 00000000004010fe 14 FUNC LOCAL DEFAULT 6 __pthread_create_2_1.cold
    205: 0000000000000000 0 FILE LOCAL DEFAULT ABS pthread_join.c
    206: 0000000000000000 0 FILE LOCAL DEFAULT ABS pthread_join_common.c
    208: 0000000000000000 0 FILE LOCAL DEFAULT ABS pthread_mutex_lock.c
    :

If there is more efficient way please reply.

You should not be manually creating imported static libraries for system libraries! The correct commands are find_library or (better) find_package. In this case, the FindThreads module is what you need.

Also, for installing, prefer to use the GNUInstallDirs module.

cmake_minimum_required(VERSION 3.13)
project(pthread_task)

set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)

add_executable(pthread_task main.c)
target_link_libraries(pthread_task PRIVATE Threads::Threads)

include(GNUInstallDirs)
install(TARGETS pthread_task DESTINATION ${CMAKE_INSTALL_BINDIR})

Thanks for the advice alex. I check your cmake script also built and ran successfully.

I noticed the suggested method, which uses include(GNUInstallDirs), by alex is the best way to make a packge by cpack. My script created .deb and .rpm package with absolute pass. This is going to be trouble when you install to your system. However, the proposed method generate packages with relocatable path.