I am trying to build my c project on windows using a makefile and nmake.
I get the following error:
NMAKE : fatal error U1071: cycle in dependency tree for target 'src\source.c'
Stop.
The full makefile is this
CC = cl
LINK = link
CFLAGS = /Ox \
/I ext\MulticoreBSP-for-C\ \
/I ext\unistd\include \
/I ext\pthreads-win32\sources\pthreads-w32-2-9-1-release \
/D HAVE_STRUCT_TIMESPEC
SOURCE_DIR = src
OBJECT_DIR = build
LIBS = ext\pthreads-win32\sources\pthreads-w32-2-9-1-release\pthreadVC2.lib
DLLS = bin\pthreadVC2.dll
DLLS_SRC = ext\pthreads-win32\sources\pthreads-w32-2-9-1-release\pthreadVC2.dll
BSP_SOURCES = ext\MulticoreBSP-for-C\mcbsp.c ext\MulticoreBSP-for-C\mcinternal.c ext\MulticoreBSP-for-C\mcutil.c
USER_SOURCES = source.c
SOURCES = src\$(USER_SOURCES) $(BSP_SOURCES)
OBJECTS = $(SOURCES:*.c=build\*.obj)
# OBJECTS = build\source.obj build\mcbsp.obj build\mcinternal.obj build\mcutil.obj
EXECUTABLE = bin\BSP.exe
all: $(EXECUTABLE) $(DLLS) $(OBJECTS)
$(EXECUTABLE): $(OBJECTS)
$(LINK) $(OBJECTS) $(LIBS) /OUT:$(EXECUTABLE)
$(DLLS): $(DLLS_SRC)
copy $** $@
$(OBJECTS): $(SOURCES)
$(CC) $(LDFLAGS) /c /Fo.\$(OBJECT_DIR)\ $@ $** $(CFLAGS)
clean:
del $(OBJECT_DIR)\*.obj bin\*.dll bin\*.exe
I can see that the issue comes from defining OBJECTS
in line 21 as
OBJECTS = $(SOURCES:*.c=build\*.obj)
and then having the rule $(OBJECTS): $(SOURCES)
. The fact that this is cyclic is fairly clear, and using the commented definition of OBJECTS
in line 22 works fine.
How can I achieve an automatic definition of OBJECTS
without the rule at line 33 causing trouble? Do I need a different rule, or something else?
(I have separate folders for the source files and the objects, and I think having that prevents me from using a simple rule like .c.obj:
. At least, I haven't got it to work using something of that form).
Thanks.
Although the pattern matching syntax $(macroname:string1=string2)
is supported by nmake, use of wildcards in this way is not. I will edit this answer if I find a way to use wildcards in nmake's version of string substitution.
Edit:
Its a little dodgy, but the following solves the problem
BSP_SOURCES = mcbsp.c mcinternal.c mcutil.c
USER_SOURCES = source.c
SOURCES = src\$(USER_SOURCES) ext\MulticoreBSP-for-C\$(BSP_SOURCES: = ext\MulticoreBSP-for-C\)
_OBJECTS = build\$(USER_SOURCES) build\$(BSP_SOURCES: = build\)
OBJECTS = $(_OBJECTS:.c=.obj)
Basically, pattern matching the spaces inbetween the elements in the list of sources, rather than using a wildcard. Note that the first prefix is added outside of the pattern match, because there is no space at the start of the list. Also note that the substitution had to be done in two steps.
Inelegant but effective.