pkg-config não funciona com makefile?

2

Estou tentando executar o makefile , mostrado em este repositório , que é um simples Cliente Wayland. Mas quando eu corro make , parece que a saída de $(WAYLAND) está em branco, e ele falha em compilar devido a não ser capaz de encontrar o wayland-client.h arquivo de cabeçalho. cc (GCC) versão 5.3.1 no Fedora 23 no bash.

Abaixo estão alguns detalhes. A minha pergunta é: que erro estou a com o meu ambiente que está a impedir que este makefile funcione para mim como pretendido?

Conteúdo do makefile :

WAYLAND='pkg-config wayland-client --cflags --libs'
CFLAGS?=-std=c11 -Wall -Werror -O3 -fvisibility=hidden

hello_wayland: hello_wayland.o helpers.o helpers.h images.bin
    $(CC) -o hello_wayland *.o $(WAYLAND) -lrt

images.bin: images/convert.py images/window.png images/fish.png
    images/convert.py
    cat window.bin fish.bin > images.bin

clean:
    $(RM) *.o fish.bin window.bin hello_wayland

Saída de make :

cc -std=c11 -Wall -Werror -O3 -fvisibility=hidden -c -o hello_wayland.o hello_wayland.c hello_wayland.c:6:28: fatal error: wayland-client.h: No such file or directory

Observe como as opções para cc acima parecem estar sem a saída de $(WAYLAND) especificada em makefile . Se eu manualmente executar cc assim:

cc -std=c11 -Wall -Werror -O3 -fvisibility=hidden -c -o hello_wayland.o hello_wayland.c \
-I/home/me/install/include -L/home/me/install/lib -lwayland-client

A compilação é bem sucedida.

Saída de pkg-config wayland-client --cflags --libs :

-I/home/me/install/include -L/home/me/install/lib -lwayland-client

Conteúdo de ~ / .bash_profile :

source ~/.profile
source ~/.bashrc

Conteúdos relevantes de ~ / .bashrc :

export WLD=$HOME/install
export LD_LIBRARY_PATH=$WLD/lib
export PKG_CONFIG_PATH=$WLD/lib/pkgconfig/:$WLD/share/pkgconfig/
export PATH=$WLD/bin:$PATH
export ACLOCAL_PATH=$WLD/share/aclocal
export ACLOCAL="aclocal -I $ACLOCAL_PATH"

Obrigado por apontar algo que provavelmente deveria ser totalmente óbvio para mim.

    
por ybakos 20.03.2016 / 18:36

1 resposta

2

o makefile postado está faltando alguns detalhes

Nota: é (quase) sempre melhor separar a etapa de compilação da etapa do link

O makefile a seguir corrige esses detalhes

Nota: <tab> significa usar a tecla tab no makefile real

RM             := /usr/bin/rm

LFLAGS         += 'pkg-config wayland-client --libs'

CFLAGS         := -std=c11 -Wall -Werror -O3 -fvisibility=hidden
CFLAGS         += 'pkg-config wayland-client --cflags'

OBJS           := hello_wayland.o helpers.o
HDRS           := helpers.h

TARGET         := hello_wayland

.PHONY: all
all: $(TARGET)

$(TARGET): $(OBJS) images.bin
<tab>$(CC) -o hello_wayland *.o $(LFLAGS) -lrt

%.o:%.c $(HDRS)
<tab>$(CC) $(CFLAGS)-c $< -o $@ -I.

images.bin: images/convert.py images/window.png images/fish.png
<tab>images/convert.py
<tab>cat window.bin fish.bin > images.bin

.PHONY: clean
clean:
<tab>$(RM) *.o fish.bin window.bin hello_wayland

Você pergunta o que está errado com o makefile original:

aqui estão algumas observações:

-- macros in a make file are of two types:
   those evaluated only once using ':='
   those evaluated every time they are referenced '='

WAYLAND='pkg-config wayland-client --cflags --libs'
== WAYLAND will be re-evaluated every time referenced

CFLAGS?=-std=c11 -Wall -Werror -O3 -fvisibility=hidden
== invalid format for macro.  '?=' should be ':='

== in a makefile,  typical usage is 'make all'  but this makefile is missing that target (which should be the first target so 'make' by itself, will execute the first target)
== 'targets' for a link step should not be the actual file name
==== but rather a macro name where that macro contains the target name
==== This usage of a macro also makes it easy to set the resulting executable file name at the invocation of 'make'
==== while either way will work, for flexability it is best to create a macro
==== this is expecially true when writing a recursive makefile or multiple different executables
hello_wayland: hello_wayland.o helpers.o helpers.h images.bin

== this is a link step, with hidden compiles, using the default recipe, which knows nothing about any specific header file
==== so the hidden compiles will not be done if the header file changes
== and a header file 'helpers.h' should never be in a link step
== the '*.o' is a 'glob' operation, which should not be used in makefiles
==== instead use the make facilties:

SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)

== the 'target' is properly referenced by '$@' and there can be no keypunch errors if the '$@' is used.
    $(CC) -o hello_wayland *.o $(WAYLAND) -lrt

images.bin: images/convert.py images/window.png images/fish.png
    images/convert.py
    cat window.bin fish.bin > images.bin

== when a 'target' is not the name of a produced file,
==== especially in older versions of 'make'
==== then the target needs to be preceeded by a 

.PHONY: <list of target names that produce no actual output file>

== using  a 'glob' operation in a makefile is a bad idea
==== instead use the appropriate macro
==== like the $(OBJS) macro listed above
clean:
    $(RM) *.o fish.bin window.bin hello_wayland

Então, por que o makefile original não funcionou? uma combinação de coisas que se acumulam em uma falha de fabricação. Aqui estão as razões mais óbvias:

1) the incorrect setting of the CFLAGS macro
2) the combining of the link operation with the compile operations
3) the missing .PHONY: statement
4) the use of the 'glob' statements
    
por 20.03.2016 / 22:23