一文はCプログラムのコンパイルの問題を解決します

6091 ワード

Cソースコードのコンパイルについては、ほとんどの人が./configure --prefix=XXX && make && make installにとどまっています.ほとんどのプログラムは順調にこのステップを完了し、指定されたファイルの下にインストールされます.一部のプログラムはxxxが不完全でエラーになります.そして、この問題を検索エンジンに置くと、sudo apt-get/yum install xxxで問題を解決し、問題が解決するというブログが見つかります.そのため、ある意味でコンパイルは問題を構成すべきではありません.root権限がなくなるまで、サーバーの管理を開始し、管理者権限でプログラムをインストールすることができなくなるまで、問題が発生しました.
1つ目の問題は、サーバのGCCバージョンが低すぎることですが、勝手にアップグレードすることはできません.別のバージョンで新しいGCCをコンパイルして/opt/local/usr、またはホームディレクトリの下にインストールするしかありません.私は普通次のコードを使います.
cd ~/src
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/gcc-7.2.0/gcc-7.2.0.tar.gz
tar xf gcc-7.2.0.tar.gz
cd gcc-7.2.0
./contrib/download_prerequisites
mkdir build && cd build
../configure --prefix=$HOME/opt/sysoft/gcc-7.2.0 --disable-multilib --enable-threads=posix
make -j 8 && make install

コンパイルしたgccを環境変数に追加すれば基本的に問題はありません.だからもしあなたが間違っていたら、私に連絡して、私に間違いを見せてください.
この問題を解決した後、./configure && make && make installがいったいそんなことをしたのかを深く理解してみましょう.
周知のように、Linuxのリリース版は非常に多く、コード開発の機器と実際に稼働している機器では確率が大きく異なり、コンパイルが通過することを保証するためには、まず実際に稼働している機器が要求に合っているかどうかをチェックしなければならない.configureの主な目的は、依存するヘッダファイルと関数ライブラリがターゲットマシン上に存在するかどうかを確認することであり、存在すれば万事順調であり、快適なmake && make installがあり、存在しなければconfigureの第2の機能を使用し、コンパイル動作を調整することである../configure --helpを使用すると、いくつかの出力が表示され、大きく分けて次のようになります.
  • は、--prefix
  • のような設置経路を変更する.
  • インストールディレクトリを調整し、--prefix=PREFIXを前提にlib、include、shareなどのファイルの位置
  • を調整することができる.
  • ツール依存インストールアドレス
  • を指定する.
  • コンパイル動作に影響する環境変数
  • 最後のクラスの環境変数は、gccパラメータを変更することによってコンパイルの異なる段階に影響を及ぼすことができるため、非常に重要である.この場合、コンパイルがいくつかの段階に分かれているかを知る必要があり、いくつかの簡単な例を説明する必要がある.
    最も簡単なCプログラムもコンパイルしたことがありますが、画面から「hello world!」を出力する機能があります.次のコードを「hello.c」として保存します.
    #include 
    
    int main(){
        printf("hello world!
    "); return 0; }

    その後、gcc -o hello hello.cを用いる実行可能なhelloが生成され、簡単であるが、gccが行うタスクは少なくない.まず、前処理、コンパイル、アセンブリのステップでヘッダファイル「stdio.h」を探します.デフォルトの検索パスは/usr/include/usr/local/includeです.この2つの場所が見つからず、追加のパスが提供されていない場合は、デフォルトのパスにないヘッダファイルを追加しました.zlib.h、システムにこのファイルがあるにもかかわらず、それは間違っています.
    #include 
    #include 
    int main(){
        printf("hello world!
    "); return 0; } # error hello.c:2:19: fatal error: zlib.h: No such file or directory # include ^ compilation terminated.

    では、どのように解決すればいいのでしょうか.第1の方法は、絶対パス、すなわち, , ; gcc , -I/path/to/whereを することであり、 なコンパイルコードはgcc -I/cluster/zlib-1.2.11/include/ -o hello hello.cである.ほとんどのconfigureは「CPPFLAGS」を することを し、「CFLAGS」はヘッダファイルの を させ、この2つの は の「CXXXFLAGS」と に である.Makefileの は$(CC) $(CPPFLAGS) $(CFLAGS) example.c -c -o example.oであるからである.

    , , , c

     :hello.c
    # include 
    int main(){
        printf("hello world!
    "); reply(); return 0; } : reply.c #include void reply(){ printf("hi!
    "); }

    , ld ,

    gcc -c hello.c reply.c
    gcc -o hello hello.o  reply.o
    

    (.o) , , xxx.soファイル.R で も くの を び すRパッケージを しているように、Cでsin(3.14/2)を したい は、 を くことを えずに、 の を び します. に けてcとreply.cを にとると、これは の が ライブラリlibreplyをコンパイルしたにすぎない.soは たちに び します.

    gcc -shared -fPIC  -c reply.c
    gcc -shared -fPIC -o libreply.so reply.o
    

    たちが helloをコンパイルするとcの 、 たちのlibreplyのため、このステップをリンクしません.soはデフォルトの パスにはありません
    $ gcc -o hello reply.c
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
    (.text+0x20): undefined reference to `main'
    collect2: error: ld returned 1 exit status
    

    コンパイルが できるようにするには、-L-lのパラメータを して、 に ライブラリの パスを し、2 の ライブラリの 、すなわち「lib」と「.so」の りの を する があります.
    gcc -o hello hello.c -L. -lreply
    

    コンパイルは かに しましたが、./helloが されている にエラーが し、このエラーはよく られているかもしれません.
    ./hello
    ./hello: error while loading shared libraries: libreply.so: cannot open shared object file: No such file or directory
    #  ldd 
    $ ldd hello
        linux-vdso.so.1 =>  (0x00007ffc0a75f000)
        libreply.so => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007f6224d36000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f622510f000)
    

    どうしてこんなことになったの?これは, ライブラリの が2つに かれているため,まずコンパイル に いられ, に な にも いられる.したがって、コンパイルに したにもかかわらず、libreply.soは、システムの ライブラリ パス(ldconfig-pおよびcat/etc/ld.so.confで できます)ではなく、 つからないためにエラーが します. 1の は、LD_LIBRARY_PATHを いて ライブラリのランタイムパスを させることであり、これはconfigureとは である.
    export LD_LIBRARY_PATH="$HOME/temp:LD_LIBRARY_PATH"
    ./hello
    

    このようにして を したように えますが、 にはより きな をもたらす があります.glibcをコンパイルして、glibcのlibをLD_LIBRARY_PATHに すると、 なコアが した に することができます.これが ライブラリ の であるため、より い はgccのWl,-R/path/to/whereパラメータでldのリンク を し、 な ライブラリにソフトに し、 であっても であってもよい.lddでbiocondaがインストールしたプログラムのダイナミックライブラリの を ることができます.
    gcc -L. -lreply -Wl,-R./ hello.c -o hello
    $ ldd hello
        linux-vdso.so.1 =>  (0x00007ffe6cb11000)
        libreply.so => ./libreply.so (0x00007fd7609e8000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fd76060d000)
        /lib64/ld-linux-x86-64.so.2 (0x000055fb9fc84000)
    
    ./configureと ライブラリに する はLDFLAGSであり、export LDFLAGS=-L/path/to/lib -Wl,-R/paht/to/libで を することができる.
    まとめてみると、./configure && make && make installを してプログラムをコンパイルする 、エラーが した は、 にヘッダファイルとダイナミックライブラリが つからないため、CFLAGS/CXXFLAGS/CPPFLAGSを じてヘッダファイルパスを やし、LDFLAGSを じてダイナミックライブラリのコンパイルと のパスを やすことができます.LD_LIBRARY_PATHの はあまり されず、コアが します.プログラムのインストール に./configureがない は、 するMakefileの を してエラーを できます.