makefile with many source folders - linux

The original makefile I have, which works, only involves one source folder and the makefile is stored inside this folder. Now I have multiple folders inside my src folder.
I am using an autogeneration script to work out dependencies and objective files. Each subfolder has a Make-deps and Make-objs file. These are generated from the $(AUTOGEN) command
Before I had this:
deps:
$(AUTOGEN) -d -s $(SRCDIR) -f ../scripts/fgenrc ;\
sed -i "" -e's/(SRCDIR)/(OBJDIR)/' Make-objs ; \
sed -i "" -e's/(SRCDIR)\(.*\)\.o/(OBJDIR)\1\.o/g' Make-deps ; \
So $(AUTOGEN) is just the shell script which makes the dependencies and $(SRCDIR) is where the source files are. Make-obj and Make-deps are the files containing the dependencies and objective file names.
Somewhere else I have the following:
$(OBJDIR)/%.o: %.f Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $<
Now I want to this but where my %.f files are in various folders, and also where I have several Make-obj and Make-deps.
Maybe I should show an example of Make-obs and Make-deps:
Make-deps:
$(OBJDIR)/fluxes.o fluxes.o: \
path/to/src/folder1/fluxes.f90 \
$(OBJDIR)/mod.o \
$(OBJDIR)/ig.o ig.o: \
path/to/src/folder1/ig.f90 \
$(OBJDIR)/mod.o \
from the sed command I change the objective file path to be $(OBJDIR) because this is where I move them when being compiled.
Make-obj
OBJS = \
$(OBJDIR)/fluxes.o \
$(OBJDIR)/ig.o \
Now I have defined
SOURCE_FILES_c := $(shell find $(SRCDIR) -name '*.c')
SOURCE_FILES_f90 := $(shell find $(SRCDIR) -name '*.f90')
which are all source files found the SRCDIR and its subfolders. Also I have defined
DEPS_FILES := $(shell find $(SRCDIR) -name 'Makefile-deps')
OBJS_FILES := $(shell find $(SRCDIR) -name 'Makefile-objs')
which are all dependency and objective files. These are found in each subfolder containing some source code.
Then, I am trying to do following. (The target deps seems to work as when I comment out the compilation rule it does create the deps and objs file correctly in each folder.)
code: create_dir deps scripts
#make -j $(CORES) $(NAMEEXE)
$(NAMEEXE): $(LIBRARY) $(OBJS)
#$(F90) $(FFLAGS) $(OPTIONS) -o $(OBJDIR)/$(MAIN).o main/$(MAIN).f90
#$(F90) -o $(NAMEEXE) $(LOPTIONS) $(OBJS) $(LIBRARY) && \
deps:
${AUTOGEN} -d $(AUTOGEN_COMMAND) -f ${AUTOCONF} ; \
$(SEDI) -e "s/[(][^)]*[)]/\$$(OBJDIR)/g" $(OBJS_FILES) ; \
$(SEDI) -e "s/[(][^)]*[)]\(.*\)\.o/\$$(OBJDIR)\1\.o/g"
$(DEPS_FILES) ; \
$(OBJDIR)/%.o: $(SOURCE_FILES_f:.f90=.o) Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $< && \
( mv -f *.mod $(OBJDIR) > /dev/null 2>&1;
$(OBJDIR)/%.o: $(SOURCE_FILES_c:.c=.o) Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $< && \
( mv -f *.mod $(OBJDIR) > /dev/null 2>&1;
%.o: $(SOURCE_FILES_c:.c=.o) Makefile
#make $(OBJDIR)/$#
%.o: $(SOURCE_FILES_c:.c=.f90) Makefile
#make $(OBJDIR)/$#
I am including the deps and objs by this command
-include $(DEPS_FILES)
-include $(OBJS_FILES)
I obviously did not want put the entire makefile here, but if something is missing before you can understand what's going on please let me know.
When I type make the error I get is that my $(main) source file cannot open the compiled module file which is included in the main source.
This is because it is not compiled, but this also means that my dependency file is not working as intended?
When I look into my corresponding dep file which includes the main file, I can see that the dependency modules are added to the source file

Related

Multiple SRCDIR folders for compilation using makefile

I am trying to do the following, where SRCDIRS includes all folders containing the source code by doing the following in the makefile:
SRCDIRS := $(shell find $(SRCDIR) -type d )
$(OBJDIR)/%.o: $(SRCDIRS)/%.f90 Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $<
My make file seems to ignore the %.o rule?
I also have a defined $(OBJS) which includes all my %.o files
You can't "multiply" strings that way in Make. And even if you could, you'd be specifying the wrong paths. Use vpath:
vpath %.f90 $(SRCDIRS)
$(OBJDIR)/%.o: %.f90 Makefile
#$(F90) $(FFLAGS) $(POPTIONS) -o $# $<

Compilation issue while using traceroute in a custom tool

For my master thesis, I am developing a tool to test and evaluate a formula for multipath networks.
I will be using the traceroute tool to trace the network between two multihomed hosts by passing to it -s flag, src IP and dst IP. I have multiple source and dest IPs. So the traceroute will be performed multiple times.
I am not good with compilation stuff. The downloaded code for traceroute-2.1.0 from the website https://sourceforge.net/projects/traceroute/files/traceroute/ has following "make" related files.
Makefile
make.defines
make.rules
default.rules
I have applied my changes to the code in traceroute.c, and I can compile it properly by "make" and "make install". But these changes are made to the traceroute tool for the system(obviously).
What I want to achieve is, to have it with a new name, for example "mytrace" instead of "traceroute". So it doesnt come in conflict with the traceroute tool and I could use both tools. Calling with "traceroute" and other with "mytrace" in cmd line.
Question is: What changes I must make before recompiling, in order to achieve it.
Here is the code of the file "makefile".
# Global Makefile.
# Global rules, targets etc.
#
# See Make.defines for specific configs.
#
srcdir = $(CURDIR)
override TARGET := .MAIN
dummy: all
include ./Make.rules
targets = $(EXEDIRS) $(LIBDIRS) $(MODDIRS)
# be happy, easy, perfomancy...
.PHONY: $(subdirs) dummy all force
.PHONY: depend indent clean distclean libclean release store libs mods
allprereq := $(EXEDIRS)
ifneq ($(LIBDIRS),)
libs: $(LIBDIRS)
ifneq ($(EXEDIRS),)
$(EXEDIRS): libs
else
allprereq += libs
endif
endif
ifneq ($(MODDIRS),)
mods: $(MODDIRS)
ifneq ($(MODUSERS),)
$(MODUSERS): mods
else
allprereq += mods
endif
ifneq ($(LIBDIRS),)
$(MODDIRS): libs
endif
endif
all: $(allprereq)
depend install: $(allprereq)
$(foreach goal,$(filter install-%,$(MAKECMDGOALS)),\
$(eval $(goal): $(patsubst install-%,%,$(goal))))
what = all
depend: what = depend
install install-%: what = install
ifneq ($(share),)
$(share): shared = yes
endif
ifneq ($(noshare),)
$(noshare): shared =
endif
$(targets): mkfile = $(if $(wildcard $#/Makefile),,-f
$(srcdir)/default.rules)
$(targets): force
#$(MAKE) $(mkfile) -C $# $(what) TARGET=$#
force:
indent:
find . -type f -name "*.[ch]" -print -exec $(INDENT) {} \;
clean:
rm -f $(foreach exe, $(EXEDIRS), ./$(exe)/$(exe)) nohup.out
rm -f `find . \( -name "*.[oa]" -o -name "*.[ls]o" \
-o -name core -o -name "core.[0-9]*" -o -name a.out \) -print`
distclean: clean
rm -f `find $(foreach dir, $(subdirs), $(dir)/.) \
\( -name "*.[oa]" -o -name "*.[ls]o" \
-o -name core -o -name "core.[0-9]*" -o -name a.out \
-o -name .depend -o -name "_*" -o -name ".cross:*" \) \
-print`
libclean:
rm -f $(foreach lib, $(LIBDIRS), ./$(lib)/$(lib).a ./$(lib)/$(lib).so)
# Rules to make whole-distributive operations.
#
STORE_DIR = $(HOME)/pub
release release1 release2 release3:
#./chvers.sh $#
#$(MAKE) store
store: distclean
#./store.sh $(NAME) $(STORE_DIR)
I wrote to the programmer of the tool, his solution worked for me. Here it is:
Just rename the sub-directory "traceroute" to another name, say "mytrace".
IOW, you'll have "include, libsupp, mytrace" instead of "include, libsupp, traceroute".
Additionally, if you plan to create a tarball with the changed name etc., it seems that you have to rename "NAME = traceroute" to "NAME = mytrace" in the Make.defines file.
Best regards,
Dmitry Butskoy

Confusing Makefile

I just came across this makefile, and it's confusing to me:
PROJECT_ROOT = ../..
LIBDIR = $(PROJECT_ROOT)/src/lib
INCDIR = $(PROJECT_ROOT)/include
SRCS = proj_start.c function1.c
LIBS = $(LIBDIR)/libtest.a
OBJS = $(SRCS:.c=.o)
PROJECT = project1
FLAGS = -I$(INCDIR)
CC = gcc $(FLAGS)
.c.o:
$(CC) -c $<
$(PROJECT): $(OBJS)
$(CC) $(OBJS) $(LIBS) -o $#
it: $(PROJECT)
clean:
rm -f $(OBJS) $(PROJECT)
depend: $(SRCS)
$(CC) -M $(SRCS) > dependList
sed -e '1,/^# DO NOT DELETE/!d' Makefile > make.tmp
cat dependList >> make.tmp
mv make.tmp Makefile
rm dependList
# DO NOT DELETE THIS LINE
These are the parts that confuse me:
LIBDIR = $(PROJECT_ROOT)/src/lib
Why is LIBDIR in the root/src/lib library?
Shouldn't it be the root/lib directory (both directories are present in the file hierarchy)?
.c.o:
$(CC) -c $<
What the heck does this do? The "$<" evaluates to .c.o? I see that it is a 'suffix rule' but what are they really used for?
depend: $(SRCS)
$(CC) -M $(SRCS) > dependList
sed -e '1,/^# DO NOT DELETE/!d' Makefile > make.tmp
cat dependList >> make.tmp
mv make.tmp Makefile
rm dependList
# DO NOT DELETE THIS LINE
Why do we need this part? It seems all the dependencies have already been handled...?
Yeah, putting lib/ under src/ looks like a bad, counterintuitive design.
This:
.c.o:
...
is the old way of writing an implicit rule. These days we'd write it like this:
%.o: %.c
...
It's a slightly Rube Goldberg (i.r. clever but over-complicated) way of doing automatic dependency handling. So if foo.c contains the line #include bar.h, this rule will append the line foo.o: bar.h to the makefile. This is actually important.

How to prevent Makefile cleaning objects before linking (using -j option)

I'm trying to learn how to use linux makefiles.
I have the following two files:
makefile.config
# Project Configurations
# Project Name
PROJECT_NAME = myapp
# Project Version
PROJECT_VERSION = 0.1
# Program or Shared Library
IS_LIBRARY = no
# Source Files Directory
SRC_DIRECTORY = src
# Header Files Directory
INC_DIRECTORY = inc
# Library Header Files Directory
LIB_DIRECTORY = lib
# Build Output Directory
BIN_DIRECTORY = ../Executable
# Installation Directory Exec
INS_DIRECTORY = /usr/local/bin/
# Installation Directory Headers
INS_HEARERS_DIRECTORY = /usr/local/include/
# Installation Directory SO
INS_SO_DIRECTORY = /usr/local/lib/
# C Flags
CFLAGS = -O3 -D_GNU_SOURCE -Wfatal-errors
# C++ Flags
CXXFLAGS = $(CFLAGS)
# Linker Flags
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
# Linker Libraries
LDLIBS = -fno-inline
# Debug Yes / No
DEBUG = yes
# C Compiler
CC = gcc
# C++ Compiler
CXX = g++
Makefile
$(info Starting building process)
# include configurations
include makefile.conf
$(info - Makefile.conf loaded)
# find project files
H_FILES := $(shell find -L ./ -name '*.h' -exec dirname {} \; | sed 's/ /\\ /g' | uniq)
C_FILES := $(shell find ./ -name '*.c' -type f | sed 's/ /\\ /g' | uniq)
CXX_FILES := $(shell find ./ -name '*.cpp' -type f | sed 's/ /\\ /g' | uniq)
O_FILES := $(C_FILES:.c=.o)
O_FILES += $(CXX_FILES:.cpp=.o)
H_FILES := $(notdir $(H_FILES))
C_FILES := $(notdir $(C_FILES))
CXX_FILES := $(notdir $(CXX_FILES))
INCLUDES := $(H_FILES:%=-I%)
$(info - Project Files Loaded)
ifeq ($(DEBUG),yes)
$(info - Debug flag added [makefile.conf DEBUG = yes])
CFLAGS := -g3 $(CFLAGS)
endif
ifeq ($(IS_LIBRARY),yes)
$(info - Set Parameters for Shared Library build process)
ALL_PARAMETERS = lib$(PROJECT_NAME).so.$(PROJECT_VERSION) clean
ALL_TYPE = lib$(PROJECT_NAME).so.$(PROJECT_VERSION): $(O_FILES)
LIBFLAGS = -shared -Wl,-soname,lib$(PROJECT_NAME).so
CFLAGS := -fPIC $(CFLAGS)
CXXFLAGS := -fPIC $(CXXFLAGS)
else
$(info - Set Parameters for Application build process)
ALL_PARAMETERS = $(PROJECT_NAME) clean
ALL_TYPE = $(PROJECT_NAME): $(O_FILES)
LIBFLAGS =
endif
# Build Process
all: $(ALL_PARAMETERS)
$(ALL_TYPE)
#echo - [OUTPUT][CXX] $# #[$(BIN_DIRECTORY)]
#$(CXX) $(CFLAGS) $(INCLUDES) $(LDFLAGS) $(LIBFLAGS) -o $(BIN_DIRECTORY)/$# $^ $(LDLIBS)
%.o: %.c
#echo - [CC] $#
#$(CC) $(CFLAGS) -c $(INCLUDES) -o $# $< $(LFLAGS)
%.o: %.cpp
#echo - [CXX] $#
#$(CXX) $(CXXFLAGS) -c $(INCLUDES) -o $# $< $(LFLAGS)
# Clear Objects
clean:
$(info - Remove all .o [object] files)
#find . -name \*.o -type f -delete
# Clear Objects & Executables
cleanall:
$(info - Remove all .o [object] files)
#find . -name \*.o -type f -delete
$(info - Remove all files in $(BIN_DIRECTORY))
#find $(BIN_DIRECTORY) -name \*.* -type f -delete
# Install Project
install:
#cp -r $(BIN_DIRECTORY)/lib$(PROJECT_NAME).so.$(PROJECT_VERSION) $(INS_SO_DIRECTORY)
#cp -r $(LIB_DIRECTORY)/* $(INS_HEARERS_DIRECTORY)
#ln -s $(INS_SO_DIRECTORY)/lib$(PROJECT_NAME).so.$(PROJECT_VERSION) $(INS_SO_DIRECTORY)/lib$(PROJECT_NAME).so
#ldconfig
$(info - Installation completed)
# Uninstall Project
uninstall:
#rm $(INS_SO_DIRECTORY)/lib$(PROJECT_NAME).so
#rm $(INS_SO_DIRECTORY)/lib$(PROJECT_NAME).so.*.*
#rm $(INS_HEARERS_DIRECTORY)/$(PROJECT_NAME).h
#ldconfig
$(info - Uninstallation completed)
Everything works perfect ...well at least for what i'm using it for.. however when i try to execute the makefile with -j option (ex.)
$ make -j4
the procedure cleans the objects (.o) before linking them.
iikem#isca-lab:Source Code$ make -j4
Starting building process
- Makefile.conf loaded
- Project Files Loaded
- Debug flag added [makefile.conf DEBUG = yes]
- Set Parameters for Shared Library build process
- [CXX] src/isca-streamer.o
- [CXX] src/isca-streamer-pause.o
- [CXX] src/isca-streamer-thread-image.o
- [CXX] src/isca-streamer-initialize.o
- [CXX] src/isca-streamer-start.o
- [CXX] src/isca-streamer-stop.o
- [CXX] src/isca-streamer-thread-socket.o
- [CXX] src/isca-streamer-clear.o
- Remove all .o [object] files
- [CXX] src/isca-streamer-settings.o
- [OUTPUT][CXX] libisca-streamer.so.0.1 #[../Executable]
g++: error: src/isca-streamer.o: No such file or directory
g++: error: src/isca-streamer-initialize.o: No such file or directory
g++: error: src/isca-streamer-thread-image.o: No such file or directory
g++: error: src/isca-streamer-pause.o: No such file or directory
g++: error: src/isca-streamer-start.o: No such file or directory
g++: error: src/isca-streamer-stop.o: No such file or directory
Makefile:71: recipe for target 'libisca-streamer.so.0.1' failed
make: *** [libisca-streamer.so.0.1] Error 1
How can i fix this problem? (prevent cleaning objects step to execute before linking step)
You can't add clean as a prerequisite for your all target if you use -j, because it will be run in parallel with the linker and deleting files is a lot faster than linking them.
So you have to remove the clean target from your ALL_PARAMETERS variable, then you won't delete objects in the middle of your link line anymore.
I have no idea why you want to delete all the objects after every run: you don't even need make or makefiles at all if you're going to rebuild everything from scratch every time: just create a shell script. The entire point of using a makefile is to avoid rebuilding parts of the project that haven't changed.
But, if you really do want to do that then the simplest way is probably using recursive make; for example:
all: $(ALL_PARAMETERS)
$(MAKE) clean
will only ever make clean after all the prerequisites of all have completely built, even if you run with -j.

how to include .h document in makefile

I am programming for a big project, so I cooperate with others.
To make the directory easily managed, my directory is like below:
project:
--include (header files from others supplied for me)
--lib (libraries from others supplied for me)
--L3_CVS (this folder include all my files)
-- Makefile
-- sourceFile (all my source files here)
-- include_private(all header files used only by myself)
-- appl (all my C files here)
My Makefile is below:
####################################################
CROSS_COMPILE=/home/powerpc-wrs-linux-gnu/x86-linux2/powerpc-wrs-linux-gnu-ppc_e500v2-glibc_cgl-
EXTRA_CFLAGS += -g
EXTRA_LDFLAGS +=
LIBSB =-Wl,--start-group -ldiag -ldiag_esw -lacl -ldiagcint -lcint -lsal_appl -lsal_appl_editline -lsal_appl_plat\
-lbcm -lbcm_esw -lbcm_common -lfirebolt -ltitan -ltrident -lhumv -lbradley -lherc -ldraco -lscorpion\
-ltriumph -ltrx -ltriumph2 -lenduro -lkatana -lflexctr -lptp -lsoc_esw -lsoc -lsoc_phy -lsoc_mcm\
-lsoccommon -lsoc_shared -lshared -lsal_core -lsal_core_plat -lcustomer -lsoc_nemo -lsoc_clsbuilder\
-lsoc_sal \
-lbcm_compat -lbcm_rpc -lcpudb -ltrx -lstktask -llubde -ldrivers -ldiscover -lcputrans \
-lrcu -lpthread -lrt -lm -Wl,--end-group
LIBS = -ldiag -lrcu
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)strip
SRC_PATH := ./SourceFile/appl
HEAD_PATH := ./SourceFile/include-private
INC_DIR = ../include
LIB_PATH = ../lib
APP_NAME = L3appl
SRCS := $(wildcard $(SRC_PATH)/*.c)
export $(SRCS)
OBJS:= $(patsubst %.c,%.o,$(SRCS))
%.d: %.c
#set -e; rm -f $#; \
$(CC) -MM $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
sinclude $(SRCS:.c=.d)
INCLUDES = $(wildcard $(HEAD_PATH)/*.h)
$(APP_NAME):$(OBJS)
$(CC) -c -I$(INC_DIR) $(SRCS)
$(CC) -o $(APP_NAME) $(OBJS) -L$(LIB_PATH) $(LIBSB) -lpthread -lrt -lm
.PHONY:clean
clean:
rm -f $(OBJS) $(APP_NAME)
#################################################
My problem is that when I run make in terminal, it always show : ***No such file or directory
compilation terminated. which seems the .h files in ./SourceFile/include-private do not be included.
But, in fact, I have use "INCLUDES = $(wildcard $(HEAD_PATH)/*.h)" include these .h files.
I don't know where is wrong!
this is my first time to write makefile. So if there are mistakes in my makefile, I would appreciate that you would point them out !
thank you for your help very much!!!!!!!
You should have something like
CFLAGS = -Wall $(OPTIMFLAGS) $(INCLUDEFLAGS)
INCLUDEFLAGS = -I $(INC_DIR) -I $(HEAD_PATH)
OPTIMFLAGS = -g -O
You can use remake to debug your Makefile.
You can try to change $(CC) -c -I$(INC_DIR) $(SRCS) to $(CC) -c -I$(INC_DIR) -include $(INCLUDES) $(SRCS)
or $(CC) -c -I$(INC_DIR) $(SRCS) to $(CC) -c -I$(INC_DIR) -I$(INCLUDES) $(SRCS)
where INCLUDES is ./SourceFile/include-private (only the directory, no .h files)
Edit: Usually you don't have to explicitly include the .h files, but that's what the first change do. The second change does not add the .h files explicitely but provide the compiler another include directory where it could search for necessary .h files.
Refer to GCC man file for more info.
Regards

Resources