I can't figure out why in the following the two different versions yield different results:
$(INCLUDE_DIR)/%: TRGT_PATH = \
$(INCLUDE_DIR)/$(patsubst $(word 1,$(subst /, ,$(dir $*)))/%,%,$*)
$(INCLUDE_DIR)/%: INCLUDEDS = $(TRGT_PATH)
$(INCLUDED_FILES) : $(INCLUDE_DIR)/%: %
ifeq ($(TRGT_PATH),$(findstring $(TRGT_PATH),$(INCLUDEDS)))
#echo [INC][WARN] File $(TRGT_PATH) already exists while copying from $*
else
#echo $(findstring $(TRGT_PATH),$(INCLUDEDS))
#echo [INC] $* $(TRGT_PATH)
#cp $* $(TRGT_PATH)
endif
Output:
[INC][WARN] File include/GeometricObject.h already exists while copying from engine/GeometricObject.h
[INC][WARN] File include/util.h already exists while copying from engine/util.h
[INC][WARN] File include/util.h already exists while copying from test/util.h
If I change the line ifeq ($(TRGT_PATH),$(findstring $(TRGT_PATH),$(INCLUDEDS))) to ifneq (,$(findstring $(TRGT_PATH),$(INCLUDEDS))) the output is:
include/GeometricObject.h
[INC] engine/GeometricObject.h include/GeometricObject.h
include/util.h
[INC] engine/util.h include/util.h
include/util.h
[INC] test/util.h include/util.h
As far as I know $(findstring t,l) returns the t if t is in l and else an empty string. But the output (if VAR is equals LIST) still is:
foo
bar
Can someone explain?
PS: I tested a more simple code and that worked fine...
If you'd provided a complete example, including the values of VAR and LIST, we'd be able to help. As it is, all I can say is "it works for me", so you must not be accurately reporting your environment in your question:
$ cat Makefile
VAR = v
LIST = v
all:
ifneq (,$(findstring $(VAR),$(LIST)))
#echo foo
else
#echo bar
endif
$ make
foo
ETA:
Aha. Well, your problem has absolutely nothing to do with findstring, so it's not surprising that your original question was not answerable.
The issue is that you're trying to use target-specific variables in a non-recipe context, and the documentation clearly states that they are not available outside of recipes.
The ifeq, etc. statements are like preprocessor statements: they are evaluated as the makefile is being parsed, not later when the recipes are being invoked. So the values of TRGT_PATH and INCLUDEDS when the ifeq/ifneq is invoked are the global values of those variables (which might be the empty string if they're not set otherwise) not the target-specific values.
Related
I'm having an issue with an URL in an if-statement using batch.
#ECHO OFF
SET /P input="Insert Link "
if %input%==l (echo true) else (echo false)
cmd /k
I want to determine if the user input is a link or a single character (in this case l). I get that the operators within the URL might cause the problem. But shouldn't the if-statement just check if %input% is l and everything else would trigger the else? Using SET %input%=l leads to the true case being triggered.
Any ideas on how to make this work in a simple way? Am I missing something regarding syntax?
Putting %input% and l within the if-statement in quotes solved the problem.
#ECHO OFF
SET /P input="Insert Link "
if "%input%"=="l" (echo true) else echo false
cmd /k
The way the Command Line works, %ThisIsAVariable% will be replaced with whatever ThisIsAVariable contains and then be interpreted as such. Hence, running your example prompts the following error:
=6zswl5YrvVw==l was unexpected at this time.
The simplest way to solve this is to wrap your %input% with ""
e.g.
#ECHO OFF
SET input=https://www.youtube.com/watch?v=6zswl5YrvVw
if "%input%"==l (echo true) else (echo false)
cmd /k
That would prompt false
The ax_boost_base page indicates that it sets HAVE_BOOST. So I tried it in my configure.ac file:
AX_BOOST_BASE([1.48],, [AC_MSG_ERROR([libfoo needs Boost, but it was not found in your system])])
AC_MSG_NOTICE(["HAVE_BOOST value"])
AC_MSG_NOTICE([$HAVE_BOOST])
When I run configure, HAVE_BOOST does not seem to have any value:
checking for boostlib >= 1.48 (104800)... yes
configure: "HAVE_BOOST value"
configure:
How do I use this HAVE_BOOST in my configure.ac? Specifically, I want to append a file into my AC_OUTPUT if HAVE_BOOST is set. For example, if HAVE_BOOST is not set, then I want:
AC_OUTPUT([
Makefile
include/Makefile
comm/Makefile
ordinary_app/Makefile
])
But if HAVE_BOOST is set, then I want this:
AC_OUTPUT([
Makefile
include/Makefile
comm/Makefile
ordinary_app/Makefile
boost_enabled_app/Makefile
You missed to set the result back to some variable. You can try this
AX_BOOST_BASE([1.48],
[have_boost=yes],
[AC_MSG_ERROR([libfoo needs Boost, but it was not found in your system])]
)
AC_MSG_NOTICE(["have_boost value"])
AC_MSG_NOTICE([$have_boost])
The HAVE_BOOST is set in the m4 macro ax_boost_base uses AC_DEFINE that would be generated in config.h. It's not a shell variable.
Eventually you can use the var $have_boost to get what you want
if test "$have_boost" != yes; then
AC_OUTPUT([
Makefile
include/Makefile
comm/Makefile
ordinary_app/Makefile
])
else
AC_OUTPUT([
Makefile
include/Makefile
comm/Makefile
ordinary_app/Makefile
boost_enabled_app/Makefile
])
fi
I am having trouble understanding this error.
make: None: Command not found
make: *** [Makefile:3879: api/api_commands.o] Error 127
I have tried looking but I can't find an answer to the specific issue make: None:.
The full issue and error message is here for clarification.
Help on this would be highly appreciated.
Update
The make file consists of the following (line 3879 separated from the rest for clarification):
...
includes_65 = -I../src/tactic/portfolio -I../src/tactic/smtlogics -I../src/ackermannization -I../src/model -I../src/ast/rewriter -I../src/ast -I../src/util -I../src/math/polynomial -I../src/math/automata -I../src/solver -I../src/tactic -I../src/ast/proofs -I../src/sat/sat_solver -I../src/tactic/core -I../src/ast/macros -I../src/ast/normal_forms -I../src/tactic/aig -I../src/tactic/bv -I../src/ast/rewriter/bit_blaster -I../src/tactic/arith -I../src/sat -I../src/sat/tactic -I../src/nlsat/tactic -I../src/nlsat -I../src/smt/tactic -I../src/smt -I../src/cmd_context -I../src/interp -I../src/smt/proto_model -I../src/smt/params -I../src/ast/pattern -I../src/parsers/smt2 -I../src/parsers/util -I../src/ast/substitution -I../src/math/grobner -I../src/math/euclid -I../src/math/simplex -I../src/ast/fpa -I../src/util/lp -I../src/muz/fp -I../src/muz/base -I../src/qe -I../src/muz/pdr -I../src/muz/transforms -I../src/math/hilbert -I../src/muz/dataflow -I../src/muz/clp -I../src/muz/tab -I../src/muz/rel -I../src/muz/bmc -I../src/muz/duality -I../src/duality -I../src/muz/ddnf -I../src/muz/spacer -I../src/tactic/nlsat_smt -I../src/tactic/ufbv -I../src/tactic/fpa -I../src/tactic/sls -I../src/math/subpaving/tactic -I../src/math/subpaving -I../src/math/interval -I../src/math/realclosure -I../src/opt -I../src
api/z3_macros.h.node: ../src/api/z3_macros.h
#echo done > api/z3_macros.h.node
api/z3_api.h.node: ../src/api/z3_api.h
#echo done > api/z3_api.h.node
...
api/api_ast_vector$(OBJ_EXT): ../src/api/api_ast_vector.cpp api/z3.h.node api/api_log_macros.h.node api/api_context.h.node api/api_ast_vector.h.node ast/ast_translation.h.node ast/ast_smt2_pp.h.node
#echo src/api/api_ast_vector.cpp
#$(CXX) $(CXXFLAGS) $(includes_65) $(CXX_OUT_FLAG)api/api_ast_vector$(OBJ_EXT) ../src/api/api_ast_vector.cpp
api/api_bv$(OBJ_EXT): ../src/api/api_bv.cpp api/z3.h.node api/api_log_macros.h.node api/api_context.h.node api/api_util.h.node ast/bv_decl_plugin.h.node
#echo src/api/api_bv.cpp
#$(CXX) $(CXXFLAGS) $(includes_65) $(CXX_OUT_FLAG)api/api_bv$(OBJ_EXT) ../src/api/api_bv.cpp
api/z3_replayer.h.node: ../src/api/z3_replayer.h api/z3.h.node util/z3_exception.h.node
#echo done > api/z3_replayer.h.node
api/api_commands$(OBJ_EXT): ../src/api/api_commands.cpp api/z3.h.node api/z3_replayer.h.node
#echo src/api/api_commands.cpp
#$(CXX) $(CXXFLAGS) $(includes_65) $(CXX_OUT_FLAG)api/api_commands$(OBJ_EXT) ../src/api/api_commands.cpp
api/api_config_params$(OBJ_EXT): ../src/api/api_config_params.cpp api/z3.h.node
...
Since the previous lines in the make file are of similar format and did not cause any errors, the problem must lie within the api_commands.cpp file. I have looked into this file, but I can't understand what is happening in this code exactly, so I cannot interpret where a None variable is created.
The api_commands.cpp file in question is 4856 lines long, but it consists of several functions of ther format
void exec_Z3_params_set_bool(z3_replayer & in) {
Z3_params_set_bool(
reinterpret_cast<Z3_context>(in.get_obj(0)),
reinterpret_cast<Z3_params>(in.get_obj(1)),
in.get_symbol(2),
in.get_bool(3));
}
and a function void register_z3_replayer_cmds(z3_replayer & in) containing lines such as
in.register_cmd(16, exec_Z3_params_set_bool, "Z3_params_set_bool");
If anyone is familiar with such or similar code and would know how this file is creating a None variable, your help would be highly appreciated.
I need to call submakes recursively with different variable settings. During this, I need to build a list of the variable settings. After all submakes are complete, I need to check the results of all the submakes using the list built up.
tests:
echo "Testcase 1 $(testname)..."; \
$(MAKE) -e TESTCASE=1 guimode=no run > test.tc1.log; \ # must save variable TESTCASE_LIST = {1} or similar
$(MAKE) -e TESTCASE=2 guimode=no run > test.tc2.log; \ # must append to variable TESTCASE_LIST = {1 2}
$(MAKE) -e TESTCASE=2 guimode=no run > test.tc3.log; \ # must append to variable TESTCASE_LIST = {1 2 3}
echo "Completed Tests at time $(realtime) ..."; \
$(MAKE) check_test_results; # must run through results of tests 1,2,3 and get data
check_test_results:
for testcase in $(TESTCASE_LIST); do something; done
Sub-make is a child process, so it cannot transfer environment variables to its parent. I suggest simply to examine exit codes and process them inside tests recipe, kind of:
.ONESHELL:
tests:
$(MAKE) TEST=1 ... && TESTCASE_LIST+=(1)
$(MAKE) TEST=2 ... && TESTCASE_LIST+=(2)
...
# check results
echo "Successful tests: $${TESTCASE_LIST[#]}"
How to pass argument to Makefile from command line?
I understand I can do
$ make action VAR="value"
$ value
with Makefile
VAR = "default"
action:
#echo $(VAR)
How do I get the following behavior?
$ make action value
value
How about
$make action value1 value2
value1 value2
You probably shouldn't do this; you're breaking the basic pattern of how Make works. But here it is:
action:
#echo action $(filter-out $#,$(MAKECMDGOALS))
%: # thanks to chakrit
#: # thanks to William Pursell
EDIT:
To explain the first command,
$(MAKECMDGOALS) is the list of "targets" spelled out on the command line, e.g. "action value1 value2".
$# is an automatic variable for the name of the target of the rule, in this case "action".
filter-out is a function that removes some elements from a list. So $(filter-out bar, foo bar baz) returns foo baz (it can be more subtle, but we don't need subtlety here).
Put these together and $(filter-out $#,$(MAKECMDGOALS)) returns the list of targets specified on the command line other than "action", which might be "value1 value2".
Here is a generic working solution based on #Beta's
I'm using GNU Make 4.1 with SHELL=/bin/bash atop my Makefile, so YMMV!
This allows us to accept extra arguments (by doing nothing when we get a job that doesn't match, rather than throwing an error).
%:
#:
And this is a macro which gets the args for us:
args = `arg="$(filter-out $#,$(MAKECMDGOALS))" && echo $${arg:-${1}}`
Here is a job which might call this one:
test:
#echo $(call args,defaultstring)
The result would be:
$ make test
defaultstring
$ make test hi
hi
Note! You might be better off using a "Taskfile", which is a bash pattern that works similarly to make, only without the nuances of Maketools. See https://github.com/adriancooney/Taskfile
Much easier aproach. Consider a task:
provision:
ansible-playbook -vvvv \
-i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
--private-key=.vagrant/machines/default/virtualbox/private_key \
--start-at-task="$(AT)" \
-u vagrant playbook.yml
Now when I want to call it I just run something like:
AT="build assets" make provision
or just:
make provision in this case AT is an empty string
Few years later, want to suggest just for this: https://github.com/casey/just
action v1 v2=default:
#echo 'take action on {{v1}} and {{v2}}...'
You will be better of defining variables and calling your make instead of using parameters:
Makefile
action: ## My action helper
#echo $$VAR_NAME
Terminal
> VAR_NAME="Hello World" make action
Hello World
don't try to do this
$ make action value1 value2
instead create script:
#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$#"
and do this:
$ ./buildthenaction.sh value1 value2
for more explanation why do this and caveats of makefile hackery read my answer to another very similar but seemingly not duplicate question: Passing arguments to "make run"