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

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)

Related

Use fgsl in fortran: how to compile with gfortran

I am trying to do something basic, but I can't find the relevant information on how to compile. I tried the following without success:
gfortran testintegral.f90 -lgsl -lgslcblas
testintegral.f90:19.6:
use fgsl
1
Fatal Error: Can't open module file 'fgsl.mod' for reading at (1): No such file
The file is taken from http://de.wikibooks.org/wiki/Fortran:_FGSL#Beispiel:_Numerische_Integration (page in german but readily understandable) so I suppose it is OK.
Maybe the syntax of the compilation command is incorrect ?
EDIT:
I edit my initial post so as not to bury important information in the comments.
Those are the paths of the libraries:
sudo find -name '*libgsl.so*'
./usr/lib/libgsl.so.0
./usr/lib/libgsl.so.0.17.0
sudo find -name '*libgslcblas.so*'
./usr/lib/libgslcblas.so.0
./usr/lib/libgslcblas.so.0.0.0
But I still got an error message when doing:
gfortran testintegral.f90 -L/usr/lib -I/usr/include/fgsl -lfgsl -lgsl -lgslcblas
/usr/bin/ld: cannot find -lgsl
/usr/bin/ld: cannot find -lgslcblas
collect2: error: ld returned 1 exit status
Use the -I flag. For example,
gfortran -I/usr/local/fgsl/include testintegral.f90 -lgsl -lgslcblas
All the .mod files in that directory are then included.
EDIT: See also comments below.
Compilation of a file containing modules in gfortran produces two file types: The source file foo.f90 is translated into foo.o. If foo.f90 contains the modules bar and baz, then bar.mod and baz.mod are also generated. They contain the interface information for these modules. Note that there is no required mapping between module and file names (although programming guildelines may require this).
When the statement use fsgl is found, the interface information is read from fsgl.mod. If that file is not found, you get the error message
Can't open module file 'fgsl.mod' for reading at (1): No such file
So, you have to change your order of compilation (possibly through changing a Makefile).
1) the easiest way is
gfortran testintegral.f90 -I/usr/local/include/fgsl -lfgsl
2) this also works
gfortran -I/usr/local/include/fgsl testintegral.f90 -lgsl -lgslcblas -lm
3) I read the log of the make check in the package, the developer used such a way
gfortran -I/usr/local/include/fgsl -g -O2 -c -o test.o testintegral.f90
/bin/bash /path/.../fgsl-1.3.0/libtool --tag=FC --mode=link gfortran -g -O2 -o test test.o /usr/local/lib/libfgsl.la -lgsl -lgslcblas -lm
UPDATE:
First check the linkers for fgsl
pkg-config --libs fgsl
probably will get something like this
-L/usr/local/lib -lfgsl -lgsl -lgslcblas -lm
Then you put the linkers, works for all the cases!
gfortran -I/usr/include/fgsl example.f90 -lfgsl -lgsl -lgslcblas -lm
UPDATE: I answered too soon, here is the best universal method I found:
gfortran `pkg-config --cflags fgsl` testintegral.f90 -o integral `pkg-config --libs fgsl`

how to make command substitution in fish shell?

in bash or zsh I can write
clang++ main.cpp -g -o bin/main `pkg-config --cflags --libs opencv`
how can I translate this to fish shell?
fish uses parenthesis for command substitutions.
clang++ main.cpp -g -o bin/main (pkg-config --cflags --libs opencv)
note that parenthesis nest nicely, unlike backticks!

bash substring and positional parameters

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)

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.

compiling using libnids

I have been trying to install libnids (Ubuntu LTS and Mac OS X) all the day and now I know how to compile programs with it.
I write this here because there is not much documentation but there are samples in the libnids downloaded folder with a makefile. The important things of this makefile are these:
CC = gcc
PCAPLIB = -lpcap
LNETLIB = -lnet
LIBS = -L../src -lnids $(PCAPLIB) $(LNETLIB) -lgthread-2.0 -lnsl
example:
$(CC) example.c -o example $(LIBS)
And if you're compiling it in Mac OS X ignore this: -lgthread-2.0 -lnsl -L../src
But I don't know if something stop to works because of these omitted things.
I found it. The best way is to compile the library and then use local reference to the ".a" file.
Makefile example
CC = gcc -g -Wall
GLIB = `pkg-config --cflags --libs glib-2.0`
PCAPLIB = -lpcap
LNETLIB = -lnet
LIBS_SRC = libnids-1.24/src/libnids.a
LIBS = $(PCAPLIB) $(LNETLIB) -lgthread-2.0
program: program.c
$(CC) -c $(CFLAGS) program.c -o program.o $(GLIB) $(LIBS)
$(CC) program.o -o program $(LIBS_SRC) $(GLIB) $(LIBS)
But if you want to compile the library and install it into your system you got to use -lnids instead of the above way. But the first solution always works.
I got errors when compiling samples under libnids:
gcc -o overflows overflows.o -L../src -lnids -lpcap -lnet -lgthread-2.0 -lnsl ../src/libnids.a
/usr/bin/ld: ../src/libnids.a(libnids.o): undefined reference to symbol 'g_async_queue_pop'
/lib/x86_64-linux-gnu/libglib-2.0.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: * [overflows] Error 1
You recommendation
GLIB = `pkg-config --cflags --libs glib-2.0`
solves my problem.
PS: my system Ubuntu 13.10. 64bit.

Resources