1. 程式人生 > >簡談用g++編譯執行c++程式碼流程,以及動態庫靜態庫的建立與使用

簡談用g++編譯執行c++程式碼流程,以及動態庫靜態庫的建立與使用

一 g++ 編譯執行hello world

1編寫hello world 程式碼

#include<iostream>

using namespace std;

int main()
{
  cout << "hello world!" << endl;
  return 0;
}

2 編譯及執行

自動生成了a.out可執行的檔案

huxiang@shenyong-Opt790:~/work/cpp$ g++ hello.cpp 
huxiang@shenyong-Opt790:~/work/cpp$ ls
a.out  hello.cpp
huxiang@shenyong
-Opt790:~/work/cpp$ ./a.out hello world!

二 程式執行步驟

預處理   .i .ii檔案         gcc -E hello.cpp -o hello.i
編譯    .s檔案             gcc -S hello.cpp -o hello.s
彙編    .o .obj檔案       gcc -c hello.cpp -o hello.o
連結    .lib .a檔案

1 預處理

vim hello.i

  ...上面很長省略了..
  extern wostream wclog;




  static ios_base::Init __ioinit;


}
# 2 "hello.cpp" 2
using namespace std; int main() { cout << "hello world!" << endl; return 0; }

2 編譯

vim hello.s

       .file   "hello.cpp"
        .local  _ZStL8__ioinit
        .comm   _ZStL8__ioinit,1,1
        .section        .rodata
.LC0:
        .string "hello world!"
        .text
        .globl
main .type main, @function main: .LFB971: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %esi movl $_ZSt4cout, %edi call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi movq %rax, %rdi

3 彙編

vim hello.o

^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^^A^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@@^@^O^@^L^@UH<89>å¾^@^@^@^@¿^@^@^@^^@^@^@^^@^@^@^@H<89>Çè^@^@^@^^@^@^@^@]ÃUH<89>åH<83>ì^P<89>}ü<89>uø<83>}ü^Au'<81>}øÿÿ^@^@u^^¿^@^@^@^@è^@^@^@^@º^@^@^@^@¾^@^@^@^@¿^@^@^@^@è^@^@^@^@ÉÃUH<89>å¾ÿÿ^@^@¿^A^@^@^@è°ÿÿÿ]Ãhello world!^@^@^@^@^@^@^@^@^@^@^@^@GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4^@^@^@^@^@^T^@^@^@^@^@^@^@^AzR^@^Ax^P^A^[^L^G^H<90>^A^@^@^\^@^@^@^\^@^@^@^@^@^@^@'^@^@^@^@A^N^P<86>^BC^M^Fb^L^G^H^@^@^@^\^@^@^@<^@^@^@^@^@^@^@=^@^@^@^@A^N^P<86>^BC^M^Fx^L^G^H^@^@^@^\^@^@

4 連結

三 多檔案編譯連結

1 編寫add.h add.cpp main.cpp程式碼

add.h 標頭檔案

#ifndef _ADD_H
#define _ADD_H
extern int add(int a,int b);
//extern 表示函式實現在另一個檔案中
#endif
~       

add.cpp 函式實現

int add(int a,int b)
{
  return (a+b);
}

main.cpp main函式

#include<iostream>
#include"add.h"

using namespace std;

int main()
{
  int a = 1,b = 2;
  int c = add(a,b);
  cout << a << " + " << b << " = " << c << endl;
  return 0;
}

2 編譯執行

huxiang@shenyong-Opt790:~/work/cpp$ g++ add.h add.cpp main.cpp -o main
huxiang@shenyong-Opt790:~/work/cpp$ ls
add.cpp  add.h  main  main.cpp
huxiang@shenyong-Opt790:~/work/cpp$ ./main 
1 + 2 = 3

四 動態庫與靜態庫

靜態庫 .a (linux) .lib (windows)
動態庫 .so (linux) .dll (windows)
gcc時,用-I和-L分別制定庫名和庫路徑

1 靜態庫的建立與使用

  • 1 建立add.c和add.h,其中main函式中用到了add這個函式,如果直接執行會報錯說找不到add這個函式。
  • 2 先add.c編譯成二進位制檔案add.o
    g++ -c add.c -o add.o
  • 3 再用ar這個工具將add.o做成靜態庫
    ar -r libadd.a add.o
  • 4 這樣就可以呼叫了,即在編譯的時候加上庫的名字,路徑並申明為靜態庫-static等引數即可。
    g++ mian.c -ladd -L/home/huxiang/work/cpp -static -o main
  • 5 注意要其他地方也要用的話要把add.h也拷貝過去才能用
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  a.out  mian.c
huxiang@hp:~/work/cpp$ rm a.out 
huxiang@hp:~/work/cpp$ ar -r libadd.a add.o 
ar: creating libadd.a
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  libadd.a  mian.c
huxiang@hp:~/work/cpp$ g++ mian.c -llibadd -L./ -static -o main
/usr/bin/ld: cannot find -llibadd
collect2: error: ld returned 1 exit status
huxiang@hp:~/work/cpp$ g++ mian.c -libadd -L./ -static -o main
/usr/bin/ld: cannot find -libadd
collect2: error: ld returned 1 exit status
huxiang@hp:~/work/cpp$ pwd
/home/huxiang/work/cpp
huxiang@hp:~/work/cpp$ g++ mian.c -libadd -L/home/huxiang/work/cpp -static -o main
/usr/bin/ld: cannot find -libadd
collect2: error: ld returned 1 exit status
huxiang@hp:~/work/cpp$ g++ mian.c -ladd -L/home/huxiang/work/cpp -static -o main
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  libadd.a  main  mian.c
huxiang@hp:~/work/cpp$ ./main 
1+2=3

其他地方也要用的話

huxiang@hp:~/work$ ls
add.h  cpp  mian.c
huxiang@hp:~/work$ g++ mian.c -ladd -L./cpp -static -o main
huxiang@hp:~/work$ ls
add.h  cpp  main  mian.c
huxiang@hp:~/work$ ./main 
1+2=3

2 動態函式庫的建立與使用

  • 1.首先建立libmyadd.so,即利用add.c這個函式生成動態庫
    g++ -share -fPIC -o libmyadd.so add.c
    -share指為共享的,-fPIC表示position independent code位置無關,這是動態庫特性
  • 2.指定動態庫生成可執行檔案,-L.表示當前資料夾,-lmyadd表示去找libmyadd.so這個動態庫檔案。
    g++ main.c -L. -lmyadd
  • 3.直接使用會抱錯,找不到動態庫,要指定動態庫的路徑
    ./a.out會報錯
    LD_LIBRARY_PATH=. ./a.out指定當前庫的路徑後在執行就可以了
  • 4.如果要一直用,可以將.so檔案的目錄新增到/etc/ld.so.conf裡面,然後再執行ldconfig就行了,具體如下面:
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  main.c
huxiang@hp:~/work/cpp$ g++ -share -fPIC -o libmyadd.so add.c
g++: error: unrecognized command line option ‘-share’
huxiang@hp:~/work/cpp$ g++ -shared -fPIC -o libmyadd.so add.c
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  libmyadd.so  main.c
huxiang@hp:~/work/cpp$ g++ main.c -L. -lmyadd
huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  a.out  libmyadd.so  main.c
huxiang@hp:~/work/cpp$ ./a.out 
./a.out: error while loading shared libraries: libmyadd.so: cannot open shared object file: No such file or directory
huxiang@hp:~/work/cpp$ LD_LIBRARY_PATH=. ./a.out
1+2=3

如果要永久使用的話該怎麼辦呢?

huxiang@hp:~/work/cpp$ ls
add.c  add.h  add.o  a.out  libmyadd.so  main.c
huxiang@hp:~/work/cpp$ ./a.out  這裡直接用會報錯
./a.out: error while loading shared libraries: libmyadd.so: cannot open shared object file: No such file or directory
huxiang@hp:~/work/cpp$ vi /etc/ld.so.conf  在這個檔案裡面新增.so所在的目錄就行了
huxiang@hp:~/work/cpp$ pwd
/home/huxiang/work/cpp
huxiang@hp:~/work/cpp$ vi /etc/ld.so.conf
huxiang@hp:~/work/cpp$ sudo ldconfig
huxiang@hp:~/work/cpp$ ./a.out 
1+2=3

例如,我的新增後的ld.so.conf檔案就是這個樣子:

include /etc/ld.so.conf.d/*.conf
/home/huxiang/work/cpp