# [Record] Utilization of make and Makefile to build a binary ###### tags: `make`, `Makefile`, `gcc`, `hello world`, `compile`, `link` [toc] ## Introduction >In software development, Make is a build automation tool that builds executable programs and libraries from source code by reading files called makefiles which specify how to derive the target program. Though integrated development environments and language-specific compiler features can also be used to manage a build process, Make remains widely used, especially in Unix and Unix-like operating systems. > >Make can be used to manage any project where some files need to be updated automatically from others whenever the others change in addition to building programs. This page is make and Makefile hello world to show you how to use it. ## Compile and link hello world Write a c code named main.c as shown below. ```C #include <stdio.h> int main() { printf("Hello, world!\n"); return 0; } ``` And we can **compile and link** it in linux with gcc. ```bask Tomas# gcc main.c Tomas# ls -al -rwxrwxr-x 1 tomas tomas 16696 十 8 14:01 a.out -rw-rw-r-- 1 tomas tomas 76 十 8 13:32 main.c Tomas# ./a.out Hello, world! ``` After compiling it, we get a a.out, and we can execute it to get the output "Hello, world!" On the other hand, we can directly build the hello world program to the name what we like by ```bash Tomas# gcc -o hello main.c Tomas# ls -al total 52 drwxrwxr-x 2 tomas tomas 4096 十 8 14:09 . drwxr-xr-x 26 tomas tomas 4096 十 8 14:09 .. -rwxrwxr-x 1 tomas tomas 16696 十 8 14:01 a.out -rwxrwxr-x 1 tomas tomas 16696 十 8 14:09 hello -rw-rw-r-- 1 tomas tomas 76 十 8 13:32 main.c Tomas# ./hello Hello, world! ``` The usage of gcc is shown below. :::spoiler ```bash! Tomas# gcc --h Usage: gcc [options] file... Options: -pass-exit-codes Exit with highest error code from a phase. --help Display this information. --target-help Display target specific command line options. --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]. Display specific types of command line options. (Use '-v --help' to display command line options of sub-processes). --version Display compiler version information. -dumpspecs Display all of the built in spec strings. -dumpversion Display the version of the compiler. -dumpmachine Display the compiler's target processor. -print-search-dirs Display the directories in the compiler's search path. -print-libgcc-file-name Display the name of the compiler's companion library. -print-file-name=<lib> Display the full path to library <lib>. -print-prog-name=<prog> Display the full path to compiler component <prog>. -print-multiarch Display the target's normalized GNU triplet, used as a component in the library path. -print-multi-directory Display the root directory for versions of libgcc. -print-multi-lib Display the mapping between command line options and multiple library search directories. -print-multi-os-directory Display the relative path to OS libraries. -print-sysroot Display the target libraries directory. -print-sysroot-headers-suffix Display the sysroot suffix used to find headers. -Wa,<options> Pass comma-separated <options> on to the assembler. -Wp,<options> Pass comma-separated <options> on to the preprocessor. -Wl,<options> Pass comma-separated <options> on to the linker. -Xassembler <arg> Pass <arg> on to the assembler. -Xpreprocessor <arg> Pass <arg> on to the preprocessor. -Xlinker <arg> Pass <arg> on to the linker. -save-temps Do not delete intermediate files. -save-temps=<arg> Do not delete intermediate files. -no-canonical-prefixes Do not canonicalize paths when building relative prefixes to other gcc components. -pipe Use pipes rather than intermediate files. -time Time the execution of each subprocess. -specs=<file> Override built-in specs with the contents of <file>. -std=<standard> Assume that the input sources are for <standard>. --sysroot=<directory> Use <directory> as the root directory for headers and libraries. -B <directory> Add <directory> to the compiler's search paths. -v Display the programs invoked by the compiler. -### Like -v but options quoted and commands not executed. -E Preprocess only; do not compile, assemble or link. -S Compile only; do not assemble or link. -c Compile and assemble, but do not link. -o <file> Place the output into <file>. -pie Create a dynamically linked position independent executable. -shared Create a shared library. -x <language> Specify the language of the following input files. Permissible languages include: c c++ assembler none 'none' means revert to the default behavior of guessing the language based on the file's extension. Options starting with -g, -f, -m, -O, -W, or --param are automatically passed on to the various sub-processes invoked by gcc. In order to pass other options on to these processes the -W<letter> options must be used. For bug reporting instructions, please see: <file:///usr/share/doc/gcc-9/README.Bugs>. ``` ::: ## Compile and link hello world manually In a big project, it is possible to compile the source code to get many object files at one time and link them latter. For example, ```shell # Compiling gcc -c x.c gcc -c y.c gcc -c z.c # Linking gcc -o mytool x.o y.o z.o ``` Here demos a simple example. ```shell Tomas# gcc -c main.c Tomas# ls -al -rw-rw-r-- 1 tomas tomas 1680 十 8 14:17 main.o Tomas# gcc -o main main.o Tomas# ls -al -rwxrwxr-x 1 tomas tomas 16696 十 8 14:19 main -rw-rw-r-- 1 tomas tomas 76 十 8 13:32 main.c -rw-rw-r-- 1 tomas tomas 1680 十 8 14:17 main.o Tomas# ./main Hello, world! ``` ## Makefile hello world Beside, we can write a simple Makefile to build the program, too. ```bash Tomas# vi Makefile all: @echo build the hello world. gcc -o hello main.c @echo execute the hello world. ./hello clean: @echo clean all except for the source rm *.o hello ``` And now, we can build it simply by "*make*". ```bash Tomas# make build the hello world. gcc -o hello main.c execute the hello world. ./hello Hello, world! Tomas# ls -al -rwxrwxr-x 1 tomas tomas 16696 十 8 14:25 hello -rw-rw-r-- 1 tomas tomas 76 十 8 13:32 main.c -rw-rw-r-- 1 tomas tomas 99 十 8 14:25 Makefile Tomas# file hello hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b1825aad62ec89f9b5048d7a8b5371a722ee4830, for GNU/Linux 3.2.0, not stripped Tomas# readelf -a hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x1060 Start of program headers: 64 (bytes into file) Start of section headers: 14712 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 13 Size of section headers: 64 (bytes) Number of section headers: 31 Section header string table index: 30 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000000318 00000318 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.gnu.propert NOTE 0000000000000338 00000338 0000000000000020 0000000000000000 A 0 0 8 [ 3] .note.gnu.build-i NOTE 0000000000000358 00000358 0000000000000024 0000000000000000 A 0 0 4 [ 4] .note.ABI-tag NOTE 000000000000037c 0000037c 0000000000000020 0000000000000000 A 0 0 4 [ 5] .gnu.hash GNU_HASH 00000000000003a0 000003a0 0000000000000024 0000000000000000 A 6 0 8 [ 6] .dynsym DYNSYM 00000000000003c8 000003c8 00000000000000a8 0000000000000018 A 7 1 8 [ 7] .dynstr STRTAB 0000000000000470 00000470 0000000000000082 0000000000000000 A 0 0 1 [ 8] .gnu.version VERSYM 00000000000004f2 000004f2 000000000000000e 0000000000000002 A 6 0 2 [ 9] .gnu.version_r VERNEED 0000000000000500 00000500 0000000000000020 0000000000000000 A 7 1 8 [10] .rela.dyn RELA 0000000000000520 00000520 00000000000000c0 0000000000000018 A 6 0 8 [11] .rela.plt RELA 00000000000005e0 000005e0 0000000000000018 0000000000000018 AI 6 24 8 [12] .init PROGBITS 0000000000001000 00001000 000000000000001b 0000000000000000 AX 0 0 4 [13] .plt PROGBITS 0000000000001020 00001020 0000000000000020 0000000000000010 AX 0 0 16 [14] .plt.got PROGBITS 0000000000001040 00001040 0000000000000010 0000000000000010 AX 0 0 16 [15] .plt.sec PROGBITS 0000000000001050 00001050 0000000000000010 0000000000000010 AX 0 0 16 [16] .text PROGBITS 0000000000001060 00001060 0000000000000185 0000000000000000 AX 0 0 16 [17] .fini PROGBITS 00000000000011e8 000011e8 000000000000000d 0000000000000000 AX 0 0 4 [18] .rodata PROGBITS 0000000000002000 00002000 0000000000000012 0000000000000000 A 0 0 4 [19] .eh_frame_hdr PROGBITS 0000000000002014 00002014 0000000000000044 0000000000000000 A 0 0 4 [20] .eh_frame PROGBITS 0000000000002058 00002058 0000000000000108 0000000000000000 A 0 0 8 [21] .init_array INIT_ARRAY 0000000000003db8 00002db8 0000000000000008 0000000000000008 WA 0 0 8 [22] .fini_array FINI_ARRAY 0000000000003dc0 00002dc0 0000000000000008 0000000000000008 WA 0 0 8 [23] .dynamic DYNAMIC 0000000000003dc8 00002dc8 00000000000001f0 0000000000000010 WA 7 0 8 [24] .got PROGBITS 0000000000003fb8 00002fb8 0000000000000048 0000000000000008 WA 0 0 8 [25] .data PROGBITS 0000000000004000 00003000 0000000000000010 0000000000000000 WA 0 0 8 [26] .bss NOBITS 0000000000004010 00003010 0000000000000008 0000000000000000 WA 0 0 1 [27] .comment PROGBITS 0000000000000000 00003010 000000000000002b 0000000000000001 MS 0 0 1 [28] .symtab SYMTAB 0000000000000000 00003040 0000000000000618 0000000000000018 29 46 8 [29] .strtab STRTAB 0000000000000000 00003658 0000000000000202 0000000000000000 0 0 1 [30] .shstrtab STRTAB 0000000000000000 0000385a 000000000000011a 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x00000000000002d8 0x00000000000002d8 R 0x8 INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318 0x000000000000001c 0x000000000000001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x00000000000005f8 0x00000000000005f8 R 0x1000 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x00000000000001f5 0x00000000000001f5 R E 0x1000 LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000 0x0000000000000160 0x0000000000000160 R 0x1000 LOAD 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8 0x0000000000000258 0x0000000000000260 RW 0x1000 DYNAMIC 0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8 0x00000000000001f0 0x00000000000001f0 RW 0x8 NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338 0x0000000000000020 0x0000000000000020 R 0x8 NOTE 0x0000000000000358 0x0000000000000358 0x0000000000000358 0x0000000000000044 0x0000000000000044 R 0x4 GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338 0x0000000000000020 0x0000000000000020 R 0x8 GNU_EH_FRAME 0x0000000000002014 0x0000000000002014 0x0000000000002014 0x0000000000000044 0x0000000000000044 R 0x4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 GNU_RELRO 0x0000000000002db8 0x0000000000003db8 0x0000000000003db8 0x0000000000000248 0x0000000000000248 R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 03 .init .plt .plt.got .plt.sec .text .fini 04 .rodata .eh_frame_hdr .eh_frame 05 .init_array .fini_array .dynamic .got .data .bss 06 .dynamic 07 .note.gnu.property 08 .note.gnu.build-id .note.ABI-tag 09 .note.gnu.property 10 .eh_frame_hdr 11 12 .init_array .fini_array .dynamic .got Dynamic section at offset 0x2dc8 contains 27 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x1000 0x000000000000000d (FINI) 0x11e8 0x0000000000000019 (INIT_ARRAY) 0x3db8 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x3dc0 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x3a0 0x0000000000000005 (STRTAB) 0x470 0x0000000000000006 (SYMTAB) 0x3c8 0x000000000000000a (STRSZ) 130 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000003 (PLTGOT) 0x3fb8 0x0000000000000002 (PLTRELSZ) 24 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x5e0 0x0000000000000007 (RELA) 0x520 0x0000000000000008 (RELASZ) 192 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000000000001e (FLAGS) BIND_NOW 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE 0x000000006ffffffe (VERNEED) 0x500 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x4f2 0x000000006ffffff9 (RELACOUNT) 3 0x0000000000000000 (NULL) 0x0 Relocation section '.rela.dyn' at offset 0x520 contains 8 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003db8 000000000008 R_X86_64_RELATIVE 1140 000000003dc0 000000000008 R_X86_64_RELATIVE 1100 000000004008 000000000008 R_X86_64_RELATIVE 4008 000000003fd8 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0 000000003fe0 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 000000003fe8 000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 000000003ff0 000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0 000000003ff8 000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x5e0 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend 000000003fd0 000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported. Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000318 0 SECTION LOCAL DEFAULT 1 2: 0000000000000338 0 SECTION LOCAL DEFAULT 2 3: 0000000000000358 0 SECTION LOCAL DEFAULT 3 4: 000000000000037c 0 SECTION LOCAL DEFAULT 4 5: 00000000000003a0 0 SECTION LOCAL DEFAULT 5 6: 00000000000003c8 0 SECTION LOCAL DEFAULT 6 7: 0000000000000470 0 SECTION LOCAL DEFAULT 7 8: 00000000000004f2 0 SECTION LOCAL DEFAULT 8 9: 0000000000000500 0 SECTION LOCAL DEFAULT 9 10: 0000000000000520 0 SECTION LOCAL DEFAULT 10 11: 00000000000005e0 0 SECTION LOCAL DEFAULT 11 12: 0000000000001000 0 SECTION LOCAL DEFAULT 12 13: 0000000000001020 0 SECTION LOCAL DEFAULT 13 14: 0000000000001040 0 SECTION LOCAL DEFAULT 14 15: 0000000000001050 0 SECTION LOCAL DEFAULT 15 16: 0000000000001060 0 SECTION LOCAL DEFAULT 16 17: 00000000000011e8 0 SECTION LOCAL DEFAULT 17 18: 0000000000002000 0 SECTION LOCAL DEFAULT 18 19: 0000000000002014 0 SECTION LOCAL DEFAULT 19 20: 0000000000002058 0 SECTION LOCAL DEFAULT 20 21: 0000000000003db8 0 SECTION LOCAL DEFAULT 21 22: 0000000000003dc0 0 SECTION LOCAL DEFAULT 22 23: 0000000000003dc8 0 SECTION LOCAL DEFAULT 23 24: 0000000000003fb8 0 SECTION LOCAL DEFAULT 24 25: 0000000000004000 0 SECTION LOCAL DEFAULT 25 26: 0000000000004010 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 29: 0000000000001090 0 FUNC LOCAL DEFAULT 16 deregister_tm_clones 30: 00000000000010c0 0 FUNC LOCAL DEFAULT 16 register_tm_clones 31: 0000000000001100 0 FUNC LOCAL DEFAULT 16 __do_global_dtors_aux 32: 0000000000004010 1 OBJECT LOCAL DEFAULT 26 completed.8061 33: 0000000000003dc0 0 OBJECT LOCAL DEFAULT 22 __do_global_dtors_aux_fin 34: 0000000000001140 0 FUNC LOCAL DEFAULT 16 frame_dummy 35: 0000000000003db8 0 OBJECT LOCAL DEFAULT 21 __frame_dummy_init_array_ 36: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.c 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 38: 000000000000215c 0 OBJECT LOCAL DEFAULT 20 __FRAME_END__ 39: 0000000000000000 0 FILE LOCAL DEFAULT ABS 40: 0000000000003dc0 0 NOTYPE LOCAL DEFAULT 21 __init_array_end 41: 0000000000003dc8 0 OBJECT LOCAL DEFAULT 23 _DYNAMIC 42: 0000000000003db8 0 NOTYPE LOCAL DEFAULT 21 __init_array_start 43: 0000000000002014 0 NOTYPE LOCAL DEFAULT 19 __GNU_EH_FRAME_HDR 44: 0000000000003fb8 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_ 45: 0000000000001000 0 FUNC LOCAL DEFAULT 12 _init 46: 00000000000011e0 5 FUNC GLOBAL DEFAULT 16 __libc_csu_fini 47: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 48: 0000000000004000 0 NOTYPE WEAK DEFAULT 25 data_start 49: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5 50: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 25 _edata 51: 00000000000011e8 0 FUNC GLOBAL HIDDEN 17 _fini 52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 53: 0000000000004000 0 NOTYPE GLOBAL DEFAULT 25 __data_start 54: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 55: 0000000000004008 0 OBJECT GLOBAL HIDDEN 25 __dso_handle 56: 0000000000002000 4 OBJECT GLOBAL DEFAULT 18 _IO_stdin_used 57: 0000000000001170 101 FUNC GLOBAL DEFAULT 16 __libc_csu_init 58: 0000000000004018 0 NOTYPE GLOBAL DEFAULT 26 _end 59: 0000000000001060 47 FUNC GLOBAL DEFAULT 16 _start 60: 0000000000004010 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 61: 0000000000001149 27 FUNC GLOBAL DEFAULT 16 main 62: 0000000000004010 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 64: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2 Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 1 ( 50.0%) 100.0% Version symbols section '.gnu.version' contains 7 entries: Addr: 0x00000000000004f2 Offset: 0x0004f2 Link: 6 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 004: 0 (*local*) 0 (*local*) 2 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 1 entry: Addr: 0x0000000000000500 Offset: 0x000500 Link: 7 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2 Displaying notes found in: .note.gnu.property Owner Data size Description GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 Properties: x86 feature: IBT, SHSTK Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: b1825aad62ec89f9b5048d7a8b5371a722ee4830 Displaying notes found in: .note.ABI-tag Owner Data size Description GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 3.2.0 ``` ## Advanced Makefile with a library Assume we are going to build an application together with a library mylib which can be a static or a dynamic library. ```shell # # 'make depend' uses makedepend to automatically generate dependencies # (dependencies are added to end of Makefile) # 'make' build executable file 'mycc' # 'make clean' removes all .o and executable files # # define the C compiler to use CC = gcc # define any compile-time flags CFLAGS = -Wall -g # define any directories containing header files other than /usr/include # INCLUDES = -I/home/tomas/include -I../include # define library paths in addition to /usr/lib # if I wanted to include libraries not in /usr/lib I'd specify # their path using -Lpath, something like: LFLAGS = -L/home/tomas/lib -L../lib # define any libraries to link into executable: # if I want to link in libraries (libx.so or libx.a) I use the -llibname # option, something like (this will link in libmylib.so: LIBS = -lmylib -lm # define the C source files SRCS = main.c # define the C object files # # This uses Suffix Replacement within a macro: # $(name:string1=string2) # For each word in 'name' replace 'string1' with 'string2' # Below we are replacing the suffix .c of all words in the macro SRCS # with the .o suffix # OBJS = $(SRCS:.c=.o) # define the executable file MAIN = hello # # The following part of the makefile is generic; it can be used to # build any executable just by changing the definitions above and by # deleting dependencies appended to the file from 'make depend' # .PHONY: depend clean all: $(MAIN) @echo Simple application named hello has been compiled $(MAIN): $(OBJS) $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS) # this is a suffix replacement rule for building .o's from .c's # it uses automatic variables $<: the name of the prerequisite of # the rule(a .c file) and $@: the name of the target of the rule (a .o file) # (see the gnu make manual section about automatic variables) .c.o: $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ clean: $(RM) *.o *~ $(MAIN) depend: $(SRCS) makedepend $(INCLUDES) $^ # DO NOT DELETE THIS LINE -- make depend needs it ``` ## Reference https://en.wikipedia.org/wiki/Make_(software) https://blog.gtwang.org/programming/gcc-comipler-basic-tutorial-examples/ https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_makefiles.html https://hackmd.io/@TomasZheng/ByLACT1Wp