一文はCプログラムのコンパイルの問題を解決します
6091 ワード
Cソースコードのコンパイルについては、ほとんどの人が
1つ目の問題は、サーバのGCCバージョンが低すぎることですが、勝手にアップグレードすることはできません.別のバージョンで新しいGCCをコンパイルして
コンパイルしたgccを環境変数に追加すれば基本的に問題はありません.だからもしあなたが間違っていたら、私に連絡して、私に間違いを見せてください.
この問題を解決した後、
周知のように、Linuxのリリース版は非常に多く、コード開発の機器と実際に稼働している機器では確率が大きく異なり、コンパイルが通過することを保証するためには、まず実際に稼働している機器が要求に合っているかどうかをチェックしなければならない.は、 のような設置経路を変更する.インストールディレクトリを調整し、 を調整することができる.ツール依存インストールアドレス を指定する.コンパイル動作に影響する環境変数 最後のクラスの環境変数は、gccパラメータを変更することによってコンパイルの異なる段階に影響を及ぼすことができるため、非常に重要である.この場合、コンパイルがいくつかの段階に分かれているかを知る必要があり、いくつかの簡単な例を説明する必要がある.
最も簡単なCプログラムもコンパイルしたことがありますが、画面から「hello world!」を出力する機能があります.次のコードを「hello.c」として保存します.
その後、
では、どのように解決すればいいのでしょうか.第1の方法は、絶対パス、すなわち
./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などのファイルの位置最も簡単な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の を してエラーを できます.