Cプログラムを実行しようとすると、Makefileは失敗します。

Cプログラムを実行しようとすると、Makefileは失敗します。

Makefileの作成にはたくさんありますが、次のファイルがあります。

https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/boo.c
https://github.com/systems-cs-pub-ro/uso/raw/master/tema1/light.o
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.c 
https://raw.githubusercontent.com/systems-cs-pub-ro/uso/master/tema1/sound.h

Makefileを作成する必要があります。 「実行ファイルを生成execし、light.o以前の実装のsound.oコンパイル時に生成しますsound.c。コマンドを受け取るか、makeファイルmake buildを生成する必要があります。必要に応じて、プログラム全体に準拠したexecMakefileにルールを追加し、作成したオブジェクトファイルを削除するルールを追加しますrun。実行します。また、コンパイル後に中間ファイル(、)を生成するルールを追加します。cleantemplatesboo.sboo.oboo.c

これは私のメイクファイルです。

build: light.o sound.o
        gcc light.o sound.o -o exec
sound.o: sound.c
        gcc -c sound.c
templates: boo.c
        gcc -c boo.c
        gcc -S boo.c
run: exec
     ./exec
clean:
      rm -f sound.o boo.o boo.s exec

ただし、「正しい」実行可能ファイルを作成していないというメッセージが表示されます。私が何を間違っているのでしょうか?私はboo.oexecファイルに追加する必要があると思いますが、そうしようとすると次のような結果が表示されますboo.c multiple definition of main light.o:light.c:first defined here

答え1

(宿題のように聞こえますね。)

まずエラーメッセージ:

boo.c multiple definition of main
light.o:light.c:first defined here.

これは、リンクするファイルに名前が付けられた関数のコピーが複数あることを意味します。main()これは明らかに間違っています。

を再利用しようとしていlight.oますが、それ以外の機能がある場合にのみ実際に機能しますmain()。ただそう呼んでくださいlight()。また、コンパイラがソースコードを表示せずに関数の属性(デフォルトではパラメータ型と戻り値型)を知ることができるように.hファイル#includedが必要です。boo.clight()

私が見ると、あなたのファイルが課題で予想したものとは少し異なるように構成されているようです。教授が一連の相互接続された課題を作成した可能性があります。シリーズの以前の課題からショートカットを選択すると、以前の課題のコードを再利用する後続の課題は正しく機能しません。

教授は、再利用できるようにコードを配置する方法と、そうでなければどうなるかを教えようとします。

Makefile ルールの基本形式は次のとおりです。

<name of target>: <names of files the creation process depends on>
        <command(s) to create the target file>

ファイルの作成は、.cファイル自体だけでなく、.hファイルに含まれるファイルによっても異なります。通常、システムにはファイルが含まれていると想定できます(含まれるファイルは#include <filename>変更されないため、Makefileルールに追加する必要はありません)。ただし、.hプロジェクトの一部であるすべてのファイルも含める必要があります。 。

実際にはファイルではなく「仮想ターゲット」があるかもしれません。同様のことができますmake clean。仮想ターゲットを他のターゲットの依存関係として使用することもできます。仮想ターゲットには接続された物理ファイルがないため、仮想ターゲットが何かへの依存関係としてリストされるたびに、仮想ターゲットを「生成」するコマンドが実行されます。他のものを構築する必要があります。

また、コマンドは含まれていませんが、1つ以上のMakefileターゲットを依存関係としてリストするMakefileルールがある可能性があります。依存関係が1つしかない場合、コマンドを持たないターゲットは、依存関係としてリストされているターゲットの別の名前として機能します。依存関係が複数ある場合、コマンドレスターゲットは、単一のコマンドを使用して複数のMakefileターゲットを構築する方法になります。

build:教授は自分の指示なしに対象を作りたいと思っているようです。これは2つの目標にのみ依存する必要があります。

  • 実際の実行可能ファイルをビルドする別のターゲット
  • templates目標

light.oソースコードを見ずにこれが何であるかをどうやって知ることができるのか疑問に思います。簡単 - 私はあなたのものをダウンロードし、light.o次のコマンドを使用しました。

$ readelf -s light.o

Symbol table '.symtab' contains 12 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS light.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 SECTION LOCAL  DEFAULT    7 
     7: 00000000     0 SECTION LOCAL  DEFAULT    8 
     8: 00000000     0 SECTION LOCAL  DEFAULT    6 
     9: 00000000    51 FUNC    GLOBAL DEFAULT    1 main
    10: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND puts
    11: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND sound

light.oこれは、という名前のソースファイルで、light.cという関数が定義され、ここで定義されていないという関数をmain()使用していることを示します。標準ライブラリで提供されていますが、完全な実行可能ファイルを形成するには、このファイルに関連付けられている他のファイルで定義する必要があります。puts()sound()puts()sound()

関連情報