Make: wildcard работает через раз

Есть простенький Makefile В папке только 3 файла exp.h exp.cpp main.cpp

1) Ввел команду "make" в первый раз

Такая вот ошибка:

g++    -o EXECUTABLE.work   
clang: error: no input files
make: *** [all] Error 1

2) Ввел команду "make" во второй раз(без make clean)

g++   ./obj-all/exp.o ./obj-all/main.o -o EXECUTABLE.work

Все хорошо собралось.

Почему ето происходит? Я подозреваю, что make не может на ходу найти файлы в только что созданной папке obj-all. Но, все же, у нас последовательное выполнение.

Версия Make:

GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0

Код:

CC=g++ 

DIRS:=obj-main obj-exp  
MAIN_OBJ=obj-all

.PHONY: all
.PHONY: clean

all:  exp.o main.o
        mkdir -p obj-all   # mkdir -p would not brake makefile if folder exist
        for dir in $(DIRS); do \
                cd $$dir; \
                cp *.o ./../obj-all; \
                cd -; \
        done
        $(CC) $(wildcard ./obj-all/*.o) -o EXECUTABLE.work #работает через раз
#       $(CC) $(MAIN_OBJ)/*.o  -o EXECUTABLE.work  #работает всегда
main.o:
        mkdir -p obj-main
        $(CC) main.cpp -c
        mv *.o obj-main/
exp.o:
        mkdir -p obj-exp
        $(CC) -c exp.cpp
        mv *.o obj-exp/
clean:
        rm -f *.o
        rm -rf obj-*
        rm -f *.work

Ответы (1 шт):

Автор решения: aleksandr barakin
  1. синтаксис правила:

    цели : пререквизиты
        рецепт
    
  2. функции программой gnu/make вычисляются до начала выполнения рецепта
  3. $(wildcard ...) — это функция

отсюда вывод: так как при первом запуске функция была вычислена до начала выполнения рецепта, она вернула пустую строку (не было файлов, соответствующих шаблону). а при втором запуске файлы уже были, и функция вернула их имена.

рекомендация: создавайте файлы до выполнения рецепта, в котором вам надо будет получить их список с помощью функции wildcard.


иллюстрация:

правило:
    mkdir -p каталог
    touch каталог/файл
    echo $(wildcard каталог/*)

рецепт, начинающийся с echo, выведет пустую строку. хотя к этому моменту каталог/файл уже будет существовать.

правило: каталог
    echo $(wildcard каталог/*)

каталог:
    mkdir -p $@
    touch $@/файл

сначала выполнится правило каталог, в котором он будет создан, а в нём создан файл. а уже затем выполнится рецепт, начинающийся с echo, и будет выведено имя каталог/файл

→ Ссылка