Skip to content

Migrating from Makefile

If you’ve been using makefile-for-monorepos, this guide explains the differences and how to migrate to EMB.

EMB was created as the spiritual successor to makefile-for-monorepos, addressing its limitations while keeping the same philosophy:

  • Auto-discovery of components (folders with Dockerfiles)
  • Incremental builds using sentinel files
  • Simple commands for common operations
Aspectmakefile-for-monoreposEMB
Configurationconfig.mk + per-component makefile.mkSingle .emb.yml + optional Embfile.yml per component
SyntaxMake syntax (error-prone, hard to debug)YAML (readable, validated)
DependenciesManual declaration in makefilesDeclared in YAML, automatically resolved
FlavorsEnvironment variables + conditionalsFirst-class support with JSON Patch
TasksCustom make targetsDeclarative task definitions with executors
Error messagesCryptic make errorsClear, actionable error messages
ExtensibilityInclude makefilesPlugin system

Here’s how makefile commands map to EMB:

MakefileEMBNotes
make imagesemb resources buildBuild all images
make {component}.imageemb resources build {component}:imageBuild specific image
make images FORCE=1emb resources build --forceForce rebuild
MakefileEMBNotes
make upemb upBuild and start services
make downemb downStop services
make psemb psShow running services
make {component}.logsemb logs {service}View logs (followed by default)
make {component}.bashemb shell {service}Get a shell
make {component}.onemb up {component}Start specific service
make {component}.offemb down {component}Stop specific service
MakefileEMBNotes
make testsemb run testRun all tests (if task defined)
make {component}.testsemb run {component}:testRun component tests

Replace your config.mk with a .emb.yml file:

.emb.yml
project:
name: my-project
plugins:
- autodocker # Auto-discovers components with Dockerfiles
env:
DOCKER_TAG: ${env:DOCKER_TAG:-latest}

If you have per-component makefile.mk files with custom settings, create Embfile.yml files instead:

Before (api/makefile.mk):

DOCKER_BUILD_TARGET = production
DEPENDS_ON = base

After (api/Embfile.yml):

resources:
image:
type: docker/image
dependsOn:
- base:image
params:
target: production

Dependencies between components are now declared in YAML:

Before (config.mk):

api.image: base.image
web.image: base.image

After (in each component’s Embfile.yml):

api/Embfile.yml
resources:
image:
type: docker/image
dependsOn:
- base:image

Custom make targets become EMB tasks:

Before (api/makefile.mk):

api.test:
docker-compose run --rm api npm test
api.lint:
docker-compose run --rm api npm run lint

After (api/Embfile.yml):

tasks:
test:
description: Run tests
executor:
type: docker/cli
run: npm test
lint:
description: Run linter
executor:
type: docker/cli
run: npm run lint

Environment-specific configurations become flavors:

Before (environment variables):

Terminal window
DOCKER_BUILD_TARGET=production make images

After (.emb.yml):

flavors:
production:
patches:
- op: replace
path: /components/api/resources/image/params/target
value: production

Then use:

Terminal window
emb up --flavor production

Both tools use sentinel files for incremental builds. EMB stores them in .emb/sentinels/ instead of .build/.

To clean sentinels:

Terminal window
# Makefile
make clean
# EMB
emb clean

Both tools use docker-compose under the hood. Your existing docker-compose.yml files work with EMB without modification.

One of the biggest improvements is error handling. Instead of cryptic make errors like:

make: *** No rule to make target 'foo.image', needed by 'bar.image'. Stop.

EMB provides clear messages:

Error: Component 'foo' not found
Did you mean: api, web, base?

You can migrate gradually by keeping both systems during transition:

  1. Start with .emb.yml and basic auto-discovery
  2. Migrate one component at a time to Embfile.yml
  3. Update your CI/CD scripts to use emb commands
  4. Remove makefiles once fully migrated

If you encounter issues migrating, open an issue with your makefile configuration and we’ll help you convert it.