patternjavascriptMinor
A Makefile to make some Cheese
Viewed 0 times
makefilecheesesomemake
Problem
Excuse the pun in the title, the project this is for is called "Cheddar" (a type of cheese).
Github
I have recently been writing a language, in which I was using grunt. Grunt was very slow for me, and had a lot more problems for me, so I switched my tasks over to makefile. Most of my makefile knowledge is based off examples, googling, and brief tutorials, which is why I want to ask here on how it could be improved.
Essentially what this does is it defined a couple of tasks:
-
default: This is the default task. It runs babel, a compiler I need to compile the code from the
Following is
Github
I have recently been writing a language, in which I was using grunt. Grunt was very slow for me, and had a lot more problems for me, so I switched my tasks over to makefile. Most of my makefile knowledge is based off examples, googling, and brief tutorials, which is why I want to ask here on how it could be improved.
PREFIX=./node_modules/.bin
## Compiler
# The compiler to use for the ES7 -> ES5 transformation
JC=$(PREFIX)/babel
# Location of files
SRC=src/
OUT=dist/
# The flags to pass to the compiler
JCFLAGS=$(SRC) -d $(OUT)
# The binary files to copy
BIN=cli/cheddar
EXE=cheddar
BIN_MAKE=$(foreach BIN_FILE,$(BIN),chmod 755 $(SRC)$(BIN_FILE) && cp $(SRC)$(BIN_FILE) $(OUT)$(BIN_FILE)${\n});\
ln -s $(OUT)cli/$(EXE) ./$(EXE)
## Tests
TESTRUNNER=$(PREFIX)/babel-node
COVERAGE=$(PREFIX)/babel-istanbul
TEST=$(PREFIX)/_mocha
TFLAGS=cover $(TEST)
## Rules
all: default
# The default task
# The **production** build
default: $(JC) $(SRC)
$(JC) $(JCFLAGS) --minified
$(BIN_MAKE)
# Development build task
# This builds and includes source maps
build: $(JC) $(SRC)
$(JC) $(JCFLAGS) --sourceMaps="inline"
$(BIN_MAKE)
# Runs install with default method
install: ./bin/install
./bin/install --method=path
# Performs testing, including coverage
# At the moment uses mocha for testing
# and babel-istanbul for coverage
test: $(TESTRUNNER) $(COVERAGE) $(TEST)
$(TESTRUNNER) $(COVERAGE) $(TFLAGS)
clean:
rm -rf ./dist/
.PHONY: testEssentially what this does is it defined a couple of tasks:
-
default: This is the default task. It runs babel, a compiler I need to compile the code from the
src/ directory to the output dist/ directory. It passes the --minified flag because this is a production build so we don't want big unminified code.Following is
BIN_MAKE. This runs code to chmod 755 a list of binary files stored in the BIN variSolution
- In makefiles you can have spacing around equals signs, making the code slightly easier to read. For example
PREFIX = ./node_modules/.bin.
UPPER_CASEvariables are generally used for things that the end user might want to change when running, whilelower_caseis for internal use variables. The user is presumably not supposed to change for example the source directory, soSRCshould really besrc.
- Single-use internal variables like
BINmake the code harder to read for no tangible benefit. Introduce a variable when you need to reuse the value.
- Any target which has a name that doesn't correspond to an actual file created by that target should IMO be marked as
.PHONY(because it is).
- Conversely, targets which do generate result files from their dependencies should be named for the files they generate, so that the Magic of Make™ can kick in and skip targets when they are up to date.
BIN_MAKEwould be much easier to understand as either commands in a target or as a separate script.
- The default target of a Makefile is the first one, by definition. That makes it redundant to have two phony targets (
allanddefault) to do the default thing.
- Some more space between the targets would be nice.
- The comments are a bit verbose. Most of the time I find it's possible to make the code understandable enough (especially by naming things carefully) that comments become redundant.
- There should be an end user variable for each command you run that's assumed to be on the
PATH, for exampleCP = /bin/cp. This may be considered overkill, especially for common tools, but it allows people who have tools off thePATH(for example after building it themselves) to run your Makefile without modifying it. A common use case (just like with RVM or Virtualenv) is if you want to test your Makefile with a tool version not installed on your base system.
RMis an implicit variable at least in GNU Make for just this purpose.
Context
StackExchange Code Review Q#132700, answer score: 4
Revisions (0)
No revisions yet.