Asmodean
Asmodean

Reputation: 339

Makefile recompiling unchanged files

I'm attempting to get my Makefile(s) to only recompile when files have changed and it works brilliantly for the Java target, but not for JS. There aren't any errors reported, but when I run make bundle the second time around, it still re-runs all of those commands.

The output of running find ... manually seems to produce exactly what is expected, with no extra or missing lines.

JAVA_SRC_DIR := .
JAVA_SOURCES := $(shell find $(JAVA_SRC_DIR) -name '*.java' -o -name '*pom.xml')

JS_SRC_DIR := ./ui-bundle
JS_EXCLUDE := \(node_modules\|coverage\)
JS_SOURCES := $(shell find $(JS_SRC_DIR) -name '*.js' -o -name '*.jsx' -o -name '.babelrc' -o -name 'package.json' | grep -v $(JS_EXCLUDE) | grep -v -e '^$')

bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package

service: $(JAVA_SOURCES)
    mvn clean install -pl "!integration"

I'm guessing this has something to do with it, but when I try to find what files make thinks has changed with make -d | grep "\(older\|newer\)" it doesn't find anything, but make -d concludes with:

 Finished prerequisites of target file `bundle'.
 Must remake target `bundle'.

Additionally make -d seems to try to run some sort of npm command.

Where am I going wrong?

Upvotes: 0

Views: 225

Answers (1)

Beta
Beta

Reputation: 99084

The problem is that bundle is just a name for the rule, and the rule doesn't actually build a file named "bundle". No matter how new or old the prerequisites are, when you make bundle, Make sees that no such file exists, deduces that it must be built, and executes the rule.

If you want Make to refrain from executing the rule when the prerequisites have not changed, you must give it something to compare them to. If you can identify some file that the rule always modifies, you can make that file the target. I can't suggest a candidate because I don't know what npm, jest and gulp do, but suppose it's jest_output:

jest_output: $(JS_SOURCES)
    ...

Or you could have an actual file called bundle, which serves as a marker for Make, an empty file that has a name and modification time and nothing else:

bundle: $(JS_SOURCES)
    npm install
    ./node_modules/jest-cli/bin/jest.js --verbose
    ./node_modules/gulp/bin/gulp.js package
    touch bundle

Upvotes: 5

Related Questions