Thread: Experiment in makefile went wrong...

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Experiment in makefile went wrong...

    For some reason make is not noticing the target I set for one of the binaries it's supposed to find & update/build:

    Code:
    make: *** No rule to make target 'bin/out.quick.elf', needed by 'quick'.  Stop.
    Code:
    exe_sfx:=elf
    src_files:=$(wildcard *.c)
    inc_files:=$(wildcard *.h)
    
    def_exe=bin/out.$1.$(exe_sfx)
    def_obj=$(src_files:%.c=%.$1.c.o)
    
    quick@program:=$(call def_exe,quick)
    quick@objects:=$(call def_obj,quick)
    quick@outputs:=$(quick@objects) $(quick@trial)
    quick@options:=-O3 -D _QUICK
    debug@program:=$(call def_exe,debug)
    debug@objects:=$(call def_obj,debug)
    debug@outputs:=$(debug@objects) $(debug@trial)
    debug@options:=-ggdb -D _DEBUG
    timed@program:=$(call def_exe,timed)
    timed@objects:=$(call def_obj,timed)
    timed@outputs:=$(timed@objects) $(timed@trial)
    timed@options:=-ggdb -pg -D _TIMED
    
    using:=-lglfw -lGLEW -lGL
    objects:=$(quick@objects) $(debug@objects) $(timed@objects)
    
    WALL:=-Wall -Wextra -Werror=implicit-function-declaration
    mkdir:=$(if $(wildcard $1),,$(shell echo mkdir $1))
    mkdirs:=$(if $(dir $1),$(call mkdirs,$(dir $1))) $(call mkdir,$1)
    trydir:=$(call mkdirs,$(dir $1))
    
    _cmd=$(foreach i,$2,$(if $(filter @%,$i),$($1$i),$i))
    var=$(patsubst .%,%,$(suffix $(basename $1)))
    cmd=$(call _cmd,$(call var,$1),$2)
    
    vpath %.exe		./bin
    vpath %.dll		./bin
    vpath %.AppImage	./bin
    vpath %.elf		./bin
    vpath %.out		./bin
    vpath %.so		./bin
    vpath %.app		./bin
    vpath %.o		./bin/obj
    
    rebuild: clean build
    
    clean:
    	$(RM) -R bin/*
    
    run: quick
    	./$(quick@program)
    
    test: debug
    	./$(debug@program)
    
    gprof: timed
    	./$(timed@program)
    	gprof ./$(timed@program)
    
    ddd: debug
    	ddd ./$(debug@program)
    
    gdb: debug
    	gdb -ex run --args ./$(debug@program)
    
    gede: debug
    	gede --args ./$(debug@program)
    
    nemiver: debug
    	nemiver ./$(debug@program)
    
    build: quick debug timed
    quick: $(quick@program)
    debug: $(debug@program)
    timed: $(timed@program)
    
    bin/%.$(exe_sfx): bin/ $(objects)
    	@echo $(call cmd,$@,$(CC) @options -o $@ @objects $(using))
    
    bin/obj/%.c.o: bin/src/%.c bin/ bin/obj/ $(inc_files)
    	@echo $(call cmd,$@,$(CC) $(WALL) @options -o $@ -c $<)
    
    bin/src/%.quick.c: %.c bin/src/
    	$(CC) -o $@ -E $<
    bin/src/%.debug.c: %.c bin/src/
    	$(CC) -o $@ -E $<
    bin/src/%.timed.c: %.c bin/src/
    	$(CC) -o $@ -E $<
    
    %/:
    	mkdir $@

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Never mind, I fixed it, forgot how as I forgot about this thread by the time I did fix it.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Got side-tracked onto a different problem, trying to simplify my makefiles further, ran into a problem trying to extract the 1st directory in a path so for example src/try/sub/file.c should become src or src/, either is fine, It tried this:
    Code:
    initdir=$(if $(dir $1),$(call initdir,$(patsubst %/,%,$(dir $1))),$1)
    but the makefile simply failed when I tried to use it, any ideas? As for why I need the 1st directory it's a by product of trying to retrieve the sub project name from the path which I'm attempting like this:
    Code:
    project=$(call initdir,$(patsubst $(SRC_DIR)/%,%,$1))
    Where src/try/sub/file.c would become just try

    Edit: Never mind, just found out why it wasn't working, instead of following the normal "return nothing if nothing matches" convention that most makefile functions follow, dir decided to be the one .............. that does differently "if nothing matches return ./ instead"

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    For anyone that wanted the functions also, here's what I settle with along with what outputs what:
    Code:
    equal=$(if $(filter "$1","$2"),1)
    noteq=$(if $(filter "$1","$2"),,1)
    _TRY:=src/try/sub/file
    TRY:=$(_TRY)$(ext)_debug.c
    variant=$(patsubst .$(_ext)_%,%,$(suffix $(basename $1)))
    #$(dir ...) returns ./ if nothing is extracted so we have to force the empty
    #result ourselves with an alternate function
    dotdir=$(patsubst %/,%,$(dir $1))
    folder=$(patsubst .,,$(call dotdir,$1))
    paths=$(if $(call folder,$1),$(call paths,$(call folder,$1))) $1
    __dirs=$(filter-out $1,$2) $(if $(suffix $1),,$1)
    _dirs=$(call __dirs,$(lastword $1),$1)
    dirs=$(call _dirs,$(call paths,$1))
    Code:
    make info
    ...
    equal a,b=
    noteq a,b=1
    dir bin=./
    folder bin=
    folder bin/obj=bin
    dirs src/try/sub/file=src src/try src/try/sub src/try/sub/file
    dirs src/try/sub/file._x86_64_linux_cc_debug.c=src src/try src/try/sub
    uptwice src/try/sub/file._x86_64_linux_cc_debug.c=src/try
    variant src/try/sub/file._x86_64_linux_cc_debug.c=debug
    lastdir src/try/sub/file._x86_64_linux_cc_debug.c=sub
    initdir src/try/sub/file._x86_64_linux_cc_debug.c=src
    project src/try/sub/file._x86_64_linux_cc_debug.c=try
    Edit: Here's some other useful functions I'm experimenting with along with example usage:
    Code:
    mkdir=$(if $(wildcard $1),echo,mkdir $1)
    mkdirs=$(foreach i,$(call dirs,$1),$(call mkdir,$i))
    command=$(foreach i,$3,$(if $(filter @%,$i),$($1@$2$i),$i))
    create=$(call command,$(call project,$1),$(call variant,$1),$2)
    precompile=$(call create,$1,$(CC) @options -E $1 -c $2)
    
    $(OBJ_DIR)/%_debug.c: $(SRC_DIR)%.c
    	$(call mkdirs,$@)
    	$(call precompile,$@,$<)
    $(OBJ_DIR)/%_quick.c: $(SRC_DIR)%.c
    	$(call mkdirs,$@)
    	$(call precompile,$@,$<)
    $(OBJ_DIR)/%_timed.c: $(SRC_DIR)%.c
    	$(call mkdirs,$@)
    	$(call precompile,$@,$<)
    $(OBJ_DIR)/%_trace.c: $(SRC_DIR)%.c
    	$(call mkdirs,$@)
    	$(call precompile,$@,$<)

  5. #5
    Registered User
    Join Date
    Apr 2021
    Posts
    140
    Worth pointing this out: vpath is for finding sources, not targets. You will probably be a lot more successful if you cd into $outdir, and then use vpath to refer to $sources, rather than cd'ing into $sources and trying to generate/locate $outdir/foo.o using vpath.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's wrong with this Makefile??
    By Necromancer in forum C Programming
    Replies: 1
    Last Post: 02-07-2008, 08:58 AM
  2. experiment I'm doing
    By David.Joseph in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 07-20-2007, 12:52 AM
  3. My new experiment.
    By Brian in forum A Brief History of Cprogramming.com
    Replies: 23
    Last Post: 04-14-2006, 10:10 AM
  4. character pixel width experiment
    By ober in forum Tech Board
    Replies: 0
    Last Post: 05-19-2004, 11:17 AM
  5. CD experiment
    By confuted in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 09-28-2003, 08:27 PM

Tags for this Thread