gcc/g++ 编译与链接(2)

一、前言:

这里主要理清楚两个问题:

问题一、第三方程序引用的静态库(.a文件)依赖于其他动态库(.so文件)时编译此第三方文件要链接.a依赖的.so吗?

问题二、上述情况 程序所运行的机器是否一定要有.a所依赖的那些动态库在现场?

 

问题一:

这个问题详细的描述就是。假设libXXX.a用了libpthread.so的函数“pthread_create”,那libXXX.a在链接时,有没有把“pthread_create”函数copy到自己身上,使其完全独立?main.c在链接时,只需要链接libXXX.a,还是连libpthread.so也要链接?

下面来测试一下:

1、首先是生成静态库文件

static_lib_example.h

//static_lib_example.h
#ifndef STATIC_LIB_EXAMPLE_H_INCLUDED
#define STATIC_LIB_EXAMPLE_H_INCLUDED

int testFunc(int x);

#endif

static_lib_example.c

//static_lib_example.c
#include "static_lib_example.h"
#include <stdio.h>
#include <pthread.h>

/* this function is run by the second thread */
void *thread_exe(void *x_void_ptr)
{
    /* increment x to 100 */
    int *x_ptr = (int *)x_void_ptr;
    while(++(*x_ptr) < 100);
        printf("x increment finished\n");

    return NULL;
}

int testFunc(int x)
{
    printf(" testFunc %i\n",x);
    pthread_t inc_x_thread;
    int y;
    /* create a second thread which executes thread_exe(&y) */
    if(pthread_create(&inc_x_thread, NULL, thread_exe, &y)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
    return 0;
}

编译成目标文件和静态库文件

gcc -c static_lib_example.c -o static_lib_example.o

ar rcs libstatic_lib_example.a static_lib_example.o

2、第三方程序文件

 这里就写一个main.c,他会链接libstatic_lib_example.a,并调用函数testFunc(int x)

//main.c
#include "static_lib_example.h"
int main(int argc, char* argv[])
{
    testFunc(100);
    return 1;
}

3、编译

(1)不链接动态库的编译

gcc -g -O3 -Wall main.c -o main -I./ -L ./ -lstatic_lib_example

 如下所示编译出错,提示没有‘pthread_create’的引用。

(2)链接动态库的编译

gcc -g -O3 -Wall main.c -o main -I./ -L ./ -lstatic_lib_example -lpthread

 成功的编译了,如下:

4、思考与验证

看来静态库libXXX.a并没有把动态库的函数copy到自己身上,只留了符号表,所以main.c要用libXXX.a时,还必须链接动态库libpthread.so。

我们可以使用nm工具来看看libXXX.a到底有没有把pthread_create函数的实现打包进来。

U表示仅仅调用而没有定义,也就是说该静态库并不独立,而是依赖于其他库(这里就是libpthread.so)。

5、结论

这里写图片描述

对于静态库libXXX.a,其中有函数testFunc()用到了其他的动态库的函数,比如libAA.so的AA(),libBB.so的BB(),libCC.so的CC()。那么该libXXX.a对这些动态库的调用仍是动态调用,而不是把动态库的相关函数copy到自己身上。

第三方程序想用libXXX.a的话,链接时需要链接libXXX.a所依赖的动态库。

 

问题二:

接着上面的问题。程序执行的机器需要需要一定要有上述libXXX.a所依赖的那些动态库呢??这里先把结论说了。

结论:这取决与gcc有没有带-static选项,带了就是可以的。

对于如下程序我们分别用不带-static选项和带-static选项分别编译

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

/* this function is run by the second thread */
void *thread_exe(void *x_void_ptr)
{
    /* increment x to 100 */
    int *x_ptr = (int *)x_void_ptr;
    while(++(*x_ptr) < 100);
        printf("x increment finished\n");

    return NULL;
}

int testFunc(int param)
{
    printf(" testFunc %i\n",param);
    pthread_t inc_x_thread;
    int x = 0, y = 0;
    /* create a second thread which executes thread_exe(&y) */
    if(pthread_create(&inc_x_thread, NULL, thread_exe, &x)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
    /* increment y to 100 in the first thread */
    while(++y < 100);

    printf("y increment finished\n");

    /* wait for the second thread to finish */
    if(pthread_join(inc_x_thread, NULL)) {
        fprintf(stderr, "Error joining thread\n");
       return 2;
    }

    /* show the results - x is now 100 thanks to the second thread */
    printf("x: %d, y: %d\n", x, y);
    return 0;
}

int main(int argc, char* argv[])
{
    int a = 100;
    testFunc(a);
    return 1;
}
gcc -static test_main.c -o main_static -lpthread 
gcc test_main.c -o main_no_static -lpthread

加static生成的可执行文件很大;不加static的可执行文件要小很多。

这是因为main_static是静态的程序,它已经把各种依赖的函数,比如pthread_create()函数,以及所有pthread_create()依赖的任何东西,都包含进来了。这意味着跑test_main不需要依赖任何库了!

我们可以通过nm指令对比两者的区别,如下附录。

U表示在本程序只是调用,没有定义,需要其他库支持。
T表示本程序定义。

总结

gcc -static 用于编译一个程序时,会使此程序静态编译(把动态库的函数和所依赖的任何的东西都编译进本程序)。编译好后文件会非常大,这意味着程序运行时就不需要依赖任何动态库了。

 

 

#main_no_static
0000000000600e18 d _DYNAMIC
0000000000601000 d _GLOBAL_OFFSET_TABLE_
0000000000400940 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000400b38 r __FRAME_END__
0000000000600e10 d __JCR_END__
0000000000600e10 d __JCR_LIST__
0000000000601058 D __TMC_END__
0000000000601054 B __bss_start
0000000000601050 D __data_start
0000000000400720 t __do_global_dtors_aux
0000000000600e08 t __do_global_dtors_aux_fini_array_entry
0000000000400948 R __dso_handle
0000000000600e00 t __frame_dummy_init_array_entry
                 w __gmon_start__
0000000000600e08 t __init_array_end
0000000000600e00 t __init_array_start
0000000000400930 T __libc_csu_fini
00000000004008c0 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000601054 D _edata
0000000000601068 B _end
0000000000400934 T _fini
00000000004005d8 T _init
0000000000400680 T _start
0000000000601060 b completed.6352
0000000000601050 W data_start
00000000004006b0 t deregister_tm_clones
0000000000400740 t frame_dummy
                 U fwrite@@GLIBC_2.2.5
000000000040088f T main
                 U printf@@GLIBC_2.2.5
                 U pthread_create@@GLIBC_2.2.5
                 U pthread_join@@GLIBC_2.2.5
                 U puts@@GLIBC_2.2.5
00000000004006e0 t register_tm_clones
0000000000601058 B stderr@@GLIBC_2.2.5
00000000004007b0 T testFunc
0000000000400770 T thread_exe
#main_static截取部分
00000000004a7180 R _nl_C_LC_CTYPE_class_digit
00000000004a7000 R _nl_C_LC_CTYPE_class_graph
00000000004a7240 R _nl_C_LC_CTYPE_class_lower
00000000004a7060 R _nl_C_LC_CTYPE_class_print
00000000004a6ee0 R _nl_C_LC_CTYPE_class_punct
00000000004a70c0 R _nl_C_LC_CTYPE_class_space
00000000004a72a0 R _nl_C_LC_CTYPE_class_upper
00000000004a7120 R _nl_C_LC_CTYPE_class_xdigit
00000000004a6d00 R _nl_C_LC_CTYPE_map_tolower
00000000004a6dc0 R _nl_C_LC_CTYPE_map_toupper
00000000004a7300 R _nl_C_LC_CTYPE_tolower
00000000004a7900 R _nl_C_LC_CTYPE_toupper
00000000004a6ca0 R _nl_C_LC_CTYPE_width
00000000004b7440 R _nl_C_LC_IDENTIFICATION
00000000004b7240 R _nl_C_LC_MEASUREMENT
00000000004b6360 R _nl_C_LC_MESSAGES
00000000004b63e0 R _nl_C_LC_MONETARY
00000000004b7040 R _nl_C_LC_NAME
00000000004b65a0 R _nl_C_LC_NUMERIC
00000000004b6fc0 R _nl_C_LC_PAPER
00000000004b71c0 R _nl_C_LC_TELEPHONE
00000000004b6c00 R _nl_C_LC_TIME
00000000004b2644 R _nl_C_codeset
00000000004b2660 R _nl_C_locobj
00000000004b45af R _nl_C_name
00000000004b2653 R _nl_POSIX_name
00000000004a2200 T _nl_archive_subfreeres
00000000004a60b5 R _nl_category_name_idxs
00000000004a60a8 R _nl_category_name_sizes
00000000004a60e0 R _nl_category_names
00000000004a68a0 r _nl_category_num_items
00000000004a6040 r _nl_category_postload
0000000000432210 T _nl_cleanup_ctype
00000000004718e0 T _nl_cleanup_time
                 w _nl_current_LC_ADDRESS
                 w _nl_current_LC_ADDRESS_used
                 w _nl_current_LC_COLLATE
                 w _nl_current_LC_COLLATE_used
0000000000000008 D _nl_current_LC_CTYPE
0000000000000001 A _nl_current_LC_CTYPE_used
                 w _nl_current_LC_IDENTIFICATION
                 w _nl_current_LC_IDENTIFICATION_used
                 w _nl_current_LC_MEASUREMENT
                 w _nl_current_LC_MEASUREMENT_used
                 w _nl_current_LC_MESSAGES
                 w _nl_current_LC_MESSAGES_used
0000000000000018 D _nl_current_LC_MONETARY
0000000000000001 A _nl_current_LC_MONETARY_used
                 w _nl_current_LC_NAME
                 w _nl_current_LC_NAME_used
0000000000000020 D _nl_current_LC_NUMERIC
0000000000000001 A _nl_current_LC_NUMERIC_used
                 w _nl_current_LC_PAPER
                 w _nl_current_LC_PAPER_used
                 w _nl_current_LC_TELEPHONE
                 w _nl_current_LC_TELEPHONE_used
                 w _nl_current_LC_TIME
                 w _nl_current_LC_TIME_used
00000000006d2700 D _nl_current_default_domain
00000000004a6180 r _nl_current_used
00000000004b7b81 R _nl_default_default_domain
00000000004b7b90 R _nl_default_dirname
00000000004a62d0 R _nl_default_locale_path
00000000006d9768 B _nl_domain_bindings
0000000000444a60 T _nl_expand_alias
0000000000445160 T _nl_explode_name
0000000000442c70 T _nl_find_domain
0000000000441cc0 T _nl_find_locale
0000000000480110 T _nl_find_msg
00000000004a22e0 T _nl_finddomain_subfreeres
00000000004714d0 T _nl_get_alt_digit
0000000000471300 T _nl_get_era_entry
0000000000471610 T _nl_get_walt_digit
00000000006d25c0 D _nl_global_locale
0000000000471100 t _nl_init_era_entries.part.0
00000000004422a0 T _nl_intern_locale_data
0000000000442f10 T _nl_load_domain
00000000004423f0 T _nl_load_locale
0000000000442710 T _nl_load_locale_from_archive
00000000006d8960 b _nl_loaded_domains
00000000006d9660 B _nl_locale_file_list
00000000004a1a30 T _nl_locale_subfreeres
0000000000444be0 T _nl_make_l10nflist
00000000006d96c8 B _nl_msg_cat_cntr
0000000000445040 T _nl_normalize_codeset
0000000000471740 T _nl_parse_alt_digit
0000000000442bf0 T _nl_postload_ctype
0000000000442250 T _nl_remove_locale
0000000000471460 T _nl_select_era_entry
00000000006d8c40 B _nl_state_lock
00000000004a2330 T _nl_unload_domain
00000000004426b0 T _nl_unload_locale
00000000004a63e0 r _nl_value_type_LC_ADDRESS
00000000004a6840 r _nl_value_type_LC_COLLATE
00000000004a6720 r _nl_value_type_LC_CTYPE
00000000004a6360 r _nl_value_type_LC_IDENTIFICATION
00000000004a63a0 r _nl_value_type_LC_MEASUREMENT
00000000004a6450 r _nl_value_type_LC_MESSAGES
00000000004a6660 r _nl_value_type_LC_MONETARY
00000000004a6420 r _nl_value_type_LC_NAME
00000000004a6640 r _nl_value_type_LC_NUMERIC
00000000004a643c r _nl_value_type_LC_PAPER
00000000004a63b0 r _nl_value_type_LC_TELEPHONE
00000000004a6480 r _nl_value_type_LC_TIME
00000000004a62e0 r _nl_value_types
00000000004090d0 T _pthread_cleanup_pop
0000000000409160 T _pthread_cleanup_pop_restore
00000000004090b0 T _pthread_cleanup_push
0000000000409100 T _pthread_cleanup_push_defer
00000000004816c0 T _quicksort
00000000006d9740 B _r_debug
00000000006d84a0 B _res
0000000000411540 T _setjmp
0000000000401ad0 T _start
00000000004bc300 V _sys_errlist
00000000004bc300 R _sys_errlist_internal
00000000004bc738 V _sys_nerr
00000000004bc738 R _sys_nerr_internal
00000000004b7d20 R _tens_in_limb
00000000004a2dbc R _thread_db___nptl_initial_report_events
00000000004a2dc8 R _thread_db___nptl_last_event
00000000004a2dd4 R _thread_db___nptl_nthreads
00000000004a2db0 R _thread_db___pthread_keys
00000000004a2d20 R _thread_db__dl_tls_dtv_slotinfo_list
00000000004a2f48 R _thread_db_const_thread_area
00000000004a2d50 R _thread_db_dtv_dtv
00000000004a2cf0 R _thread_db_dtv_slotinfo_gen
00000000004a2d14 R _thread_db_dtv_slotinfo_list_len
00000000004a2d08 R _thread_db_dtv_slotinfo_list_next
00000000004a2cfc R _thread_db_dtv_slotinfo_list_slotinfo
00000000004a2ce4 R _thread_db_dtv_slotinfo_map
00000000004a2d38 R _thread_db_dtv_t_counter
00000000004a2d44 R _thread_db_dtv_t_pointer_val
00000000004a2d68 R _thread_db_link_map_l_tls_modid
00000000004a2d5c R _thread_db_link_map_l_tls_offset
00000000004a2e10 R _thread_db_list_t_next
00000000004a2e04 R _thread_db_list_t_prev
00000000004a2e70 R _thread_db_pthread_cancelhandling
00000000004a2d2c R _thread_db_pthread_dtvp
00000000004a2e40 R _thread_db_pthread_eventbuf
00000000004a2e34 R _thread_db_pthread_eventbuf_eventmask
00000000004a2e28 R _thread_db_pthread_eventbuf_eventmask_event_bits
00000000004a2d80 R _thread_db_pthread_key_data_data
00000000004a2d74 R _thread_db_pthread_key_data_level2_data
00000000004a2d8c R _thread_db_pthread_key_data_seq
00000000004a2d98 R _thread_db_pthread_key_struct_destr
00000000004a2da4 R _thread_db_pthread_key_struct_seq
00000000004a2eac R _thread_db_pthread_list
00000000004a2e1c R _thread_db_pthread_nextevent
00000000004a2e88 R _thread_db_pthread_pid
00000000004a2ea0 R _thread_db_pthread_report_events
00000000004a2e58 R _thread_db_pthread_schedparam_sched_priority
00000000004a2e64 R _thread_db_pthread_schedpolicy
00000000004a2e4c R _thread_db_pthread_specific
00000000004a2e7c R _thread_db_pthread_start_routine
00000000004a2e94 R _thread_db_pthread_tid
00000000004a2f4c R _thread_db_sizeof_dtv_slotinfo
00000000004a2f4c R _thread_db_sizeof_dtv_slotinfo_list
00000000004a2f4c R _thread_db_sizeof_list_t
00000000004a2f5c R _thread_db_sizeof_pthread
00000000004a2f4c R _thread_db_sizeof_pthread_key_data
00000000004a2f50 R _thread_db_sizeof_pthread_key_data_level2
00000000004a2f4c R _thread_db_sizeof_pthread_key_struct
00000000004a2f54 R _thread_db_sizeof_td_eventbuf_t
00000000004a2f58 R _thread_db_sizeof_td_thr_events_t
00000000004a2de0 R _thread_db_td_eventbuf_t_eventdata
00000000004a2dec R _thread_db_td_eventbuf_t_eventnum
00000000004a2df8 R _thread_db_td_thr_events_t_event_bits
00000000006d96e0 B _tmbuf
0000000000426a60 T _wordcopy_bwd_aligned
0000000000426be0 T _wordcopy_bwd_dest_aligned
0000000000426800 T _wordcopy_fwd_aligned
0000000000426930 T _wordcopy_fwd_dest_aligned
0000000000472610 W _xstat
0000000000411640 T abort
0000000000409a90 W accept
00000000004727f0 W access
000000000040f210 t add_fdes
0000000000439f20 t add_module.isra.1
0000000000476a60 t add_name_to_object.isra.3
000000000049b6f0 t add_to_global
00000000004330e0 W addmntent
00000000006d1100 d adds.8359
00000000004bcaa0 r afs.8670
00000000004445a0 t alias_compare
0000000000420860 W aligned_alloc
00000000006d79f0 b aligned_heap_area
00000000004a6910 r archfname
00000000006d8860 b archive_stat
00000000006d8840 b archloaded
00000000006d8910 b archmapped
000000000041adc0 t arena_get2.isra.3
000000000041b310 t arena_get_retry
00000000006d7a40 b arena_mem
00000000004a2a90 t arena_thread_freeres
00000000004653b0 W argz_add_sep
0000000000465220 W argz_count
0000000000465270 W argz_create_sep
0000000000465360 W argz_stringify
000000000048b320 W asprintf
00000000006d7a00 b atfork_recursive_cntr
0000000000436a10 W backtrace
0000000000436980 t backtrace_helper
0000000000436a70 W backtrace_symbols_fd
000000000040fab0 t base_from_cb_data.isra.4
000000000040ed30 t base_from_object.isra.3
00000000004104a0 t base_of_encoded_value
00000000004257f0 i bcmp
000000000049a1d0 W bind
00000000004b4080 r blanks
00000000004b40e0 r blanks
0000000000472f40 W brk
00000000004465f0 T bsearch
00000000006d9798 b buf
00000000004a0ee0 t buffer_free
000000000044ca40 t buffered_vfprintf
00000000004a5a60 r builtin_aliases
00000000006d2320 d builtin_modules
000000000046c050 W c32rtomb
00000000006d8c30 b cache
00000000006d87a0 b cache_malloced
00000000006d8c20 b cache_new
00000000004783b0 t cache_rpath.part.8

 

 

 

 

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

/* this function is run by the second thread */
void *thread_exe(void *x_void_ptr)
{
    /* increment x to 100 */
    int *x_ptr = (int *)x_void_ptr;
    while(++(*x_ptr) < 100);
        printf("x increment finished\n");

    return NULL;
}

int testFunc(int param)
{
    printf(" testFunc %i\n",param);
    pthread_t inc_x_thread;
    int x = 0, y = 0;
    /* create a second thread which executes thread_exe(&y) */
    if(pthread_create(&inc_x_thread, NULL, thread_exe, &x)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
    /* increment y to 100 in the first thread */
    while(++y < 100);

    printf("y increment finished\n");

    /* wait for the second thread to finish */
    if(pthread_join(inc_x_thread, NULL)) {
        fprintf(stderr, "Error joining thread\n");
       return 2;
    }

    /* show the results - x is now 100 thanks to the second thread */
    printf("x: %d, y: %d\n", x, y);
    return 0;
}

int main(int argc, char* argv[])
{
    int a = 100;
    testFunc(a);
    return 1;
}

 

参考:

https://blog.csdn.net/newchenxf/article/details/51735600

https://blog.csdn.net/newchenxf/article/details/51743181

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页