I have what should be a rather trivial problem of creating a makefile for a shared library, but the main header files for the program API are located in a separate folder to the source files for the library project (there are many different shared library projects that all access these common header files). My folder structure is sometime like this:
-Folder
|
+--API Header Files Dir
|
+--Library (.so) Project One
| +-- MakeFile Project One
| +-- *.cpp files
|
+--Library (.so) Project Two
| +-- MakeFile Project Two
| +-- *.cpp files
|
+--Library (.so) Project Three
| +-- MakeFile Project Three
| +-- *.cpp files
where each library project is unrelated to each other, but each one needs to access the *.h files in the "API Header Files Dir".
Because the number of source files in each library can vary anywhere between 1-20 depending on the complexity of the library I wanted to write a makefile that would simply search the current directory for the .cpp files and include the header files from the other directory.
The biggest problem, i still don't quite understand the intricacies of make files and I've made quite a mess of this.
# Makefile template for shared library
##############################################################################
# Application-specific variables
# TARGET_LIB is the name of the shared library file
# SRCS is a list of all source code files that must be linked
# to create the executable
##############################################################################
MAJOR := 1
MINOR := 2
NAME := Test
VERSION := $(MAJOR).$(MINOR)
TARGET_LIB: lib$(NAME).so.$(VERSION) # target lib
# define the C source files
SRCS = srcFile1.cpp srcFile2.cpp \
srcFile3.cpp srcFile4.cpp srcFile5.cpp \
srcFile6.cpp srcFile7.cpp
##############################################################################
# Where to find related files
# API_DIR is where various header files (.h)
# relating to the API are found.
# LIB_DIR is where other libraries (not specific) are kept.
# for header files and additional libraries
API_DIR = ../API_SRC_Files
LIB_DIR =
# What flags should be passed to the C pre-processor
# In other words, where should we look for files to include - note,
# you should never need to include compiler specific directories here
# because each compiler already knows where to look for its system
# files (unless you want to override the defaults)
# define any directories containing header files other than /usr/include
INCLUDES = -I. \
-I$(API_DIR)
##############################################################################
# Compiler specifications
# These match the variable names given in /usr/share/lib/make/make.rules
# so that make's generic rules work to compile our files.
# gmake prefers CXX and CXXFLAGS for c++ programs
##############################################################################
# Which compiler should be used
# Which compiler should be used
CXX = g++
CC = $(CXX)
# What flags should be passed to the compiler
OPTIMIZE = -O3
DEBUG_LEVEL = # -g if debug version
CFLAGS = -fPIC -Wall -Wextra -march=native $(OPTIMIZE) $(DEBUG_LEVEL) $(INCLUDES)
# What flags should be passed to the linker
# In other words, where should we look for libraries to link with - note,
# you should never need to include compiler specific directories here
# because each compiler already knows where to look for its system files.
LDFLAGS = -shared
# For tidying up
RM = rm -f # rm command
# define the C object files
#
# This uses Suffix Replacement within a macro:
# $(name:string1=string2)
# For each word in 'name' replace 'string1' with 'string2'
# Below we are replacing the suffix .c of all words in the macro SRCS
# with the .o suffix
#
OBJS = $(SRCS:%.cpp=%.o)
###########################################################################
# Additional rules make should know about in order to compile our files
###########################################################################
# all is the default rule
.PHONY: all
all: ${TARGET_LIB}
@echo Library file has been compiled
lib$(NAME).so.$(VERSION): $(OBJS)
$(CC) $(CFLAGS) ${LDFLAGS} -o $@ $^
$(SRCS:%.cpp=%.d):%.d:%.cpp
$(CC) $(CFLAGS) -MM $< >$@
include $(SRCS:%.cpp=%.d)
# clean up after you're done
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS} $(SRCS:%.cpp=%.d)
Anyway, like I said, I've made a mess of this and don't really have a clue what the problem is, just that any-time g++ called one of the header files it just spits out "No such file or directory" before all the compilation errors related to not finding the header files.
Any help sorting this out would be greatly appreciated - also if there a simple way to a build directory for the created .so file that would be useful too - but that's for after I get the thing to compile in the first place!
Yep, your makefile is a mess. Too many comments actually doesn't help readability. I cleaned it up for you:
NAME := Test
MAJOR := 1
MINOR := 2
VERSION := $(MAJOR).$(MINOR)
TARGET_LIB := lib$(NAME).so.$(VERSION)
SRC := $(wildcard *.cpp)
OBJ := $(SRC:.cpp=.o)
DEP := $(OBJ:.o=.d)
# preprocessor flags
CPPFLAGS := -MMD -MP -I../API_SRC_Files
# C++ compiler flag
CXXFLAGS := -Wall -W -fPIC -O3 -march=native
# Linker parameter flags
LDFLAGS := -shared
# Linker library flags
LDLIBS :=
.PHONY: all debug clean
all: $(TARGET_LIB)
debug: CXXFLAGS += -g
debug: $(TARGET_LIB)
$(TARGET_LIB): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
clean:
$(RM) $(TARGET_LIB) $(OBJ) $(DEP)
ifeq "$(MAKECMDGOALS)" ""
-include $(DEP)
endif
Don't use $(CC)
and $(CFLAGS)
when using C++, use $(CXX)
and $(CXXFLAGS)
instead (and here the builtin rule to compile .o
files is enough, no need to use it by yourself).
Don't spread your flags everywhere, keep things clear.
Don't redefine everything needlessly: $(RM)
is already defined like you want (and the -f
means you don't need the dash in the call like -$(RM)
since it won't fail anyway), $(CXX)
is also already defined like you want.
Reading (even parts of) the manual is a good starting point when you don't really understand what you're doing.