bash substring and positional parameters - bash

I have to compile some mysql c api code and tired of writing all this in command line:
gcc main.c -o main `mysql_config --cflags --libs`
I wrote a shell script in bash and pass positional parameter in bash:
gcc $1 -o ${"$1":0:2} 'mysql_config --cflags --libs' but this doesn't work. I get error message: ./compile: line 2: ${"$1":0:-2}: bad substitution. Can someone please tell me what I am doing wrong?
The only way I got this to work is by assigning a new variable:
filename=$1;
gcc $filename -o ${filename:0:-2} `mysql_config --cflags --libs`
Is this the only way to do it or is there a way to fix what I am doing wrong in the first case?

You almost had it:
${1:0:2}
You don't need another reference to $1 inside the brackets since everything in it will be interpreted as the name of the variable, as in the case of ${filename:0:-2}.

In response to the comments under the question, here's an example makefile for this situation:
MSQL_FLAGS := $(shell mysql_config --cflags)
MSQL_LIBS := $(shell mysql_config --libs)
main : main.c
gcc $(MSQL_FLAGS) -o $# $< $(MSQL_LIBS)

Related

Using glib in C - correct invocation of pkg-config in a Makefile

I am trying to make a web server in C. I am using the glib library which I include in my .c file with the syntax:
#include <glib.h>
To be able to use the library I have added the following two lines in my Makefile:
CFLAGS = 'pkg-config --cflags glib-2.0'
LDLIBS = 'pkg-config --libs glib-2.0'
But when I compile from the Shell I get the following error messages
gcc 'pkg-config --cflags glib-2.0' httpd.c 'pkg-config --libs glib-2.0' -o httpd
gcc: error: pkg-config --cflags glib-2.0: No such file or directory
gcc: error: pkg-config --libs glib-2.0: No such file or directory
make: *** [httpd] Error 1
Is there anyone who knows a solution to this problem?
pkg-config is a tool meant to print needed CFLAGS and LIBS to standard out, so I see kind of a "double error" here:
What you probably read was giving a parameter like CFLAGS = `pkg-config --cflags glib-2.0` to make. Note the backticks here, they tell the shell to run a command and replace the whole construct with the output of that command (alternate syntax for shells is $()).
Even with backticks, this wouldn't work inside a Makefile which has different syntax from sh. The corresponding construct in GNU make is $(shell ), so just write CFLAGS = $(shell pkg-config --cflags glib-2.0).
Depending on which make you are using, you might just want:
CFLAGS = $(shell pkg-config --cflags glib-2.0)
LDLIBS = $(shell pkg-config --libs glib-2.0)

make file preprocessor directive

I am not very experienced with make files and am trying to define a preprocessor variable in my make file,in Eclipse (linux).
It turns up a non trivial task,since as it seems am missing something...
Bellow you can find my make file's structure:
var_first=g++
all:
g++ main_cell.cpp -o hello
in this way am building my code,that i want to do is to define a variable in my make files that would then be asserted with an #ifdef,#endif in my code.
I have gone through numerous combinations but am missing some steps as it seems...
Could you please give some pointers?
To add a definition while compiling, use the -D g++ option. Like this:
g++ -DMyDefine=123 main_cell.cpp -o hello
Now in main_cell.cpp you can do:
#if MyDefine == 123
doStuff();
#endif
To use makefile variables for this, do something like:
all: g++ main_cell.cpp -o hello -Dvar_first=$(var_first)
That is equivalent of #define var_first g++ in the .cpp file
If you want to pass the preprocessor variable directly to the compiler, you use a -D flag.
E.g. you want to define the variable PRE_MY_VAR to 1, you can write:
g++ -o myexecutable *.cpp -DPRE_MY_VAR=1
So in your makefile this would be:
all:
g++ main_cell.cpp -o hello -Dvar_first="g++"

clang: warning: -l*: 'linker' input unused

When I compile code using GNU Make I get multiple warnings like:
clang: warning: -lGui: 'linker' input unused
This is probably because I have messed something up in my Makefile (below). Can anyone point me toward the problem?
CXX=g++
CC=g++
CXXFLAGS=-g -Wall -W -Wshadow -Wcast-qual -Wwrite-strings $(shell root-config --cflags --glibs)
CPPFLAGS+=-MMD -MP
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
xSec_x: xSec_x.o xSec.o Analysis.o
-include xSec_x.d xSec.d Analysis.d
xSec.o: xSec.cpp xSec.h Analysis.h Analysis.cpp
xSec_x.o: xSec_x.cpp xSec.h Analysis.h
clean:
rm -f #rm -f $(PROGRAMS) *.o *.d
That message means you are passing linker flags (like -l which tells the linker to pull in a library) to the compiler.
This means that the result of running root-config --cflags --glibs is generating linker flags, and those are going into CXXFLAGS, which is being passed to the compiler. I don't know what root-config is, but you should investigate its command line and invoke it in a way where it doesn't generate linker flags. Probably removing the --glibs option will do it.
ETA: you really want to be using := to assign these flags variables if you're going to run $(shell ...) there. It will work either way, but if you use = then the shell command will be run every time make expands the variable, which is once per compilation. If you use := it will only be run once, when the makefile is parsed.
I got this same error and the reason was that I forgot to add -I in front of my included paths for cflags in makefile. For example:
CFLAGS += $(path)/dir/subdir/include -> Got the above mentioned error.
CFLAGS += -I$(path)/dir/subdir/include -> Fixed the issue.

How to pass arguments to commands in GNU make shell function?

I'm compiling a SDL program using a Makefile. Typically I can compile my SDL projects with gcc like so:
# gcc -c test.c `sdl-config --cflags`
# gcc -o test test.o `sdl-config --libs`
# ./test
I'm having trouble executing sdl-config in my Makefile however. This is what I have:
CFLAGS := $(shell sdl-config --cflags)
LDFLAGS := $(shell sdl-config --libs)
test : test.o
gcc $(CFLAGS) $(LDFLAGS) -o test test.o
test.o:
But I keep getting the sdl-config usage line back rather than the respective output. I suspect the arguments (--cflags and --libs) are not being passed to sdl-config.
How do I pass arguments to the shell function? Is there a better way to achieve my end goal?
What you're doing is correct. If you run "sdl-config --cflags" from the command line, does it work or do you get the usage line? The best way to debug scripting problems is to run the script from your shell prompt. If it works there, it will work in make, too.

windows equivalent of command substitution in makefiles

I want to display current build(hg revision) number in the about box of my program. I thought about using a "define" (std::string rev = REVISION;) in the code and pass the value to g++ via makefile:
$(CPP) -c main.cpp -o main.o -DREVISION=`hg id -i`
would work like a charm, but im developing on windows for windows, so my Q: how to create such a behavior on windows.
If you're using g++ then your assumption is mostly right, excepting that passing a macro definition is done using -D option, not -d. Also, $(CPP) in Make usually refers to C PreProcessor. C++ compiler is $(CXX).
$(CXX) -c main.cpp -o main.o -DREVISION=`hg id -i`
Regarding command substitution, it should work fine if you run your build in UNIX-ish compatibility layer, like Cygwin or MinGW. If not, you could avoid using command substitution at all, and pass the result of hg id -i to the compiler literally, e.g. as follows:
REVISION := $(shell hg id -i)
...
$(CXX) -c main.cpp -o main.o -DREVISION=$(REVISION)

Resources