Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile rule depend on directory content changes

Using Make is there a nice way to depend on a directories contents.

Essentially I have some generated code which the application code depends on. The generated code only needs to change if the contents of a directory changes, not necessarily if the files within change their content. So if a file is removed or added or renamed I need the rule to run.

My first thought is generate a text file listing of the directory and diff that with the last listing. A change means rerun the build. I think I will have to pass off the generate and diff part to a bash script.

I am hoping somehow in their infinite intelligence might have an easier solution.

like image 207
Halsafar Avatar asked Jul 28 '14 22:07

Halsafar


3 Answers

Kudos to gjulianm who got me on the right track. His solution works perfect for a single directory.

To get it working recursively I did the following.

ASSET_DIRS = $(shell find ../../assets/ -type d)
ASSET_FILES = $(shell find ../../assets/ -type f -name '*')

codegen: ../../assets/ $(ASSET_DIRS) $(ASSET_FILES)
     generate-my-code

It appears now any changes to the directory or files (add, delete, rename, modify) will cause this rule to run. There is likely some issue with file names here (spaces might cause issues).

like image 177
Halsafar Avatar answered Nov 07 '22 08:11

Halsafar


Let's say your directory is called dir, then this makefile will do what you want:

FILES = $(wildcard dir/*)

codegen: dir # Add $(FILES) here if you want the rule to run on file changes too.
    generate-my-code

As the comment says, you can also add the FILES variable if you want the code to depend on file contents too.

like image 7
gjulianm Avatar answered Nov 07 '22 09:11

gjulianm


A disadvantage of having the rule depend on a directory is that any change to that directory will cause the rule to be out-of-date — including creating generated files in that directory. So unless you segregate source and target files into different directories, the rule will trigger on every make.

Here is an alternative approach that allows you to specify a subset of files for which additions, deletions, and changes are relevant. Suppose for example that only *.foo files are relevant.

# replace indentation with tabs if copy-pasting

.PHONY: codegen
codegen:
        find . -name '*.foo' |sort >.filelist.new
        diff .filelist.current .filelist.new || cp -f .filelist.new .filelist.current
        rm -f .filelist.new
        $(MAKE) generate

generate: .filelist.current $(shell cat .filelist.current)
        generate-my-code

.PHONY: clean
clean:
        rm -f .filelist.*

The second line in the codegen rule ensures that .filelist.current is only modified when the list of relevant files changes, avoiding false-positive triggering of the generate rule.

like image 2
Daira Hopwood Avatar answered Nov 07 '22 08:11

Daira Hopwood