61

そのため、別の C (file1.c) ファイルで定義された関数を自分のファイル (file2.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

file1の関数をfile2で使用するには、「オブジェクトファイルをリンクする」必要があると言われましたが、それが何を意味するのかわかりません:(

4

5 に答える 5

103

gccオブジェクトファイルを単純にリンクするために、を使用していると思います:

$ gcc -o output file1.o file2.o

オブジェクトファイルを取得するには、次を使用してコンパイルするだけです

$ gcc -c file1.c

これにより、file1.o などが生成されます。

ファイルを実行可能ファイルにリンクする場合は、

$ gcc -o output file1.c file2.c
于 2013-03-15T20:53:30.270 に答える
26

既存の回答はすでに「どのように」をカバーしていますが、不思議に思っているかもしれない他の人のために「何を」と「なぜ」について詳しく説明したかっただけです。

コンパイラ (gcc) の機能: 「コンパイル」という用語は、「ソース コードをプログラムに変換する」という意味で高レベルで使用されるため、少しオーバーロードされた用語ですが、より技術的には「ソース コードをプログラムに変換する」という意味です。オブジェクトコード」。gcc のようなコンパイラは、ソース コードをプログラムに変換するために、実際には 2 つの関連しているがほぼ間違いなく異なる機能を実行します。コンパイル (ソースをオブジェクト コードに変換することの後者の定義のように) とリンク (必要なオブジェクト コード ファイルを 1 つに結合するプロセス) です。 1 つの完全な実行可能ファイル)。

表示された元のエラーは、技術的には「リンク エラー」であり、リンカの「ld」によってスローされます。(厳密な) コンパイル時エラーとは異なり、リンカーは既にオブジェクト空間にあるため、ソース コード行への参照はありません。

デフォルトでは、gcc にソース コードが入力として与えられると、それぞれをコンパイルしてから、それらをすべてリンクしようとします。他の回答で述べたように、フラグを使用してgccに最初にコンパイルするように指示し、後でオブジェクトファイルを使用して別のステップでリンクすることができます。この 2 段階のプロセスは不必要に思えるかもしれません (おそらく非常に小さなプログラムの場合です) が、小さな変更を加えるたびにプロジェクト全体をコンパイルすると、かなりの時間を浪費する非常に大きなプログラムを管理する場合には非常に重要です。

于 2013-03-16T04:04:36.680 に答える
12

1 つのコマンドでコンパイルとリンクを行うことができます。

gcc file1.c file2.c -o myprogram

そして実行します:

./myprogram

しかし、尋ねられたように質問に答えるには、オブジェクトファイルをgcc次の場所に渡すだけです。

gcc file1.o file2.o -o myprogram
于 2013-03-15T20:53:23.720 に答える
8

foo1.c 、 foo2.c 、 foo3.c 、および makefile を 1 つのフォルダーに追加し、bash でタイプを make にします。

メイクファイルを使用したくない場合は、次のコマンドを実行できます

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
于 2016-02-15T16:04:34.417 に答える
3

.c ファイルを一連の .o ファイルと一緒にコンパイルする方法については言及されていないため、このコメントはそれを求めています。

この回答の main.c はどこにありますか? :/ file1.c がメインの場合、それを他の既にコンパイル済みの .o ファイルとどのようにリンクしますか? — トム・ブリト

$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin

ここで、main.c は main() 関数を含む C ファイルで、オブジェクト ファイル (*.o) はプリコンパイルされています。GCC はこれらを一緒に処理する方法を認識しており、それに応じてリンカーを呼び出し、最終的な実行可能ファイル (この場合は x0rbin) を生成します。

main.c で定義されていない関数を使用できますが、オブジェクト ファイル (*.o) で定義された関数への extern 参照を使用します。

オブジェクト ファイルが正しい形式 (COFF など) の場合は、.obj またはその他の拡張子を使用してリンクすることもできます。

于 2015-08-26T09:44:41.643 に答える