Advertisement
linuxlizard

Makefile with Backslashes Parsed-ish

Oct 6th, 2014
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.06 KB | None | 0 0
  1. # How does GNU Make handle \'s as line continuation?
  2. #
  3. # davep 24-Sep-2014
  4.  
  5. # Manual 3.1.1 says:
  6. # "Outside of recipe lines, backslash/newlines are converted into a single space
  7. # character. Once that is done, all whitespace around the backslash/newline is
  8. # condensed into a single space: this includes all whitespace proceding the
  9. # backslash, all whitespace at the beginning of the line after the
  10. # backslash/newline, and any consecutive backslash/newline combinations."
  11. #
  12. #
  13. # TODO .POSIX will change the behavior of this file
  14. #
  15.  
  16. # Don't use the shell because the shell will eat the whitespaces. Make also
  17. # preserves the leading whitespaces.
  18. SHELL=/bin/echo
  19.  
  20. all : test-backslash-semicolon test-backslash-recipes lots-of-fore-whitespace\
  21. lots-of-aft-whitespace backslash-in-string backslash-in-string-echo\
  22. backslash-eol backslash-o-rama backslash-space-eol assignment split-assignment \
  23. split-prereqs-with-backslashes this-is-a-rule-with-backslashes \
  24. backslash-in-comment rule-not-highlighted-by-vim \qqq \n \
  25. ; @echo $@ $^
  26.  
  27.  
  28. # silent output without launching a shell
  29. #silent : SHELL=/usr/bin/touch
  30. #silent : ; @/dev/null
  31. # Using test doesn't work. I don't know why. Always throws an error. Need to
  32. # run GNU Make under the debugger.
  33. #silent : SHELL=/bin/test
  34. #silent : ; @ 1 -eq 1
  35.  
  36. test-backslash-semicolon : ; @echo $@ \
  37. qqqq
  38.  
  39. test-backslash-recipes :
  40. @echo $@ \
  41. qqqq
  42.  
  43. # whitespace before is preserved
  44. lots-of-fore-whitespace :
  45. @echo $@ \
  46. qqqq
  47.  
  48. # whitespace and after before qqq is preserved
  49. # there is a lot of whitespace after the qqqq
  50. lots-of-aft-whitespace :
  51. @echo $@ \
  52. qqqq
  53.  
  54. # uh oh \ in string will make my life difficult
  55. # try with shell to see the printf (bonus: rule specific variable)
  56. #backslash-in-string : SHELL=/bin/sh
  57. backslash-in-string :
  58. @printf "foo%s bar%s baz%s \n" \
  59. @printf "FOO BAR BAZ\n"
  60.  
  61. # back to using /bin/echo
  62. backslash-in-string-echo:
  63. @printf "foo bar baz\n" \
  64. @printf "FOO BAR BAZ\n"
  65.  
  66. # does Make need \<eol> or is it just the last \ on a line that makes it happy?
  67. backslash-eol :
  68. @echo $@ \
  69. newline!
  70.  
  71. # space after backslash is error
  72. # the following throws error "missing separator"
  73. #backslash-space-eol :
  74. # @echo $@ \
  75. #newline!
  76.  
  77. # <tab>\ <-- starts the recipe, \ continues to next line
  78. # <tab>\ <-- literal <tab> before \ is eaten (why?)
  79. # <space>...<space>\\\\\\\ <-- six spaces then six \'s; seeing the leading
  80. # spaces in the output
  81. # \ <-- empty line
  82. # \ <-- empty line
  83. # @echo $@ <--- leading spaces
  84. #
  85. # first <tab> starts the recipe, continues to next line
  86. # next line is <tab>
  87. backslash-o-rama :
  88. @\
  89. \
  90. \\\\\\\
  91. \
  92. \
  93. @echo $@
  94.  
  95. # this works (spaces after backslash)
  96. # because the recipes end. The \ becomes a literal \ in the string
  97. backslash-space-eol :
  98. @echo $@ \
  99. space after this backslash!\
  100.  
  101.  
  102. # this works \ in RHS of assignment is ok
  103. I am an assignment statement = \
  104. that equals \ a bunch of stuff \ with \
  105. backslashes \ that should not be \ confused with \
  106. continuation \ of the \ line
  107.  
  108. assignment :
  109. @echo $(I am an assignment statement)
  110.  
  111. # this works. \ in LHS of assignment is ok
  112. # fails in 3.82 and 4.0
  113. I am a \
  114. split assignment = legal in 3.81
  115.  
  116. split-assignment :
  117. @echo $(I am a split assignment)
  118.  
  119. # splitting RHS of rule (the prerequisites) parses ok
  120. # Error "no rule to make target 'backslash-'
  121. split-prereqs-with-backslashes : backslash-\
  122. space-\
  123. eol \
  124. ;\
  125. @echo $@
  126.  
  127. # GNU make successfully parses this with no complaints. Can't seem to hit it.
  128. # for "this-is-a-rule-with-backslashes"
  129. # Ah ha! is creating a rule with the targets: this- is- a- rule- with- backslashes
  130. # 3.1.1 says" backslash/newlines are converted into a single space character"
  131. this-\
  132. is-\
  133. a-\
  134. rule-\
  135. with-\
  136. backslashes : ; @echo $@
  137.  
  138. # I think "space" this winds up being an empty string. But the blank line after
  139. # is confusing my backslash handling so this is a good test regardless
  140. space=\
  141.  
  142. fake-out : this-$(space)is-$(space)a-$(space)rule-$(space)with-$(space)backslashes
  143. @echo $@
  144.  
  145. fake-out-2 : this- is- a- rule- with- backslashes
  146. @echo $@
  147.  
  148. #$(info = @@space@@=@@space$(space)@@)
  149.  
  150. # from ffmpeg
  151. # Note in the $(info) output all the extra spaces are collapsed into a single space
  152. SUBDIR_VARS := CLEANFILES EXAMPLES FFLIBS HOSTPROGS TESTPROGS TOOLS \
  153. HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \
  154. ARMV5TE-OBJS ARMV6-OBJS VFP-OBJS NEON-OBJS \
  155. ALTIVEC-OBJS VIS-OBJS \
  156. MMX-OBJS YASM-OBJS \
  157. MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSPR1-OBJS MIPS32R2-OBJS \
  158. OBJS HOSTOBJS TESTOBJS
  159. #$(info $(SUBDIR_VARS))
  160. subdir_vars : $(SUBDIR_VARS)
  161.  
  162. # from Linux kernel 3.12.5 (removed the 'rm' so it's not dangerous)
  163. # (plus this makefile uses SHELL=/bin/echo so it's doubly not dangerous)
  164. clean: $(clean-dirs)
  165. # $(call cmd,rmdirs)
  166. # $(call cmd,rmfiles)
  167. @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
  168. \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
  169. -o -name '*.ko.*' \
  170. -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
  171. -o -name '*.symtypes' -o -name 'modules.order' \
  172. -o -name modules.builtin -o -name '.tmp_*.o.*' \
  173. -o -name '*.gcno' \) -type f -print | xargs
  174.  
  175. # use this shell on this so can tinker with the prerequisites
  176. #backslash-in-prereqs : SHELL=/bin/sh
  177. backslash-in-prereqs : a\
  178. b\
  179. c\
  180. d\
  181. e\
  182. f
  183. @for t in $^ ; do echo $$t ; done
  184. @for t in $^ ; do echo $(addprefix @@,$$t) ; done
  185.  
  186. backslash-in-comment : # this is a comment \
  187. does this continue the comment?\
  188. how about now?\
  189. seems like it does\
  190.  
  191. rule-not-highlighted-by-vim : ; @echo $@
  192. # the trailing \ on the backslash-in-comment is confusing vim but gnu make
  193. # seems happy with it
  194.  
  195. # backslash in rules/prereqs?
  196. \qqq : \abc
  197. @echo $@
  198.  
  199. \n : \r
  200. @echo $@
  201.  
  202. \t : \g ; @echo \\\
  203. \\\
  204. \\
  205.  
  206. slash-o-rama\
  207. =\
  208. foo\
  209. bar\
  210. baz\
  211. blahblahblah
  212. #$(info = foo bar baz blahblahblah=$(slash-o-rama))
  213.  
  214. #slash-o-rama-rule : SHELL=/bin/echo
  215. slash-o-rama-rule :
  216. @echo slash-o-rama=$(slash-o-rama)
  217.  
  218. embedded-slash-o-rama\ =\ foo\ bar\ baz\ blahblahblah
  219. #$(info = \ foo\ bar\ baz\ blahblahblah=$(embedded-slash-o-rama\))
  220.  
  221. #embedded-slash-o-rama-rule : SHELL=/bin/echo
  222. embedded-slash-o-rama-rule :
  223. @echo embedded-slash-o-rama=$(embedded-slash-o-rama\)
  224.  
  225. # reserved symbols backslashable?
  226. # \% -> % ? Or just a literal "\%"
  227. \% = percent
  228. #$(info = percent=$(\%))
  229. %\ = percent
  230. #$(info = percent=$(%\))
  231.  
  232. # 3.1.1 Splitting Long Lines
  233. # "Outside of recipe lines, backslash/newlines are converted into a single
  234. # space character. Once that is done, all whitespace around the
  235. # backslash/newline is condensed into a single space: this includes all
  236. # whitespace preceding the backslash, all whitespace at the beginning of the
  237. # line after the backslash/newline, and any consecutive backslash/newline
  238. # combinations."
  239. more-fun-in-assign\
  240. = \
  241. the \
  242. leading \
  243. and \
  244. trailing\
  245. white \
  246. space \
  247. should \
  248. be \
  249. eliminated\
  250. \
  251. \
  252. \
  253. including \
  254. \
  255. \
  256. blank\
  257. \
  258. \
  259. lines
  260. #$(info = the leading and trailing white space should be eliminated including blank lines=$(more-fun-in-assign))
  261.  
  262. # all these empty lines should be ignored
  263. many-empty-lines\
  264. =\
  265. \
  266. \
  267. \
  268. \
  269. \
  270. \
  271. \
  272. \
  273. \
  274. foo
  275. #$(info = foo=$(many-empty-lines))
  276.  
  277. # lone backslash (Trailing space after \ to make a literal \<space>
  278. backslash-space = \
  279. #$(info = one backslash \ =one backslash $(backslash-space))
  280.  
  281. # two backslash (Trailing space after \ to make a literal \\<space>
  282. two-backslash-space = \\
  283. #$(info = two backslash \\ =two backslash $(two-backslash-space))
  284.  
  285. # lone backslash with continuation
  286. # XXX this should become two backslashes
  287. literal-2-backslash = \\\
  288. q
  289. #$(info = 1 \ q=1 $(literal-2-backslash))
  290.  
  291. # lone backslash with continuation (spaces before q are eaten)
  292. # this is so weird. I'm getting lone \ for the two \\ when I expect to see two
  293. # \\ (backslashes) output. Did I find a GNU make parser bug?
  294. literal-2-backslash-spaces = \\\
  295. q
  296. #$(info = 2 \ q=2 $(literal-2-backslash-spaces))
  297.  
  298. # Do spaces after my \\ give me two \\ output? yes! WTF?
  299. literal-2-backslash-more-spaces = \\ \
  300. q
  301. #$(info = 3 \\ q=3 $(literal-2-backslash-more-spaces))
  302.  
  303. # Leading backslash seems to violate GNU Make's manual.
  304. # By the manual's rules there should be a space before foo.
  305. leading-backslash\
  306. =\
  307. foo
  308. #$(info = 1 foo=1 $(leading-backslash))
  309.  
  310. leading-backslash-2\
  311. =\
  312. foo
  313. #$(info = 2 foo=2 $(leading-backslash-2))
  314.  
  315. # there is a space between foo and bar but not before foo
  316. leading-backslash-3\
  317. =\
  318. foo\
  319. bar
  320. #$(info = 3 foo bar=3 $(leading-backslash-3))
  321.  
  322. # implicit "catch all" rule to trap busted rules
  323. % : ; @echo {implicit} $@
  324.  
  325.  
  326.  
  327. AssignmentExpression( [Expression( [Literal("SHELL")]),AssignOp("="),Expression( [Literal("/bin/echo")])])RuleExpression( [Expression( [Literal("all")]),RuleOp(":"),PrerequisiteList( [Literal("test-backslash-semicolon"),Literal("test-backslash-recipes"),Literal("lots-of-fore-whitespace"),Literal("lots-of-aft-whitespace"),Literal("backslash-in-string"),Literal("backslash-in-string-echo"),Literal("backslash-eol"),Literal("backslash-o-rama"),Literal("backslash-space-eol"),Literal("assignment"),Literal("split-assignment"),Literal("split-prereqs-with-backslashes"),Literal("this-is-a-rule-with-backslashes"),Literal("backslash-in-comment"),Literal("rule-not-highlighted-by-vim"),Literal("\\qq"),Literal("\\")]),RecipeList( [])])RuleExpression( [Expression( [Literal("test-backslash-semicolon")]),RuleOp(":"),PrerequisiteList( []),RecipeList( [])])RuleExpression( [Expression( [Literal("test-backslash-recipes")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal(" \\\n qqqq")])])])RuleExpression( [Expression( [Literal("lots-of-fore-whitespace")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal(" \\\n qqqq")])])])RuleExpression( [Expression( [Literal("lots-of-aft-whitespace")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal(" \\\n qqqq ")])])])RuleExpression( [Expression( [Literal("backslash-in-string")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@printf \"foo%s bar%s baz%s \\n\" \\\n\t@printf \"FOO BAR BAZ\\n\" ")])])])RuleExpression( [Expression( [Literal("backslash-in-string-echo")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@printf \"foo bar baz\\n\" \\\n@printf \"FOO BAR BAZ\\n\" ")])])])RuleExpression( [Expression( [Literal("backslash-eol")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal(" \\\nnewline!")])])])RuleExpression( [Expression( [Literal("backslash-o-rama")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@\\\n\t\\\n \\\\\\\\\\\\\\\n\\\n\\\n @echo "),VarRef( [Literal("@")]),Literal("")])])])RuleExpression( [Expression( [Literal("backslash-space-eol")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal(" \\\nspace after this backslash!\\ ")])])])AssignmentExpression( [Expression( [Literal("I am an assignment statement")]),AssignOp("="),Expression( [Literal("that equals \\ a bunch of stuff \\ with backslashes \\ that should not be \\ confused with continuation \\ of the \\ line")])])RuleExpression( [Expression( [Literal("assignment")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("I am an assignment statement")]),Literal("")])])])AssignmentExpression( [Expression( [Literal("I am a split assignment")]),AssignOp("="),Expression( [Literal("legal in 3.81 ")])])RuleExpression( [Expression( [Literal("split-assignment")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("I am a split assignment")]),Literal("")])])])RuleExpression( [Expression( [Literal("split-prereqs-with-backslashes")]),RuleOp(":"),PrerequisiteList( [Literal("backslash-"),Literal("space-"),Literal("eol")]),RecipeList( [])])RuleExpression( [Expression( [Literal("this-"),Literal("is-"),Literal("a-"),Literal("rule-"),Literal("with-"),Literal("backslashes")]),RuleOp(":"),PrerequisiteList( []),RecipeList( [])])AssignmentExpression( [Expression( [Literal("space")]),AssignOp("="),Expression( [Literal("")])])RuleExpression( [Expression( [Literal("fake-out")]),RuleOp(":"),PrerequisiteList( [Literal("this-"),VarRef( [Literal("space")]),Literal("is-"),VarRef( [Literal("space")]),Literal("a-"),VarRef( [Literal("space")]),Literal("rule-"),VarRef( [Literal("space")]),Literal("with-"),VarRef( [Literal("space")]),Literal("backslashes")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal("")])])])RuleExpression( [Expression( [Literal("fake-out-2")]),RuleOp(":"),PrerequisiteList( [Literal("this-"),Literal("is-"),Literal("a-"),Literal("rule-"),Literal("with-"),Literal("backslashes")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal("")])])])AssignmentExpression( [Expression( [Literal("SUBDIR_VARS")]),AssignOp(":="),Expression( [Literal("CLEANFILES EXAMPLES FFLIBS HOSTPROGS TESTPROGS TOOLS HEADERS ARCH_HEADERS BUILT_HEADERS SKIPHEADERS ARMV5TE-OBJS ARMV6-OBJS VFP-OBJS NEON-OBJS ALTIVEC-OBJS VIS-OBJS MMX-OBJS YASM-OBJS MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSPR1-OBJS MIPS32R2-OBJS OBJS HOSTOBJS TESTOBJS")])])RuleExpression( [Expression( [Literal("subdir_vars")]),RuleOp(":"),PrerequisiteList( [Literal(""),VarRef( [Literal("SUBDIR_VARS")]),Literal("")]),RecipeList( [])])RuleExpression( [Expression( [Literal("clean")]),RuleOp(":"),PrerequisiteList( [Literal(""),VarRef( [Literal("clean-dirs")]),Literal("")]),RecipeList( [Recipe( [Literal("@find "),VarRef( [Literal("if "),VarRef( [Literal("KBUILD_EXTMOD")]),Literal(", "),VarRef( [Literal("KBUILD_EXTMOD")]),Literal(", .")]),Literal(" "),VarRef( [Literal("RCS_FIND_IGNORE")]),Literal(" \\\n\t\t\\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \\\n\t\t-o -name '*.ko.*' \\\n\t\t-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \\\n\t\t-o -name '*.symtypes' -o -name 'modules.order' \\\n\t\t-o -name modules.builtin -o -name '.tmp_*.o.*' \\\n\t\t-o -name '*.gcno' \\) -type f -print | xargs ")])])])RuleExpression( [Expression( [Literal("backslash-in-prereqs")]),RuleOp(":"),PrerequisiteList( [Literal("a"),Literal("b"),Literal("c"),Literal("d"),Literal("e"),Literal("f")]),RecipeList( [Recipe( [Literal("@for t in "),VarRef( [Literal("^")]),Literal(" ; do echo $t ; done")]),Recipe( [Literal("@for t in "),VarRef( [Literal("^")]),Literal(" ; do echo "),VarRef( [Literal("addprefix @@,"),VarRef( [Literal("t")]),Literal("")]),Literal(" ; done")])])])RuleExpression( [Expression( [Literal("backslash-in-comment")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [])])RuleExpression( [Expression( [Literal("rule-not-highlighted-by-vim")]),RuleOp(":"),PrerequisiteList( []),RecipeList( [])])RuleExpression( [Expression( [Literal("\\qqq")]),RuleOp(":"),PrerequisiteList( [Literal("\\bc")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal("")])])])RuleExpression( [Expression( [Literal("\\n")]),RuleOp(":"),PrerequisiteList( [Literal("\\")]),RecipeList( [Recipe( [Literal("@echo "),VarRef( [Literal("@")]),Literal("")])])])RuleExpression( [Expression( [Literal("\\t")]),RuleOp(":"),PrerequisiteList( [Literal("\\")]),RecipeList( [])])AssignmentExpression( [Expression( [Literal("slash-o-rama")]),AssignOp("="),Expression( [Literal("foo bar baz blahblahblah")])])RuleExpression( [Expression( [Literal("slash-o-rama-rule")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo slash-o-rama="),VarRef( [Literal("slash-o-rama")]),Literal("")])])])AssignmentExpression( [Expression( [Literal("embedded-slash-o-rama\\")]),AssignOp("="),Expression( [Literal("\\ foo\\ bar\\ baz\\ blahblahblah")])])RuleExpression( [Expression( [Literal("embedded-slash-o-rama-rule")]),RuleOp(":"),PrerequisiteList( [Literal("")]),RecipeList( [Recipe( [Literal("@echo embedded-slash-o-rama="),VarRef( [Literal("embedded-slash-o-rama\\")]),Literal("")])])])AssignmentExpression( [Expression( [Literal("\\%")]),AssignOp("="),Expression( [Literal("percent")])])AssignmentExpression( [Expression( [Literal("%\\")]),AssignOp("="),Expression( [Literal("percent")])])AssignmentExpression( [Expression( [Literal("more-fun-in-assign")]),AssignOp("="),Expression( [Literal("the leading and trailing white space should be eliminated including blank lines")])])AssignmentExpression( [Expression( [Literal("many-empty-lines")]),AssignOp("="),Expression( [Literal("foo")])])AssignmentExpression( [Expression( [Literal("backslash-space")]),AssignOp("="),Expression( [Literal("\\ ")])])AssignmentExpression( [Expression( [Literal("two-backslash-space")]),AssignOp("="),Expression( [Literal("\\\\ ")])])AssignmentExpression( [Expression( [Literal("literal-2-backslash")]),AssignOp("="),Expression( [Literal("\\\\ q")])])AssignmentExpression( [Expression( [Literal("literal-2-backslash-spaces")]),AssignOp("="),Expression( [Literal("\\\\ q")])])AssignmentExpression( [Expression( [Literal("literal-2-backslash-more-spaces")]),AssignOp("="),Expression( [Literal("\\\\ q")])])AssignmentExpression( [Expression( [Literal("leading-backslash")]),AssignOp("="),Expression( [Literal("foo")])])AssignmentExpression( [Expression( [Literal("leading-backslash-2")]),AssignOp("="),Expression( [Literal("foo")])])AssignmentExpression( [Expression( [Literal("leading-backslash-3")]),AssignOp("="),Expression( [Literal("foo bar")])])RuleExpression( [Expression( [Literal("%")]),RuleOp(":"),PrerequisiteList( []),RecipeList( [])])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement