defining default values in makefile - command-line

My makefile has line like this
CFLAGS = -c -g -D OPT1 -D OPT2
I want to pass this arguments through command line like this
make ARG1= OPT1 ARG2 =OPT2
If I dont pass these arguments through command line I want makefile to use take default values defined in makefile. How do I do that ?

Just do something like this in the makefile:
OPT1 = MY_OPT_1 # defaults
OPT2 = MY_OPT_2
CFLAGS = -c -g -D $(OPT1) -D $(OPT2)
Then on the command line:
$ make -e OPT1=SOME_OTHER_OPT1 OPT2=SOME_OTHER_OPT2
When you specify falues for OPT1 and/or OPT2 on the command line these will override the default values in the makefile.
Note that you probably want the -e option with make in most cases to force everything to be re-built with the new OPT1, OPT2 values.

Another way is to use the ?= assignment operator. It only assigns the value if it is not defined at runtime.
OPT1?=opt1_default
OPT2?=opt2_default
and at call-time you just
make OPT1=a OPT2=b
# OR
make # to use default values
more info

Related

Why is this docopt string not working either with or without optional args?

Here is the complete docopt string I used:
foo.
Usage:
foo [options] <file> -o <output>
foo --help | --version
Options:
-h, --help print this help message.
--target <target> target.
--version print the version.
According to the official parser, either foo a -o b or foo --target abc a -o b is not correctly parsed. What could be possible reasons for this case? Any help would be appreciated.
I'm not entirely sure about the allowed combinations of options for your script, but here's something that should be close.
Just for fun, I wrote a script that has similar options to yours to test this out with the latest docopts.
I found it simplest to write just [options] in the main Usage section, and have all the options below as alternatives, with no specific combinations required.
I'm on macOS so I'm using bash 3.2 (with patched docopts.sh to fix some Mac issues). You can avoid some of the code in this script if you're on bash 4.x - see the commented-out section with --auto option and docopt_print_ARGS function. Currently you would need bash 4.x to avoid patching docopts.sh.
#!/bin/bash
#
# foo.
#
# Usage:
# foo [options] <file>
# foo --help | --version
#
# Options:
# -t, --target <target> target.
# -o, --output <output> output.
# -h, --help print this help message.
# --version print the version.
#
# bash 3.2 (patched docopts.sh) - include set -x to see the args easily
source docopts.sh
usage=$(docopt_get_help_string "$0")
set -x
eval "$(docopts -G ARGS -V "$VERSION" -h "$usage" : "$#")"
# On bash 4.x, replace preceding section with this, or use -A instead of -G above
# source docopts.sh --auto "$#"
# docopt_print_ARGS
This parses the Usage section OK and processes command lines such as:
foo --target a -o b file1
foo --target a --output b file1
foo --target a file1
Partial output with set -x to show args processed correctly:
$ ./foo --target a file1 --output b
...
++ ARGS_target=a
++ ARGS_output=b
++ ARGS_file=file1
++ ARGS_help=false
++ ARGS_version=false
Thanks for #RichVel's efforts. Yesterday I finally found out the underlying (stupid) cause for this problem.
In the official online parser the first part, i.e. foo shouldn't be used. --target abc a -o b works fine in the online example.
Regarding my question, the bug actually comes from that docopt.rs stores --target abc in flag_target instead of arg_target.

How to implement dynamic tab completion of options in Fish shell?

I want to implement dynamic tab completion of options to a Fish command. This is easy for the -a switch, but I can't figure out how to do it for the -l switch.
Consider the following lines:
$ complete -c foo -a '(echo bar\nbaz\nbiz)' -f
$ complete -c foo -l '(echo bar\nbaz\nbiz)' -f
The behavior of my shell is then as follows:
$ foo b<tab>
bar baz biz
$ foo --<tab>
foo --\(echo\ bar\\nbaz\\nbiz\)
Instead I'd like it to suggest three options --bar, --baz and --biz. Is this possible?
edit: Now I understand better. You can do this by just making your "arguments" start with dashes. Here's an example that uses a function for clarity:
function get_foo_completions
echo --bar
echo --baz
echo --biz
set prev_arg (commandline -pco)[-1]
test "$prev_arg" = print
and echo --conditional
end
complete -c foo -a '(get_foo_completions)' -f
The --conditional argument will only be printed if the previous argument is print which illustrates that these can be dynamic.
To my knowledge this isn't yet possible. Options are declarative, and only arguments to those options may be dynamic.
If you give more details about your use case I might be able to suggest other approaches.

How to run perl test in debugger mode?

I try to run test under debugger as:
perl -d $(which prove) t/file.t
But this has no effect because each test is run as separate job.
I have found --exec option, but when I provide it I lost any option from .proverc file and command line
prove -Ithis/is/lost --exec 'perl -d' t/file.t
How to run tests by prove with additional options and do not lose those options which were provided at .proverc file and command line?
I do not want repeat myself and write:
prove --exec 'perl -d -Ilib -Ilocal/lib/perl5' t/file.t
While -Ilib and -Ilocal/lib/perl5 are both at .proverc file
You can repeat yourself once if you set the PERL5OPT environment variable.
export DBG_MODE='-d -Ilib -Ilocal/lib/perl5'
prove t/file1.t # regular use
PERL5OPT=$DBG_MODE prove t/file2.t # with debugger
or with an alias or bash function
alias proved='PERL5OPT="-d -Ilib -Ilocal/lib/perl5" prove'

How to create a variable in shell script whose name is present in variable?

Let's say I declare two variables key and value like this in shell script
$ key=key1
$ value=value1
now I want to create a variable of name key1 and assign it value value1. What I tried is
$ export ${key}
$ export ${value}
$ $($key=$value)
output: key1=value1: command not found
I don't know how to do this.
Use eval $key=$value instead of $($key=$value): The shell substitutes variable values first, and then the $(...) substitution. As there is not command with that name the shell shows command not found in STDERR. Tell the shell to evaluate the substitution result as a regular shell command again by using eval. Later you can export the result with export $key. Using the -x flag for the shell provides a good insight of what happens:
$ key=key1
$ value=value1
$ set -x
$ $key=$value
+ key1=value1
sh: key1=value1: not found [No such file or directory]
$ $($key=$value)
+ key1=value1
sh: key1=value1: not found [No such file or directory]
$ eval $key=$value
+ eval key1=value1
+ key1=value1
$ echo $key1
+ echo value1
value1
$ export $key
+ export key1
Also, be careful when dealing with variables this way: Whitespaces in shell variables can have unexpected results in this kind of constructions.

What is a perl one liner to replace a substring in a string?

Suppose you've got this C shell script:
setenv MYVAR "-l os="\""redhat4.*"\"" -p -100"
setenv MYVAR `perl -pe "<perl>"`
Replace with code that will either replace "-p -100" with "-p -200" in MYVAR or add it if it doesn't exist, using a one liner if possible.
The topic does not correspond to content, but I think it may be usefull if someone posts an answer to topic-question. So here is the perl-oneliner:
echo "my_string" | perl -pe 's/my/your/g'
What you want will look something like
perl -e' \
use Getopt::Long qw( :config posix_default ); \
use String::ShellQuote; \
GetOptions(\my %opts, "l=s", "p=s") or die; \
my #opts; \
push #opts, "-l", $opts{l} if defined($opts{l}); \
push #opts, "-p", "-100"; \
print(shell_quote(#opts)); \
' -- $MYVAR
First, you need to parse the command line. That requires knowing the format of the arguments of the application for which they are destined.
For example, -n is an option in the following:
perl -n -e ...
Yet -n isn't an option in the following:
perl -e -n ...
Above, I used Getopt::Long in POSIX mode. You may need to adjust the settings or use an entirely different parser.
Second, you need to produce csh literals.
I've had bad experiences trying to work around csh's defective quoting, so I'll leave those details to you. Above, I used String::ShellQuote's shell_quote which produces sh (rather than csh) literals. You'll need to adjust.
Of course, once you got this far, you need to get the result back into the environment variable unmangled. I don't know if that's possible in csh. Again, I leave the csh quoting to you.