Split makefile and import targets from separate files
Tags: make, makefile, autocomplete
Published: 2022-06-18 23:15:48

---
title: Split makefile and import targets from separate files
published: true
description: how to include targets from external source
tags: make, makefile, autocomplete
series: makefile
---

## Start your makefile

Imagine the beginning of a project where some task are managed with a `Makefile`. At the beginning of the project maybe your tasks are two or three. Imagine the Makefile of something similar of the following few lines.

```make
install:
	@echo "some install stuff"
build:
	@echo "some build stuff"
```

## Adding features

And then imagine that the project grow and grow also the number of tasks. Some tasks to run tests. Some other to drop, init, create, migrate or add fixtures to the database. And so on ...

```make
install:
	@echo "some stuff"
build:
	@echo "some other stuff"
test:
	@echo "some unit test"
e2e:
	@echo "some end 2 end stuff"
fixtures:
	@echo "fixtures"
init-db:
	@echo "database, ..."
erase:
	@echo "clear cache, containers and other stuffs"
some-docker-task:
	@echo "do something"
some-other-task:
	@echo "leave a comment"
some-other-task:
	@echo "please click on Hear or Unicorn"
```

I mean, ... your makefile may explode soon if you do nothing to keep it clean and easy to read or try to, .. hay! Can we split makefile? Mmm no, .. isn the right question.

## May I import command from other sources?

YES! And the keyword to use is "include". Ok, .. follow me in the rest of the article: Try to split some tasks in different sets. For example you can have these sets of tasks:

 - tests
   - unit
   - e2e
   - functional
 - docker-stuff
   - build
   - up
   - stop

An hypothetical file could be similar to the following:

```make
tests-unit:
    echo @"do something"
test-e2e:
    echo @"do something"
test-functional:
    echo @"do something"
docker-build:
    echo @"do something"
docker-up:
    echo @"do something"
docker-stop:
    echo @"do something"
```

Ok, this is not so big but imagine tens od sets. You makefile could really contains. Imagine hundred of lines of makefile. I am sure the reading could not be so easy.

## Split one Makefile

Now imagine two file: `test.file` and `docker.file`.

`docker.file` may contain

```make
docker-build:
    echo @"do something"
docker-up:
    echo @"do something"
docker-stop:
    echo @"do something"
```

and `test.file` may contain

```make
tests-unit:
    echo @"do something"
test-e2e:
    echo @"do something"
test-functional:
    echo @"do something"
```

And imagine to include them inside the main Makefile:

```make
include test.file docker.file
```

Now you can run simply `make test-unit` and it works. But 

## Autocompletion lost

Whenever all targets are inside the Makefile autocompletion works. Moving targets outside, it stop working. Is not a Makefile issue but is an autocompletion issue. I am using oh-my-zsh. Maybe I need some plugin. I do not know. Did you know how to fix this?

## Fix autocompletion

I've found a little trick to fix autocompletion. I've updated my Makefile with new target that call targets inside imported files. This works!!! Now `make<tab>` shows also `unit-test`.

```make
include test.file docker.file

unit-test: test-unit
```

## Conclusion

Keep makefile ordered and clean is good. But is not so good lost autocompletion. If you know all the targets is ok. But without autocompletion, for a new teammate could be hard to find the right command inside included file. But, ... this is fixable. So, ... I am simply happy to this nice feature of makefiles.