On Sat, Apr 23, 2011 at 11:07:06AM +0430, ali hagigat wrote: > I have a makefile and I want to print each word of the variable, .VARIABLES > on a separate line.
> It seems that the previous simple solution of Mr. Johnson here does not > work, means: printf "%s\n" $var make(1) is a separate program from bash. The printf solution would work with a *bash* variable: imadev:~$ var='D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...' imadev:~$ printf '%s\n' $var D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ... (Technically you'd need to do a 'set -f' first, to avoid globbing of the individual words. E.g. if I had happened to have a file named IF in my directory, the word ?F would have been expanded out to match the filename(s). I omitted that for simplicity, but you can't omit it in real life.) > This is the content of .VARIABLES: > > .VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D > XAUTHORITY GDMSESSION XMODIFIERS CURDIR SHELL RM GDM_LANG _ PREPROCESS.F > var2 LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST @F HISTCONTROL USERNAME > ........................... > It was long and I did not copy the rest of the lines. Now you've gone and changed the question. You're asking a question about make(1) on the bash bug mailing list. Specifically, you're asking a question about make(1) *and assuming that it is the same as asking a question about bash*, and that is (I believe) the primary source of your confusion. Makefiles use a separate syntax, have a separate variable space, have an entirely separate *purpose*, and therefore separate semantics associated with their lines. Lines of a bash program are commands that are executed in sequence. Bash is a procedural language. Lines of a Makefile are not commands; they are definitions. In a Makefile, you define variables that can be used by rules, and then you define rules that tell make(1) what to do with file X to produce file Y. Makefiles are therefore closer to a functional language than a procedural language. Now, you're probably even more confused, because you aren't focused on the overall structure of the language; you're just focused on one little tiny part of one rule, which happens to be something that gets passed to a shell (typically /bin/sh, not bash) after processing. The "after processing" part is key here. make(1) does its *own* processing of the line from the rule, before passing the result to the shell. This is because make(1) has its own variables, and it expands those before passing the command to the shell -- then the shell has *its* own set of variables, which may or may not be relevant, depending on the command in question. So. You have a Makefile, and in it you have some variable defined (I don't actually know what the period at the start of the make(1) variable name means, so I'll assume it's not relevant at this time). Then you want to write a rule which somehow uses this variable; and you want this variable to be passed to a shell, and then you want the shell to take that variable and write it on standard output, one word per line. Right? Right. Let me brush off my 15-year-old knowledge of Makefiles and see if I can hack this together.... OK, here's the first try, using the most naive approach: imadev:~/tmp$ cat Makefile .VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...> default: printf '%s\n' $(.VARIABLES) But this doesn't work: imadev:~/tmp$ make printf '%s\n' <D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO TZ _ PREPROCESS.F ftp_proxy LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST LINK.p CC COMPILE.f NETHACKOPTIONS CHECKOUT,v CPP LINK.cc P4CLIENT PATH LYNX_CFG LD TEXI2DVI FVWM_USERDIR YACC COMPILE.mod ARFLAGS LINK.r WINDOWID FVWM_MODULEDIR LINT.c LINT YACC.y AR .FEATURES TANGLE LPDEST GET %F DISPLAY COMPILE.F no_proxy CTANGLE VISUAL .LIBPATTERNS LINK.C PWD LINK.S PREPROCESS.r PKG_CONFIG_PATH LINK.c MANPATH LINK.s HOME LOGNAME ^D LC_TIME COLORTERM MAKE SHLVL AS PREPROCESS.S ERASE COMPILE.p MAKE_VERSION EDITOR FC HOSTDISPLAY .DEFAULT_GOAL LESS %D WEAVE MAKE_COMMAND LINK.cpp F77 OLDPWD .VARIABLES PC *F COMPILE.def LEX MAKEFLAGS MFLAGS *D EMAIL LPHOSTS LEX.l SLAB_PATH +D COMPILE.r +F M2C COLORFGBG MAKEFILES COMPILE.cc <F CXX COFLAGS PAGER COMPILE.C ^F COMPILE.S LINK.F SUFFIXES COMPILE.c COMPILE.s .INCLUDE_DIRS MAKELEVEL MAKEINFO http_proxy TEX LANG TERM F77FLAGS LINK.f /bin/sh: D: cannot open make: *** [default] Error 1 OK, this is informative. Do **NOT** ignore an error message. Learn from it. We can see that /bin/sh tried to open "D". This is obviously because it interpreted the <D as a redirection, rather than an argument for the printf command. So, we're making progress! We just need to get the make(1) variable into an actual shell variable, and then let the shell expand it. imadev:~/tmp$ cat Makefile .VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...> default: v='$(.VARIABLES)'; printf '%s\n' $$v (Note that this would fail if .VARIABLES contained any single quotes of its own; we'll just use this simple-but-dangerous form for now.) And then: imadev:~/tmp$ make v='<D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO TZ _ PREPROCESS.F ftp_proxy LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST LINK.p CC COMPILE.f NETHACKOPTIONS CHECKOUT,v CPP LINK.cc P4CLIENT PATH LYNX_CFG LD TEXI2DVI FVWM_USERDIR YACC COMPILE.mod ARFLAGS LINK.r WINDOWID FVWM_MODULEDIR LINT.c LINT YACC.y AR .FEATURES TANGLE LPDEST GET %F DISPLAY COMPILE.F no_proxy CTANGLE VISUAL .LIBPATTERNS LINK.C PWD LINK.S PREPROCESS.r PKG_CONFIG_PATH LINK.c MANPATH LINK.s HOME LOGNAME ^D LC_TIME COLORTERM MAKE SHLVL AS PREPROCESS.S ERASE COMPILE.p MAKE_VERSION EDITOR FC HOSTDISPLAY .DEFAULT_GOAL LESS %D WEAVE MAKE_COMMAND LINK.cpp F77 OLDPWD .VARIABLES PC *F COMPILE.def LEX MAKEFLAGS MFLAGS *D EMAIL LPHOSTS LEX.l SLAB_PATH +D COMPILE.r +F M2C COLORFGBG MAKEFILES COMPILE.cc <F CXX COFLAGS PAGER COMPILE.C ^F COMPILE.S LINK.F SUFFIXES COMPILE.c COMPILE.s .INCLUDE_DIRS MAKELEVEL MAKEINFO http_proxy TEX LANG TERM F77FLAGS LINK.f'; printf '%s\n' $v <D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO TZ _ PREPROCESS.F ftp_proxy LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST LINK.p CC COMPILE.f NETHACKOPTIONS CHECKOUT,v CPP LINK.cc P4CLIENT PATH LYNX_CFG LD TEXI2DVI FVWM_USERDIR YACC COMPILE.mod ARFLAGS LINK.r WINDOWID FVWM_MODULEDIR LINT.c LINT YACC.y AR .FEATURES TANGLE LPDEST GET %F DISPLAY ... I stopped pasting here and added the "..." myself. The output goes on for quite some time. Why? Hell if I know. Some make(1) thing I assume. Presumably one of those weird <D or ?D or @D things in your make(1) variable definition meant something to make(1) and was expanded in some way. Maybe that's even what you wanted. I really don't know, nor do I care at this point. If you have any further questions about bash, feel free to ask them here. But if your questions are really about make(1), you'll have to find some place that supports make(1).