Pablo Fallas
Pablo Fallas

Reputation: 801

Makefile not recognizing already generated sources

I'm trying to generate an RPM with a makefile, the behavior I'm expecting from the makefile is the following:

  1. If RPM doesn't exist and the sources are not yet prepared, go ahead and do both: generate sources and then the RPM
  2. If RPM already exist but the sources changed, go ahead and prepare the sources and generate the RPM once again
  3. If the sources haven't changed and the RPM already exist don't do anything

However, right now the behavior I'm getting from the makefile below is not quite the way I want it, as it recognizes whether the RPM exist but when it comes down to the sources it doesn't really recognize that they already exist.

Here's the makefile:

SHELL        = /bin/bash
.SHELLFLAGS  = -o pipefail -c
COLORIZE    := 2>&1 | sed -re "s/^(Executing|Wrote)(.*: )/"$$'\E'"[32m\1\2"$$'\E'"[0m/g" \
    -e "s/(error[s]?)/"$$'\E'"[31m\1"$$'\E'"[0m/ig" \
    -e "s/(warn|warning)/"$$'\E'"[33m\1"$$'\E'"[0m/ig"

SPEC        := $(shell find . -name \*spec -printf '%f' -quit)
ARCH        := $(shell rpm -q --qf '%{arch}' --specfile $(SPEC))
DIST        := .el
NAME        := $(basename $(SPEC))
RELEASE     := $(shell rpm -q --qf '%{release}' --specfile $(SPEC) | cut -d. -f1)
VERSION     := $(shell rpm -q --qf '%{version}' --specfile $(SPEC))

BUILDDIR    := ./rpm-build
RPM         := $(BUILDDIR)/RPMS/$(ARCH)/$(NAME)-$(VERSION)-$(RELEASE)$(DIST).$(ARCH).rpm
RPMBUILD    := rpmbuild --define "_topdir %(pwd)/$(BUILDDIR)" \
    --define "_source_filedigest_algorithm md5" \
    --define "_binary_filedigest_algorithm md5" \
    --define "_source_payload w9.gzdio" \
    --define "_binary_payload w9.gzdio" \
    --define "_sourcedir  %{_topdir}/SOURCES" \
    --define "_target_os linux" \
    --define "dist .el"

SOURCE0     := $(BUILDDIR)/SOURCES/$(NAME)-$(VERSION).jar

.PHONY: all clean

all: $(RPM)

$(BUILDDIR):
    @mkdir -p $(BUILDDIR)/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS,TEMP}

$(SOURCE0): $(BUILDDIR) $(SPEC)
    spectool -g -C $(BUILDDIR)/SOURCES $(SPEC)

$(RPM): $(SPEC) $(SOURCE0)
    @echo -e "Building $(RPM)"
    $(RPMBUILD) -bb $< $(COLORIZE)

clean:
    @- $(RM) -rf ./$(BUILDDIR)

Is there anything I'm doing wrong for managing the sources, I just don't want them to be prepared everytime I run a make command ?

Upvotes: 1

Views: 138

Answers (1)

MadScientist
MadScientist

Reputation: 100856

You should never have a target with a directory as a prerequisite, because directory timestamps are updated at unusual times. I shouldn't say "never"; it can be very useful but it means something quite different than what you think.

You can try using an order-only prerequisite for this:

$(BUILDDIR):
        @mkdir -p $(BUILDDIR)/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS,TEMP}

$(SOURCE0): $(SPEC) | $(BUILDDIR)
        spectool -g -C $(BUILDDIR)/SOURCES $(SPEC)

Or you can just put the mkdir inside the recipe:

$(SOURCE0): $(SPEC)
        @mkdir -p $(BUILDDIR)/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS,TEMP}
        spectool -g -C $(BUILDDIR)/SOURCES $(SPEC)

Note, you're using bash-specific issues here ({}). If you want to be portable you need to add:

SHELL := /bin/bash

to your makefile.

Upvotes: 1

Related Questions