埋め込み Linux エントリ gcc と makefile の 2 つの共通構文

GCCコンパイラ

コンパイルプロセス

GCC がプロジェクトをコンパイルするとき、それは 4 つのステップに分かれています: 前処理、コンパイル、アセンブル、およびリンク. もちろん、日常生活でよく使用されるコンパイルはこれら 4 つのステップと総称されます. 使用される対応する GCC 命令は次のとおりです:
1

一般的なコンパイル オプション

  • -E は前処理ステップのみを実行し、前処理されたソース コードを標準出力に出力します。> によってファイルにリダイレクトでき、「-E -dM」オプションの組み合わせを使用して、ファイル内で使用されているすべてのマクロ定義を出力します。表示値
  • -c 前処理、コンパイル、アセンブリを実行しますが、リンクは実行しません
  • -o は出力ファイルを指定します
  • -I (大文字の i) は、インクルードするヘッダー ファイル ディレクトリを指定します。
  • -L は、リンク時に検索するライブラリ ファイルのディレクトリを指定します。このディレクトリは、-l (L 小文字) オプションを追加すると有効になります。
  • -l (小文字の L) は、リンクするライブラリ ファイルを指定します。このファイルは、デフォルトのディレクトリおよび -L オプションで指定されたディレクトリで検索されます。

複数のファイルをコンパイルする方法

  • 各ファイルの .o ファイルは gcc -c を使用して個別にコンパイルでき、その後 gcc はリンク用に複数の .o ファイルを渡します (一般的に makfile で使用されます)。
  • 複数のソース ファイルを直接渡すことができ、gcc は自動的にコンパイルとリンクを行います (メイクファイルを使用せずに小さなプロジェクトをコンパイルするときに使用できます)。

ダイナミックリンクライブラリを利用する

  • 作る

    gcc -c -o main.o main.c #先生成主程序的.o文件
    gcc -c -o sub.o sub.c #要生成动态链接库的.o文件
    gcc -shared -o libsub.so sub.o #生成动态链接库,这里可以使用多个.o文件生成一个库
    
    # 使用-l来传入动态链接库,动态链接库的文件名为lib<libraryname>.so,传入时只需要传入<libraryname>这一部分,比如希望链接libsub.so文件,则传入-lsub
    # 使用-L dir来传入搜寻库文件时指定要搜索的目录,比如希望搜索/home/usr/则传入 -L /home/usr
    gcc -o test main.o -lsub -L <so文件所在目录>
    
  • 実行
    ダイナミック リンク ライブラリ ファイルをシステムの /lib ディレクトリまたは /usr/lib ディレクトリに配置します。これら 2 つは Linux のデフォルトのライブラリ ファイル検索ディレクトリであり、特定のディレクトリに配置してから実行することもできます。次のコマンド:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/myso #将/myso目录添加到系统链接库搜寻目录,注=两边不能有空格
    

    これにより、ダイナミック リンク ライブラリを参照する実行可能ファイルを順番に実行できるようになります。

静的にリンクされたライブラリを利用する

  • 作る

    gcc -c -o main.o main.c #先生成主程序的.o文件(和动态库步骤一致)
    gcc -c -o sub.o sub.c #要生成静态链接库的.o文件
    ar crs libsub.a sub.o #生成静态链接库,这里可以使用多个.o文件生成一个库
    
    # 如果静态链接库不在当前目录下,需要指定他的绝对路径或相对路径,比如假设库在当前目录的mylib目录下
    gcc -o test main.o ./mylib/libsub.a
    # 当然也可以跟链接动态库一样操作
    # 使用-l来传入静态链接库,动态链接库的文件名为lib<libraryname>.a,传入时只需要传入<libraryname>这一部分,比如希望链接libsub.a文件,则传入-lsub
    # 使用-L dir来传入搜寻库文件时指定要搜索的目录,比如希望搜索./mylib则传入 -L ./mylib
    gcc -o test main.o -lsub -L ./mylib
    
  • 使用方法
    通常の実行ファイルと同様に、スタティックリンクライブラリも実行ファイルに直接埋め込むことになりますが、当然プログラムサイズの増加にもつながります

その他の一般的なオプション

# -Wp,-MD这个选项到底意味着什么?不明白
gcc -Wp,-MD,abc.dep -c -o main.o main.c # 生成依赖文件abc.dep,makefile中会用到

メイクファイル

簡単な紹介

make コマンドは、コンパイル速度を向上させるために、すべてのファイルをコンパイルするのではなく、メイクファイル内のルールを読み取り、変更されたソース コードを再コンパイルします。

メイクファイル形式

target : prerequiries
	command

メイクファイル本体は上記の形式で構成されており、前提条件の変更時期が目標より遅い場合、または対象ファイルが存在しない場合にコマンド文が実行されます。

コマンドを作成する

make コマンドを実行すると、デフォルトで make は現在のディレクトリで Makefile という名前のファイルを検索し、最初に見つかったターゲットを生成します。make コマンドの一般的なオプションは次のとおりです。

make -f Makefile.build # 使用 -f 选项指定要读取的文件名
make -C /dir # 使用 -C 选项指定要切换到的目录
make other_target # 可以指定从makefile文件内的特定target开始执行

メイクファイル変数

Makefile で変数を定義するには、次のメソッドを使用できます。Makefile の変数の本質は、エイリアス化された文字列です。

VER1 := 123     // 定义即时变量VER1并赋值常量123
VER2 ?= ${VER1} // 定义延时变量VER2并赋值VER1变量的值
VER3 = ${VER2}  // 定义延时变量VER3并赋值VER2变量的值

変数は ${var_name} または $(var_name) の形式で参照できます。変数は即時変数と遅延変数の 2 種類に分けられます。これらの違いは主に変数値を決定する時点に反映されます。おおよそ次のようになります。

  • インスタント変数
    インスタント変数の値は、Makefile が解析されるときに決定されます。次の例では、インスタント変数 VER2 が定義されており、その値は VER1 の値です。Makefile は VER2 に解析するため、VER1 の値は 10 です, そのため、後で VER1 が 20 に再割り当てされても、VER2 の値は 10 のままになり、VER2 の値は更新されなくなります。

    VER1 := 10
    VER2 := ${VER1}
    VER1 := 20
    
    all :
    	echo VER2 //打印结果为10
    
  • 遅延変数
    遅延変数の値は使用時に決定されます。次の例では、遅延変数 VER2 が定義されており、その値は VER1 の値です。Makefile は VER2 に解析しますが、VER1 の値は 10 です。ただし、VER2 を使用すると、変数を使用するときに VER1 が 20 に再割り当てされるため、使用時に VER2 を展開して得られる値は 20 になります。

    VER1 := 10
    VER2 = ${VER1}
    VER1 := 20
    
    all :
    	echo VER2 //打印结果为20
    

いくつかの特別な事前定義変数もあります

test : a.o b.o c.o
	echo $@ //目标的名字,会打印 all
	echo $^ //构建所需文件列表的所有文件名字,会打印 a.o b.o c.o
	echo $< //构建所需文件列表中第一个文件的名字,会打印 a.o
	echo $? / 构建所需文件列表中更新过的文件,打印所有修改时间比test晚的文件

メイクファイルの共通関数

関数の形式: ${function_name param1,param2,parma3,…} または $(function_name param1,param2,parma3,…)

関数名とパラメータはスペースで区切られ、複数のパラメータはカンマで区切られます。

  • ${foreach var,list,text} は、
    リスト内の要素を走査して var に代入し、text で記述された形式で var を変更します。

    obj := a.o b.o
    dep_files := ${foreach f, ${obj}, ${f}.d} // 最终 dep_files := a.o.d b.o.d
    
  • ${wildcard pattern}
    指定されたパターン形式に一致する現在のディレクトリ内のすべてのファイルを検索します

    src_files := ${wildcard *.c} //找出当前目录下所有.c结尾的文件并赋值给src_files
    // 假设当前目录下存在文件 a.c b.c d.c,则执行后 src_files := a.c b.c d.c
    
  • ${filter pattern...,text} は、
    パターン形式に一致するテキスト内のすべてのフィールドを保持します。スペースで区切られた複数のパターンが存在する可能性があり、任意のパターンに一致するフィールドが予約されます。

    obj := a.c b.c d.c a/ b/ c/
    DIR := ${filter %/, ${obj}} //运行结果 DIR := a/ b/ c/
    
  • ${filter-out pattern..., text} は、
    パターン形式に一致するテキスト内のすべてのフィールドを除外します。スペースで区切って複数のパターンを指定することができ、任意のパターンに一致するフィールドは除外されます

    obj := a.c b.c d.c a/ b/ c/
    src := ${filter-out %/, ${obj}} //运行结果 src := a.c b.c d.c
    
  • ${patsubst pattern, replace, text} は、
    形式パターンに一致するテキスト内のフィールドを検索し、それらを置換によって示される形式に変換します。

    subdir := c/ d/
    subdir := ${patsubst %/ %, ${subdir}} //变换结果为subdir := c d
    

その他の知識ポイント

  • 変数のエクスポートMakefile A が Makefile B を呼び出すときに、Makefile A の変数を Makefile B で表示したい場合は、次のように
    、export コマンドを使用して変数をエクスポートできます。

    VER := hello
    export VER
    
    all :
    	make -f ./sub_makefile // 在sub_makefile中可以直接使用VER变量
    
  • シェルコマンドの実行
    Makefile内でシェルコマンドを直接実行できます。

    TOPDIR := ${shell pwd} // 执行shell指令pwd并将返回的结果赋值给变量TOPDIR
    
  • 最初のターゲットを設定する
    Make は、デフォルトで Makefile の最初のターゲットから実行されます。場合によっては、実行を開始したいターゲットをファイルの先頭に置いて「宣言」し、後で改善することもできます。

    First_target : //什么都不干
    
    ... //执行一些其他操作:包含其他makefile、声明变量、编写其他目标等
    
    First_target : ${xxx} ${yyy} // 目标本体
    	command
    
  • 仮想ターゲット
    .PHONY を使用してターゲットを仮想ターゲットとして設定します。ターゲット ファイルが存在するかどうかに関係なく、ターゲットが実行されると、ターゲット内のコマンドが常に実行されます。

    .PHONY : clean
    clean : 
    	rm -f ${shell find -name "*.o"}
    	rm -f ${TARGET}
    

通用Makefile

Wei Dongshan 氏のチュートリアル資料から抜粋したもので、サンプルと手順が含まれているので、自分で試すことができ、Makefile にあまり時間をかける必要はありません。

リンク:汎用メイクファイル

抽出コード:vjbj

おすすめ

転載: blog.csdn.net/lczdk/article/details/123569125