Here comes a short interruption from my Nand2Tetris studies. The interruption is actually strongly related to Nand2Tetris. I am at the point where I should write an assembler in a language of my choice. Given my personal experience and environment, my natural choice is C++ under Linux.
When it comes to the IDE choice, I have recently used Code::Blocks with success, except for one very irritating issue. I and apparently others (Google for it if you are interested) have experienced that when using Code::Blocks in XFCE (Manjaro’s standard desktop environment), copy/paste of code does not work well. This is a pretty basic function and while there is a workaround, it is painful and I finally got tired of it. Being nerdy as I am, I decided to gave a new go to GNU Emacs, my friend of old times. Since I wanted my experience to be as modern as possible – in the scope of Emacs – I watched through this and other videos, read quite many blog articles, and finally installed CEDET from their Bazaar repository, since the version bundled with my Emacs 24.3.1 is not complete.
I went through the beginning of the CEDET manual and was quite impressed by what I saw. But when I got into the EDE part (project management) I just found it too complicated for the kind of small project I am starting right now (a small assembler, remember?).
So I will still use Emacs + CEDET, but “managing source files” and building will be handled by a simple Makefile.
And if anybody is interested and doesn’t know, it is possible to a write Makefile that is generic for a C++ flat project (all cpp, hpp and Makefile in the same directory). And by generic I mean:
- Put any number of cpp and hpp files in the directory TheUltimateApplication.
- Put the generic Makefile in the same directory. Do not make a single change in the file (except of course, if you are using special libraries or flags, in which case, well, just add them).
./TheUltimateApplication. Watch the results on your screen.
- Of course, I also mean that the dependencies are handled correctly (as far as I know, I make no guarantee).
Here is the Makefile:
CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))
EXE = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
EXE = a.out
DEP_FLAGS = -MD -MP
CPPFLAGS = $(DEP_FLAGS) $(DEBUG_FLAGS) -Wall -std=c++11
CXXFLAGS = -g -O3
SRC = $(wildcard *.cpp)
OBJS = $(SRC:%.cpp=%.o)
DEPS = $(SRC:%.cpp=%.d)
$(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS)
rm -f *.o $(EXE) *~
@echo 'EXE:' $(EXE)
Note that there is even a target that will run your program:
make run. I use that to run the program from Emacs (
M-x compile RET make run RET).
Also note how this Makefile automagically learns about any new file in the project. Just put in it the directory, it will be in the project (i.e. automatically built and linked next time you run
make). That’s what I call effective source file management!