3. GNU Make image/svg+xml 3. GNU Make Zidarics Zoltánzamek@vili.pmmf.hu 2020 EmbeddedProgramming 2. git 4. Testing GNU Make Task compile automation lifecycle management automating repetitive tasks providing portability Compile automation all required files for a project must be compiled individually by configuration, some modules are not required compiled modules need to be linking one project needs to be translated on multiple platforms Linux kernel ~30 processzor archtitecture drivers system fine tuning system resources 23437 .c & 18018 .h file 15836728 code lines (4.8.0-rc5) make config; make; make install only re-compile necessary/modified files Lifecycle management deployment functions git management (generating desired versions) managing user configurations (patching) compiling to a specific platform management of installation files handling config files Automate repetitive tasks for embedded systems compile, flash, debug cycles managing patches automation of backups and conversions automated generation of file system handling config files for embedded Linux systems "If you need to do a job more than once  execute, make it a make rule! " Providing portability the destination computer does not have an IDE, maybe even a graphical interface (embedded Linux) command line compilation use of conventional rules(make config; make; make install) GNU Make Make original by Stuart Feldman (1977) https://www.gnu.org/software/make/ disadvantages GNU Make: Richard M. Stallman and Roland McGrath greatly builds the host operating systemadvanced command line capabilities, so on Windowshard to use (win10-bash?) if the required module header and lib files do not existinstalled on the target computer, you cannot handle thisthe state. (Automake) demo Operation Makefile is the control file in the project directory each task is called a rule: what: from→ how mp3player: controller.o file.o media.o→ gcc -o mp3player controller.o file.o media.o controller.o: controller.c→ gcc -c controller.c -o controller.o -Wall -g -pedantic --std=c99 file.o:file.c→ gcc -c file.c -o file.o -Wall -g -pedantic --std=c99 media.o:media.c→ gcc -c media.c -o media.o -Wall -g pedantic --std=c99  "what" is called a target by defaultconsiders it a file, but it can also be an activity (install, clean) a rule usually contains one goal the "from" element is called prerequisites the "how" element is called a recipe,a recipe can contain multiple commands.Note that at least one command is required before each commandtab character (→) run make command to execute Makefile in the given directory. if it is not Makefile, make -f <makefilename> if you do not specify the desired target, execute the default target(first goal of the first rule in the Makefile order) determining the need for compilation if the target file date is earlier than the associated prerequisite file date, it will automatically attempt to targetexecute (searches for a rule) e.g. the programmer modified file.c but nothing else 1. file.o, controller.o and media.o are prerequisites for mp3player2. file.o exists? if it doesn't compile, if it does, it will only compile if file.o date is earlier than file.c3. controller.o exists? if not compile, if yes then compiles only if controller.o date is earlier than controller.c4. media.o exists? if it doesn't compile, if it does, it only compiles if media.o date is earlier than media.c5. mp3player exists? if you don't create it, if you do, you only create it if any .o file has a date later than the mp3player if the source files are not changed and the .o and mp3player files exist, they will exit without action you can specify multiple goals at once:make clean compile install Makefile structure notes # variable definitions directives explicit and implicit rules Variable definitions variables are always string type they are for text substitution pl. CFLAGS = -Wall -g -pedantic --std=c99 before the variable name and = on both sidesdeletes any whitespace characters the variable name is case sensitive variable can be referred to as $(name) or ${name} # Makefile for mp3player CFLAGS=-Wall -g -pedantic --std=c99 mp3player: controller.o file.o media.o→ gcc -o mp3player controller.o file.o media.o controller.o: controller.c→ gcc -c controller.c -o controller.o $(CFLAGS) file.o:file.c→ gcc -c file.c -o file.o $(CFLAGS) media.o:media.c→ gcc -c media.c -o media.o $(CFLAGS)  variable definition may include other variable references # Makefile for mp3player  ARCH=arm BINARY_DIR=bin OBJ_DIR=$(BINARY_DIR)/$(ARCH)/obj #bin/arm/objEXEC_DIR=$(BINARY_DIR)/$(ARCH)/executable #bin/arm/executable  the referenced variable is replaced onlyif you use the variable in a rule Automatic variables $@ is the target value for the current rule $< is the value of the first prerequisite of the current rule $? a space-separated list of new prerequisites for the current rule's purpose $^ is a space-separated list of preconditions for the current rule For $+ as $^, any duplicate items are listed only once $(@D) is the directory component of the current rule's target, with / without the closing $(@F) is the filename component of the target for the current rule $(<F) is the file name component of the first prerequisite of the current rule $(^F) is a list of all filenames for the prerequisites of the current rule $(+D) is a directory list of all prerequisites for the current rule, including duplicate elements $(?D) is the directory component of newer prerequisites for the current rule than the target $(<D) is the directory component of the first prerequisite of the current rule $(^D) is a directory list of all prerequisites for the current rule $(+F) is a list of all filenames for the current rule, including duplicate elements $(?F) is the filename component of newer prerequisites for the current rule than the target directives specifications for special activities including another Makefile conditional execution defining multi-row variables Explicit rules is a rule that describes when and how to create onemultiple files based on the goals assigned to them. controller.o: controller.c→ gcc -c controller.c -o controller.o -Wall -g -pedantic --std=c99 Implicit rules rules that are used to create goals that fit a specific pattern AR Archive maintenance program (library management) e.g. For C translation we can give an implicit rule: "all .o files from the associated .c filecan be made such that gcc -c% .c -o% .o %.o: %.c→ gcc -c $< -o $@ -Wall -g -pedantic --std=c99 there are built-in implicit rules for different programming languagesfor translation (C, C ++, Pascal, Fortran, Ratfor, etc.) predefined variables that can be used in implicit rules AS Assembler translation program CC C compiler (gcc on linux) CXX C ++ compiler (g ++ on linux) CPP C preprocessor program (linuxon cpp) RM on this operating system file delete command (linuxon rm -rf) ARFLAGS is the arguments for the ar command. default: rv CFLAGS arguments to be passed to the C compiler CXXFLAGS arguments to be passed to the C++ compiler CPPFLAGS arguments to be passed to preprocessor C LDFLAGS is the lib file directory argument to be passed to the C linker LDLIBS is the lib file argument to be passed to the C linker Using Variables variable names cannot contain # = or whitespace characters named variables that begin with a dot and continue in capital letters are special make variables two flavor of variables recursive simple variable names are case sensitive. lower case letters are recommended instead of old conventions reference to the variable in the form $(name) or ${name} operating system environment variables automaticallyare converted to make variables Recursive variable extraction assignment = with operator extraction at use, following variable references foo=$(bar)bar=$(ace)ace=Hello world $(info foo:$(foo), bar:$(bar), ace:$(ace)) result:foo:Hello world, bar:Hello world, ace:Hello world  the order of the definitions is irrelevant a recursive variable cannot be in the same assignmenton both sides of the = signal (infinite loop) $(foo)=$(foo) gargleblaster since variables are expressed at use, recursive variablesthey slow down by referring to them several times Simple variable extraction value assignment := or ::= operator extraction in the definition x:=fooy:=$(x) bar $(z)x:=later $(info x:$(x), y:$(y)) result:x:later, y:foo bar the order of the definitions is relevant faster operation redefine variables!   Additional value assigning operators ?= conditional assignment += append if the variable is undefined, it is populated with the right expression foo:=bar foo?=not bar ace?=hello world $(info foo:$(foo), ace:$(ace)) result:foo:bar, ace:Hello world    equivalent to: ifeq ($(origin foo), undefined) foo := not barendif    appends the value of the right expression to the content of a variable foo:=bar foo+=ace $(info foo:$(foo)) result:foo bar    Define multi-row variables define two-lines=echo fooecho $(bar)endef      can also be used in a recipe: two-lines= echo foo; echo $(bar)      foo:=foobar=bar undefine fooundefine bar $(info foo:$(origin foo), bar:$(flavor bar)) result:foo:undefined, bar:undefined      Elimination of variables undefine name Special variables make fills up them MAKEFILELIST is a list of all Makefiles read by make .DEFAULT_GOAL contains the default target, can be modified MAKE_RESTARTS only exists if a given instance of make is restarted .VARIABLES is a list of all defined global variables .INCLUDE_DIRS is a directroy list of other Makefiles encoded by make .FEATURES is a list of extra features provided by make Conditions make run control based on conditions libs_for_gcc = -lgnunormal_libs = foo: $(objects)ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc)else $(CC) -o foo $(objects) $(normal_libs)endif  syntax: conditional-directivetext-if-trueelsetext-if-falseendif usable forms: ifeq (arg1, arg2)ifeq 'arg1' 'arg2'ifeq "arg1" "arg2"ifeq "arg1" 'arg2'ifeq 'arg1' "arg2"ifneq (arg1, arg2)ifneq 'arg1' 'arg2'ifneq "arg1" "arg2"ifneq "arg1" 'arg2'ifneq 'arg1' "arg2"ifdef variableifndef variable Text transformation functions comma:=,empty:=space:=$(empty) $(empty)foo:=a b cbar:=$(subst $(space), $(comma),$(foo)) result: a,b,c built-in functions for text transformations syntax: $(function arguments)or${function arguments} arguments with space separated from function name bysome arguments separated by commas arguments may include additional function calls subst() comma:=,empty:=space:=$(empty) $(empty)foo:=a b cbar:=$(subst $(space), $(comma),$(foo)) result: a,b,c Replace text in a variable syntax: $(subst from,to,text) patsubst() $(patsubst %.c,%.o, modulea.c moduleb.c) result: module.o moduleb.o locates in a whitespace-separated list (text)a pattern and a replacement syntax: $(patsubst pattern,replacement,text) if you include the% character in the sample and in the replacement,then the replacement will cover the portion of the sample selected by%replacing strip() $(info strip " a b c " is:[$(strip a b c ))result: strip a b c is:[a b c] deletes the leading and trailing whitespace characters from the string.more than one whitespace in the text is being replaced syntax: $(strip string) findstring() $(info find a in a b c is: $(findstring a,a b c))$(info find q in a b c is: $(findstring q,a b c))result:find a in a b c is:afind q in a b c is:   looks for the find pattern in the text. If exists,returns with find, if not, with an empty string syntax: $(findstring find,in) filter() source := foo.c bar.c baz.s ugh.h$(info filter %.c %.s in $(source) is: $(filter, %.c %.s, $(source))) result: filter %.c %.s in foo.c bar.c baz.s ugh.h is: foo.c bar.c baz.s   returns text that matches the pattern in the text. Ifpattern contains% characters, then described in patsubst ()works syntax: $(filter pattern...,text) filter-out() source := foo.c bar.c baz.s ugh.h$(info filter-out %.c %.s in $(source) is: $(filter-out, %.c %.s, $(source))) result: filter-out %.c %.s in foo.c bar.c baz.s ugh.h is: ugh.h   returns text that does not match the pattern in the text. Ifpattern contains% characters, then described in patsubst ()works syntax: $(filter-out pattern...,text) $(info sort of loose foo bar foo is: $(sort loose foo bar foo)) result: sort of loose bar foo is: bar foo loose   sort() sort text in the list, remove duplicate items syntax: $(sort list) word() $(info word,2,foo bar baz is:$(word,2,foo bar baz))$(info word,4,foo bar baz is:$(word,4,foo bar baz))$(info word,0,foo bar baz is:$(word,0,foo bar baz)) result: word,2,foo bar baz is:barword,4,foo bar baz is:word,0,foo bar baz is:   gives back nth. word of the text. The minimum value of n is 1. syntax: $(word n,text) if n is greater than the number of words, it returns an empty string. wordlist() $(info wordlist 2,3, foo bar baz is:$(wordlist 2,3, foo bar baz))$(info wordlist 5,3, foo bar baz is:$(wordlist 5,3, foo bar baz))$(info wordlist 2,5, foo bar baz is:$(wordlist 2,5, foo bar baz))$(info wordlist 2,0, foo bar baz is:$(wordlist 2,0, foo bar baz)) result: wordlist 2,3, foo bar baz is:bar bazwordlist 5,3, foo bar baz is:wordlist 2,5, foo bar baz is:bar bazwordlist 2,0, foo bar baz is:     gives back the words from 's' to 'e' in text. minimal value of 's' is 1. syntax: $(wordlist s,e,text) the minimum value of 'e' can be 0. if 's' is greater than the number of wordsor 's' greater than this, returns an empty string. if 'e' is greater than the number of words, it returns it to the end of the listthe words $(info words foo bar baz is:$(words foo bar baz)) result: words foo bar baz is:3     words() returns the number of words in the text text. syintax: $(words text) firstword() $(info firstword foo bar baz is:$(firstword foo bar baz)) result: firstword foo bar baz is:foo     returns the first word in the names list. syntax: $(firstword names...) lastword() $(info lastword foo bar baz is:$(lastword foo bar baz)) result: lastword foo bar baz is:foo     returns the last word in the names list. syntax: $(lastword names...) dir() $(info dir of ~/.bashrc is:$(dir $(HOME)/.bashrc)) result: dir of ~/.bashrc is:/home/zamek     returns the directory element of the names filelist. syntax: $(dir names...) notdir() $(info notdir of ~/.bashrc is:$(notdir $(HOME)/.bashrc)) result: notdir of ~/.bashrc is:.bashrc     returns the file-name element of the names file list. syntax: $(notdir names...) suffix() $(info suffix of src/foo.c src-1.0/bar.c hacks is: $(suffix src/foo.c src-1.0/bar.c hacks)) result: suffix of src/foo.c src-1.0/bar.c hacks is: .c .c     returns the extension of the elements in the names list syntax: $(suffix names...) basename() $(info basename of src/foo.c src-1.0/bar hacks is: $(basename src/foo.c src-1.0/bar hacks)) result: basename of src/foo.c src-1.0/bar hacks is: src/foo src-1.0/bar hacks     returns the file names of items in the names file list without extension syntax: $(basename names...) addsuffix() $(info addsuffix .c,foo bar.h is: $(addsuffix .c,foo bar.h )) result: addsuffix .c,foo bar.h is: foo.c bar.h.c      adds a suffix to the names in the names list syntax: $(addsuffix suffix,names...) addprefix() $(info addprefix src/,foo bar.h is: $(addprefix src/,foo bar.h )) result: addprefix src/,foo bar.h is: src/foo.c src/bar.h      inserts a prefix before the names in the names list syntax: $(addprefix prefix,names...) join() $(info join a b,.o .c is: $(join a b,.o .c )) result: join a b,.o .c is: a.o b.c       converts items from both lists into one list syntax: $(join list1,list2) $(info wildcard /usr/lib/*.so is: $(wildcard /usr/lib/*so)) result: wildcard /usr/lib/*.so is: /usr/lib/libgettextsrc-0.19.8.1.so /usr/lib/libpyglib-2.0-python2.7.so /usr/lib/libknotifyplugin.so /usr/lib/libGraphicsMagick++.so /usr/lib/libusbprog.so /usr/lib/libinproctrace.so /usr/lib/attica_kde.so /usr/lib/libGraphicsMagick.so /usr/lib/preloadable_libintl.so /usr/lib/libGraphicsMagickWand.so /usr/lib/libqgroupwise.so /usr/lib/libtidy.so /usr/lib/libgettextlib-0.19.8.1.so        wildcard() returns a list of filenames specified by the pattern syntax: $(wildcard pattern) realpath() $(info realpath . is: $(realpath . )) result: realpath . is: /home/zamek/oktat/prog3_vill/practice/P3_MakeTest         returns the true path of the pattern file name syntax: $(realpath pattern) abspath() $(info abspath . is: $(abspath . )) result: abspath . is: /home/zamek/oktat/prog3_vill/practice/P3_MakeTest         returns the absolute path of the pattern file name syntax: $(abspath pattern) does not follow softlinks uname:=$(shell uname -s)is_darwin:=$(filter Darwin,$(uname))viewpdf:=$(if $(is_darwin), open, evince)$(info viewpdf is:$(viewpdf)) result: viewpdf is: evince         if() is the same as the if directive syntax: $(if condition, then-part[, else-part]) uname:=$(shell uname -a)is_darwin:=$(filter Darwin,$(uname))is_debian:=$(filter Debian,$(uname))is_linux:=$(filter Linux,$(uname))is_deb_or_darwin:=$(or $(is_darwin),$(is_debian))is_linux_and_debian:=$(and $(is_linux), $(is_debian))viewpdf:=$(if $(is_deb_or_darwin), open, evince)$(info viewpdf is:$(viewpdf))$(info linux & debian:$(is_linux_and_debian)) result: viewpdf is: openlinux & debian:Debian          or(), and() logical OR and AND relationship syntax: $(or condition1[, condition2 [,condition3...]])$(and condition1[, condition2 [,condition3...]])  call() reverse=$(2) $(1) foo:=$(call reverse,a,b) $(info foo is: $(foo)) result: foo is: b a         call a user-defined macro syntax: $(call variable, param,param,...)  origin() provides information about the variable syntax: $(origin variable)  result value undefined: the variable is not defined default: the variable is a make default variable like CC environment: the variable is derived from system environment variables environment: override variable from make argument overwritten file: is defined in the variable Makefile command line: defined in the variable command line override: overwritten by the variable override directive automatic: the variable is used in a recipe foreach function flavor() provides information about the variable syntax: $(flavor variable)  return value: undefined the variable is not defined recursive the variable is a recursive extracted variable simple the variable is a simple variable ERROR1=file not found ifdef ERROR1 $(error found an error:$(ERROR1))endif result: Makefile:203: *** found an error:file not found. Stop.          error() generate an error message syntax: $(error text...)  warning() ERROR1=file not found ifdef ERROR1 $(warning warning:$(ERROR1))endif result: Makefile:211: warning:file not found           generate an error message but make does not exit. syntax: $(warning text...)  workdir:=$(shell pwd)$(info current directory is:$(workdir)) result: current directory is:/home/zamek/oktat/prog3_vill/practice/P3_MakeTest            shell() executes the command command of the operating system syntax: $(shell command)  the output of the command can be stored in a variable .PHONY: clean install           Special goals if a goal is not a file .PHONY Task simplify Makefile in the project at this link implement as many simplifications as possible Task upload the completed task to your personal Gitlab repository in Makefile you can configure translation for different platforms have a separate Makefile for tests and documentation Portability problems hardware differences Endian-ness word Size operating system differences executable file name device file name file name convention compiler differences compiler name and arguments header file names and definitions keywords Why use Autoconf / Automake? portability reusing codebase professonality demo Principle of operation source Makefile.in config.h.in configure.ac configure *.c,*.h host Makefile.in config.h.in configure.ac configure *.c,*.h Makefile config.h ./configure configure generation existing Makefile autoscan mv configure.scan configure.ac autoconf mv Makefile Makefile.in autoheader ./configure Configure Code :: Blocks to use make Do a project as usual Copy the source files and the Makefile into the project directory Add files to project (right click on project / add files ...) Open project properties (Project / properties ...) On the first tab of Makefile, set the Makefile name. (by default, the projectroot Makefile) Below, check-in this is a custom Makefile checkbox In the execution directory, set the directory to which make will point Configure Eclipse CDT to use make in File/import menu, under C/C++ Existing Code as Makefile Project/ next In language, check C for C In the Toolchain for Indexer Settings, select Linux GCC Use Finish to import the project Fill in the Project name and click Browse next to Existing Code Locationset up a project directory
1
  1. Main
  2. Task
  3. Compile automation
  4. Lifecycle management
  5. Automate repetitive tasks
  6. Providing portability
  7. GNU Make
  8. Operation
  9. Run
  10. Makefile structure
  11. Variable definitions
  12. Automatic variables
  13. Directives
  14. Explicit rules
  15. Implicit rules
  16. Using variables
  17. Recursive variable extraction
  18. Simple variable extraction
  19. Additional value assigning operators
  20. Define multi-row variables
  21. Elimination of variables
  22. Special variables
  23. Conditions
  24. Text transformation functions
  25. subst()
  26. patsubst()
  27. strip()
  28. findstring()
  29. filter()
  30. filter-out()
  31. sort()
  32. word()
  33. wordlist()
  34. words()
  35. firstword()
  36. lastword()
  37. dir()
  38. notdir()
  39. suffix()
  40. basename()
  41. addsuffix()
  42. addprefix()
  43. join()
  44. wildcard()
  45. realpath()
  46. abspath()
  47. if()
  48. or() and()
  49. call()
  50. origin()
  51. flavor()
  52. error()
  53. warning()
  54. shell()
  55. Special goals
  56. Task
  57. Portability problems
  58. Why use Autoconf/Automake?
  59. Principle of operation
  60. configure generálás
  61. Code::Blocks beállítása make használatára
  62. Eclipse CDT beállítása make használatára
  63. next