I have a makefile that I've been using to compile my shared libraries which reads in the files from different folders and then builds the objects and binaries in their own folders.
The folder structure I'm using roughly:
-Folder | +--API Header Files Dir | +--Library (.so) Project One | +-- MakeFile Project One | +-- src (*.cpp files) | +-- inc (*.h files) | +-- obj (compiled object files) | +-- bin (compiled libraries) | +--Library (.so) Project Two | +-- MakeFile Project Two | +-- src (*.cpp files) | +-- inc (*.h files) | +-- obj (compiled object files) | +-- bin (compiled libraries) |
I've tried to put together a general makefile that can accomplish this and this post was quite nice and I've edited my original makefile to the best of my understanding to try to make this work.
Here's my makefile:
######################################################################################
# Date Created : 25-06-2015
# Date Modified : 03-08-2015
#
# Note : 1. make : to build unoptimized standard build
# 2. make debug : to build with debug symbols
# 3. make release : to build with symbols stripped and optimized
#
# Usage : change the "NAME" to your program name or else use as it is
######################################################################################
ifndef _ARCH
_ARCH := $(shell uname -m)
export _ARCH
endif
NAME := Test
MAJOR := 1
MINOR := 5
VERSION := v$(MAJOR)_$(MINOR)
TARGET := $(NAME)_$(VERSION).o
SRCEXT := cpp
SRCDIR := src
INCPATH := inc
OBJDIR := obj
BINDIR := bin
BIN_DEBUGDIR := $(BINDIR)/debug
API_DIR := /home/API/Multibody
INCLUDES := -I. \
-I$(INCPATH) \
-I$(API_DIR)
# C++ compiler flag
CXXFLAGS := -Wall -march=native $(INCLUDES) -c
# Linker parameter flags
# Linker library flags
LIBDIRS := -L$(API_DIR)/lib
# LDFLAGS := -shared
LDFLAGS := -Wl,-rpath -Wl,$(API_DIR)/lib $(LIBDIRS)
LDLIBS := -lCouplingClientV2_2_0
SRCS := $(shell find $(SRCDIR) -name '*.$(SRCEXT)')
SRCDIRS := $(shell find . -name '*.$(SRCEXT)' -exec dirname {} \; | uniq)
OBJS := $(patsubst %.$(SRCEXT),$(OBJDIR)/%.o,$(SRCS))
###########################################################################
# Rules to compile our files - Do not change below this line!
###########################################################################
ifeq ($(SRCEXT), cpp)
CC = $(CXX)
else
CXXFLAGS += -std=gnu99
endif
.PHONY: all debug release clean distclean
all: $(BINDIR)/$(TARGET)
# Build debug library
debug: CXXFLAGS += -g
debug: clean $(BIN_DEBUGDIR)/$(TARGET)
# strip all symbols from release verison
release: LDFLAGS += -s
release: CXXFLAGS += -O2
release: $(BINDIR)/$(TARGET)
$(BINDIR)/$(TARGET): buildrepo $(OBJS)
@mkdir -p `dirname $@`
# @echo "Linking $@..."
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
# @echo "$@ sucessfully built."
$(BIN_DEBUGDIR)/$(TARGET): buildrepo $(OBJS)
@mkdir -p `dirname $@`
# @echo "Linking $@..."
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
# @echo "$@ sucessfully built."
$(OBJDIR)/%.o: %.$(SRCEXT)
# @echo "Generating dependencies for $<..."
$(call make-depend,$<,$@,$(subst .o,.d,$@))
# @echo "Compiling $<..."
$(CC) $(CXXFLAGS) $< -o $@
clean:
$(RM) -r $(OBJDIR)
distclean: clean
$(RM) -r $(BINDIR)/$(TARGET)
$(RM) -r $(BIN_DEBUGDIR)/$(TARGET)
buildrepo:
$(call make-repo)
define make-repo
for dir in $(SRCDIRS); \
do \
mkdir -p $(OBJDIR)/$$dir; \
done
endef
# usage: $(call make-depend,source-file,object-file,depend-file)
define make-depend
$(CC) -MM \
-MMD \
-MF $3 \
-MP \
-MT $2 \
$(CXXFLAGS) \
$(LDFLAGS) \
$1
endef
The file is mainly used for compiling shared libraries, but also has to be able to easily switch to creating an executable linking to some libraries like it's currently set up.
What are normal best practices? Is there a neater way to write the directory building rules for the binaries and object files? Should I be including native architecture such as optimization for Intel or AMD chips in names?