Using a result of shell's find as a target in a Makefile

demeshchuk

Say, there's a source directory with non-defined internal structure, and we want to grab all the files and declare the files they are supposed to be compiled into as targets.

Something like that:

SOURCES := $(shell find src -name \*.c)
OBJS := $(addprefix /tmp,$(addsuffix .o,$(basename $(notdir $(SOURCES)))))
$(OBJS): $(SOURCES)
    cc $(CFLAGS) -o $@ $^

However, it starts with the second line not working (it's just being empty). So, I ended up replacing it:

OBJS := $(shell find src -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\/g' | sed 's/\.c/\./o/g'" \;)

I don't like this approach much, but otherwise it doesn't seem to be working anyway. Okay, now it's expected to be working. However, the targets don't work as expected, say, as if I declared them explicitly:

TARGETS := /tmp/foo.o /tmp/bar.o
$(TARGETS): $(SOURCES)
    ...

Instead, I just get an error No rule to make target /tmp/foo.o.

So, guess, I have two questions:

  1. Why the very first code snippet makes $(OBJS) empty?
  2. Is there a way to actually implement dynamic targets?
Nikolai Popov

Testing first snippet on my machine.

uname -a
Linux - 3.2.0-4-686-pae #1 SMP Debian 3.2.54-2 i686 GNU/Linux

make -v
GNU Make 3.81

cat makefile
SOURCES := $(shell find ./ -name \*.c)
OBJS := $(addprefix /tmp,$(addsuffix .o,$(basename $(notdir $(SOURCES)))))
$(info $(OBJS))

mkdir test; touch test/1.c; touch test/2.c; make -f makefile

Output:
/tmp1.o /tmp2.o

Test shows, that first snippet is ok, except missing slash after /tmp.
How do you test emptiness of OBJS?
Are you sure that SOURCES not empty?
What the output of make with $(info $(SOURCES)) in makefile?
Are there any *.c files in the src directory?

Testing the second snippet on my machine.

sed --version
GNU sed 4.2.1

cat makefile
SOURCES := $(shell find ./ -name \*.c)
OBJS := $(shell find ./ -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\/g' | sed 's/\.c/\./o/g'" \;)
$(info $(OBJS))

make -f makefile

Output:
sed: -e expression #1, symbol 10: unknown modifier for s'
sed: -e expression #1, символ 12: incomplete command s'
sed: -e expression #1, символ 12: incomplete command s'
sed: -e expression #1, символ 10: unknown modifier for s'

With that version of second snippet OBJS is not empty.
(Note removed '\' in first sed command and removed '/' in second command.)
OBJS := $(shell find ./ -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\//g' | sed 's/\.c/\.o/g'" \;)

Is there a way to actually implement dynamic targets?

Yep. It's easy, if you can store .o files in source directories.
The next snippet does the trick:

sources := $(shell find ./ -name \*.c)
objects := $(sources:.c=.o)

$(objects): %.o: %.c
    $(cc) -c $<

But perhaps it's not what you want.
With using VPATH and a couple of additional strings you can do better.

target   := ./a.out
obj_dir  := ./tmp/
sources  := $(shell find ./ -name \*.c)
objects  := $(addprefix $(obj_dir), $(notdir $(sources:.c=.o)))
dirs     := $(dir $(sources))
VPATH    := $(dirs)

$(target): $(objects)
    $(cc) -o $@ $^

$(objects): $(obj_dir)%.o: %.c
    $(cc) -o $@ -c $<

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Put command result in variable within makefile target

From Dev

How to pass target stem to a shell command in Makefile

From Dev

Can't find the target specified for makefile

From Dev

Makefile can't find a target that is already there

From Dev

Make can find specified target, Makefile cannot

From Dev

Running a makefile using shell script

From Dev

Makefile rule not a target when using eval

From Dev

Make command using default target name 'Makefile'

From Dev

Makefile: How to export environment variable to shell before target?

From Dev

Makefile target with wildcard to create symlink using target string

From Dev

Makefile target references Makefile

From Dev

Using find in shell script

From Dev

Using makefile assignments from a shell script

From Dev

Makefile patsubst using value of shell variable

From Dev

ember-data find using a model fetched using other find's result

From Dev

Save the result of find as a variable in a shell script

From Dev

What's the standard makefile idiom for trying different ways to make a target

From Dev

how to do a string compare with a makefile's target name

From Dev

Makefile Error while using GNU compiler: Multiple Target patterns

From Dev

Makefile Error while using GNU compiler: Multiple Target patterns

From Dev

Find the different content using shell

From Dev

Find files using shell script

From Dev

GNU Make - Set MAKEFILE variable from shell command output within a rule/target

From Dev

Makefile set variable in target

From Dev

Alias target name in Makefile

From Dev

Makefile generic target rule

From Dev

Target name in Makefile prerequisite

From Dev

Dynamic Makefile target

From Dev

Makefile target color output

Related Related

HotTag

Archive