だから私は私のファイル(file2.c)で別のC(file1.c)ファイルで定義された関数を使用しようとしています。これを行うために、file1(file1.h)のヘッダーを含めています。
ただし、gccを使用してファイルをコンパイルしようとすると、常に次のエラーが表示されます。
Undefined symbols for architecture x86_64:
"_init_filenames", referenced from:
_run_worker in cc8hoqCM.o
"_read_list", referenced from:
_run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64
File2のfile1の関数を使用するには、「オブジェクトファイルをリンクする」必要があると言われましたが、それが何を意味するのかわかりません:(
オブジェクトファイルを単にリンクするためにgcc
を使用していると仮定します。
$ gcc -o output file1.o file2.o
オブジェクトファイルを取得するには、単に次を使用してコンパイルします
$ gcc -c file1.c
これにより、file1.oなどが生成されます。
ファイルを実行可能ファイルにリンクしたい場合
$ gcc -o output file1.c file2.c
既存の答えはすでに「どのように」をカバーしていますが、私は疑問に思うかもしれない他の人のために「何」と「なぜ」について詳しく述べたかっただけです。
コンパイラー(gcc)の機能:「コンパイル」という用語は、「ソースコードをプログラムに変換する」という意味で高レベルで使用されますが、技術的には「ソースコードをオブジェクトコード」。 gccのようなコンパイラは、実際には、ソースコードをプログラムに変換するための2つの関連する、しかし間違いなく異なる機能を実行します。コンパイル(ソースをオブジェクトコードに変換する後者の定義)とリンク(必要なオブジェクトコードファイルを結合するプロセス) 1つの完全な実行可能ファイル)。
あなたが見た元のエラーは技術的には「リンクエラー」であり、リンカーである「ld」によってスローされます。 (厳密な)コンパイル時エラーとは異なり、リンカはすでにオブジェクト空間にあるため、ソースコード行への参照はありません。
デフォルトでは、gccに入力としてソースコードが渡されると、gccはそれぞれをコンパイルしてから、それらをすべてリンクしようとします。他の応答で述べたように、フラグを使用してgccに最初にコンパイルするよう指示し、その後オブジェクトファイルを使用して別のステップでリンクすることができます。この2段階のプロセスは不必要に思えるかもしれません(おそらく非常に小さなプログラムの場合です)が、非常に大きなプログラムを管理する場合は非常に重要です。小さな変更を加えるたびにプロジェクト全体をコンパイルすると、かなりの時間が無駄になります。
1つのコマンドでコンパイルおよびリンクできます。
gcc file1.c file2.c -o myprogram
そして実行:
./myprogram
ただし、質問に答えるには、オブジェクトファイルをgcc
に渡すだけです。
gcc file1.o file2.o -o myprogram
Foo1.c、foo2.c、foo3.cおよびmakefileをbashのmakeタイプの1つのフォルダーに追加します
メイクファイルを使用したくない場合は、コマンドを実行できます
gcc -c foo1.c foo2.c foo3.c
それから
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h>
#include <string.h>
void funk1();
void funk1() {
printf ("\nfunk1\n");
}
int main(void) {
char *arg2;
size_t nbytes = 100;
while ( 1 ) {
printf ("\nargv2 = %s\n" , arg2);
printf ("\n:> ");
getline (&arg2 , &nbytes , stdin);
if( strcmp (arg2 , "1\n") == 0 ) {
funk1 ();
} else if( strcmp (arg2 , "2\n") == 0 ) {
funk2 ();
} else if( strcmp (arg2 , "3\n") == 0 ) {
funk3 ();
} else if( strcmp (arg2 , "4\n") == 0 ) {
funk4 ();
} else {
funk5 ();
}
}
}
foo2.c
#include <stdio.h>
void funk2(){
printf("\nfunk2\n");
}
void funk3(){
printf("\nfunk3\n");
}
foo3.c
#include <stdio.h>
void funk4(){
printf("\nfunk4\n");
}
void funk5(){
printf("\nfunk5\n");
}
メイクファイル
outputTest: foo1.o foo2.o foo3.o
gcc -o output foo1.o foo2.o foo3.o
make removeO
outputTest.o: foo1.c foo2.c foo3.c
gcc -c foo1.c foo2.c foo3.c
clean:
rm -f *.o output
removeO:
rm -f *.o
.cファイルを多数の.oファイルと一緒にコンパイルする方法については言及されていないため、このコメントはそれを求めています。
この答えのmain.cはどこですか? :/ file1.cがメインの場合、既にコンパイルされている他の.oファイルとどのようにリンクしますか? –トムブリトー14年10月12日19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
ここで、main.cはmain()関数を含むCファイルであり、オブジェクトファイル(* .o)はプリコンパイルされています。 GCCはこれらを一緒に処理する方法を知っており、それに応じてリンカーを呼び出し、最終的な実行可能ファイル(この場合はx0rbin)を生成します。
Main.cで定義されていない関数を使用できますが、オブジェクトファイル(* .o)で定義されている関数への外部参照を使用できます。
オブジェクトファイルの形式が正しい場合(COFFなど)、. objまたは他の拡張子とリンクすることもできます。