CMake compile-time defines - c++

I am new to using CMake and am attempting to transfer our previous Makefiles into CMakeLists. I have one file, *dsplink_defines.txt* that has the following compile-time defines.
*-DOS_LINUX -DMAX_DSPS=1 -DMAX_PROCESSORS=2 -DID_GPP=1 -DOMAPL1XX -DPROC_COMPONENT -DPOOL_COMPONENT -DNOTIFY_COMPONENT -DMPCS_COMPONENT -DRINGIO_COMPONENT -DMPLIST_COMPONENT -DMSGQ_COMPONENT -DMSGQ_ZCPY_LINK -DCHNL_COMPONENT -DCHNL_ZCPY_LINK -DZCPY_LINK -DKFILE_DEFAULT -DDA8XXGEM -DDA8XXGEM_PHYINTERFACE=SHMEM_INTERFACE -DGPP_SWI_MODE -D_REENTRANT -DVERIFY_DATA -DDDSP_DEBUG*
Our previous Makefile took care of this in the following manner and took care of this by using shell cat starting on line 8:
BIN = ../../build/bin
TMP = build
BUILD_DEF = -DBUILD=$(BUILD_VERSION) -DBUILD_DATE=$(BUILD_DATE)
# these files are captured from the DSPLink Sample build directory (and the named changed)
# they contain the appropriate includes and flags to build a dsplink application.
DSPLINK_INCLUDES = $(shell cat ../dsplink_config/dsplink_includes.txt)
DSPLINK_FLAGS = $(shell cat ../dsplink_config/dsplink_flags.txt)
DSPLINK_DEFINES = $(shell cat ../dsplink_config/dsplink_defines.txt)
DSPLINK_LIBS = $(DSPLINK_PACKAGE_DIR)/dsplink/gpp/export/BIN/Linux/OMAPL1XX/RELEASE/dsplink.lib
#Our project variables
INCLUDE = -I../framework -I../io_master -I../logging -I../../dsp/include - I../flagDictionary
#TOOLCHAIN = ${FACTORY_DIR}/build_armv5l-timesys-linux-uclibcgnueabi/toolchain/bin
TOOLCHAIN = /OMAP-L137/timesys/SDK/omapl137_evm/toolchain/bin
PLATFORM=armv5l-timesys-linux-uclibcgnueabi
#Compile Options
CC=$(TOOLCHAIN)/$(PLATFORM)-g++
LINKER=$(TOOLCHAIN)/$(PLATFORM)-g++
CFLAGS+= $(BUILD_DEF) $(INCLUDE) $(DSPLINK_DEFINES) $(DSPLINK_FLAGS) $(DSPLINK_INCLUDES)
DEBUG = -O
#list of things to compile.
FW_BUILD_DIR=../framework/build
LOG_BUILD_DIR=../logging/build
FLAG_DICT_BUILD_DIR=../flagDictionary/build
FRAMEWORK_OBJECTS= $(FW_BUILD_DIR)/com.o \
$(FW_BUILD_DIR)/application.o \
$(FW_BUILD_DIR)/memoryManagerBase.o \
$(FW_BUILD_DIR)/memoryManager.o \
$(FW_BUILD_DIR)/arguments.o \
$(FW_BUILD_DIR)/lockManager.o \
$(FW_BUILD_DIR)/controlCom.o \
$(FW_BUILD_DIR)/paths.o \
$(LOG_BUILD_DIR)/subsystemLogMasks.o \
$(LOG_BUILD_DIR)/logger.o
FLAG_DICT_OBJECTS= $(FLAG_DICT_BUILD_DIR)/flagEntry.o \
$(FLAG_DICT_BUILD_DIR)/flagDictionary.o
OBJECTS = spidev_test.o sysMon.o
EXES = sysMon
all: $(OBJECTS) $(EXES)
.c.o:
mkdir -p build
$(CC) -c $(CFLAGS) $(DEBUG) -o $(TMP)/$# $<
.cpp.o:
mkdir -p build
$(CC) -c $(CFLAGS) $(DEBUG) -o $(TMP)/$# $<
spidev_test: $(FRAMEWORK_OBJECTS) spidev_test.o
$(LINKER) -lpthread -lc -o $(BIN)/$# $(DSPLINK_LIBS) build/spidev_test.o $(FRAMEWORK_OBJECTS)
sysMon: $(FRAMEWORK_OBJECTS) sysMon.o
$(LINKER) -lpthread -lc -o $(BIN)/$# $(DSPLINK_LIBS) build/sysMon.o $(FLAG_DICT_OBJECTS) $(FRAMEWORK_OBJECTS)
deploy:
../../build/deploy
How do I pass these in using a CMakeList

This should work:
file(READ path/to/dsplink_defines.txt defines) #read file into variable 'defines'
string(REPLACE " " ";" defines "${defines}") #turn space separation into CMake list
add_definitions(${defines})
Of course, if you have full control of the file and can change its format to use semicolons for separation instead of spaces, you can do that and skip the string() line (probably speeding up your CMake processing a little bit by this).

Related

Is this the right way to include a subdir in a makefile

prefix=#prefix#
exec_prefix=#exec_prefix#
bindir=#bindir#
CFLAGS = -pipe -O2 -g `freetype-config --cflags` -c -Wall -Wno-multichar `cat #top_srcdir#/madlax.specs`
CPPFLAGS= $(CFLAGS) -Woverloaded-virtual -Wnon-virtual-dtor
CC = #CC#
EXE = jpegtranslator
MLXLIBDIR = #top_srcdir#/src/kits/objs
SUBDIR = libjpeg
SRC := $(SUBDIR)/jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c \
jchuff.c jcinit.c jclhuff.c jclossls.c jclossy.c jcmainct.c jcmarker.c jcmaster.c jcodec.c \
jcomapi.c jcparam.c jcphuff.c jcpred.c jcprepct.c jcsample.c jcscale.c jcshuff.c jctrans.c \
jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jddiffct.c jdhuff.c \
jdinput.c jdlhuff.c jdlossls.c jdlossy.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \
jdpostct.c jdpred.c jdsample.c jdscale.c jdshuff.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \
jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jmemmgr.c jmemnobs.c jquant1.c jquant2.c \
jutils.c
OBJS = be_jdatadst.o be_jdatasrc.o be_jerror.o JPEGTranslator.o $(SRC)
OBJDIR := objs
include #top_srcdir#/makefile.rules
all : $(OBJDIR) $(OBJDIR)/$(EXE)
$(OBJDIR):
mkdir $(OBJDIR) -C $(SUBDIR)
The main part of concern is the $(OBJDIR) -C $(SUBDIR), because I don't really know if I also need the -I$(SUBDIR) or the -L$(SUBDIR), or if I just use -ljpeg
First of all the -l option (lower-case L) is for linking with a library, and -L is for adding a path to the linkers library-search-path-list.
And yes you need -L if you want to link with a library in a non-standard location using -l.
You can also skip both the -L and -l options, and provide the full path to the library instead.

C++ makefile will compile only first 3 entries

Good day,
recently i switched from jamfile to makefile. The reason of this switch is that i think that jamfile does not really cooperate with armadillo and openmp libraries. I have code divided into multiple *.h and *.cpp files.
# makefile for my PhD thesis
# Created by Michal Buday, no copyrights
# Datum: 01.07.2016
SHELL := /bin/sh
SRC := methods
BIN := bin
CXX := g++ # GNU C++ compiler
CXXFLAGS := -Wall
ARMAF := -larmadillo # ARMADILLO matrix library
OPT := -O
# GGG := -g # for debugging
# bash$ gdp ${program name} core
# ===============================================================================================
# standard stuff
all: coord_trans.o geodetic_functions.o geo_models.o interpolations.o \
legendre.o loadpoints.o physical_constants.o sphere_int.o \
3Dtransformations.o
LIBOBJ = coord_trans.o geodetic_functions.o geo_models.o interpolations.o \
legendre.o loadpoints.o physical_constants.o sphere_int.o \
3Dtransformations.o #topo_corrections.o
geodetic_functions.o: $(SRC)/geodetic_functions.h
$(CXX) $(OPT) -c $(SRC)/geodetic_functions.h -o $(BIN)/$#
geo_models.o: $(SRC)/geo_models.h $(SRC)/legendre.h $(SRC)/geodetic_functions.h \
$(SRC)/physical_constants.h
$(CXX) $(OPT) -c $(SRC)/geo_models.h -o $(BIN)/$#
interpolations.o: $(SRC)/interpolations.cpp $(SRC)/interpolations.h
$(CXX) $(OPT) -c $(SRC)/interpolations.cpp -o $(BIN)/$#
legendre.o: $(SRC)/legendre.h
$(CXX) $(OPT) -c $(SRC)/legendre.h -o $(BIN)/$#
loadpoints.o: $(SRC)/loadpoints.h
$(CXX) $(OPT) -c $(SRC)/loadpoints.h -o $(BIN)/$#
sphere_int.o: $(SRC)/sphere_int.h $(SRC)/sphere_int.cpp
$(CXX) $(OPT) -c $(SRC)/sphere_int.cpp $(ARMAF) -o $(BIN)/$#
#topo_corrections.o: $(SRC)/topo_corrections.h $(SRC)/geodetic_functions.h
# $(CXX) $(OPT) -c $(SRC)/topo_corrections.h $(ARMAF)
3Dtransformations.o: $(SRC)/3Dtransformations.h $(SRC)/3Dtransformations.cpp
$(CXX) $(OPT) -c $(SRC)/3Dtransformations.cpp $(ARMAF) -o $(BIN)/$#
coord_trans.o: $(SRC)/coord_trans.h $(SRC)/geodetic_functions.h
$(CXX) $(OPT) -c $(SRC)/coord_trans.h -o $(BIN)/$#
main.o: $(LIBOBJ)
$(CXX) $(OPT) $(BIN)/$(LIBOBJ) -o $# $(ARMAF)
# ======================================================================== #
#
clean:
rm *.o
The dependencies are:
# coord_trans.h << geodetic_functions.h
# geodetic_functions.h << armadillo
# geo_models.h << legendre.h geodetic_functions.h physical_constants.h
# interpolations.h << std
# legendre.h << std
# loadpoints.h << std
# physical_constants.h << define only
# sphere_int.h << armadillo
# topo_corrections.h << geodetic_functions.h
# 3Dtransformations.h << armadillo
But when i call
make
in terminal it creates only the first 3 entries in makefile and also the size of binary files is over 107 MB (the code itself has 100k or less). What am i missing?
Thank you for any advices.
First of all, you may want to use $< (first dependancie) for your -c argument instead of repeating it.
Also, I would advise to build the list of object files given the cpp files (wildcard function?).
Finally, you may want to try to replace $(BIN)/$(LIBOBJ) by $(FULLPATH_LIBOBJ) constructed using:
FULLPATH_LIBOBJ = $(addprefix $(BIN)/, $(LIBOBJ))
Not sure this changes anything, but your makefile looks complicated to me, whereas it should be much simpler!
Also, it is hard to help you compiling the project without the project itself.

How to write make files with auto dependancy generator

In expansion to my previous question how to write a makefile for structured file system:
The file structure:
.
├── Headers
│   ├── function.h
│   └── test.h
├── makefile
├── README.md
└── Sources
├── function.c
├── main.c
└── test.c
I'm trying to write a makefile that reads the #include<...> on any given source file and compile as required.
Originally I used to have a make file that looked like this:
INC_DIR = Headers
SRC_DIR = Sources
OBJ_DIR = Objects
#CXXFLAGS = -c -Wall -I. -IHeaders
CXXFLAGS = -c -Wall -I. -IHeaders
CC = gcc
SRCS = $(SRC_DIR)/*.c
OBJS = $(OBJ_DIR)/*.o
#The wildcard and patsubt commads will come handy
DEPS = $(INC_DIR)/*.h
#need to use an automatic dependency generator
output: $(OBJ_DIR)/main.o $(OBJ_DIR)/function.o
$(CC) $^ -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEPS)
$(CC) $(CXXFLAGS) $< -o $#
run: output
./output
clean:
rm $(OBJ_DIR)/*.o
rm output
-#echo "Clean completed"
That meant that for every source file that output was dependent on i had to add that object to this line.
output: $(OBJ_DIR)/main.o $(OBJ_DIR)/function.o $(OBJ_DIR)/test.o
$(CC) $^ -o $#
And is any other source file was dependent on one or more sources additional rules had to be added.
To solve this:
here is what I have gathered from Auto-Dependency Generation and 4.14 Generating Prerequisites Automatically
As mentioned by the community members, I have a mixed understanding of dependency generation and how to make use of the files generated.
DEP_DIR = .d
$(shell mkdir -p $(DEP_DIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEP_DIR)/$*.Td
INC_DIR = Headers
SRC_DIR = Sources
OBJ_DIR = Objects
$(shell mkdir -p $(OBJ_DIR) >/dev/null)
CXXFLAGS = -c -Wall -I. -IHeaders
CC = gcc
SRCS = $(SRC_DIR)/*.c
OBJS = $(OBJ_DIR)/*.o
#The wildcard and patsubt commads will come handy
#DEPS = $(INC_DIR)/*.h
MAKEDEPEND = $(CC) $(CXXFLAGS) $< \
| sed -n 's/^\# *[0-9][0-9]* *"\([^"]*\)".*/$*.o: \1/p' \
| sort | uniq > $*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CXXFLAGS)
#need to use an automatic dependency generator
#%.d: %.c
# #set -e; rm -f $#; \
# $(CC) -MP -MD $(CXXFLAGS) $< > $#.$$$$; \
# sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
# rm -f $#.$$$$
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEP_DIR)/%.d
#$(MAKEDEPEND); \
cp $*.Td $*.d; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.Td >> $*.d; \
rm -f $*.Td
#$(COMPILE.c) -o $# $<
$(CC) $(CXXFLAGS) $(DEPFLAGS) $< -o $#
-include $(SRCS:.c=.d)
$(DEP_DIR)/%.d: ;
.PRECIOUS: $(DEP_DIR)/%.d
output: $(OBJS)
$(CC) $^ -o $#
run: output
./output
clean:
rm -r $(OBJ_DIR)
rm -r $(DEP_DIR)
rm output
-#echo "Clean completed"
The error when make is executed is:
$ make
gcc -c -Wall -I. -IHeaders -MT Objects/*.o -MMD -MP -MF .d/*.Td Sources/function.c -o Objects/*.o
gcc Objects/*.o -o output
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
makefile:48: recipe for target 'output' failed
make: *** [output] Error 1
So, I'm hoping to achieve the auto dependency detection and compilation. I think the error is in the way that the dependencies are detected and the way they are generated for a given source file.
It looks to me like you're trying to combine multiple different ways of generating dependency info, and that can't work. The advanced post talks about multiple ways to solve the problem: you need to pick one not try to use them all together.
If you want to use the advanced method then use it as described in the "TL;DR" section at the top, or else in the "Combining Compilation and Dependency Generation" section at the bottom. If you're using GCC there's no need for MAKEDEPEND, sed, etc.
The advanced post says that your rule should look like this:
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
%.o : %.c
%.o : %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
That's it.

Incremental build with GCC and manual makefile?

I am coding to the NRF51822 bluetooth chip, in Eclipse with GCC and a makefile that I maintain myself.
My problem is that every time I press build, it will compile everything, which is beginning to take quite some time. I am not that experienced in creating and maintaining make-files, so I have no idea where to start in order to get it to build incremtal instead?
My makefile is composed like this (I know there's a lot, and I haven't created this myself - found it in a tutorial, so I don't know what's relevant and what's not :-) ):
PROJECT_NAME := my_project
export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
TEMPLATE_PATH = nrf51_sdk/toolchain/gcc
ifeq ($(OS),Windows_NT)
include $(TEMPLATE_PATH)/Makefile.windows
else
include $(TEMPLATE_PATH)/Makefile.posix
endif
MK := mkdir
RM := rm -rf
#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
else
NO_ECHO := #
endif
# Toolchain commands
CC := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-gcc"
AS := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-as"
AR := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ar" -r
LD := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ld"
NM := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-nm"
OBJDUMP := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objdump"
OBJCOPY := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objcopy"
SIZE := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-size"
#function for removing duplicates in a list
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
#source common to all targets
C_SOURCE_FILES += \
main.c \
file1.c \
file2.c \
file3.c \
file4.c \
#assembly files common to all targets
ASM_SOURCE_FILES = nrf51_sdk/toolchain/gcc/gcc_startup_nrf51.s
#includes common to all targets
INC_PATHS = -I Dir1/
INC_PATHS = -I Dir2
INC_PATHS += -I Dir3
INC_PATHS += -I Dir4
OBJECT_DIRECTORY = _build
LISTING_DIRECTORY =$(OBJECT_DIRECTORY)
OUTPUT_BINARY_DIRECTORY =$(OBJECT_DIRECTORY)
# Sorting removes duplicates
BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY) )
#flags common to all targets
CFLAGS = -DSOFTDEVICE_PRESENT
CFLAGS += -DNRF51
CFLAGS += -DS110
CFLAGS += -DBOARD_PCA10028
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -mcpu=cortex-m0
CFLAGS += -mthumb -mabi=aapcs --std=gnu99
CFLAGS += -Wall -O0 -g3
CFLAGS += -mfloat-abi=soft
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
#CFLAGS += -flto -fno-builtin
# keep every function in separate section. This will allow linker to dump unused functions
LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m0
# let linker to dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys
# Assembler flags
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DNRF51
ASMFLAGS += -DS110
ASMFLAGS += -DBOARD_PCA10028
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
#default target - first one defined
default: clean nrf51422_xxac_s110
#building all targets
all: clean
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e cleanobj
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e nrf51422_xxac_s110
#target for printing all targets
help:
#echo following targets are available:
#echo nrf51422_xxac_s110
#echo flash_softdevice
C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES))
C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) )
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) )
ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES))
ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) ))
ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) )
vpath %.c $(C_PATHS)
vpath %.s $(ASM_PATHS)
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)
nrf51422_xxac_s110: OUTPUT_FILENAME := nrf51422_xxac_s110
nrf51422_xxac_s110: LINKER_SCRIPT=ble_app_hrs_gcc_nrf51.ld
nrf51422_xxac_s110: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e finalize
## Create build directories
$(BUILD_DIRECTORIES):
echo $(MAKEFILE_NAME)
$(MK) $#
# Create objects from C SRC files
$(OBJECT_DIRECTORY)/%.o: %.c
#echo Compiling file: $(notdir $<)
#echo arm-none-eabi-gcc $(CFLAGS) $(INC_PATHS) -c -o $# $<
$(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $# $<
# Assemble files
$(OBJECT_DIRECTORY)/%.o: %.s
#echo Compiling file: $(notdir $<)
$(NO_ECHO)$(CC) $(ASMFLAGS) $(INC_PATHS) -c -o $# $<
# Link
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
## Create binary .bin file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
finalize: genbin genhex echosize
genbin:
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
genhex:
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
echosize:
-#echo ""
$(NO_ECHO)$(SIZE) $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
-#echo ""
clean:
$(RM) $(BUILD_DIRECTORIES)
cleanobj:
$(RM) $(BUILD_DIRECTORIES)/*.o
flash: $(MAKECMDGOALS)
#echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex
nrfjprog --reset --program $(OUTPUT_BINARY_DIRECTORY)/$<.hex)
## Flash softdevice
flash_softdevice:
#echo Flashing: s110_softdevice.hex
nrfjprog --reset --program nrf51_sdk/softdevice/s110/hex/s110_softdevice.hex
all: clean
check this line. The default (first) Target of your Makefile depends on clean, so before any build is started, the clean target is executed that likely will remove all built files, to rebuild them.
Drop the clean and you should get the incremental behaviour make was designed for.

undefined reference to `main' with makefile on linux, with boost and mpi

I am not very familiar with make; i've always used and modified this highly ancient makefile I inherited from another project, modifying it as necessary. Up until now, it has functioned perfectly, compiling together projects with 20-50 files, even within sub-directories, determining and building all the dependencies properly.
Today I am running a very simple test code to determine if BOOST.MPI will work on a cluster I recently got access to. I am trying to compile a 1-file test case to make sure that the library works. This is also my first time building and linking to boost on this system.
I have boost installed in my user directory: ~/boost, and I've run the appropriate bjam to ensure that BOOST.MPI is present. I don't believe my problem lies there. As you'll see in a moment, however, I had to include -lboost_mpi and -lboost_serialization to get as far as I did.
The makefile seems to compile, and assemble just fine producing the intermediary .a file. It hangs up on the linking step with a surprising error:
Creating dependency for "boosttest.cpp"
Compiling "boosttest.cpp"
Assembling ag...
ar: creating ./libag.a
Linking bt1...
/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [bt1] Error 1
The only source code I've written (copy/pasted right out of the Boost.MPI implementation page):
boosttest.cpp:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
int main(int argc, char* argv[])
{
boost::mpi::environment env(argc, argv);
boost::mpi::communicator world;
std::cout << "I am process " << world.rank() << " of " << world.size()<< "." << std::endl;
return 0;
}
Now for the part where I get lost. This is the makefile I've modified. I mostly understand what parts of it are doing, and it is the only makefile I've ever seen (although as mentioned I'm not very experienced with them) to produce .d files containing a list of all dependent libraries.
Makefile:
PROJECT = boosttest
# The names of the sub-projects that the executable depends on. These names are used later on to define targets, location, libraries, etc.
DEPS =
# The names of the sub-projects that the test executable depends on.
TEST_DEPS =
EXE_DEPS =
LOCAL_O_FILES = boosttest.o
LOCAL_TEST_O_FILES =
LOCAL_LIB_NAME = ag
LOCAL_LIB_DIR = .
LOCAL_TEST_LIB_NAME =
LOCAL_TEST_LIB_DIR =
LOCAL_INCLUDE_ROOT = .
EXE_NAME = BT
MPIC_DIR = /usr/local/mvapich2-1.6-gcc/
#these assume our local path and bin are set up properly since I don't know where the compilers are
CC = $(MPIC_DIR)/bin/mpicc
CCC = $(MPIC_DIR)/bin/mpicxx
F77 = $(MPIC_DIR)/bin/mpif77
CLINKER = $(MPIC_DIR)/bin/mpicc
CCLINKER = $(MPIC_DIR)/bin/mpicxx
FLINKER = $(MPIC_DIR)/bin/mpif90
F90 = $(MPIC_DIR)/bin/mpif90
F90LINKER = $(MPIC_DIR)/bin/mpif90
MAKE = make --no-print-directory
SHELL = /bin/sh
#PROF = -ggdb -O2
PROF = -O2
ADDITIONAL_LIBS = -lboost_mpi -lboost_serialization
SED = $(shell which sed)
GREP = $(shell which grep)
# Warnings will depend on the GCC version -- if it's 4, have "-Wdeclaration-after-statement -Wunused-value -Wunused-variable"
#GCC_MAJOR_VERSION = $(shell $(CCC) --version | $(GREP) "\(egcs\|gcc\)" | $(SED) "s/[^0-9]*\([0-9]\).*/\1/")
#WARNINGS = -Wno-import $(shell if test $(GCC_MAJOR_VERSION) -eq 4; then echo -Wunused-value -Wunused-variable; fi)
#GCC_INSTALL_DIR = /turing/software-linux/mpich-eth
GCC_INSTALL_DIR = $(MPIC_DIR)
GCC_INCLUDE_DIR = $(GCC_INSTALL_DIR)/include/
GCC_LIB_DIR = $(GCC_INSTALL_DIR)/lib/
BOOST_DIR = ~/boost
BOOST_LIB_DIR = ~/boost/stage/lib
# Expand SRCDIR so that it turns into "-I <srcdir>" for each listed directory
INCLUDE_DIRS = -I $(OBJC_ROOT)/include $(foreach dep, $(UNIQUE_DEPS), -I$($(dep)_INCLUDE_ROOT)) -I $(LOCAL_INCLUDE_ROOT) -I $(BOOST_DIR) -I $(GCC_INCLUDE_DIR)
#C_FLAGS = -DROM $(PROF) $(WARNINGS) $(INCLUDE_DIRS)
C_FLAGS = -DROM $(PROF) $(INCLUDE_DIRS)
L_FLAGS = $(foreach dir, $(OBJC_ROOT) $(DEP_LIB_DIRS), -L$(dir)) -L $(BOOST_LIB_DIR) -L $(GCC_LIB_DIR) $(PROF) $(ADDITIONAL_LIBS)
TEST_L_FLAGS = $(foreach dir, $(OBJC_ROOT) $(TEST_DEP_LIB_DIRS), -L$(dir)) -L/usr/lib -Xlinker --whole-archive $(TEST_REQUIRED_LIBS) -Xlinker --no-whole-archive
REQUIRED_LIBS = $(foreach dep, $(DEPS) LOCAL, $(if $($(dep)_LIB_NAME), -l$($(dep)_LIB_NAME)))
TEST_REQUIRED_LIBS = $(foreach dep, $(TEST_DEPS) LOCAL LOCAL_TEST, $(if $($(dep)_LIB_NAME), -l$($(dep)_LIB_NAME)))
.SUFFIXES:
.SUFFIXES: .d .cc .cpp .c .o
ASSEMBLE_TARGETS = $(foreach dep,$(DEPS),$(dep)_LIB_NAME)
ASSEMBLE_TEST_TARGETS = $(foreach dep,$(TEST_DEPS),$(dep)_LIB_NAME)
CLEAN_TARGETS = $(foreach dep, $(UNIQUE_DEPS), $(dep)_CLEAN)
LOCAL_D_FILES = $(LOCAL_O_FILES:.o=.d)
LOCAL_TEST_D_FILES = $(LOCAL_TEST_O_FILES:.o=.d) $(TEST_RUNNER:.o=.d)
DEP_LIB_DIRS = $(foreach dep, $(DEPS) LOCAL, $($(dep)_LIB_DIR))
TEST_DEP_LIB_DIRS = $(foreach dep, $(TEST_DEPS) LOCAL LOCAL_TEST, $($(dep)_LIB_DIR))
UNIQUE_ASSEMBLE_TARGETS = $(sort $(ASSEMBLE_TARGETS) $(ASSEMBLE_TEST_TARGETS))
UNIQUE_DEPS = $(sort $(DEPS) $(TEST_DEPS))
LOCAL_LIB = $(if $(LOCAL_LIB_NAME), $(LOCAL_LIB_DIR)/lib$(LOCAL_LIB_NAME).a)
LOCAL_TEST_LIB = $(if $(LOCAL_TEST_LIB_NAME), $(LOCAL_TEST_LIB_DIR)/lib$(LOCAL_TEST_LIB_NAME).a)
EXE_TARGETS = $(foreach dep,$(EXE_DEPS),$(dep)_EXE_NAME)
INSTALL_TARGETS = $(foreach dep,$(EXE_DEPS),$(dep)_INSTALL)
export PROJECTS += $(PROJECT)
# PHONY targets get remade even if there exists an up-to-date file with the same name.
.PHONY: default clean compile assemble link submit
# Targets for mortals
default: link
clean: $(CLEAN_TARGETS) LOCAL_CLEAN
compile: $(DEPS) $(LOCAL_D_FILES) $(LOCAL_O_FILES)
assemble: compile $(ASSEMBLE_TARGETS) $(LOCAL_LIB)
link: assemble $(EXE_TARGETS) $(EXE_NAME)
install: $(INSTALL_TARGETS) $(if $(EXE_NAME), LOCAL_INSTALL)
submit: link
qsub $(PROJECT).qsub
# Targets for make
# Invoking sub projects
$(UNIQUE_DEPS): MAKE_TARGET = $(if $(filter %_TEST, $#), compile-tests, compile)
$(UNIQUE_DEPS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($#_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _LIB_NAME attached by ASSEMBLE_TARGETS, a
$(UNIQUE_ASSEMBLE_TARGETS): DEP_NAME = $(#:_LIB_NAME=)
$(UNIQUE_ASSEMBLE_TARGETS): MAKE_TARGET = $(if $(filter %_TEST, $(DEP_NAME)), assemble-tests, assemble)
$(UNIQUE_ASSEMBLE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _EXE_NAME attached by EXE_TARGETS, a
$(EXE_TARGETS): DEP_NAME = $(#:_EXE_NAME=)
$(EXE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) link)
$(CLEAN_TARGETS): DEP_NAME = $(#:_CLEAN=)
$(CLEAN_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) clean)
$(INSTALL_TARGETS): DEP_NAME = $(#:_INSTALL=)
$(INSTALL_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) install)
#Local stuff
# The rule to change either a '.c' or a '.m' to a '.o'
#%.o : %.c %.d %.cc %.cpp
.cc.o .cpp.o .c.o:
#echo "Compiling \"$<\""
#$(CCC) -c $(C_FLAGS) $< -o $#
.cc.d .cpp.d .c.d :
#echo "Creating dependency for \"$<\""
# #$(CCC) $(WARNINGS) $(INCLUDE_DIRS) -MM $< -o $#
# This foogly hack because gcc seems to have issues with emitting the correct target/dependency names of
# files in sub-dirs of the current dir (specifically, it doesn't add the sub-dir to the target
# name, and insists on adding the directory to the dependencies) which ends up breaking dependencies...)
#dependLine=$$( $(CCC) $(C_FLAGS) $(INCLUDE_DIRS) -MM $< ); \
dirName=$$( dirname $< | $(SED) "s/\//\\\\\//g" ); \
dependLine=$$( echo $${dependLine} | $(SED) "s/ $${dirName}\// /g" ); \
oFile=$$( echo $${dependLine} | $(SED) "s/:.*//" ); \
dependencies=$$( echo $${dependLine} | $(SED) "s/.*://" ); \
echo $${oFile} $${oFile%.o}.d: $${dependencies} | $(SED) "s/ \\\//g" > $#
$(UNIQUE_ASSEMBLE_TARGETS): DEP_NAME = $(#:_LIB_NAME=)
$(UNIQUE_ASSEMBLE_TARGETS): MAKE_TARGET = $(if $(filter %_TEST, $(DEP_NAME)), assemble-tests, assemble)
$(UNIQUE_ASSEMBLE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _EXE_NAME attached by EXE_TARGETS, a
$(EXE_TARGETS): DEP_NAME = $(#:_EXE_NAME=)
$(EXE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) link)
$(CLEAN_TARGETS): DEP_NAME = $(#:_CLEAN=)
$(CLEAN_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) clean)
$(INSTALL_TARGETS): DEP_NAME = $(#:_INSTALL=)
$(INSTALL_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) install)
#Local stuff
# The rule to change either a '.c' or a '.m' to a '.o'
#%.o : %.c %.d %.cc %.cpp
.cc.o .cpp.o .c.o:
#echo "Compiling \"$<\""
#$(CCC) -c $(C_FLAGS) $< -o $#
.cc.d .cpp.d .c.d :
#echo "Creating dependency for \"$<\""
# #$(CCC) $(WARNINGS) $(INCLUDE_DIRS) -MM $< -o $#
# This foogly hack because gcc seems to have issues with emitting the correct target/dependency names of
# files in sub-dirs of the current dir (specifically, it doesn't add the sub-dir to the target
# name, and insists on adding the directory to the dependencies) which ends up breaking dependencies...)
#dependLine=$$( $(CCC) $(C_FLAGS) $(INCLUDE_DIRS) -MM $< ); \
dirName=$$( dirname $< | $(SED) "s/\//\\\\\//g" ); \
dependLine=$$( echo $${dependLine} | $(SED) "s/ $${dirName}\// /g" ); \
oFile=$$( echo $${dependLine} | $(SED) "s/:.*//" ); \
dependencies=$$( echo $${dependLine} | $(SED) "s/.*://" ); \
echo $${oFile} $${oFile%.o}.d: $${dependencies} | $(SED) "s/ \\\//g" > $#
$(LOCAL_LIB): compile $(ASSEMBLE_TARGETS)
#echo Assembling $(LOCAL_LIB_NAME)...
#ar rs $(LOCAL_LIB) $(LOCAL_O_FILES)
# Create the executable
$(EXE_NAME): assemble
#echo Linking $(EXE_NAME)...
#$(CCC) -o $(EXE_NAME) $(L_FLAGS)
# Erase all object files, the dependencies file, the core file and the executable, then rebuild everything
LOCAL_CLEAN:
#echo Cleaning $(PROJECT)...
#rm -f $(LOCAL_O_FILES) $(LOCAL_TEST_O_FILES) $(LOCAL_LIB) $(LOCAL_TEST_LIB) $(EXE_NAME) $(TEST_EXE_NAME) $(LOCAL_D_FILES) $(LOCAL_TEST_D_FILES) $(TEST_RUNNER) $(TEST_RUNNER:.o=.d) core*
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
-include $(LOCAL_O_FILES:.o=.d) $(LOCAL_TEST_O_FILES:.o=.d)
endif
The paths to my mpicxx compiler (needed for the cluster, and for those unfamiliar, it wraps gcc) are correct, as evidenced by the fact that it does compile, it just won't link. Similarly, my boost library paths seem functional, the -lboost_mpi flag gets caught properly.
At this point, my question has extended to be for my own education based on how this makefile works/intends to work. Ultimately the entirely obvious/simple command:
mpicxx boosttest.cpp -L ~/boost/stage/lib/ -lboost_mpi -lboost_serialization -o test
however I want to get a proper makefile going as once I get past this test case verifying Boost.MPI's equivalent of a hello world, I'll be moving on to projects involving my full source code, 20+ files with cross dependencies, etc. Any help or intuition would be greatly appreciated.
Based on the suggestion of #Oktalist above, I was able to find something that works, at least for the single-file case, but I can't see why it won't work when I extend this to multiple files. I'm still at a loss why this worked in the past but not now, but perhaps I changed something I wasn't tracking.
The correction is near the end, in this block:
# Create the executable
$(EXE_NAME): assemble
#echo Linking $(EXE_NAME)...
#$(CCC) $(L_FLAGS) $(LOCAL_LIB) -o $(EXE_NAME)