Following this question on meta TL;DR Not sure whether this question is too general...
The idea is to have a universal (ish) makefile, that can be dropped into any C++ Sublime Text Project and it work with any combination of the GMP,SDL2 and pthread libraries. There is then a choice of how I compile/link through the Sublime Text 3 build system.
(Unfortunately I can't show you the Sublime build api, because when I try a screen shot the relavent window automatically closes.)
In essence ST3 (Sublime Text 3) is calling the makefile 'build_MUTAG_Dbug.mk' with various different flags passed to it eg GMP=true PED=true THREAD=true and depending on these values, that dictates the various libraries the project will be compiled/linked with.
I am going to put my questions in the comments of the makefile so that questions have context.
(As per) I'm self learning.
The Sublime Text 3 build system looks like this. The actual JSON file is much bigger, as there are options to just build one source file (with all lib combinations), as well as the whole project:
{
"cmd" : ["make default --file=build_MUTAG_Dbug.mk -B TARGET=\"$file_base_name\""],
"selector" : "source.c",
"shell": true,
"file_regex": "^(.+):([0-9]*):([0-9]*):(.*)$",
"working_dir": "${file_path}",
"syntax": "Packages/Makefile/Make Output.sublime-syntax",
"variants":
[
{
"name": "Clang++ GMP, SDL2 & thread",
"shell_cmd": "make sdl2 --file=build_MUTAG_Dbug.mk -B DEBUGFLAG=-DDEBUG GMP=true THREAD=true TARGET=\"$file_base_name\""
},
{
"name": "Clang++ Pedantic GMP, SDL2 & thread",
"shell_cmd": "make sdl2 --file=build_MUTAG_Dbug.mk -B DEBUGFLAG=-DDEBUG GMP=true PED=true THREAD=true TARGET=\"$file_base_name\""
},
{
"name": "Clang++ GMP, SDL2 & thread NOT everything Only CHANGED",
"shell_cmd": "make sdl2 --file=build_MUTAG_Dbug.mk DEBUGFLAG=-DDEBUG GMP=true THREAD=true TARGET=\"$file_base_name\""
},
{
"name": "G++ SDL2",
"shell_cmd": "make sdl2 --file=build_MUTAG_Dbug.mk -B CC=g++-7 DEBUGFLAG=-DDEBUG TARGET=\"$file_base_name\""
},
]
}
Here's the makefile build_MUTAG_Dbug.mk ,directory structure (& code)
# Directory structure:
# Main Project/FileHandling
# Main Project/Graphics
# Main Project/Ancillaries
# The final app MUTAG has some of the larger header and source files # in the same directory
# and then all the ancillary header and sources are distributed
# according to function
# in the other directories (See before makefile code).
# Is this the correct way to use VPATH ?
# Is this generally the right way of writing a make file to compile a project with a directory structure such as this ?
# Would there be some command-line magic to get a list of all directories using a bash
# script say and then 'feeding' that to VPATH, or does the directory structure always
# have to be hard coded into the makfile ?
VPATH = FileHandling:Graphics:Ancillaries
# These are for string substitutions later
DIR1 = FileHandling/
DIR2 = Graphics/
DIR3 = Ancillaries/
CC = clang++-3.8
GMP = false
THREAD = false
PED = false
SDL2FLAGS = -lSDL2 -lSDL2_image -lSDL2_ttf
GMPFLAGS = -lgmp -lgmpxx
THREADFLAGS = -pthread
LDTHEADFLAGS = -lpthread
PEDFLAGS = -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy\
-Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations\
-Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls\
-Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef\
-Werror -Wunused -Wextra -Wunused-but-set-parameter -fdiagnostics-show-option
DEBUGFLAG =
SANITIZEFLAGS = -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
LDLIBSXTRA = -lstdc++fs
# Note to self:LDFLAGs for -L rather than -l LDFLAGS = ...
# lc++ for libstd clang gdb symbols
LDLIBS = -lc++ -lm -lgcc_s -lgcc -lc
# Sorting the different flags out for different compilers and modes
# stdlib=libc++ if for gdb to "decode" std::string
ifeq ($(CC),g++-7)
CXXFLAGS = -std=c++17 -w -O0 -ggdb
LDLIBS += $(LDLIBSXTRA)
sdl2:LDLIBS += $(SDL2FLAGS)
else
CXXFLAGS = -std=c++14 -stdlib=libc++ -w -O0 -ggdb3
sdl2:LDLIBS += $(SDL2FLAGS)
endif
# I'm sure using the 'sdl2' flag like this is wrong (it does however work).
# The first flag after make is for all/clean etc. Am I correct in
# this assumption?
# To do it properly I'd have to have another flag say SDL and check
# whether it was true/false like the other flags (PED,GMP etc) ?
# Resolving flags passed to makefile to determine which libraries are
# used during compile and link
ifeq ($(THREAD),true)
CXXFLAGS += $(THREADFLAGS)
LDLIBS += $(LDTHEADFLAGS)
endif
ifeq ($(GMP),true)
LDLIBS += $(GMPFLAGS)
endif
ifeq ($(PED),true)
CXXFLAGS += $(PEDFLAGS)
endif
# Am I using the '-I' flag correctly? Again would there be someway
# of automating this so that it would work for any directory
# structure ?
CPPFLAGS = -I"/home/elitebook/Desktop/Big Mandlebrot/Final Project/FileHandling/"\
-I"/home/elitebook/Desktop/Big Mandlebrot/Final Project/Graphics/"\
-I"/home/elitebook/Desktop/Big Mandlebrot/Final Project"\
-I"/home/elitebook/Desktop/Big Mandlebrot/Final Project/Ancillaries/"
CXXFLAGS += $(DEBUGFLAG)
SRCS4 := $(wildcard $(DIR3)*.cpp)
SRCS3 := $(wildcard $(DIR2)*.cpp)
SRCS2 := $(wildcard $(DIR1)*.cpp)
SRCS1 := $(wildcard *.cpp)
# So that sources are *.cpp /FileHandling/*.cpp & /Graphics/*.cpp
SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4)
# However all the object files are in the same dir as the linker so have
# to remove FileHandling/ and Graphics/ from the source files to get correct
# object file names , ie one without directory precursors
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
OBJS := $(patsubst $(DIR1)%,%,$(OBJS))
OBJS := $(patsubst $(DIR2)%,%,$(OBJS))
OBJS := $(patsubst $(DIR3)%,%,$(OBJS))
# check srcs and objs are ok...
$(info SRCS are $(SRCS))
$(info OBJS are $(OBJS))
sdl2: $(TARGET)
default:$(TARGET)
%.o: %.cpp
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c $< ; pwd
$(TARGET): $(OBJS)
g++-7 $^ $(LDLIBS) -o $@
Finally I've left the object files in the directory, to make sure they've been compiled and I can check the time stamp.
Traditionally they're removed ?
And there should be a .PHONEY which I'm not sure about as all the above works?
Edit: I was having some comment formatting issues, which I've changed and are detailed in the comments