I am trying to have a command executed depending on the current target from a list of targets (currently only one entry in that list) before another makefile is executed.
i have this:
$(LIBS):
ifeq ($#,libname)
my command here
endif
$(MAKE) -C ./lib/$#
the problem is, that the ifeq does not get executed even if the target name is correct. Using an $(info $#) shows exactly the libname but the expression is not evaluated as true.
I thought maybe there is a problem with expansion of the automatic variable in a conditional so i tried using an eval like this:
$(LIBS):
$(eval CURRENT_LIB := $#)
ifeq ($(CURRENT_LIB),libname)
my command here
endif
$(MAKE) -C ./lib/$#
info shows that the variable now equals exactly the libname but the ifeq does not get excuted.
When i enter something like ifeq (libname,libname) it works so the statement is working, but the comparison between variable and text does not evaluate to true even if the two are equal and it should work.
GNU make version is 4.1
What am i missing here?
Complete Makefile:
CC := g++
CFLAGS := -v -std=c++0x -pthread -Wall -g -O3
OBJ := mycode.o
OBJ += moreobjects.o
#more objects in here
LIBS = libname
.PHONY: libs $(LIBS)
SRC = $(OBJ:%.o=%.cpp)
DEPFILE := .depend
mytarget: libs $(OBJ)
$(CC) $(CFLAGS) -o $# $(OBJ)
-include $(DEPFILE)
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
$(CC) -MM -std=c++11 $(SRC) > $(DEPFILE)
libs: $(LIBS)
$(LIBS):
$(eval CURRENT_LIB := $#)
ifeq ($(CURRENT_LIB),libname)
./lib/$(CURRENT_LIB)/configure
endif
$(MAKE) -C ./lib/$#
.PHONY: clean_all
clean_all: clean
$(foreach dir,$(LIBS),$(MAKE) clean -C ./lib/$(dir))
.PHONY: clean
clean:
rm -rf mytarget $(OBJ) $(DEPFILE)
Thank You very much!
What you are trying to do cannot work. From the documentation:
Conditionals control what 'make' actually "sees" in the makefile, so they cannot be used to control recipes at the time of execution.
The way I put it is that conditionals are evaluated at the time the Makefile is read. So make reads your Makefile, your conditional is false and it is removed.
"Normal" conditionals, don't work in a recipe with GNU make. Unfortunately that's true.
Workaround:
But you can use Functions for Conditionals and The eval Function instead. A small example for error detection from my build system. Here I use the eval and if function.
Snippet from Makefile.xu, which use eval and if:
xubuild_check_objects:
$(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
#echo 'echo nothing (dummy)' >/dev/null
$(if $(filter n,$(RESULT)), \
$(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)
NOTE:
#echo 'echo nothing (dummy)' >/dev/null
This here is required. When no command will be executed after eval, you get a make: Nothing to be done for 'xubuild_check_objects message.
Project Makefile (root directory) with error:
# XUbuild system (MUST included first)
include Makefile.xu
# This produces an error and aborts the build
xu-src-c-y = test.c
all: xubuild_check_objects
Error output:
$ make
Makefile.xu:104: *** XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting. Stop.
$
Project Makefile (root directory) without error:
# XUbuild system (MUST included first)
include Makefile.xu
# My build system is happy with this:
xu-src-c-y += test.c
all: xubuild_check_objects
Output (no error):
$ make
$
The full error detection from my build system simplified. I removed the most Makefile.xu "code" and only post the error detection here. (I don't explain my whole build system in this answer):
# XUbuild generic object
xu-obj := :xu-obj
xu-obj_del := :
# XUbuild object types
xu-obj_nop := n
xu-obj_yes := y
xu-obj_module := m
xu-obj_src := s
xu-obj_flag := f
# XUbuild source priority
xu-obj_src_head := 0
xu-obj_src_normal := 1
# XUbuild source types
xu-obj_src_a := 0
xu-obj_src_c := 1
xu-obj_src_cpp := 2
# XUbuild object functions
xu-obj_func-get = $(filter $(xu-obj)%,$(1))
xu-obj_func-remove = $(filter-out $(xu-obj)%,$(1))
xu-obj_func-valid = $(if $(call xu-obj_func-get,$(1)),y,n)
# XUbuild source objects
xu-src := $(xu-obj)$(xu-obj_del)
# XUbuild C source
xu-src-c := $(xu-src)$(xu-obj_src_normal)$(xu-obj_del)$(xu-obj_src_c)$(xu-obj_del)
xu-src-c- := $(xu-src-c)$(xu-obj_nop)
xu-src-c-y := $(xu-src-c)$(xu-obj_yes)
XUBUILD_PHONY += xubuild_check_objects
xubuild_check_objects:
$(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
#echo 'echo nothing (dummy)' >/dev/null
$(if $(filter n,$(RESULT)), \
$(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)
.PHONY: $(XUBUILD_PHONY)
Related
I've built a number of projects with Veins on Omnet++ without issues at this stage, and I decided to implement CAM messages into a simulation. However, upon building I arrive at the following error:
12:41:23 **** Incremental Build of configuration release for project v2x ****
make MODE=release all
cd src && make make[1]: Entering directory '/home/veins/workspace.omnetpp/v2x/src'
Creating executable: ../out/clang-release/src/v2x /usr/bin/ld: cannot open output file ../out/clang-release/src/v2x: Is a directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]:
*** [Makefile:117: ../out/clang-release/src/v2x] Error 1 make[1]: Leaving directory '/home/veins/workspace.omnetpp/v2x/src'
make: *** [Makefile:2: all]
Error 2 "make MODE=release all" terminated with exit code 2.
Build might be incomplete.
12:41:24 Build Failed. 3 errors, 0 warnings. (took 549ms)
My Makefile reads:
#
# OMNeT++/OMNEST Makefile for v2x
#
# This file was generated with the command:
# opp_makemake -f --deep -KINET_PROJ=/home/veins/src/inet -KLTE_PROJ=/home/veins/src/simulte -KVEINS_INET_PROJ=/home/veins/src/veins/subprojects/veins_inet -KVEINS_PROJ=/home/veins/src/veins -DINET_IMPORT -DVEINS_IMPORT -DVEINS_INET_IMPORT -I$$\(INET_PROJ\)/src -I$$\(LTE_PROJ\)/src -I$$\(VEINS_INET_PROJ\)/src -I$$\(VEINS_PROJ\)/src -I. -L$$\(INET_PROJ\)/src -L$$\(LTE_PROJ\)/src -L$$\(VEINS_PROJ\)/src -L$$\(VEINS_INET_PROJ\)/src -lINET$$\(D\) -llte$$\(D\) -lveins$$\(D\) -lveins_inet$$\(D\)
#
# Name of target to be created (-o option)
TARGET_DIR = .
TARGET_NAME = v2x$(D)
TARGET = $(TARGET_NAME)$(EXE_SUFFIX)
TARGET_IMPLIB = $(TARGET_NAME)$(IMPLIB_SUFFIX)
TARGET_IMPDEF = $(TARGET_NAME)$(IMPDEF_SUFFIX)
TARGET_FILES = $(TARGET_DIR)/$(TARGET)
# User interface (uncomment one) (-u option)
USERIF_LIBS = $(ALL_ENV_LIBS) # that is, $(TKENV_LIBS) $(QTENV_LIBS) $(CMDENV_LIBS)
#USERIF_LIBS = $(CMDENV_LIBS)
#USERIF_LIBS = $(TKENV_LIBS)
#USERIF_LIBS = $(QTENV_LIBS)
# C++ include paths (with -I)
INCLUDE_PATH = -I$(INET_PROJ)/src -I$(LTE_PROJ)/src -I$(VEINS_INET_PROJ)/src -I$(VEINS_PROJ)/src -I.
# Additional object and library files to link with
EXTRA_OBJS =
# Additional libraries (-L, -l options)
LIBS = $(LDFLAG_LIBPATH)$(INET_PROJ)/src $(LDFLAG_LIBPATH)$(LTE_PROJ)/src $(LDFLAG_LIBPATH)$(VEINS_PROJ)/src $(LDFLAG_LIBPATH)$(VEINS_INET_PROJ)/src -lINET$(D) -llte$(D) -lveins$(D) -lveins_inet$(D)
# Output directory
PROJECT_OUTPUT_DIR = ../out
PROJECTRELATIVE_PATH = src
O = $(PROJECT_OUTPUT_DIR)/$(CONFIGNAME)/$(PROJECTRELATIVE_PATH)
# Object files for local .cc, .msg and .sm files
OBJS = \
$O/v2x/GeneralMessageSerializer.o \
$O/v2x/VeinsInetApplicationBase.o \
$O/v2x/VeinsInetManager.o \
$O/v2x/VeinsInetManagerBase.o \
$O/v2x/VeinsInetManagerForker.o \
$O/v2x/VeinsInetMobility.o \
$O/v2x/VeinsInetSampleApplication.o \
$O/v2x/VeinsInetSampleMessageSerializer.o \
$O/v2x/GeneralMessage_m.o \
$O/v2x/VeinsInetSampleMessage_m.o
# Message files
MSGFILES = \
v2x/GeneralMessage.msg \
v2x/VeinsInetSampleMessage.msg
# SM files
SMFILES =
# Other makefile variables (-K)
INET_PROJ=/home/veins/src/inet
LTE_PROJ=/home/veins/src/simulte
VEINS_INET_PROJ=/home/veins/src/veins/subprojects/veins_inet
VEINS_PROJ=/home/veins/src/veins
#------------------------------------------------------------------------------
# Pull in OMNeT++ configuration (Makefile.inc)
ifneq ("$(OMNETPP_CONFIGFILE)","")
CONFIGFILE = $(OMNETPP_CONFIGFILE)
else
CONFIGFILE = $(shell opp_configfilepath)
endif
ifeq ("$(wildcard $(CONFIGFILE))","")
$(error Config file '$(CONFIGFILE)' does not exist -- add the OMNeT++ bin directory to the path so that opp_configfilepath can be found, or set the OMNETPP_CONFIGFILE variable to point to Makefile.inc)
endif
include $(CONFIGFILE)
# Simulation kernel and user interface libraries
OMNETPP_LIBS = $(OPPMAIN_LIB) $(USERIF_LIBS) $(KERNEL_LIBS) $(SYS_LIBS)
ifneq ($(PLATFORM),win32.x86_64)
LIBS += -Wl,-rpath,$(abspath $(INET_PROJ)/src) -Wl,-rpath,$(abspath $(LTE_PROJ)/src) -Wl,-rpath,$(abspath $(VEINS_PROJ)/src) -Wl,-rpath,$(abspath $(VEINS_INET_PROJ)/src)
endif
COPTS = $(CFLAGS) $(IMPORT_DEFINES) -DINET_IMPORT -DVEINS_IMPORT -DVEINS_INET_IMPORT $(INCLUDE_PATH) -I$(OMNETPP_INCL_DIR)
MSGCOPTS = $(INCLUDE_PATH)
SMCOPTS =
# we want to recompile everything if COPTS changes,
# so we store COPTS into $COPTS_FILE (if COPTS has changed since last build)
# and make the object files depend on it
COPTS_FILE = $O/.last-copts
ifneq ("$(COPTS)","$(shell cat $(COPTS_FILE) 2>/dev/null || echo '')")
$(shell $(MKPATH) "$O")
$(file >$(COPTS_FILE),$(COPTS))
endif
#------------------------------------------------------------------------------
# User-supplied makefile fragment(s)
-include makefrag
#------------------------------------------------------------------------------
# Main target
all: $(TARGET_FILES)
$(TARGET_DIR)/% :: $O/%
#mkdir -p $(TARGET_DIR)
$(Q)$(LN) $< $#
ifeq ($(TOOLCHAIN_NAME),clang-msabi)
-$(Q)-$(LN) $(<:%.dll=%.lib) $(#:%.dll=%.lib) 2>/dev/null
endif
$O/$(TARGET): $(OBJS) $(wildcard $(EXTRA_OBJS)) Makefile $(CONFIGFILE)
#$(MKPATH) $O
#echo Creating executable: $#
$(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) $(LIBS) $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)
.PHONY: all clean cleanall depend msgheaders smheaders
.SUFFIXES: .cc
$O/%.o: %.cc $(COPTS_FILE) | msgheaders smheaders
#$(MKPATH) $(dir $#)
$(qecho) "$<"
$(Q)$(CXX) -c $(CXXFLAGS) $(COPTS) -o $# $<
%_m.cc %_m.h: %.msg
$(qecho) MSGC: $<
$(Q)$(MSGC) -s _m.cc -MD -MP -MF $O/$(basename $<)_m.h.d $(MSGCOPTS) $?
%_sm.cc %_sm.h: %.sm
$(qecho) SMC: $<
$(Q)$(SMC) -c++ -suffix cc $(SMCOPTS) $?
msgheaders: $(MSGFILES:.msg=_m.h)
smheaders: $(SMFILES:.sm=_sm.h)
clean:
$(qecho) Cleaning $(TARGET)
$(Q)-rm -rf $O
$(Q)-rm -f $(TARGET_FILES)
$(Q)-rm -f $(call opp_rwildcard, . , *_m.cc *_m.h *_sm.cc *_sm.h)
cleanall:
$(Q)$(CLEANALL_COMMAND)
$(Q)-rm -rf $(PROJECT_OUTPUT_DIR)
help:
#echo "$$HELP_SYNOPSYS"
#echo "$$HELP_TARGETS"
#echo "$$HELP_VARIABLES"
#echo "$$HELP_EXAMPLES"
# include all dependencies
-include $(OBJS:%=%.d) $(MSGFILES:%.msg=$O/%_m.h.d)
It's correct in saying that clang-release/src/v2x is a directory, but it has always been so (even before making the recent changes) and it hasn't produced this error.
Other than the MakeFile error, there is no other error in any of the scripts for the project.
You want to create the executable file clang-release/src/v2x but you can't because that file already exists and is a directory.
The name of the file you attempt to create is
v2x$(D)$(EXE_SUFFIX) and nowhere in your Makefile do you have Make variables D or EXE_SUFFIX defined, so they evaluate to empty strings.
Probably you want to make sure you have D and EXE_SUFFIX defined somewhere.
There is a $(CONFIGFILE) you are including, Make finds it but you did not provide the text of it, check if these variables should be defined in there but are not.
I have a problem while compiling my code on Windows (it depends on a huge header only library exprtk), and in particular on msys and Cygwin64 shells. I am trying to compile my code using this makefile:
#====================================================
# OS detection
#====================================================
ifeq ($(OS),Windows_NT)
O_SYSTEM = Windows
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
O_SYSTEM = Linux
else ifeq ($(UNAME_S),Darwin)
O_SYSTEM = MacOS
endif
endif
#====================================================
# VARIABLES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
TARGET_EXEC := examples
TEST_EXEC := tests
else
TARGET_EXEC := examples.exe
TEST_EXEC := tests.exe
endif
LIB := libarsenalgear.a
CC := g++
#====================================================
# FOLDERS
#====================================================
BUILD_DIR := bin
SRC_DIR := src
OBJ_DIR := obj
TEST_DIR := test
LIB_DIR := lib
ifeq ($(O_SYSTEM),Windows)
WIN_INCLUDE := C:\include
WIN_BOOST := C:\boost\include\boost-1_79
endif
#====================================================
# SOURCE FILES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
SRC_LIB := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp')
TEST := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp') $(shell find $(TEST_DIR) -name '*.cpp')
else
SRC := $(wildcard $(SRC_DIR)/*.cpp)
SRC_LIB := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp))
TEST := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp)) $(wildcard $(TEST_DIR)/*.cpp)
endif
#====================================================
# SOURCE OBJECTS
#====================================================
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
OBJ_LIB := $(SRC_LIB:%=$(OBJ_DIR)/%.o)
TEST_OBJ := $(TEST:%=$(OBJ_DIR)/%.o)
#====================================================
# DEPENDENCIES AND FLAGS
#====================================================
DEPS := $(OBJ:.o=.d)
ifeq ($(O_SYSTEM),Linux)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else ifeq ($(O_SYSTEM),MacOS)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) `pcre-config --cflags`
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else
INC_DIR := $(SRC_DIR)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) $(addprefix -I,$(WIN_INCLUDE)) $(addprefix -I,$(WIN_BOOST))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
endif
#====================================================
# ALIASES
#====================================================
.PHONY: clean all
#====================================================
# BUILDING
#====================================================
#Building all:
all: $(BUILD_DIR)/$(TARGET_EXEC) $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
examples: $(BUILD_DIR)/$(TARGET_EXEC) $(LIB_DIR)/$(LIB)
tests: $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
#Building main executable:
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJ)
# mkdir -p $(dir $#)
$(CC) $(OBJ) -o $# $(LDFLAGS)
#Building test executable:
$(BUILD_DIR)/$(TEST_EXEC): $(TEST_OBJ)
# mkdir -p $(dir $#)
$(CC) $(TEST_OBJ) -o $# $(LDFLAGS)
#Put object files into the object dir:
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
#Create a static library from object files and put it in the library dir:
$(LIB_DIR)/$(LIB): $(OBJ_LIB)
# mkdir -p $(dir $#)
ar rcs $(LIB_DIR)/$(LIB) $(OBJ_LIB)
#====================================================
# CLEAN
#====================================================
clean:
rm -r $(OBJ_DIR) $(BUILD_DIR) $(LIB_DIR)
#====================================================
# INCLUDE
#====================================================
-include $(DEPS)
Which should be a cross-platform makefile. It perfectly works on Ubuntu and MacOS, but on Windows (Cygwin64 and msys) I got the following error:
g++ -std=c++17 -g -Isrc -IC:\include -IC:\Boost\boost_1_79_0 -MMD -MP -c src/examples.cpp -o obj/src/examples.cpp.o
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Assembler messages:
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't write 571 bytes to section .text of obj/src/examples.cpp.o: 'File too big'
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:91: obj/src/examples.cpp.o] Error 1
I am trying to run it on codeql-analysis GitHub workflow.
What do you think?
EDIT
I tried modifing:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -Wa,-mbig-obj
and the error is the same.
If I modify instead:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -flto -Wl,-allow-multiple-definition
LDFLAGS := -fuse-linker-plugin
I got same error but the number of "too many sections" is lower (43419):
g++ -std=c++17 -g -Isrc -IC:\include -IC:\boost\include\boost-1_79 -MMD -MP -flto -Wl,-allow-multiple-definition -c src/examples.cpp -o obj/src/examples.cpp.o
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Assembler messages:
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't write 3975 bytes to section .gnu.lto_.inline.6d3ed2ee of obj/src/examples.cpp.o: 'File too big'
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:108: obj/src/examples.cpp.o] Error 1
After some hours of tests I've finally found the problem: it was due to the ExprTk library. Since it is a huge header-only library, for a reason that is not clear to me, the Cygwin and MinGW compilers failed to correctly compile it. I solved by simply ignoring this library and all the functions I defined within its objects, by simply adding this preprocessor directive:
#if defined( __linux__ ) || defined( __APPLE__ )
// code which uses ExprTk objects
#endif
In this way the program compiles correctly for Ubuntu, MacOS and Windows, but in the Windows case it ignores the ExprTk objects.
I am working on my first makefile, so far this much done.
BUILD = build
BIN = bin
OUTPUTNAME = game.out
INCLUDE = /internalLibraries/include
SRCFILES := $(wildcard src/*.cpp)
OBJFILES := $(patsubst %.cpp,%.o,$(SRCFILES))
OBJFILES := $(foreach dir,$(OBJFILES),$(subst src/,,$(dir)))
DIR := $(dir $(OBJFILES))
$(foreach d,$(DIR),$(shell mkdir -p $(BUILD)/$(d)))
$(shell mkdir -p $(BIN))
CC = g++
CFLAGS = -g -std=c++11
LIBS=-lsfml-graphics -lsfml-window -lsfml-system
G++_VER_LT48 := $(shell expr `$(CC) -dumpversion | cut -f1-2 -d.` \< 4.8 )
ifeq ("$(G++_VER_LT48)","1")
$(error old version of g++ not supported, upgrade to 4.8 or higher)
endif
default: $(BIN)/$(OUTPUTNAME)
$(info $(OBJFILES))
$(BIN)/$(OUTPUTNAME): $(BUILD)/$(OBJFILES)
$(CC) $(CFLAGS) -o $(BIN)/$(OUTPUTNAME) $(BUILD)/main.o $(BUILD)/game.o $(BUILD)/food.o $(BUILD)/snake.o $(LIBS)
$(BUILD)/%.o: %.cpp
$(CC) -c $(CFLAGS) $< -o $# -I $(INCLUDE)
the problem is, running this produces the output:
sidhin#DRAGONHEART:/mnt/c/Users/sidhi/Desktop/Projects/sfml-snake$ make
food.o game.o main.o snake.o
make: *** No rule to make target `build/food.o', needed by `bin/game.out'. Stop.
What is the problem, I cannot make it out.
$(BUILD)/%.o: %.cpp
With BUILD set to "build", this specifies the rule for building a target called "build/food.o" from "food.cpp".
The problem is, obviously, that "food.cpp" does not exist. The actual source file is "src/food.cpp", based on your declaration:
SRCFILES := $(wildcard src/*.cpp)
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.
hen I do make clean it complains about missing files. In particular it complains about mapnameserver.hthat is included in nstest.cc and nstime.cc.
I thought that doing make clean would ignore all other targets, even implicit ones.
What I want is to be able to do make clean and make vectornameserver without make complaining about the headers that nstest.cc and nstime.cc includes that I have not yet written. Is this possible?
Below is the files in the src dir
nameserverinterface.h
nstest.cc
nstime.cc
vectornameserver.cc
vectornameserver.h
And this is the Makefile
#
# Makefile for CPP
#
# Compiler and compiler options:
CC = /usr/local/bin/clang++
CXX = /usr/local/bin/clang++
CXXFLAGS = -c -pipe -O2 -Wall -W -ansi -pedantic-errors
CXXFLAGS += -Wmissing-braces -Wparentheses -Wold-style-cast
CXXFLAGS += -std=c++11 -stdlib=libc++ -nostdinc++
CXXFLAGS += -I/Users/einar/devel/libcxx/include/
LDFLAGS = -stdlib=libc++
LDLIBS = -L/Users/einar/devel/libcxx/lib/
SRCDIR = ../src
LIBDIR = ../lib
BINDIR = ../bin
DEPDIR = ../dep
VPATH = $(SRCDIR):$(LIBDIR):$(BINDIR):$(DEPDIR)
LIB_INSTALL =
BIN_INSTALL =
SRC = $(wildcard $(SRCDIR)/*.cc)
OBJ = $(notdir $(SRC:.cc=.o))
DEP = $(addprefix $(DEPDIR)/, $(notdir $(SRC:.cc=.d)))
PROGS = vectornameserver
MAKEDEPEND = $(CXX) -MM $(CPPFLAGS) -o $*.d $<
CP = /bin/cp
###
#
# Phony targets
#
###
.PHONY: all
all: $(PROGS)
.PHONY: folder_setup
folder_setup:
mkdir -p $(SRCDIR)
mkdir -p $(LIBDIR)
mkdir -p $(BINDIR)
mkdir -p $(DEPDIR)
.PHONY: clean
clean:
#$(RM) $(OBJ)
.PHONY: cleaner
cleaner:
#$(RM) $(OBJ)
#$(RM) $(PROGS)
#$(RM) $(DEP)
#$(RM) $(wildcard $(DEPDIR)/*.d*)
###
#
# Set up targets for program files in this section
# a rule should look like:
# program: obj1.o obj2.o ...
#
###
vectornameserver : vectornameserver.o
###
#
# In this section automatic dependencies are handled.
#
###
$(addprefix $(DEPDIR)/, %.d): %.cc
#set -e; rm -f $#; \
$(CXX) -MM $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $#: ,g' < $#.$$$$ \
> $#; rm -f $#.$$$$
###
#
# Include the automatically generated dependency files
#
###
include $(DEP)
Thanks in advance.
The problem is that you have an include directive in the makefile. This implicitly makes all the included dependency files implicit targets that must be refreshed BEFORE the primary target can be run. It is those rules that are running the compiler and giving you the errors.
Since generally you don't want/need the dependency files if you're just doing a make clean, the usual thing is to wrap appropriate ifs around the include:
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),cleaner)
-include $(DEP)
endif
endif
This will avoid trying to include the depfiles (and thus regenerate them) if you do make clean or make cleaner. In addition, the - prefix on the include supresses warnings about the depfiles not existing when you first run make (it will (re)generate them and reread the makefile and depfiles if need be.)