I wrote makefile which seems to works fine except for one case:
When I change the makefile itself it does not recompile all files.
I've done all those steps:
make clean
make all
make all (it returns "Nothing to be done for all") - ok
change makefile (add empty line etc.)
make all (still it returns "Nothing to be done for all" - not ok at all
In my opinion, it should recompile when the makefile file was changed.
What can be improved to force makefile to recompile all files when I make modifications in makefile?
Makefile:
################################### VARIABLES ############################################
# Output settings:
BUILD_DIR := ./build
BIN_DIR := $(BUILD_DIR)/bin
TARGET_FOLDER := $(BUILD_DIR)
TARGET_NAME := app.exe
# Input settings:
SOURCE_DIR = ./
SOURCES := $(SOURCE_DIR)/main.cpp
INCLUDES := $(SOURCE_DIR)
# Compilator settings:
CC := gcc
CXX := g++
# Compilation flags:
COMMON_FLAGS := -Wall -Werror
CFLAGS := $(COMMON_FLAGS)
CXXFLAGS := $(COMMON_FLAGS)
LDFLAGS :=
# VERBOSE OPTION
VERBOSE ?= 0 # Set to zero to silent makefile output
ifeq ($(VERBOSE),1)
NO_ECHO :=
else
NO_ECHO := #
endif
############################### MAGID PART START #########################################
TARGET := $(abspath $(TARGET_FOLDER)/$(TARGET_NAME))
# Remove double slash (//) from path, it can make issue with vpath.
# Just use abspath :)
SOURCES_ABS := $(abspath $(SOURCES) )
INCLUDES_ABS := $(abspath $(INCLUDES) )
SOURCES_C := $(filter %.c, $(SOURCES_ABS) )
SOURCES_CC := $(filter %.cc, $(SOURCES_ABS) )
SOURCES_CPP := $(filter %.cpp, $(SOURCES_ABS) )
OBJECTS_LIST := $(notdir $(patsubst %.c, %.o, $(SOURCES_C) ) )
OBJECTS_LIST += $(notdir $(patsubst %.cc, %.o, $(SOURCES_CC) ) )
OBJECTS_LIST += $(notdir $(patsubst %.cpp, %.o, $(SOURCES_CPP) ) )
OBJECTS := $(addprefix $(BIN_DIR)/, $(OBJECTS_LIST) )
DEPENDENCIES := $(patsubst %.o, %.d, $(OBJECTS) )
INCLUDES_FLAG := $(addprefix -I, $(INCLUDES_ABS) )
COMMON_FLAGS += $(INCLUDES_FLAG)
COMMON_FLAGS += -MMD -MP # Generate dependency files
CFLAGS += $(COMMON_FLAGS)
CXXFLAGS += $(COMMON_FLAGS)
# Use vpath to search sources:
VPATH += $(sort $(dir $(SOURCES_C) ) )
VPATH += $(sort $(dir $(SOURCES_CC) ) )
VPATH += $(sort $(dir $(SOURCES_CPP) ) )
all: app
app: $(TARGET)
$(TARGET): $(OBJECTS) | $(BUILD_DIR)
$(info Preparing: $#)
$(NO_ECHO) $(CXX) $(CXXFLAGS) -o $# $^
$(BIN_DIR)/%.o : %.c | $(BIN_DIR)
$(info Preparing: $#)
$(NO_ECHO) $(CC) -c $(CFLAGS) $< -o $#
$(BIN_DIR)/%.o : %.cc | $(BIN_DIR)
$(info Preparing: $#)
$(NO_ECHO) $(CXX) -c $(CXXFLAGS) $< -o $#
$(BIN_DIR)/%.o : %.cpp | $(BIN_DIR)
$(info Preparing: $#)
$(NO_ECHO) $(CXX) -c $(CXXFLAGS) $< -o $#
$(BIN_DIR): |$(BUILD_DIR)
$(NO_ECHO) -mkdir $#
$(BUILD_DIR):
$(NO_ECHO) -mkdir $#
.PHONY : clean
clean:
-rm -fr $(TARGET) $(BUILD_DIR) *.o *.d
-include $(DEPENDENCIES)
main.cpp
#include <iostream>
using namespace std;
int main(void)
{
cout<<"HA HA"<<endl;
return 0;
}
I'm currently using MinGW64, G++, and a makefile to compile my c++ project on VSCode. I have two src directories src and src/vendor/imGui containing .cpp files that I compile. As of now, the makefile is able to compile both src folders. However, the .o files are outputted in their respective src folders. How can I make it so that every .o file generated gets sent to one specific folder/directory?
Current Makefile:
CXX = g++
CXXFLAGS := -std=c++17 -Wall -Wextra -g
LFLAGS += -LC:/mingw64/x86_64-w64-mingw32/bin
LFLAGS += -LC:/mingw64/x86_64-w64-mingw32/lib
OUTPUT := output
SRC := src
SRC += src/vendor/imGui
INCLUDE := include
LIB := lib
ifeq ($(OS),Windows_NT)
MAIN := main.exe
SOURCEDIRS := $(SRC)
INCLUDEDIRS := $(INCLUDE)
LIBDIRS := $(LIB)
FIXPATH = $(subst /,\,$1)
RM := del /q /f
MD := mkdir
else
MAIN := main
SOURCEDIRS := $(shell find $(SRC) -type d)
INCLUDEDIRS := $(shell find $(INCLUDE) -type d)
LIBDIRS := $(shell find $(LIB) -type d)
FIXPATH = $1
RM = rm -f
MD := mkdir -p
endif
INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%))
INCLUDES += -IC:/Users/kimda/Desktop/Projects/C++/Libraries/glm
INCLUDES += -IC:/mingw64/x86_64-w64-mingw32/include
INCLUDES += -IC:/Users/kimda/Desktop/Projects/C++/OpenGL/src/vendor/imGui
LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%))
LIBS += -lglew32
LIBS += -lopengl32
LIBS += -lglfw3
LIBS += -lgdi32
LIBS += -lglu32
SOURCES := $(wildcard $(patsubst %,%/*.cpp, $(SOURCEDIRS)))
OBJECTS := $(SOURCES:.cpp=.o)
OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN))
all: $(OUTPUT) $(MAIN)
#echo Building complete!
$(OUTPUT):
#$(MD) $(OUTPUT)
$(MAIN): $(OBJECTS)
#$(CXX) $(CXXFLAGS) $(INCLUDES) -o $(OUTPUTMAIN) $(OBJECTS) $(LFLAGS) $(LIBS)
.cpp.o:
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
.PHONY: clean
clean:
#$(RM) $(OUTPUTMAIN)
#$(RM) $(call FIXPATH,$(OBJECTS))
#echo Cleanup complete!
run: clean all
#./$(OUTPUTMAIN)
#echo Executing complete!
If I understand you correctly you want to send all object files to some 'build' directory.
I usually do something like this
BUILDDIR := build
[...]
OBJECTS := $(addprefix $(BUILDDIR)/,$(SOURCES:.cpp=.o))
[...]
and then change your
.cpp.o:
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
to
$(BUILDDIR)/%.o: %.cpp
#$(MD) $(dir $#)
#$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
I have the following makefile and would like to also use the GSL library. Do you know how I should proceed?
I cannot find the right way to make my code compile for now.
INCLDIR := include
OBJDIR := obj
SRCDIR := src
BINDIR := bin
CC := g++
VPATH :=
LDFLAGS := -L/home/path/gsl/lib
LIBRARY :=
CFLAGS := -g -Wall -I $(INCLDIR)
#Source and object files (automatic)
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(subst $(SRCDIR)/,$(OBJDIR)/, $(subst .cpp,.o, $(SRCS)))
# Define here your main source files separated by spaces (without suffix!)
EXEC = main
#Phony = do not represent a file
#.PHONY: all
all : makedir $(EXEC)
# For multiple binaries
$(EXEC) : %: %.cpp $(OBJS)
$(CC) $(CFLAGS) -o $(BINDIR)/$# $^
$(OBJDIR)/%.o : $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -c -o $# $<
#Clean: delete every binaries and object files
.PHONY: clean
clean :
rm -rf $(OBJDIR)/*
rm -rf $(BINDIR)/*
#Building folders (-p : no error if folder do not exist)
.PHONY: makedir
makedir :
mkdir -p $(BINDIR)
mkdir -p $(OBJDIR)
Your LDFLAGS is missing -lgsl. Thus far you have only told the linker, where to search in addition to the default directories.
I'm using CODEO (Eclipse + overlay) to build an app for the ELinOS RTOS.
Thing is, I lose the ability to auto-generate the Makefile using eclipse CDT and I have a generic Makefile alreayd generated.
Instead of typing this huge Makefile (Lots and lots of include and sources directories), I tried things with addprefix patsubst and some wildcard but that didn't work out, mainly because I suck with generic makefile !
Regarding libraries, only a few are used, so I'll write them by hand.
Here is how my code is structured.
Top directory
|
---> common ---> inc/
| src/
---> pack_AAA ---> comp_AAA ---> inc/
| | src/
| ----> comp_AAB ---> inc/
| src/
---> comp_BBB ---> inc/
| src/
---> main.cpp
I'd like to enumerate only the top folders (common, pack_AAA, comp_BBB and so on, mostly because not every TOP folder has to be compiled, my Makefile is in one of these top folder).
Below there is a variable amount of subdirectories. Leafs are ALWAYS inc/ (.hpp files) and src/ (as you might guess, .cpp files) folders.
Moreover, the amount of TOP folders won't change, so I mind declaring them, but subfolders will.
Objects files can be anywhere they want (separate top build/ directory, within src/ ...) as long as the resulting executable, let's call it HUGE_PROJECT is in the top directory
Thanks in advance !
SOKS
Here is the generated makefile that I have to start with
-include makefile.init
RM := rm -rf
PROG = HUGE_PROJECT_EXECUTABLE
MODULES := common comp_AAA comp_BBB pack_AAA pack_BBB pack_CCC
SRC_DIRS := $(addprefix ../../,$(MODULES))
#BUILD_DIR := $(addprefix ../../build/,$(MODULES))
#Original non-recursive & working example
OBJS = $(patsubst %.cpp,%.o,$(wildcard ./src/*.cpp))
DEPS = $(patsubst %.cpp,%.d,$(wildcard ./src/*.cpp))
#bad attempt
#SRCS := $(foreach sdir,$(SRC_DIRS),$(wildcard $(sdir)/*.cpp))
#OBJS := $(patsubst %.cpp,%.o,$(SRCS))
#INCLUDES := $(addprefix -I,$(SRC_DIR))
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(DEPS)),)
-include $(DEPS)
endif
endif
-include makefile.defs
# All Target
all: $(PROG).tgz
$(PROG).tgz: $(PROG).mkefs $(PROG)
#echo 'Building file: $#'
#echo 'Invoking: Embeddable file system generator'
mkefs -a -s -o"$#" -f"$<"
#echo 'Finished building: $#'
#echo ' '
$(PROG): $(OBJS) $(USER_OBJS)
#echo 'Building target: $#'
#echo 'Invoking: ELinOS C/C++ Linker'
$(CXX) -o "$(PROG)" $(SRCS) $(USER_OBJS) $(LIBS)
#echo 'Finished building target: $#'
#echo ' '
clean:
-$(RM) $(OBJS) $(DEPS) $(PROG) $(PROG).tgz
-#echo ' '
./src/%.o: ./src/%.cpp
#echo 'Building file: $<'
#echo 'Invoking: ELinOS C/C++ Compiler'
$(CXX) -I./include -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
#echo 'Finished building: $<'
#echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include makefile.targets
Here is the Makefile I ended up with.
I had to hide components name.
#Executables
RM := rm -rf
CXX=YOUR_CXX_COMPILER
CC=YOUR_CC_COMPILER
PROG=YOUR_PROGRAM
#Root directory of your program (all files should be in it)
ROOT_DIR := ../../
#####################################
########################################
# Define here all directories #
# containing src/ and inc/ folders #
########################################
#pack_AAA folders
#Modules containing both src/ and inc/.
AAA_MODULES := moduleA moduleB
#Modules with an include folder only + module with both
AAA_DIRS_INC := moduleD moduleEF $(AAA_MODULES)
#pack_BBB modules list
BBB_MODULES := comp_A comp_B comp_C comp_B/comp_D comp_B/comp_E
MMM_MODULES := comp_F comp_G comp_H
PPP_MODULES := . I
CCC_MODULES := J comp_K comp_L \
comp_L/comp_M \
$(addprefix pack_BBB/,$(BBB_MODULES)) \
$(addprefix pack_MMM/,$(MMM_MODULES)) \
$(addprefix comp_PPP/,$(PPP_MODULES))
#pack_DDD
DDD_MODULES := M comp_N comp_N/comp_O
#comp_EEE
EEE_MODULES := . P Q
OTHER_MODULES := R S comp_T
#All folders containing src/ subdir
SRC_MODULES := $(OTHER_MODULES) \
$(addprefix comp_EEE/,$(EEE_MODULES)) \
$(addprefix pack_DDD/,$(DDD_MODULES)) \
$(addprefix pack_AAA/,$(AAA_MODULES)) \
$(addprefix pack_CCC/, $(CCC_MODULES))
#All folders containing inc/ subdir
INCLUDE_MODULES := $(OTHER_MODULES) \
$(addprefix comp_EEE/,$(EEE_MODULES)) \
$(addprefix pack_DDD/,$(DDD_MODULES)) \
$(addprefix pack_AAA/,$(AAA_DIRS_INC)) \
$(addprefix pack_CCC/, $(CCC_MODULES))
#####################################
#WRAPPERS
ROOT_DIR_WRAPPERS := $(ROOT_DIR)../WRAPPERS/
LIST_WRAPPERS := WA WB WC WD
SRC_WRAPPERS := $(addprefix pack_Wrappers/csc_Wrapper,$(LIST_WRAPPERS))
#DRIVERS
LIST_DRIVERS := DA DB DC DD
DIR_DRIVERS := $(addprefix pack_Drivers/csc_Driver,$(LIST_DRIVERS))
SRC_DIRS_WRAPPERS := $(addsuffix /src,$(SRC_WRAPPERS))
INCLUDE_DIRS_WRAPPERS := $(addsuffix /inc,$(SRC_WRAPPERS)) \
$(addsuffix /inc,$(DIR_DRIVERS)) \
Common
#####################################
#LIB_1 INCLUDE
ROOT_DIR_LIB_1 := $(ROOT_DIR)../../ObjetsCompiles/LIB_1/
INCLUDE_DIRS_LIB_1 := dir1 dir2 dir3
#####################################
#LIB_2 INCLUDE
ROOT_DIR_LIB_2 := $(ROOT_DIR)../../ObjetsCompiles/LIB_2/include
INCLUDE_DIRS_LIB_2 := . dir1 dir2 dir3/subdir dir4
#####################################
#Add "." to find main.cpp
SRC_DIRS := $(addsuffix /src,$(SRC_MODULES)) .
INCLUDE_DIRS_SRC:= $(addsuffix /inc,$(INCLUDE_MODULES)) pack_ZZZ/comp_Without_Inc_Folder
#All include dirs, LIB_1 + LIB_2
INCLUDE_DIRS := $(addprefix -I$(ROOT_DIR),$(INCLUDE_DIRS_SRC)) \
$(addprefix -I$(ROOT_DIR_LIB_1),$(INCLUDE_DIRS_LIB_1)) \
$(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))
INCLUDE_DIRS_CC := $(addprefix -I$(ROOT_DIR_WRAPPERS),$(INCLUDE_DIRS_WRAPPERS)) \
$(addprefix -I$(ROOT_DIR_LIB_2),$(INCLUDE_DIRS_LIB_2))
#All objects (all .cpp & all .c)
OBJS := $(foreach dir,$(SRC_DIRS), \
$(patsubst %.cpp,%.o,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
$(foreach dirs,$(SRC_DIRS_WRAPPERS), \
$(patsubst %.c,%.o,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))
#All dependencies (same list as OBJS)
DEPS := $(foreach dir,$(SRC_DIRS), \
$(patsubst %.cpp,%.d,$(wildcard $(ROOT_DIR)$(dir)/*.cpp))) \
$(foreach dirs,$(SRC_DIRS_WRAPPERS), \
$(patsubst %.c,%.d,$(wildcard $(ROOT_DIR_WRAPPERS)$(dirs)/*.c)))
#Exclude files from build
#Win32 socket files + some misc
EXCLUDED_FILES_LIST := pack_AAA/comp_BBB/src/SocketWindowsOnLinuxForExample.cpp \
pack_BBB/comp_CCC/src/SomeOtherThingForWindows.cpp
EXCLUDED_FILES_PATH := $(addprefix $(ROOT_DIR),$(EXCLUDED_FILES_LIST))
#Remove some objects (compilation is done, but no link)
EXCLUDED_OBJS := $(patsubst %.cpp,%.o,$(EXCLUDED_FILES_PATH))
EXCLUDED_DEPS := $(patsubst %.cpp,%.d,$(EXCLUDED_FILES_PATH))
#Update OBJS & DEPS list with excluded files
OBJS := $(filter-out $(EXCLUDED_OBJS),$(OBJS))
DEPS := $(filter-out $(EXCLUDED_DEPS),$(DEPS))
#FLAGS for DEBUG and RELEASE compilation
CPPFLAGS := -D__CPPFLAG1__ -D__CPPFLAG2__
CFLAGS_D := -O0 -g2 -Wall -c -fmessage-length=0
CXXFLAGS_D := -O0 -g2 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline
CFLAGS_R := -O2 -g0 -Wall -c -fmessage-length=0
CXXFLAGS_R := -O2 -g0 -Wall -c -fmessage-length=0 -m32 -mcpu=powerpc -Winline
# L
LD_PATH := -L../../path_library_1 -L../../path_library_2
LD_LIBS := -lpthread_rt -lROHC -lpthread -lnative -lrtdm -lrt
MAP := $(PROG).map
# -s (to strip)
LD_FLAGS_D := -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)
LD_FLAGS_R := -s -Wl,--wrap,pthread_create -Wl,--wrap,pthread_kill -Wl,-Map,$(MAP)
##################################################
#TARGETS
default: release
#Debug flags (-00 + -g2)
debug: CFLAGS := $(CFLAGS_D)
debug: CXXFLAGS := $(CXXFLAGS_D)
debug: LD_FLAGS := $(LD_FLAGS_D)
debug: all
#Release flags (-s + -02 + -g0)
release: CFLAGS := $(CFLAGS_R)
release: CXXFLAGS := $(CXXFLAGS_R)
release: LD_FLAGS := $(LD_FLAGS_R)
release: all
all: $(PROG)
# Tool invocations
$(PROG): $(OBJS)
#echo 'Building target: $#'
#$(CXX) $(LD_FLAGS) $(LD_PATH) -o "$(PROG)" $(OBJS) $(LD_LIBS)
#echo 'Finished building target: $#'
#echo ' '
# CXX compiler used by most of the code
%.o: %.cpp
#echo 'Building file: $<'
#$(CXX) $(CPPFLAGS) $(INCLUDE_DIRS) $(CXXFLAGS) -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
# CC compiler used by Wrappers only
%.o: %.c
#echo 'Building file: $<'
#$(CC) $(INCLUDE_DIRS_CC) $(CFLAGS) -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d)" -o "$#" "$<"
# Other Targets
clean:
-$(RM) $(OBJS) $(DEPS) $(PROG) $(MAP)
-#echo ' '
.PHONY: all clean dependents
.SECONDARY:
I am trying to understand a second level makefile of uboot (this makefile was in a sub directory)
a) What is the difference between $(COBJS:.o=.c) and COBJS := test_main.o
b) What is the meaning of $(call cmd_link_o_target, $(OBJS)). What is the cmd_link_o_target and what is the call statement doing
c) Does this line creating 2 targets ?
ALL := $(obj).depend $(LIB)
===================================Makefile===================
include $(TOPDIR)/config.mk
LIB = $(obj)libtest.o
SOBJS := test.o
COBJS := test_main.o
COBJS += diagnostic.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
ALL := $(obj).depend $(LIB)
all: $(ALL)
$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
a) $(COBJS:.o=.c) performs a suffix substitution on every element of COBJ which in this case is equivalent to using SRCS := test.S test_main.c
b) $(call cmd_link_o_target, $(OBJS)) is a way to create a parametric function in make. It will take the expression for cmd_link_o_target (contained in the included file) and replace every occurence of $(1) with $(OBJS) further expanded.
c) yes, it does (obj is also contained in the file included by the Makefile).
In case you are wondering, the difference between = and := assignments is that = allows for recursive replacement, while := is static, i.e. expanded only once, without creating references to other variables.