Martin G
Martin G

Reputation: 18109

How to run Linux shell commands from GNU make file to setup preconditions for a build target

My issue is that in my make file I want to create the directory for all object code before building it and I cannot find a way to do this whithout having it impact the output of make. Also, i want to do it in ONE place and not for each and every object file.

I have tried this:

build: setup exe.i686

setup:
    mkdir -p obj

exe.i686: $(OBJS)
    @echo 'Building target: $@'
    @echo 'Invoking: GCC C++ Linker'
    ${GCC_LOCATION}/Linux/i686/bin/i686-pc-linux-gnu-g++ $(OBJS) -o "exe.i686" -L...
    @echo 'Finished building target: $@'
    @echo ' '

where OBJS is all my object code. If I don't run setup first and there is no ./obj directory present the build will fail because of the missing directory when trying to build the object code.

Just to be clear, here is an example of how one object file is built:

./obj/Cell.o: ${CELL_ROOT}/main/cell/Cell/src/Cell.cc
    @echo 'Building file: $<'
    @echo 'Invoking: GCC C++ Compiler'
    $(GCC_C++_BUILD) -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
    @echo 'Finished building: $<'
    @echo ' '

I don't want to build the object code in the same directory I have my make file.

Now to the actual problem. When I build tarket "build" the first time like this everything works fine:

make build

But if I build it again and there are no updates in my source code (object code is up-to-date) it behaves like this:

[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ make build
mkdir -p obj
[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ 

In this situation I would have liked make to return the nothing-to-be-done string like this:

[7:37] [user1] [/local/repo/user1/project_x/test/bin] $ make build
make: Nothing to be done for `build'.
[7:41] [user1] [/local/repo/user1/project_x/test/bin] $ 

This would have been the case if I didn't have to depend on the setup target (which is added to .PHONY). Is the only alternative to do it for each object code file? That would be possible I suppose but I wanted to avoid that if possible as it clutters the make file quite a bit. At least in my opinion.

Thanks

Upvotes: 2

Views: 886

Answers (2)

minghua
minghua

Reputation: 6581

This is similar to the earlier answer, just to make it easier to read:

build: exe.i686
$(OBJS): | obj
obj:
    @if [ ! -d obj ]; then mkdir -p obj; fi

exe.i686: $(OBJS)
    @echo 'Building target: $@'
    ...

Upvotes: 1

6EQUJ5
6EQUJ5

Reputation: 3302

Your target setup is always executed because it has no dependency.

You have two choices:

(1) Make a stamp or use some other mechanism so that there is an actual dependency. The directory itself can be the target but that may incur some wrinkles: see http://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html for an example.

Modified relevant extract from the linked article:

$(OBJS): | obj

obj:
    mkdir $(OBJDIR)

(2) Suppress the output by testing for existence:

setup:
    test -d obj || mkdir -p obj

Upvotes: 2

Related Questions