一、前言:

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

问题一、第三方程序引用的静态库(.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_INCLUDEDint 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.oar 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_usedw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTablew _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_entryw __gmon_start__
0000000000600e08 t __init_array_end
0000000000600e00 t __init_array_start
0000000000400930 T __libc_csu_fini
00000000004008c0 T __libc_csu_initU __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_dummyU fwrite@@GLIBC_2.2.5
000000000040088f T mainU printf@@GLIBC_2.2.5U pthread_create@@GLIBC_2.2.5U pthread_join@@GLIBC_2.2.5U 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_timew _nl_current_LC_ADDRESSw _nl_current_LC_ADDRESS_usedw _nl_current_LC_COLLATEw _nl_current_LC_COLLATE_used
0000000000000008 D _nl_current_LC_CTYPE
0000000000000001 A _nl_current_LC_CTYPE_usedw _nl_current_LC_IDENTIFICATIONw _nl_current_LC_IDENTIFICATION_usedw _nl_current_LC_MEASUREMENTw _nl_current_LC_MEASUREMENT_usedw _nl_current_LC_MESSAGESw _nl_current_LC_MESSAGES_used
0000000000000018 D _nl_current_LC_MONETARY
0000000000000001 A _nl_current_LC_MONETARY_usedw _nl_current_LC_NAMEw _nl_current_LC_NAME_used
0000000000000020 D _nl_current_LC_NUMERIC
0000000000000001 A _nl_current_LC_NUMERIC_usedw _nl_current_LC_PAPERw _nl_current_LC_PAPER_usedw _nl_current_LC_TELEPHONEw _nl_current_LC_TELEPHONE_usedw _nl_current_LC_TIMEw _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

gcc/g++ 编译与链接(2)相关推荐

  1. linux gcc g++编译命令选项

    gcc/g++在执行编译工作的时候,总共需要4步 1.预处理,生成.i的文件[预处理器cpp] 2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs] 3.有汇编变为目标代码(机器代码) ...

  2. MinGW下载并配置gcc/g++编译环境

    本文将讲解如何下载MinGW并配置gcc\g++编译环境 #方案一:官网下载 ##一.下载MinGW 在MinGW官网中下载"mingw-get-setup.exe" 官网传送门: ...

  3. arm linux gcc fpic,【待整理】Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义

    [待整理]Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义 -fpic Generate position-independent code (PIC) suit ...

  4. windows下,对opencv进行gcc/g++编译

    opencv官网下载的Windows安装包有source文件夹和build文件夹,其中build文件夹是已经编译好的,里面有用于VS配置的库,source文件夹包含源码和编译配置文件,可以借助cmak ...

  5. linux下g编译文件或目录,【转】在linux下使用gcc/g++编译多个.h文件

    博主写得很好 多个文件编译在linux下编译,下面有三个文件,分别是1.cpp 和 2.cpp 和myhead.h 文件. 1.cpp 2.cpp myhead.h 假如他们都在一个目录下面,那么编译 ...

  6. GCC/G++编译过程

    GCC编译过程 # 编写一个最简单的C++程序 $ cat hello.cpp int main() {return 0; }# -v选项可以打印出详细的编译过程,以及编译命令. $ gcc -v - ...

  7. gcc/g++ 编译C/C++代码

    摘要:本文介绍了在windows下编译c/c++代码的完整流程 1.安装gcc/g++编译器 官网下载地址为:https://sourceforge.net/projects/mingw-w64/fi ...

  8. 用gcc/g++编译运行C/C++程序

    2019独角兽企业重金招聘Python工程师标准>>> 编译 gcc hello.c 运行 ./a.out 将源程序文件编译成指定文件 gcc hello.c -o hello 多文 ...

  9. MinGW下载,配置gcc/g++编译环境

    方案一:官网下载 一.下载MinGW 在MinGW官网中下载"mingw-get-setup.exe" 官网传送门:http://www.mingw.org/ 二.安装MinGW ...

  10. gcc g++ 支持c++11编译的标准和区别

    g++ -g -Wall -std=c++11 main.cpp gcc -g -Wall -std=c11 main.cpp 如果不想每次写这个-std=C++11这个选项该怎么办呢? 方法出处:h ...

最新文章

  1. asp.net在线人数限制
  2. html点击按钮自动获取值,如何获取HTML按钮的文本值
  3. pyspark intersection代码示例
  4. android 快速新建字符资源
  5. Java Integer类中的parseInt和valueOf的区别
  6. Android NDK学习(2)
  7. magento模板制作教程(一)
  8. android 网络图片 不能显示,求帮忙啊
  9. jerasure 2.0译文
  10. 点击控件动态创建新页面
  11. 台达服务器电源原理电路图,详细解析开关电源电路:工作原理,电路组成,电路图...
  12. 锐捷服务器虚拟化技术_网络设备-锐捷-交换机(S8607E)VSU虚拟化终结配置篇
  13. doc、docx文档批量合并
  14. Wsus更新失败错误代码:0x80244022故障排除
  15. 微信支付凭证关联开发票功能的配置
  16. 暨南大学计算机科学研究生,计算机科学系硕士研究生在IEEE Virtual Reality (VR) 2020上发表两篇论文...
  17. 在线电子书阅读微信小程序 毕业设计(5)用户登录注册
  18. 接收微信公众号的事件推送并且回复消息
  19. Gitee码云 操作
  20. Matlab 字符串时间戳转化为数值(以秒或毫秒为单位)

热门文章

  1. Harmony OS — Image图片
  2. Android EditText 常用属性总结
  3. RK3288_Android7.1调试RTC总结(一)
  4. 递归的效率问题以及递归与循环的比较
  5. OPCServer:使用Matrikon OPC Server Simulation
  6. 编译器各个步骤的介绍
  7. Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
  8. 关于php中的json_encode和json_decode的”\“(反斜杠)的问题
  9. schedule_timeout与mdelay的区别
  10. Jquery.ajax不能解析json对象,报Invalid JSON错误的原因和解决方法