How do you define a variable inside of a GNU make macro? I am using GNU Make 4.0 and whenever I do an assignment the variable is empty:
define TEST_MACRO
$(info $(1))
test_var := $(1)
$(info $(test_var))
endef
$(call TEST_MACRO,test)
Outputs:
test
(blank line)
I have tried using recursive expansion for the assignment but I get the same results.
You haven't mentioned which version of Make you're using, and there are subtle differences between versions in the handling of macros. But this works for me (using GNUMake 3.81):
define TEST_MACRO
$(info A $(1))
test_var := $(1)
$$(info B $$(test_var))
endef
$(eval $(call TEST_MACRO,test))
I eventually went with something like this as I felt the double $ was messy.
define TEST_MACRO
$(info B $(test_var))
endef
# Note test_var was defined after TEST_MACRO
test_var := test
$(eval $(value TEST_MACRO))
This has the disadvantage that you can't set the $1..$n variables but it's easier to read.
Edit - A better example of defining a variable inside of the macro. The above example was demonstrating how you would pass values into the macro, like you would with call
define TEST_MACRO
test_var := test
$(info B $(test_var))
endef
Related
I try to convert a filename such as foo/bar/baz.proto into something like foo/bar/Baz.java in my Makefile. For this purpose, I thought I could use sed. However, it seems that the command does not work as expected:
uppercase_file = $(shell echo "$(1)" | sed 's/\(.*\/\)\(.*\)/\1\u\2/')
# generated Java sources
PROTO_JAVA_TARGETS := ${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/$(call uppercase_file,%).java}
When I try to run the sed command on the command line it seems to work:
~$ echo "foo/bar/baz" | sed 's/\(.*\/\)\(.*\)/\1\u\2/'
foo/bar/Baz
Any ideas why this does not work inside the Makefile?
UPDATE:
The java files are generated with the following target:
$(JAVAGEN)/%.java: $(SRCDIR)/%.proto
How can I apply the substitution also for targets?
GNU Make does not replace % character in the replacement part of a substitution reference (which is basically a syntactic sugar for patsubst) if it is part of a variable reference. I have not found this behavior described in the documentation, but you can look it implemented in the source code (the relevant function I believe is find_char_unquote).
I suggest moving the call out of the substitution reference, since uppercase_file obviously works properly on any file path:
PROTO_JAVA_TARGETS := $(call uppercase_file,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java})
If $(PROTO_SPECS) resolves not to a single element, but rather to a list of elements, you can use foreach to call the function on every elements of a processed list:
PROTO_JAVA_TARGETS := $(foreach JAVA,${PROTO_SPECS:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java},$(call uppercase_file,$(JAVA)))
The java files are generated with the following target: $(JAVAGEN)/%.java: $(SRCDIR)/%.proto
How can I apply the substitution also for targets?
Since Make matches targets first, and there is no way to run sed backwards, what you need here is either define an inverse function, or generate multiple explicit rules. I will show the latter approach.
define java_from_proto
$(call uppercase_file,$(1:$(SRCDIR)/%.proto=$(JAVAGEN)/%.java)): $1
# Whatever recipe you use.
# Use `$$#`, `$$<` and so on instead of `$#` or `$<`.
endef
$(foreach PROTO,$(PROTO_SPECS),$(eval $(call java_from_proto,$(PROTO))))
We basically generate one rule per file in $(PROTO_SPEC) using a multiline variable syntax, and then use eval to install that rule. There is also a very similar example on this documentation page that can be helpful.
I'm trying to read and understand a file written in C (here) and not knowing much C (or if it's C++ to begin with), I'm wondering how the following:
#define BEGIN yy_start = 1 + 2 *
when called like this:
BEGIN(new_state)
is working. I know BEGIN is a macro/placeholder setting yy_start. However I can't find anything on how the argument passed in is handled and operands don't get me anywhere.
Question: How are arguments handled in a C/C++ macro if they are not handled explicitly?
How are arguments handled in a C/C++ macro if they are not handled explicitly?
If a macro is not declared with arguments then it does not take arguments at all. Indeed, C explicitly distinguishes between macros that accept arguments and those that don't. In your particular case, given a definition of BEGIN as an object-like macro:
#define BEGIN yy_start = 1 + 2 *
This invocation ...
BEGIN(new_state)
... expands to:
yy_start = 1 + 2 *(new_state)
. In particular, note that only the macro name is replaced. The parenthesized tokens following it are not part of the macro invocation, and are not affected by the macro expansion.
The macro BEGIN has no arguments so the resulting code will be
yy_start = 1 + 2 *(new_state)
It is done in preprocessing.
I'm trying to do this in my Makefile:
VAL=
TARGET1:
VAL= ... #compute value of VAL
#run some command that uses the value of VAL
TARGET2:
$(MAKE) TARGET1
#run other command that uses the value of VAL
But it turns out that value of VAL is reset when TARGET! completes in TARGET2. Thus the computed value of VAL is not available when I try to run the other command in TARGET2. Is there any way to keep the value computed in TARGET1? Thanks.
You have a fundamental misconception. The variable VAL that is set in the TARGET1 recipe is not a make variable at all: it's a shell variable. You can tell because if you change the syntax of the assignment to be something else that is still a valid make variable assignment but is not a valid shell variable assignment, like:
TARGET1:
VAL := foo
it will give you a syntax error. Basically in make, any recipe line (lines after a target that begin with a TAB character) are not interpreted by make at all: they're passed to a shell that make invokes. Nothing that happens in that shell can have any effect on the value of make variables, etc. of course.
You don't give us much detail. You don't say whether the command uses the variable from the environment or via the command line. You don't say what version of make you're using. If it's GNU make, you have a number of options. The simplest one is to set the value always; if it requires shell syntax you can use the shell function:
VAL := $(shell #compute value of VAL)
TARGET1:
#run some command that uses $(VAL)
TARGET2:
#run another command that uses $(vAL)
Before we give you more possibilities we need to understand the requirements: if you HAVE to have the value set in TARGET1 we need to know why, before we can offer possible solutions.
I am recently working with a F90 code project. I am using gfortran (linux and MinGW) to compile it. There is something interesting in file loct.F90.
# define TYPE real(4)
# define SUBNAME(x) s ## x
# include "loct_inc.F90"
# undef SUBNAME
# undef TYPE
# define TYPE real(8)
# define SUBNAME(x) d ## x
# include "loct_inc.F90"
# undef SUBNAME
# undef TYPE
...
The loct_inc.F90 file looks like this:
subroutine SUBNAME(loct_pointer_copy_1)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_1)
subroutine SUBNAME(loct_pointer_copy_2)(o, i)
...
end subroutine SUBNAME(loct_pointer_copy_2)
...
I think in the file loct.F90 the author used sets of macros (C/C++ style). Each set is used to define a data type (e.g. real(4), real(8), character, etc). The file loct_inc.F90 provide a set of function which is the same except the type of the variables.
These two files works together as a template of c++ in my opinion.
In the end one should have a set of subroutines:
sloct_pointer_copy_1(o, i)
sloct_pointer_copy_2(o, i)
...
dloct_pointer_copy_1(o, i)
dloct_pointer_copy_2(o, i)
...
But when I tried to compile loct.F90 (gfortran -c loct.F90), I get some errors.
basic/loct_inc.F90:21.13:
Included at basic/loct.F90:256:
subroutine s ## loct_pointer_copy_1(o, i)
1 Error: Syntax error in SUBROUTINE statement at (1)
It seems gfortran replace SUBNAME(loct_pointer_copy_1)(o, i) with s ## loct_pointer_copy_1(o, i). But according to c++ macro, the correct replace should be sloct_pointer_copy_1(o, i).
Could anyone tell me why this happened?
GNU Fortran uses the GNU C Preprocessor in traditional mode, in which mode the macro pasting operator ## is not available. That's why Fortran projects which were written to also compile with the GNU toolchain perform explicit preprocessing in additional Makefile targets, e.g. all *.F90 are first preprocessed with cpp to temporary .f90 files which are then compiled.
What is the Lua equivalent of the Octave/Matlab/IPython "whos" command? I'm trying to learn Lua interactively and would like to see what variables are currently defined.
All global variables in Lua reside in a table available as global variable _G (yes, _G._G == _G). Therefore if you want to list all global variable, you can iterate over the table using pairs():
function whos()
for k,v in pairs(_G) do
print(k, type(v), v) -- you can also do more sophisticated output here
end
end
Note that this will also give you all the Lua base functions and modules. You can filter them out by checking for a value in a table which you can create on startup when no global variables other than Lua-provided are defined:
-- whos.lua
local base = {}
for k,v in pairs(_G) do
base[k] = true
end
return function()
for k,v in pairs(_G) do
if not base[k] then print(k, type(v), v) end
end
end
Then, you can use this module as follows:
$ lua
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> whos = require 'whos'
> a = 1
> b = 'hello world!'
> whos()
a number 1
b string hello world!
whos function function: 0x7f986ac11490
Local variables are a bit tougher - you have to use Lua's debug facilities - but given that you want to use it interactively, you should only need globals.