How do I compile and upload Arduino sketches from the command line on Mac and Linux? I've installed the Arduino programming environment. Are there some sample makefiles anywhere?
There is a command-line Arduino toolkit named Ino. It just does that.
Compiling and uploading sketches (as apposed to C/C++ sources) on the command line (on Windows, Mac, and Linux) is supported directly via flags to the arduino executable since 1.5.0.
An ino can be compiled and uploaded with arduino --upload [sketch.ino]
Documentation
This is my boilerplate gnu make include for AVR projects, you may need to adapt some of it to fit your environment. It creates dependencies, has a host of standard gcc options I find useful or that optimize for size, as well as a library dir I use. I used this successfully to compile arduino software, I also previously hacked the PdePreprocessor in the arduino editor to be run from the command line to generate all the voodoo:
https://github.com/wesen/mididuino/blob/master/app/src/processing/app/preproc/PdePreprocessor.java
#
# generic AVR makefile
#
# (c) July 2011 - Manuel Odendahl - wesen#ruinwesen.com
#
# include this into your main Makefile, after having defined TARGET and TARGET_OBJS
all: $(TARGET).hex
CURDIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(CURDIR)MidiCtrl.mk
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
AVR_ARCH ?= atmega64
LDAVR_ARCH ?= avrmega64
FLASH_PROTOCOL = jtag2
CFLAGS += -Os -ffunction-sections -DAVR -I. -mmcu=$(AVR_ARCH) -mcall-prologues -fshort-enums -fpack-struct -Wall -Werror
CFLAGS += -Wall -DLITTLE_ENDIAN -g -flto
CFLAGS += no-tree-loop-optimize -ffreestanding -morder1 -funsigned-char -funsigned-bitfields -fshort-enums -fpack-struct
CFLAGS += -fdata-sections -fno-split-wide-types -fno-inline-small-functions -mcall-prologues
CLDFLAGS += -Wl,--relax,--gc-sections -ffunction-sections
CLDFLAGS += -mmcu=$(AVR_ARCH)
LDFLAGS = -m $(LDAVR_ARCH) -M
# generate list
# CFLAGS += -Wa,-adhlns=$#.lst
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
%.o: %.s
$(CC) $(CFLAGS) -c $< -o $#
%.s: %.c
$(CC) -S $(CFLAGS) -fverbose-asm $< -o $#
%.o: %.S
$(CC) $(CFLAGS) -c $< -o $#
%.syx: %.hex
ihex2sysex $< $#
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $#
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $#
%.ee_srec: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $#
AVR_BASE_DIR ?= $(abspath $(CURDIR)..)
AVR_LIB_DIR ?= $(AVR_BASE_DIR)/hardware/libraries
AVR_LIBS += CommonTools Midi
AVR_LIB_DIRS += $(foreach lib,$(AVR_LIBS),$(AVR_LIB_DIR)/$(lib))
AVR_INC_FLAGS += $(foreach dir,$(AVR_LIB_DIRS),-I$(dir))
AVR_OBJS += $(foreach dir,$(AVR_LIB_DIRS),$(foreach file,$(wildcard $(dir)/*.cpp),$(subst .cpp,.o,$(file))))
AVR_OBJS += $(foreach dir,$(AVR_LIB_DIRS),$(foreach file,$(filter-out $(AVR_HOST_EXCLUDE),$(wildcard $(dir)/*.c)),$(subst .c,.o,$(file))))
AVR_DEPS += $(subst .o,.d,$(AVR_OBJS))
# AVR_HOST_EXCLUDE can be used to exclude specific files later on
CXXFLAGS += $(AVR_INC_FLAGS)
CFLAGS += $(AVR_INC_FLAGS)
CXXFlags += -Werror -Wall
CFLAGS += -Werror -Wall
default: all
%.d:%.c
set -e; $(CC) -MM $(CFLAGS) $< \
| sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' > $# ; \
[ -s $# ] || rm -f $#
%.d:%.cpp
set -e; $(CXX) -MM $(CXXFLAGS) $< \
| sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' > $# ; \
[ -s $# ] || rm -f $#
%.host.d:%.c
set -e; $(CC) -MM $(CFLAGS) $< \
| sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' > $# ; \
[ -s $# ] || rm -f $#
%.host.d:%.cpp
set -e; $(CXX) -MM $(CXXFLAGS) $< \
| sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' > $# ; \
[ -s $# ] || rm -f $#
printlibs:
echo $(AVR_LIBS)
$(TARGET).elf: $(TARGET).o $(TARGET_OBJS) $(AVR_OBJS)
$(CXX) $(CLDFLAGS) -g -o $# $^
_clean:
- rm *.elf *.hex *.o .midictrl.flags
libclean:
rm -rf $(TARGET_OBJS) $(OBJS)
# concrete settings for development environment
UNAME=$(shell uname)
ISWIN=$(findstring CYGWIN,$(UNAME))
ISMAC=$(findstring Darwin,$(UNAME))
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
AVR_ARCH = atmega64
F_CPU = 16000000L
CORE = minicommand2
Official CLI tool
The arduino team is developing a cli client
https://github.com/arduino/arduino-cli
Announcement: https://blog.arduino.cc/2018/08/24/announcing-the-arduino-command-line-interface-cli/
You can do almost everything with this, from downloading boards and libraries, to compile and upload scripts. What's missing is the monitoring part.
To monitor in linux you can still use the commands stty to configure port and cat to read it.
stty -F /dev/ttyACM0 38400 # <-- Baud rate. The number in Serial.begin()
cat /dev/ttyACM0 # <-- Port
You can find the port with arduino-cli
arduino-cli board list
Full instructions in the Github repo and the man page:
$ arduino-cli Arduino Command Line Interface (arduino-cli).
Usage: arduino-cli [command]
Examples: arduino <command> [flags...]
Available Commands:
board Arduino board commands.
compile Compiles Arduino sketches.
config Arduino Configuration Commands.
core Arduino Core operations.
help Help about any command
lib Arduino commands about libraries.
sketch Arduino CLI Sketch Commands.
upload Upload Arduino sketches.
version Shows version number of Arduino CLI.
You need to actually create a viable cpp file out of your arduino sketch. The arduino environment does that for you automatically. One trick to get to those files is to open your arduino preferences.txt (it's in ~/Library/Arduino on the mac, I think in your Documents and Settings or Application Data on windows, don't remember exactly), and set build.verbose=true and upload.verbose=true. Start arduino, and compile your sketch (don't upload it). The console at the bottom will show you which files were compiled. You can now go to that directory, which will contain the cpp file, and compiled object files for all the core arduino objects. You can copy those into your project and use the cpp file to do further hacking. Let me know if you need more information about the Makefile, I can provide you with those I have.
You can actually use the arduino GUI to compile and upload, and set the editor to external in the preferences. That way, you can edit the C++ (PDE) files from xcode, and have arduino generate the actual CPP and build the whole shebang.
You can also use XCode to write plain C++/C for the arduino, using the avr-gcc compiler.
Have a look at: https://stackoverflow.com/a/8192762/153835
You can then use the plain avrdude upload tool to program the arduino. Have a look at: http://www.ladyada.net/library/arduino/bootloader.html
It used to be that the protocol spoken by Arduino was a modification of the STK500 protocol, and that only the avrdude bundled with arduino could speak it. I don't know if the mainstream avrdude was upgraded, or if you still have to resort to the avrdude inside the Arduino folder.
You can use biicode (it's a project I'm working in) which is based on CMake (but you don't actually need to write any cmake file) and is also a tool to manage Arduino libraries
It's main features are:
Dependencies resolution, transitively, as maven does, but without config files: reads dependencies directly from source code.
Central repository, anyone can upload their libraries. They can be explored, navigated and discovered in the web
Version control: it checks versions compatibility and allows safe updates of dependencies
You can use it with any text editor (it has optional eclipse integration)
It manages project setup and compilations, flashes generated firmware to the board
You can see a quick demo here and read more in the documentation.
If you can use cmake then there are some links in the same web (this and this for example). GNU makefile is a little bit different from cmake but nothing complicated. Just Google a little bit and you can find a lot of Makefile examples how to compile AVR code.
I use platformio, quite like it. It also has extensions into Visual Studio Code, so you can do everything from there. It has library manager and uploader built-in.
My setup is a NFS drive where I have the code, mounted on my linux laptop, and also mounted on my Raspberry Pi that sits next to my Arduino's.
When it's time to compile, I do so on my laptop, and as the RPi is next to the Arduino, I upload from there..
After installing and configuring, the basics are simple;
'platformio run' will compile your code.
'platformio run -t upload' will compile & upload.
I also have a bash function to upload without compiling;
function th(){
if [ "${1}" = "upload" ];then
if [ ! -f platformio.ini ]; then
echo platformio.ini not found
else
UPLOAD_PORT=`cat platformio.ini | grep upload_port | awk '{print $3}'`
if [ "${UPLOAD_PORT}" = "" ]; then
echo no upload port
else
if [ "${2}" != "" ]; then
FIRMWARE=${2}
else
#the firmware location seems to have moved
# FIRMWARE='.pioenvs/megaatmega2560/firmware.hex'
FIRMWARE='.pio/build/megaatmega2560/firmware.hex'
fi
if [ -f "${FIRMWARE}" ]; then
avrdude -v -p atmega2560 -C /home/stevenk/.platformio/packages/tool-avrdude/avrdude.conf -c wiring -b 115200 -D -P "${UPLOAD_PORT}" -U flash:w:$FIRMWARE:i
else
echo ${FIRMWARE} not found
fi
fi
fi
else
wget --timeout 8 -qO- http://192.168.178.212/$1
fi
}
If you do not insist on make there is also scons/sconstruct scons/sconstruct. Since this in basically written in Python it is much simpler to tweak than make. In addition it can be debugged with any Python debugger.
I have a makefile for Arduino which can be used to compile and upload Arduino (or plain AVR C) programs to Arduino.
Following are some of the important features of this makefile
Supports upload via Arduino as ISP or any programmer
Supports compiling plain AVR C programs
Supports user as well as system libraries.
Generate assembly and symbol files
Program using alternate Arduino core (like ATtiny or Arduino alternate cores)
There's an official Arduino CLI tool:
https://blog.arduino.cc/2021/02/15/arduino-cli-0-16-0-is-ready-for-you-all/?queryID=undefined
It works pretty well, in my opinion. The GitHub repo is here:
https://github.com/arduino/arduino-cli
It's version 0.16.0. so sort of beta, but not really....
You can find the libraries and sample codes included in the Arduino under "file->examples".
Related
I have been working on a 32-bit operating system project written in C using GNU LD version 2.34 as the linker.
As part of the build process, I use the following command:
ld -m elf_i386 -nostdlib -T ld/loader.ld build/bootloader/loader.o build/bootloader/loader.elf -o loader_full.elf
When using GNU LD version 2.34, this command succeeds. However, when I use a version higher than this, I get the following error:
ld: cannot use executable file 'build/bootloader/loader.elf' as input to a link
If necessary, here is the full Makefile script:
CC_FLAGS = -g -m32 -ffreestanding -nostartfiles -nostdlib -fno-stack-protector
LD_FLAGS = -m elf_i386 -nostdlib
CC := gcc ${CC_FLAGS}
LD := ld ${LD_FLAGS}
BOOTLOADER_DRIVERS = kernel/drivers/disk/ata.c kernel/drivers/io/screen.c kernel/drivers/utils/mem.c kernel/drivers/utils/ports.c
raw: prep os-image.bin
convert_vmdk: os-image.vmdk
all: prep os-image.bin
ESFS_raw_write: ESFS_raw_write.c
gcc $^ -o $#
# run OS in QEMU
run:
qemu-system-i386 -drive format=raw,file=os-image.bin
# assemble boot sector
build/bootloader/boot_sect.bin: boot/boot_sect.asm
nasm $^ -f bin -o $#
# compile second stage bootloader
build/bootloader/loader_2.o build/drivers/*.o: boot/*.c ${BOOTLOADER_DRIVERS}
${CC} -c $^
mv loader.o build/bootloader/loader_2.o
mv *.o build/drivers/
# link object files into kernel loader
build/bootloader/loader.elf: build/bootloader/loader_2.o build/drivers/*.o
${LD} -T ld/loader.ld $^ -o $#
rm build/bootloader/loader_2.o
# assemble first stage bootloader
build/bootloader/loader.o: boot/loader.asm
nasm $^ -f elf -o $#
# link first and second stage bootloaders
build/bootloader/loader_full.elf: build/bootloader/loader.o build/bootloader/loader.elf
${LD} -T ld/loader.ld $^ -o $#
# make bootloader binary file
build/bootloader/loader.bin: build/bootloader/loader_full.elf
objcopy $^ -O binary $#
./scripts/pad_loader.sh
# clean up unnecessary files
# rm build/bootloader/*.o build/bootloader/*.elf build/drivers/*.o
build/kernel/interrupt.o: kernel/cpu/interrupt.asm
nasm $^ -f elf -o $#
# compile kernel & write to 10MB raw drive image
build/kernel/hdd.bin: kernel/drivers/*/*.c kernel/cpu/*.c kernel/libc/*.c build/kernel/interrupt.o kernel/*.c
${CC} $^ -o build/kernel/kernel.o -T ld/kernel.ld
./scripts/write_kernel_to_drive.sh
# concat 3 boot stages into os-image file
os-image.bin: build/bootloader/boot_sect.bin build/bootloader/loader.bin build/kernel/hdd.bin
cat $^ > $#
os-image.vmdk:
VBoxManage convertfromraw os-image.bin os-image.vmdk --format VMDK
VBoxManage internalcommands sethduuid /home/tim/Dev/OSDev/os-image.vmdk 6372c00a-a62e-4241-9a21-90fa4c22f019
# prepare directory structure for build process
prep:
mkdir -p build/bootloader
mkdir -p build/drivers
mkdir -p build/kernel
# clean up build files and os-image binary
clean:
-rm -rf build/
-rm *.bin *.vmdk
-rm ESFS_raw_write
The project is also on GitHub, so you can build it for yourself:
http://github.com/TimCve/OSDev.git
I have just come up with a similar problem.
It seems ld version GNU ld (GNU Binutils) 2.36.1 links the file into an executable format.
To fix it, add -r in your ld command to output a relocatable format file.
From the ld manual:
-r
--relocateable
Generate relocatable output--i.e., generate an output file that can in turn serve as input to ld. This is often called partial linking. As a side effect, in environments that support standard Unix magic numbers, this option also sets the output file's magic number to OMAGIC. If this option is not specified, an absolute file is produced. When linking C++ programs, this option will not resolve references to constructors; to do that, use -Ur. This option does the same thing as -i.
It's not that ld can't take ELF files as input. It's that it won't take executable files as input. The error is:
ld: cannot use executable file '...' as input to a link
See https://sourceware.org/bugzilla/show_bug.cgi?id=26223
Does it work to simply use chmod -x $# after building the .elf file?
In my (eclipse-based) multicore MCUXpresso project, I had to add this line to my post-build steps to modify a byte inside of the generated "*.o" file so the linker step which used that file wouldn't complain anymore. This happened after I updated to version 11.6 which includes the LD version mentioned previously. I originally found this on the forums for NXP MCUXpresso, but I assume it will work similarly for just about anyone:
dd if=/dev/zero of="${BuildArtifactFileName}.o" bs=1 seek=16 conv=notrunc count=2
NXP MCUXpresso fix
I'm trying to build my serial port USB driver from C source using makefile but when I type sudo make or sudo make install, the output is like;
sudo make
gcc -Wall -D__KERNEL__ -DMODULE
-I/lib/modules/4.15.0-45-generic/build/include -D__SMP__ -DSMP -I/usr/src/linux-4.15.0-45-generic/drivers/usb/serial/ -O -c -o ftdi_sio.o ftdi_sio.c In file included from
/lib/modules/4.15.0-45-generic/build/include/linux/kernel.h:7:0,
from ftdi_sio.c:251: /lib/modules/4.15.0-45-generic/build/include/linux/linkage.h:8:25:
fatal
error: asm/linkage.h: No such file or directory
compilation terminated. : recipe for target 'ftdi_sio.o'
failed make: *** [ftdi_sio.o] Error 1
I know asm/linkage.h file is not in include/linux directory. The problem is, how can I change the directory of given header file or how to replace header file to given directory. I'm also open for other solutions. Makefile and Rules.make files are;
Rules.make:
# -*-makefile-*-
#
# This file is part of the sample code for the book "Linux Device Drivers",
# second edition. It is meant to be generic and is designed to be recycled
# by other drivers. The comments should be clear enough.
# It partly comes from Linux Makefile, and needs GNU make. <rubini#linux.it>
# TOPDIR is declared by the Makefile including this file.
ifndef TOPDIR
TOPDIR = .
endif
# KERNELDIR can be speficied on the command line or environment
ifndef KERNELDIR
KERNELDIR := $(shell echo "/lib/modules/`uname -r`/build")
endif
# The headers are taken from the kernel
INCLUDEDIR = $(KERNELDIR)/include
# We need the configuration file, for CONFIG_SMP and possibly other stuff
# (especiall for RISC platforms, where CFLAGS depends on the exact
# processor being used).
ifeq ($(KERNELDIR)/.config,$(wildcard $(KERNELDIR))/.config)
include $(KERNELDIR)/.config
else
MESSAGE := $(shell echo "WARNING: no .config file in $(KERNELDIR)")
endif
# ARCH can be speficed on the comdline or env. too, and defaults to this arch
# Unfortunately, we can't easily extract if from kernel configuration
# (well, we could look athe asm- symlink... don't know if worth the effort)
ifndef ARCH
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/)
endif
# This is useful if cross-compiling. Taken from kernel Makefile (CC changed)
AS =$(CROSS_COMPILE)as
LD =$(CROSS_COMPILE)ld
CC =$(CROSS_COMPILE)gcc
CPP =$(CC) -E
AR =$(CROSS_COMPILE)ar
NM =$(CROSS_COMPILE)nm
STRIP =$(CROSS_COMPILE)strip
OBJCOPY =$(CROSS_COMPILE)objcopy
OBJDUMP =$(CROSS_COMPILE)objdump
# The platform-specific Makefiles include portability nightmares.
# Some platforms, though, don't have one, so check for existence first
ARCHMAKEFILE = $(TOPDIR)/Makefile.$(ARCH)
ifeq ($(ARCHMAKEFILE),$(wildcard $(ARCHMAKEFILE)))
include $(ARCHMAKEFILE)
endif
USBDI=/linux
# CFLAGS: all assignments to CFLAGS are inclremental, so you can specify
# the initial flags on the command line or environment, if needed.
CFLAGS += -Wall -D__KERNEL__ -DMODULE -I$(INCLUDEDIR)
ifdef CONFIG_SMP
CFLAGS += -D__SMP__ -DSMP
endif
# Prepend modversions.h if we're running with versioning.
ifdef CONFIG_MODVERSIONS
CFLAGS += -DMODVERSIONS -include $(KERNELDIR)/include/linux/modversions.h
endif
#Install dir
VERSIONFILE = $(INCLUDEDIR)/linux/version.h
VERSION = $(shell awk -F\" '/REL/ {print $$2}' $(VERSIONFILE))
INSTALLDIR = /lib/modules/$(VERSION)/misc
Makefile:
# This Makefile has been simplified as much as possible, by putting all
# generic material, independent of this specific directory, into
# ../Rules.make. Read that file for details
# The usb serial headers
INCLUDEUSBSER := $(shell echo "/usr/src/linux-`uname -r`/drivers/usb/serial/")
TOPDIR := $(shell pwd)
#TOPDIR = .
include $(TOPDIR)/Rules.make
CFLAGS += -I$(INCLUDEUSBSER) -O
OBJS = ftdi.o
all: $(OBJS)
ftdi.o: ftdi_sio.o
$(LD) -r $^ -o $#
install:
install -d $(INSTALLDIR)
install -c $(OBJS) $(INSTALLDIR)
clean:
rm -f *.o *~ core
I also have ftdi_sio.c file and ftdi.sio.h file which is I think not bounded with this problem.
I am trying to interface ssd1963 LCD with Raspberry Pi3 model B+, by following this guide on Github.
https://github.com/matusnovak/rpi-tftgl
While trying to install the makefile provided for rpi-tftgl in rpi-tftgl/tftgl directory I am getting this error when I run make command.
Here is the link of my captured image of pi terminal window showing the exact error:
Following is the error i recieved when I execute make command :
gcc -c src/tftgl.c -o src/tftgl.o -I/opt/vc/include -I. -Iinclude -D:0 -O3
<command-line>:0:1: error: macro names must be identifiers
Makefile:18: recipe for target 'src/tftgl.o' failed
make: *** [src/tftgl.o] Error 1
Can I get a solution for this or any recommendation for any other source or links which I can follow to interface ssd1963 LCD with touch enabled with Raspberrypi3.
Adding the makefile,
CC=gcc
AR=ar
DISPLAY?=ERROR
CFLAGS=-I/opt/vc/include -I. -Iinclude -D$(DISPLAY) -O3
prefix?=/usr/local
.PHONY: default all clean
default: tftgl
all: default
tftgl: libtftgl.a
libtftgl.a: src/tftgl.o
$(AR) rcs libtftgl.a src/tftgl.o
src/tftgl.o: src/tftgl.c src/tftgl_ssd1963.h src/tftgl_ads7843.h
$(CC) -c src/tftgl.c -o src/tftgl.o $(CFLAGS)
install: tftgl
install -m 0755 libtftgl.a $(prefix)/lib
install -m 0644 include/tftgl.h $(prefix)/include
clean:
-rm -f src/*.o
-rm -f libtftgl.a
I am providing here link to tftgl.c,
https://github.com/matusnovak/rpi-tftgl/blob/master/tftgl/src/tftgl.c
The (writer of) the Makefile doesn't take into account that the environment variable DISPLAY can be defined to something else than a macro definition. As it's not documented whether and how you'd need to define it, the best you can do is to make with the variable unset:
(unset DISPLAY; make)
If you prefer to change the makefile, just remove the ? from DISPLAY?=ERROR, leaving DISPLAY=ERROR.
I've been trying to get the following makefile to work.
INCLUDE=Include/
LIBRARY=Lib/
CC=g++
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LIBRARIES=-lGLEW -framework OpenGL -framework GLUT
else
LIBRARIES=-lGL -lglut -lGLEW
endif
SRC := $(shell find -name *.cpp | tr '\n' ' ')
all: release debug
.PHONY: init
init:
#mkdir -p build/release/object
#mkdir -p build/debug/object
debug: init
debug: CC = g++ -g
debug: BUILD_DIR = build/debug
debug: makegeneral
release: init
release: CC = g++
release: BUILD_DIR = build/release
release: makegeneral
makegeneral: OBJ = $(SRC:./src/%.cpp=$(BUILD_DIR)/object/%.o)
makegeneral: $(OBJ)
$(CC) -I$(INCLUDE) -L$(LIBRARY) $(OBJ) $(LIBRARIES) -o VoxPop
#rm -rf $(BUILD_DIR)/shaders
#mkdir -p $(BUILD_DIR)/shaders
#cp -r src/shaders/* $(BUILD_DIR)/shaders
$(BUILD_DIR)/object/%.o: src/%.cpp
$(CC) -I$(INCLUDE) -L$(LIBRARY) -o $# -c $<
.PHONY: clean
clean:
#rm build/debug/object/* build/release/object/*
Essentially, it sets a few variables specific to a debug build and a release build and then calls a common target, makegeneral. When I run make, I get the following output:
g++ -IInclude/ -LLib/ build/release/object/VoxPop.o build/release/object/Utils.o -lGL -lglut -lGLEW -o VoxPop
g++: error: build/release/object/VoxPop.o: No such file or directory
g++: error: build/release/object/Utils.o: No such file or directory
make: *** [makegeneral] Error 1
When I echo out SRC and OBJ at the beginning of makegeneral, they appear to be correct. It seems that the problem is with the dependencies for makegeneral, since the rule for compiling object files is never invoked and no there is no "No rule to make target..." message spit out.
For reference, this is what I get when I echo out SRC and OBJ at the beginning of makegeneral.
SRC: ./src/VoxPop.cpp ./src/Utils.cpp
OBJ: build/release/object/VoxPop.o build/release/object/Utils.o
BUILD_DIR is not set at the top level so expands to the empty string in the pattern rule. This is also the reason (I believe) for why make isn't failing on unbuildable prereqs. There aren't even any rules for how to do so (beyond the built-in rules). (Though I don't have access to a machine with make at the moment to test my theories.)
I'm also don't believe (though I can't test at the moment) that make will run your makegeneral target twice in this configuration to get you what you want. I believe you will only get it run once with whichever target make chooses to build first (the first listed I believe so in this case release).
I have an issue where when I type the build command into the terminal, it works just fine, but when I use it in Codeblocks as a custom build command, Codeblocks will say that it's compiling, suck up 100% CPU, but not actually do anything. Here's my configuration:
I have a FUSE drive (sftp) set up at /home/david/The\ Quest\ of\ the\ Ions/ on the client which links to an identical directory on the server.
The build command that codeblocks runs is: ssh david#website.com 'cd /home/david/The\ Quest\ of\ the\ Ions/ && $make -f $makefile $target'
When I run the same build command as listed above in a terminal (with the variables filled in), it will fully complete without any user input.
Makefile:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp src/room.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=The\ Quest\ of\ the\ Ions
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
Debug: all
Release: all
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
I am stumped on this problem and don't know what could be causing it. Thank you for your assistance!