如何在Makefile中实现动态目标?能否优化重复目标?
如何在Makefile中实现动态目标简化重复代码?
当然可以!Make的模式规则(Pattern Rules)就是专门解决这类重复目标问题的利器,能帮你把一堆重复的compose-*目标简化成几行代码。
核心解决方案:用模式规则替代重复目标
你的大部分compose-*目标都遵循compose-${target}: docker-compose run myapp make ${target}的格式,咱们可以用Make的通配符%和自动变量$*实现动态匹配:
# 动态匹配所有compose-*目标(除了单独定义的特殊目标) compose-%: docker-compose run myapp make $* # 保留特殊的compose目标(因为它不是调用make,而是直接执行up) compose: docker-compose up myapp # 保留特殊的compose-shell(因为它直接运行bash,不是调用make shell) compose-shell: docker-compose run myapp /bin/bash
关键知识点解释
%是Make的模式通配符,会匹配compose-后面的任意字符串,比如compose-test中的test、compose-migrate中的migrate$*是Make的内置自动变量,它会自动替换成%匹配到的内容,比如处理compose-test时,$*就是test,最终执行docker-compose run myapp make test- 单独定义的目标(比如
compose、compose-shell)会优先于模式规则执行,所以特殊逻辑的目标可以单独保留,不影响模式规则的作用
修改后的完整Makefile
替换后你的Makefile会简洁很多,完整版本如下:
# 动态compose目标 compose-%: docker-compose run myapp make $* # 特殊compose目标 compose: docker-compose up myapp compose-shell: docker-compose run myapp /bin/bash # 原有核心目标不变 # run tests test: python manage.py test --settings=$(PROJECT_SETTINGS) # install depedencies (and virtualenv for linux) install: ifndef WIN -virtualenv -p python3 .venv endif pip install -r requirements.txt # handle django migrations migrate: python manage.py makemigrations --settings=$(PROJECT_SETTINGS) python manage.py migrate --settings=$(PROJECT_SETTINGS) # handle statics static: python manage.py collectstatic --settings=$(PROJECT_SETTINGS) shell: python manage.py shell_plus --settings=$(PROJECT_SETTINGS) load: python manage.py loaddata db.json --settings=${PROJECT_SETTINGS} export: python manage.py dumpdata --indent 2 --natural-foreign --natural-primary -e sessions -e admin -e contenttypes -e auth.Permission > db.json --settings=${PROJECT_SETTINGS} flush: python manage.py sqlflush --settings=$(PROJECT_SETTINGS)
额外优势
以后如果需要新增类似的compose-*目标(比如compose-static),你完全不需要再写新的规则,直接运行make compose-static,Make会自动通过模式规则执行docker-compose run myapp make static,大大降低维护成本。
内容的提问来源于stack exchange,提问作者holms
相关产品推荐
相关产品推荐

