I'm trying to build a new package for using in buildroot this useful program to power on/off the different USB ports from the raspberry pi.
The GIT repository is on this site:
https://github.com/codazoda/hub-ctrl.c
And this is the hub-ctrl.mk I've built:
################################################################################
#
# hub-ctrl
#
################################################################################
HUB_CTRL_VERSION = 42095e522859059e8a5f4ec05c1e3def01a870a9
HUB_CTRL_SITE = https://github.com/codazoda/hub-ctrl.c
HUB_CTRL_SITE_METHOD = git
HUB_CTRL_LICENSE = GPLv2+
define HUB_CTRL_BUILD_CMDS
$(TARGET_MAKE_ENV) $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(#D)
endef
define HUB_CTRL_INSTALL_TARGET_CMDS
# Install predictead application
$(INSTALL) -m 4755 -D $(#D)/hub-ctrl $(TARGET_DIR)/usr/sbin/hub-ctrl;
endef
$(eval $(generic-package))
Up to now, everything is ok. But I realize that the repository it doesn't have a Makefile, so I decided to build one on my own, but I have errors. I don't know how to link the include and library folder. I'm not an expert building makefiles so I need some help. This is my Makefile:
PROJECT_ROOT = .
OUTDIR = $(PROJECT_ROOT)/bin
BASE_NAME = hub-ctrl
NAME = $(BASE_NAME)$(D)
OBJ = $(BASE_NAME).o
INC =
LIBS = -lusb
MKDIR = mkdir -p
MV = mv
# Master rule
.PHONY: all
all: $(NAME)
# Output binary
$(NAME): $(OBJ)
$(CC) $(CFLAGS) $(INC) $(OBJ) -o $(BASE_NAME) $(LIBS)
-#$(MV) $(BASE_NAME) $(OUTDIR)/$(BASE_NAME)
rm *.o
# Intermediate object files
$(OBJ): %.o: %.c
#$(MKDIR) $(OUTDIR)
$(CC) $(CFLAGS) $(LIBS) $(INC) -c $<
# Cleanup intermediate objects
.PHONY: clean_obj
clean_obj:
rm -f $(OBJ)
#echo "obj cleaned up!"
# Cleanup everything
.PHONY: clean
clean: clean_obj
rm -rf $(OUTDIR)/$(BASE_NAME)
#echo "all cleaned up!"
This is the error I've got:
hub-ctrl.c:12:17: fatal error: usb.h: No such file or directory
#include
^
compilation terminated.
Any suggestion?
Best regards.
I've followed the indications of Peter Korsgaard. I'm using the package uhubctl from buildroot-2017.11-rc1 and I've added this package to my buildroot-2016.02 custom platform. Everything is working fine, and I'm able to power off the usb ports in my HW platform.
Thank you very much to Peter Korsgaard for his advice.
Related
Here is my project structure.
| - src
| - boot
| - table.s
| - boot.s
| - machine
| - revb
| - memmap
| - vars.s
| - os
| - utils
| - ...lots here
I am grouping features by folder, and have a special folder for machine specific code, link scripts, anything.
The problem I am having with make is that I can't seem to get the Pattern match to work.
The below runs and builds the .o files.
#This gets repetative as every file needs to have a recipe by itself.
$(TARGET_DIR)/hash.o : $(SRC_DIR)/utils/hash.s machine
#echo "compiling $<"
$(CC) $(CFLAGS) $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
The below does NOT work. It doesn't run any of the commands.
#if this works that would be perfect every folder/file will be a recipe!
$(TARGET_DIR)/%.o : $(SRC_DIR)/%.s machine
#echo "compiling $<"
$(CC) $(CFLAGS) $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
Nothing runs at all, For some reason no files seem to match that pattern.
I have also tried this.
# if this works, it would be a bit annoying as this is per feature recipe/target.
$(TARGET_DIR)/%.o : $(SRC_DIR)/boot/%.s machine
#echo "compiling $<"
$(CC) $(CFLAGS) $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
Edit
full makefile for reference
CFLAGS = -march=rv32i -mabi=ilp32
CC = riscv32-unknown-linux-gnu-as
LINKER = riscv32-unknown-linux-gnu-ld
DUMP = riscv32-unknown-linux-gnu-objdump
COPY = riscv32-unknown-linux-gnu-objcopy
SRC_DIR = src
TARGET_DIR = target
MACHINE_FILES_DIR = machine
TARGET_MACHINE = revb
# vizoros : $(TARGET_DIR)/%.o
# $(LINKER) $(TARGET_DIR)/boot.o $(TARGET_DIR)/table.o $(TARGET_DIR)/os.o $(TARGET_DIR)/hash.o -T $(TARGET_DIR)/memmap -o $(TARGET_DIR)/$#.elf
# $(DUMP) -D $(TARGET_DIR)/$#.elf > $(TARGET_DIR)/$#.list
$(TARGET_DIR)/%.o : $(SRC_DIR)/boot/%.s machine
#echo "compiling $<"
$(CC) $(CFLAGS) $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
machine: folders
cp -r $(SRC_DIR)/$(MACHINE_FILES_DIR)/$(TARGET_MACHINE)/. $(TARGET_DIR)
folders:
mkdir -p $(TARGET_DIR)
.phony: clean
clean:
rm -rf $(TARGET_DIR)
As with your other question, you are expecting too much fancy capability from make. Make is a very simple tool. It will not go looking around your directories for files that could be built. It will build only exactly what you ask it to build. It will not infer matching files based on heuristics: it will match only exact strings.
Make always works backwards: it starts with the final target you ask it to build and finds a rule that can build that. Then it looks at each of the prerequisites of that final target and finds a rule that can build each one of those. Then it looks at any prerequisites of each of the prerequisites of those, etc. Once it has built (or found source files for) all the prerequisites of a target, it builds that target, then walks back up until finally it builds the final target you asked for.
In your makefile above you've commented out the "final target" you want built (vizoros), so of course make will not build it.
I'm just going to give you a makefile that solves your problem... if you want to understand what it does please consult the GNU make manual. Note I haven't actually tried this, I just wrote it here. Also note I omitted the whole machine thing because I don't understand what it's supposed to do and you didn't really define it.
CFLAGS = -march=rv32i -mabi=ilp32
CC = riscv32-unknown-linux-gnu-as
LINKER = riscv32-unknown-linux-gnu-ld
DUMP = riscv32-unknown-linux-gnu-objdump
COPY = riscv32-unknown-linux-gnu-objcopy
SRC_DIR = src
TARGET_DIR = target
MACHINE_FILES_DIR = machine
TARGET_MACHINE = revb
# Find all .s files under SRC_DIR
SRCS := $(shell find $(SRC_DIR) -name \*.s)
# Use VPATH with a list of directories to be searched for
VPATH := $(sort $(dir $(SRCS)))
# Convert all .s files into .o files directly under TARGET_DIR
# First strip off the directory, then convert
OBJS := $(patsubst %.s,$(TARGET_DIR)/%.o,$(notdir $(SRCS)))
# Define the final target and provide all the object files as prerequisites
$(TARGET_DIR)/vizoros.elf : $(OBJS)
mkdir -p $(#D)
$(LINKER) $^ -T $(TARGET_DIR)/memmap -o $#
$(DUMP) -D $# > $(#:.elf=.list)
# Define a pattern rule to build an object file in TARGET_DIR
# The source file will be searched for via VPATH
$(TARGET_DIR)/%.o : %.s
mkdir -p $(#D)
#echo "compiling $<"
$(CC) $(CFLAGS) -c $< -o $#
#echo "assembly dump $#"
$(DUMP) -D $# > $#.list
# It must be .PHONY, not .phony: make, like all POSIX tools, is
# case-sensitive
.PHONY: clean
clean:
rm -rf $(TARGET_DIR)
References:
GNU make manual
= vs := variables
shell function
dir and notdir functions
sort and patsubst functions
VPATH
Substitution references
Automatic variables
Phony targets
Also note you had an error in your compile command; you were missing the -c option which tells the compiler to generate an object file rather than a final executable file.
Currently I am trying to get a rather big project of mine to work with a Makefile. I used Make before but in a rather crude way and not really "dynamic", this means I am pretty new to good Makefiles.
My Makefile looks like this:
INCLUDE_DIR = /inc
SOURCE_DIR = /src
BUILD_DIR = /build
BUILD_NAME = build
CC = arm-none-eabi-gcc
CFLAGS = -I$(INCLUDE_DIR)
_INCLUDES = main.h pfc.h
INCLUDES = $(patsubst %, $(INCLUDE_DIR)/%, $(_INCLUDES))
_OBJ = main.o pfc.o
OBJ = $(patsubst %, $(BUILD_DIR)/%, $(_OBJ))
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
$(CC) -c -o $# $< $(CFLAGS)
$(BUILD_NAME): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
all: $(BUILD_NAME)
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)/*
When I make the file I get this:
make: *** No rule to make target '/build/main.o', needed by 'build'. Stop.
I guess it is an error in this recipe:
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES)
$(CC) -c -o $# $< $(CFLAGS)
Sadly I am not able to get this done on my own.
All files a available in the correct folders.
I really appreciate all the help!
Tristan
You have a few issues here that I can see. But first off - just check (just incase) that all your rules are only indented with tabs and not spaces..... this can be a real "silent" killer of makefiles as they give crap error messages.
Ok so - lets assume you have:
INCLUDE_DIR = inc
SOURCE_DIR = src
BUILD_DIR = build
instead of /src etc.. as mentioned in the comments.
Do you really have inc/main.h and inc/pfc.h?
I copied and pasted your makefile added your src and inc folders (but I used gcc instead of arm-none-eabi-gcc. It did the compile lines correctly, but failed at the linker stage because you are trying to build an output file called build when there is already a folder called build (not allowed in linux - maybe ok for windows but I don't recommend).
I made an answer for another question - but it might be a better start point then you have here in the case where you have nested src/inc directories and you want to be able to clean your output folders - ill put it here for convenience:
# Get your source list (use wildcard or what ever, but just for clarity you should end up with a list of files with full paths to start with):
# Output folders/targets
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
OUTPUT_FILE = output
# Generate list of source files - this is a linux command - but you can do this in pure make using wildcard and such).
SOURCES := $(shell find $(SOURCEDIR) -name '*.c')
# Create your objects list in the obj directory
OBJECTS = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(basename $(SOURCES))))
# Create list of unique folders to create
DIRS = $(sort $(dir $(OBJECTS))) $(BIN_DIR)
# Create list of include paths
INCS = $(addprefix -I,$(sort $(dir $(SOURCES))))
# Main target rule
$(BIN_DIR)/$(OUTPUT_FILE): $(OBJECTS) | $(DIRS)
#echo linker: gcc $(OBJECTS) -o $#
#touch $#
# Rule to build your object file - ensure that the folders are created first (also create a dummy obj file) - note this works for parallel builds too (make -j
$(OBJ_DIR)/%.o: %.c | $(DIRS)
#echo compile: gcc $(INCS) -c $? -o $#
#touch $#
# Create your directories here
$(DIRS):
#echo Creating dir: $#
#mkdir -p $#
# Clean if needed
.PHONY: clean
clean:
rm -rf $(OBJ_DIR) $(BIN_DIR)
Note this is just a template, you still need to fill in the gcc/makefile flags - but its a decent start point...
Debugging
$(info ...) is your friend - for example you could do:
$(info OBJ = $(OBJ))
$(info objrule = $(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c $(INCLUDES))
To print our what make has expanded these variables / lines to be - this can yield useful debug.
Here is another version of your makefile with automatic dependency generation:
INCLUDE_DIR := inc
SOURCE_DIR := src
BUILD_DIR := build
CC := arm-none-eabi-gcc
CPPFLAGS := -I$(INCLUDE_DIR)
exes := build
build.obj := main.o pfc.o
all : ${exes:%=${BUILD_DIR}/%}
.SECONDEXPANSION:
${BUILD_DIR}:
mkdir -p $#
# Rule to link all exes.
${exes:%=${BUILD_DIR}/%} : ${BUILD_DIR}/% : $$(addprefix ${BUILD_DIR}/,$${$$*.obj}) | $${#D}
${CC} -o $# ${LDFLAGS} $^ ${LDLIBS}
# Rule to compile C sources. And generate header dependencies.
${BUILD_DIR}/%.o : ${SOURCE_DIR}/%.c | $${#D}
${CC} -o $# -c ${CPPFLAGS} ${CFLAGS} -MD -MP $<
# Include automatically generated header dependencies.
ifneq ($(MAKECMDGOALS),clean)
-include $(foreach exe,${exes},$(patsubst %.o,${BUILD_DIR}/%.d,${${exe}.obj}))
endif
clean:
rm -rf $(BUILD_DIR)
.PHONY: all clean
To add another executable target do:
exes += another
another.obj := another_main.o another_pfc.o
I downloaded this Makefile and I'm having a hard time understanding how it works.
I am programming in Ocaml and for some module, I implemented an interface (.mli). Strangely, even when I add the .mli file before the corresponding .ml file, the Makefile seems to skip it; so I'm getting the error
could not find the X.cmi for the module X.
Worse, I added some file without the required .mli and strangely again the Makefile automatically added them to the list of sources.
I'm saying strangely but perhaps its perfectly normal to Makefiles expert.
I'm not an expert when it comes to Makefile, can anyone help me understanding how this Makefile works?
The compilation works fine, when I replace the line
$(EXEC): $(OBJS)
$(CAMLC) $(CUSTOM) -o $(EXEC) $(LIBS) $(OBJS)
With
$(EXEC): $(SOURCES)
$(CAMLC) $(CUSTOM) -o $(EXEC) $(LIBS) $(SOURCES)
and add the required .mli
Try
# Makefile
PRG =
# Fichiers dans l'ordre
ML =
MLI =
CMO=${ML:.ml=.cmo}
CMX=${ML:.ml=.cmx}
CMI=${ML:.mli=.cmi}
OCAMLFLAGS = -I
OCAMLLD = -ccopt -L.
OCAMLOPT = ocamlopt.opt
OCAMLC = ocamlc.opt
OCAMLDEP = ocamldep
${PRG}: ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLLD} -o $# ${CMX}
make clean
.SUFFIXES: .ml .mli .cmo .cmx .cmi
.ml.cmx:
${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLLD} -c $<
.ml.cmo:
${OCAMLC} -c $<
.mli.cmi:
${OCAMLC} -c $<
clean:
rm -f *~ *.o *.cm? *mli
fullclean: clean
rm -f .depend ${PRG}
depend: .depend
.depend: ${ML} ${MLI}
rm -f .depend
${OCAMLDEP} ${ML} ${MLI} > .depend
include .depend
You'll have to setup PRG, ML, MLI, FLAGS, LD. :)
I have a Makefile for a C++ program that uses automatic dependency generation. The %.d recipe is taken from the GNU Make manual.
The problem is that somehow "Makefile" is being added as a target and then an implicit rule is causing it to assume it's an executable and using my src/%.cpp rule to try to compile src/Makefile.cpp. When looking at the debug info, this always happens right after the include is executed.
No need to remake target `build/Sprite.d'.
Considering target file `Makefile'.
Looking for an implicit rule for `Makefile'.
...
Trying pattern rule with stem `Makefile'.
Trying implicit prerequisite `Makefile.o'.
Looking for a rule with intermediate file `Makefile.o'.
I know include causes the given Makefiles to be rebuilt if necessary. Does it also try to rebuild the current Makefile? If so how do I stop it, and if not, then why is "Makefile" being added as a target?
Also, the include is executed, causing the .d files to be remade even if I specify a target on the command line, such as make clean. Is there any way to stop that from happening?
# $(call setsuffix,newsuffix,files)
# Replaces all the suffixes of the given list of files.
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file)))
# $(call twinfile,newdir,newsuffix,oldfile)
# Turns a path to one file into a path to a corresponding file in a different
# directory with a different suffix.
twinfile = $(addprefix $1,$(call setsuffix,$2,$(notdir $3)))
MAIN = main
SOURCE_DIR = src/
INCLUDE_DIR = include/
BUILD_DIR = build/
SOURCES = $(wildcard $(SOURCE_DIR)*.cpp)
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES))
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES))
CXX = g++
LIBS = -lpng
CXXFLAGS = -I $(INCLUDE_DIR)
.PHONY: all
all: $(MAIN)
$(MAIN): $(OBJECTS)
$(CXX) $(LIBS) $^ -o $(MAIN)
include $(DEPENDENCIES)
%.o: $(BUILD_DIR)stamp
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,$#) -o $#
$(BUILD_DIR)%.d: $(SOURCE_DIR)%.cpp $(BUILD_DIR)stamp
# echo Generate dependencies for $ $#.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o $# : ,g' $#; \
rm -f $#.$$$$
$(BUILD_DIR)stamp:
mkdir -p $(BUILD_DIR)
touch $#
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: printvars
printvars:
# echo $(SOURCES)
# echo $(OBJECTS)
# echo $(DEPENDENCIES)
Make will always try to remake the Makefile before executing the Makefile. To do so, make will look for rules which can be used to recreate the Makefile. Make will look for quite a few implicit rules and other obscure methods to (re)create the Makefile.
In your case, make somehow decided that the pattern rule %.o: $(BUILD_DIR)/stamp should be used to recreate the Makefile, which failed.
To prevent make from remaking the Makefile you can write a rule with an empty recipe:
Makefile: ;
Read the chapter Remaking Makefiles in the make manual for more explanation.
About the included Makefiles: Included Makefiles will always be included, regardless of the target. If the included makefiles are missing (or older than their prerequisites) then they will first be (re)created. That means a make clean will first generate the .d Makefiles, only to delete them again.
You can prevent the including for specific goals by wraping the include directive in a conditional:
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
Here is your entire Makefile with some fixes. I marked the places where I changed something.
# Makefile
# $(call setsuffix,newsuffix,files)
# Replaces all the suffixes of the given list of files.
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file)))
# $(call twinfile,newdir,newsuffix,oldfile)
# Turns a path to one file into a path to a corresponding file in a different
# directory with a different suffix.
twinfile = $(addprefix $1/,$(call setsuffix,$2,$(notdir $3)))
MAIN = main
SOURCE_DIR = src
INCLUDE_DIR = include
BUILD_DIR = build
SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES))
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES))
CXX = g++
LIBS = -lpng
CXXFLAGS = -I $(INCLUDE_DIR)
.PHONY: all
all: $(MAIN)
$(MAIN): $(OBJECTS)
$(CXX) $(LIBS) $^ -o $(MAIN)
# -------> only include if goal is not clean <---------
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
# ---------> fixed this target <--------------
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,$#) -o $#
# ---------> and this target <---------------
$(BUILD_DIR)/%.d: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
# echo Generate dependencies for $#;
#set -e; rm -f $#; \
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
$(BUILD_DIR)/stamp:
mkdir -p $(BUILD_DIR)
touch $#
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: printvars
printvars:
# echo $(SOURCES)
# echo $(OBJECTS)
# echo $(DEPENDENCIES)
I'm trying to create a generic makefile to build static libraries that my project uses. I've used the expertise on this site, as well as the GNU Make manual to help write the following makefile. It is working well apart from one annoying problem.
# Generic makefile to build/install a static library (zlib example)
ARCH = linux
CFLAGS = -O3 -Wall
# List of source code directories
SOURCES = src test utils
# List of header files to install
INCLUDES = src/zlib.h src/zconf.h
# Library to create
LIBNAME = libz.a
############################################################
BUILD_DIR = build/$(ARCH)
# Full path to the built library
TARGET = $(BUILD_DIR)/$(LIBNAME)
prefix = ../..
exec_prefix = prefix
libdir = $(prefix)/lib/$(ARCH)
includedir = $(prefix)/include
INSTALL_PROGRAM = install -D
INSTALL_DATA = $(INSTALL_PROGRAM) -m 644
CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c))
OBJECTS := $(addprefix $(BUILD_DIR)/,$(CFILES:.c=.o))
DEPENDS := $(OBJECTS:.o=.d)
.PHONY: all installdirs install uninstall clean
# Default
all: $(DEPENDS) $(TARGET)
# Build the dependency files
# (GNU Make Manual 4.14 Generating Prerequisites Automatically)
$(BUILD_DIR)/%.d: $(BUILD_DIR)
#echo "build dep for $*.c as $#"
#$(CC) -M $(CFLAGS) $*.c > $#.tmp
#sed s~.*:~"$(BUILD_DIR)/$*.o $#:"~ $#.tmp > $#
#rm $#.tmp
# Link all changed object files into static library
$(TARGET): $(OBJECTS)
$(AR) -rc $(TARGET) $?
# Compile C source to object code
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
# Create the necessary directory tree for the build
$(BUILD_DIR):
#for p in $(SOURCES); do mkdir -p $(BUILD_DIR)/$$p; done
# Create the necessary directory tree for installation
installdirs:
#mkdir -p $(libdir)
#mkdir -p $(includedir)
# Install the library and headers
install: all installdirs
$(INSTALL_DATA) $(TARGET) $(libdir)
for p in $(INCLUDES); do $(INSTALL_DATA) $$p $(includedir); done
# Remove the library and headers
uninstall:
rm -f $(libdir)/$(LIBNAME)
for p in $(notdir $(INCLUDES)); do rm -f $(includedir)/$$p; done
# Remove all build files
clean:
rm -fr $(BUILD_DIR)
# Pull in the dependencies if they exist
# http://scottmcpeak.com/autodepend/autodepend.html
-include $(DEPENDS)
The problem is that the dependency files are built when they don't need to be. e.g. make install shown below rebuilds the .d files before installing.
$make --version
GNU Make 3.81
$make
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
...
{ continues on making the other .d files, then the .o files }
...
cc -O3 -Wall -c src/zutil.c -o build/linux/src/zutil.o
cc -O3 -Wall -c test/test.c -o build/linux/test/test.o
cc -O3 -Wall -c utils/utils.c -o build/linux/utils/utils.o
ar rc { ... .o files ... }
All good up to this point! But a 'make install' now will rebuild the .d files
$make install
build dep for utils/utils.c as build/linux/utils/utils.d
build dep for test/test.c as build/linux/test/test.d
build dep for src/zutil.c as build/linux/src/zutil.d
{ ... }
install -D -m 644 build/linux/libz.a ../../lib/linux
for p in src/zlib.h src/zconf.h; do install -D -m 644 $p ../../include; done
I tried to 'touch' the .d files when the objects are built, so the update time is newer than the .o files, but that had no effect. What's wrong with my makefile?
The problem is that you include the dependency files (whatever.d), and you also have a rule for building these files. So every time you use this makefile, no matter what target you specify, it will rebuild them, include them, and execute again.
Try this for an approach to dependency handling that solves this problem. Basically, you don't need a separate rule for foo.d, just make it a side effect of the foo.o rule (it takes some thought to realize that this will work).