I have found the problem. It's quite simple actually when we see the Makefile in action.
gcc and clang both compile "c" files to "o" directly; cc65 cannot. Instead, it outputs an assembly file which can be assembled. Because of this, the generated dep file looks like this:
Code: Select all
build/src/test.s: src/test.c src/test.h
src/test.c src/test.h:
That's logical: it cannot know yet of the real output file, so dependency is expressed from the point of view of its real output, the "s" file. And here lies the entirety of the problem. Your Makefile does this with "c" files:
Code: Select all
### Main target files to compile ###
$(C_OBJ_FILES): $(BUILD_DIR)/%.o : %.c
@mkdir -p $(@D)
$(CC) $(CCFLAGS) $(CREATE_DEP) $< -o $(@:.o=.s)
$(AS) $(@:.o=.s) $(ASFLAGS) -l $(@:.o=)_listing.txt -o $@
Here, the rules says that for every C_OBJ_FILES, each "o" files depends on "c" files. But nothing tells make about the "s" files generated along the way. Well, the dep file mentions some dependencies, yes, but make doesn't know that "o" files are generated from "s" files from "c" files; the recipe assembles "s" files behind his back.
There are two valid solutions: split this rules into two rules, one doing "c" → "s" and the other from "s" → "o", OR use cl65.
Yes, cl65, with the
-c flag, will compile,
assemble but not link source files. The dep file will nonetheless reflect the expected dependencies: now things depends on the "o" file, which the Makefile knows about. This is the solution I prefer, because it acts more like the other compilers, and it simplify the Makefile a (tiny) bit. There are the only things to watch for with cl65:
- The order of options vs argument is important; it's better to put the source file at the end of the command line, because what's after it will not be taken into account;
- The default target is C64, use -t none to counter this.
- Most options are understood by cl65 directly, but if for some reason you need a specific compiler/assembler option that cl65 doesn't know about, then, and only then use the -Wc/-Wa option to pass that option through cl65.
So here's the diff which is quite small, and attached is the modified Makefile.
Code: Select all
diff --git a/Makefile b/Makefile
index 875a24b..2ffd942 100644
--- a/Makefile
+++ b/Makefile
@@ -44,8 +44,8 @@ TARGET = $(APP_NAME).nes
##################
# CC65 related
-AS := ca65
-CC := cc65
+AS := cl65
+CC := cl65
LD := ld65
AR := ar65
@@ -95,8 +95,8 @@ FT_DEFINES += -D FT_SFX_STREAMS=4 # Set all 4 channels for SFX
###################
# Compiler/linker flags
-ASFLAGS = -g -I $(SRC_DIR) $(INCLUDE_LIBS_FLAGS) $(INCLUDE_DATA_FLAGS) $(FT_DEFINES)
-CCFLAGS = --add-source -Oi -Cl -g $(INCLUDE_LIBS_FLAGS)
+ASFLAGS = -c -t none -g -I $(SRC_DIR) $(INCLUDE_LIBS_FLAGS) $(INCLUDE_DATA_FLAGS) $(FT_DEFINES)
+CCFLAGS = -c -t none --add-source -Oi -Cl -g $(INCLUDE_LIBS_FLAGS)
LDFLAGS = -Ln $(BUILD_DIR)/$(APP_NAME)_labels.txt -m $(BUILD_DIR)/$(APP_NAME)_map.txt --dbgfile $(APP_NAME).dbg -vm
INCLUDE_DATA_FLAGS := $(addprefix -I ,$(DATA_DIR_LIST)) $(addprefix --bin-include-dir ,$(DATA_DIR_LIST)) $(addprefix --bin-include-dir ,$(SRC_DIR_LIST))
INCLUDE_LIBS_FLAGS := $(addprefix -I ,$(SRC_DIR_LIST)) $(addprefix -I ,$(LIB_DIR_LIST))
@@ -128,12 +128,11 @@ print-% : ; @echo $* = $($*)
### Main target files to compile ###
$(C_OBJ_FILES): $(BUILD_DIR)/%.o : %.c
@mkdir -p $(@D)
- $(CC) $(CCFLAGS) $(CREATE_DEP) $< -o $(@:.o=.s)
- $(AS) $(@:.o=.s) $(ASFLAGS -l $(@:.o=)_listing.txt -o $@
+ $(CC) $(CCFLAGS) $(CREATE_DEP) -l $(@:.o=)_listing.txt -o $@ $<
$(S_OBJ_FILES): $(BUILD_DIR)/%.o : %.s
@mkdir -p $(@D)
- $(AS) $< $(ASFLAGS) $(CREATE_DEP) -l $(@:.o=)_listing.txt -o $@
+ $(AS) $(ASFLAGS) $(CREATE_DEP) -l $(@:.o=)_listing.txt -o $@ $<
##########################
### Build runtime only ###