cmakefilegnu-make

Gnu make 4.3 Makefile change output directory of dynamic target


I am trying to compile .c-files and store the output .o-files into different folders. When making a debug-build, the output files should be stored in build/debug/. When making a release-build, the output files should be stored in build/release/. My makefile creates the correct folders, but the dynamic target always stores the output files in build/release.

Minimum makefile:

.PHONY: build
.PHONY: all
.PHONY: clean
.PHONY: debug
.PHONY: release
.PHONY: buildDirectories

BUILD_BASEDIR =         build
DEBUG_BASEDIR =         debug
RELEASE_BASEDIR =       release
BUILD_EXTENSION =       ${RELEASE_BASEDIR}
OUT_BASEDIR =           out
OUTDIR =                ${OUT_BASEDIR}/${BUILD_EXTENSION}
SRC_BASEDIR =           src
SRCDIRS =               ${SRC_BASEDIR}
BUILDDIRS =             $(subst ${SRC_BASEDIR},${BUILD_BASEDIR}/${BUILD_EXTENSION},$(SRCDIRS))
SEARCHC =               $(addsuffix /*.c ,$(SRCDIRS))
SEARCHASM =             $(addsuffix /*.S ,$(SRCDIRS))
CSOURCEFILES =          $(wildcard ${SEARCHC})
COBJECTFILES =          $(patsubst $(SRC_BASEDIR)/%.c,$(BUILD_BASEDIR)/${BUILD_EXTENSION}/%.o,$(CSOURCEFILES))

all: buildDirectories build

debug: BUILD_EXTENSION = ${DEBUG_BASEDIR}
debug: all

release: all

buildDirectories:
    mkdir -p ${BUILDDIRS} ${OUTDIR}
    $(info    SRCDIRS is $(SRCDIRS))
    $(info    CSOURCEFILES is $(CSOURCEFILES))
    $(info    COBJECTFILES is $(COBJECTFILES))

build: ${COBJECTFILES}

clean:
    rm -f -r ${BUILD_BASEDIR} ${OUT_BASEDIR}
    rm -f ${DEBUGGER_CMD_FILE} ${RELEASE_CMD_FILE} ${GIT_VERSION_FILE_PATH}

${COBJECTFILES}: $(BUILD_BASEDIR)/${BUILD_EXTENSION}/%.o: $(SRC_BASEDIR)/%.c
    $(info    $< -o $@)

Output calling make debug:

SRCDIRS is src
CSOURCEFILES is src/canDebugLog.c src/canReceive.c src/commonModule.c src/crc.c src/EEPROM.c src/fileOperations.c src/fwUpdateCommon.c src/gpio.c src/hexFileHandling.c src/hyFileHandling.c src/initialization.c src/interrupts.c src/main.c src/mgv.c src/oilTemp.c src/onewire.c src/periodicTasks.c src/powerLed.c src/SerialFlash.c src/SPI.c src/systemConfig.c src/systemReport.c src/systemStates.c src/timer.c src/uniqueRomId.c src/usb.c src/usbLog.c
COBJECTFILES is build/debug/canDebugLog.o build/debug/canReceive.o build/debug/commonModule.o build/debug/crc.o build/debug/EEPROM.o build/debug/fileOperations.o build/debug/fwUpdateCommon.o build/debug/gpio.o build/debug/hexFileHandling.o build/debug/hyFileHandling.o build/debug/initialization.o build/debug/interrupts.o build/debug/main.o build/debug/mgv.o build/debug/oilTemp.o build/debug/onewire.o build/debug/periodicTasks.o build/debug/powerLed.o build/debug/SerialFlash.o build/debug/SPI.o build/debug/systemConfig.o build/debug/systemReport.o build/debug/systemStates.o build/debug/timer.o build/debug/uniqueRomId.o build/debug/usb.o build/debug/usbLog.o
mkdir -p build/debug out/debug
src/canDebugLog.c -o build/release/canDebugLog.o
src/canReceive.c -o build/release/canReceive.o
src/commonModule.c -o build/release/commonModule.o
src/crc.c -o build/release/crc.o
src/EEPROM.c -o build/release/EEPROM.o
src/fileOperations.c -o build/release/fileOperations.o
src/fwUpdateCommon.c -o build/release/fwUpdateCommon.o
src/gpio.c -o build/release/gpio.o
src/hexFileHandling.c -o build/release/hexFileHandling.o
src/hyFileHandling.c -o build/release/hyFileHandling.o
src/initialization.c -o build/release/initialization.o
src/interrupts.c -o build/release/interrupts.o
src/main.c -o build/release/main.o
src/mgv.c -o build/release/mgv.o
src/oilTemp.c -o build/release/oilTemp.o
src/onewire.c -o build/release/onewire.o
src/periodicTasks.c -o build/release/periodicTasks.o
src/powerLed.c -o build/release/powerLed.o
src/SerialFlash.c -o build/release/SerialFlash.o
src/SPI.c -o build/release/SPI.o
src/systemConfig.c -o build/release/systemConfig.o
src/systemReport.c -o build/release/systemReport.o
src/systemStates.c -o build/release/systemStates.o
src/timer.c -o build/release/timer.o
src/uniqueRomId.c -o build/release/uniqueRomId.o
src/usb.c -o build/release/usb.o
src/usbLog.c -o build/release/usbLog.o

Output calling make release:

SRCDIRS is src
CSOURCEFILES is src/canDebugLog.c src/canReceive.c src/commonModule.c src/crc.c src/EEPROM.c src/fileOperations.c src/fwUpdateCommon.c src/gpio.c src/hexFileHandling.c src/hyFileHandling.c src/initialization.c src/interrupts.c src/main.c src/mgv.c src/oilTemp.c src/onewire.c src/periodicTasks.c src/powerLed.c src/SerialFlash.c src/SPI.c src/systemConfig.c src/systemReport.c src/systemStates.c src/timer.c src/uniqueRomId.c src/usb.c src/usbLog.c
COBJECTFILES is build/release/canDebugLog.o build/release/canReceive.o build/release/commonModule.o build/release/crc.o build/release/EEPROM.o build/release/fileOperations.o build/release/fwUpdateCommon.o build/release/gpio.o build/release/hexFileHandling.o build/release/hyFileHandling.o build/release/initialization.o build/release/interrupts.o build/release/main.o build/release/mgv.o build/release/oilTemp.o build/release/onewire.o build/release/periodicTasks.o build/release/powerLed.o build/release/SerialFlash.o build/release/SPI.o build/release/systemConfig.o build/release/systemReport.o build/release/systemStates.o build/release/timer.o build/release/uniqueRomId.o build/release/usb.o build/release/usbLog.o
mkdir -p build/release out/release
src/canDebugLog.c -o build/release/canDebugLog.o
src/canReceive.c -o build/release/canReceive.o
src/commonModule.c -o build/release/commonModule.o
src/crc.c -o build/release/crc.o
src/EEPROM.c -o build/release/EEPROM.o
src/fileOperations.c -o build/release/fileOperations.o
src/fwUpdateCommon.c -o build/release/fwUpdateCommon.o
src/gpio.c -o build/release/gpio.o
src/hexFileHandling.c -o build/release/hexFileHandling.o
src/hyFileHandling.c -o build/release/hyFileHandling.o
src/initialization.c -o build/release/initialization.o
src/interrupts.c -o build/release/interrupts.o
src/main.c -o build/release/main.o
src/mgv.c -o build/release/mgv.o
src/oilTemp.c -o build/release/oilTemp.o
src/onewire.c -o build/release/onewire.o
src/periodicTasks.c -o build/release/periodicTasks.o
src/powerLed.c -o build/release/powerLed.o
src/SerialFlash.c -o build/release/SerialFlash.o
src/SPI.c -o build/release/SPI.o
src/systemConfig.c -o build/release/systemConfig.o
src/systemReport.c -o build/release/systemReport.o
src/systemStates.c -o build/release/systemStates.o
src/timer.c -o build/release/timer.o
src/uniqueRomId.c -o build/release/uniqueRomId.o
src/usb.c -o build/release/usb.o
src/usbLog.c -o build/release/usbLog.o

Solution

  • Most probably an overkill, but ...

    makefilelocation = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
    BUILD_EXTENSION =       release
    
    all: buildDirectories build
    
    debug:
        $(warning "I will call myself")
        $(MAKE) BUILD_EXTENSION=debug -f $(makefilelocation) all
    
    release: all
    
    buildDirectories:
        mkdir -p ${BUILD_EXTENSION}
    
    build:
        touch ${BUILD_EXTENSION}/file
    

    and then

    > make
    mkdir -p release
    touch release/file
    > tree
    .
    ├── Makefile
    └── release
        └── file
    > rm -rf release
    > make debug
    Makefile:7: "I will call myself"
    make BUILD_EXTENSION=debug -f ../Makefile all
    mkdir -p debug
    touch debug/file
    > ~/bin/tree
    .
    ├── debug
    │   └── file
    └── Makefile
    

    alternatively

    BUILD_EXTENSION =       release
    
    ifeq (debug,$(MAKECMDGOALS))
    BUILD_EXTENSION =       debug
    endif
    
    all: buildDirectories build
    
    debug: all
    
    buildDirectories:
        mkdir -p ${BUILD_EXTENSION}
    
    build:
        touch ${BUILD_EXTENSION}/file