how to include .h document in makefile - linux

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

Related

How to create makefile target for obj files generated in temporary directory?

I am trying to learn using makefiles again. I have a directory structure like this:
build
|- Makefile
|- Project files, like visual studio project
tmp
|- $(os name)_$(compiler)
|- *.o and any other intermediate files
bin
|- $(os name)_$(compiler)
|- the compiled binary executable
|- debug info, if any
src
|- *.cpp, *.h
So I made this Makefile after a bit of googling and experimenting:
CXX := g++
CXXFLAGS := -std=c++17 -Wall
LDFLAGS := -lpthread
ASSUMED_OS := unknownOS
SRC_DIR := ../src
EXTENSION :=
# OS detection and extension assignment for windows redacted for brevity
# ... detect OS, set extension to .exe if windows
COMPILE_PATH := $(ASSUMED_OS)_gcc
TMP_DIR := ../tmp/$(COMPILE_PATH)
TARGET_DIR := ../bin/$(COMPILE_PATH)
TARGET := $(TARGET_DIR)/MyProject$(EXTENSION)
# $(wildcard *.cpp /xxx/xxx/*.cpp): get all .cpp files from the current directory and dir "/xxx/xxx/"
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
# $(patsubst %.cpp,%.o,$(SRCS)): substitute all ".cpp" file name strings to ".o" file name strings
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
all: $(TARGET)
# Compile all obj files into an executable
$(TARGET): $(OBJS)
#mkdir -p $(#D)
$(CXX) -o $# $^ $(LDFLAGS)
# Compile all CPP files in separate obj files
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -rf $(TARGET) ../*.o
.PHONY: all clean
This works, but it creates the .o files next to the sources.
So I tried to change the OBJS variable and replace the path:
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
# Substitute src path for tmp directory path
OBJS := $(patsubst $(SRC_DIR)/%,$(TMP_DIR)/%,$(OBJS))
But then I get an error:
make: *** No rule to make target '../tmp/linux_gcc/Job.o', needed by '../bin/linux_gcc/MyProject'. Stop.
So I tried to create a different target, one that I thought would map the object file names that should be in ../tmp/linux_gcc to the source names from ../src:
# $(wildcard *.cpp /xxx/xxx/*.cpp): get all .cpp files from the current directory and dir "/xxx/xxx/"
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
# $(patsubst %.cpp,%.o,$(SRCS)): substitute all ".cpp" file name strings to ".o" file name strings
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
# Substitute src path for tmp directory path
OBJS := $(patsubst $(SRC_DIR)/%,$(TMP_DIR)/%,$(OBJS))
all: $(TARGET)
# Compile all obj files into an executable
$(TARGET): $(OBJS)
#mkdir -p $(#D)
$(CXX) -o $# $^ $(LDFLAGS)
# Compile all CPP files in separate obj files
$(OBJS): $(SRCS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
But when I do that, make always compiles the same cpp file for each .o file:
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/Job.o
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/Worker.o
g++ -std=c++17 -Wall -c ../src/Job.cpp -o ../tmp/linux_gcc/WorkManager.o
I think I am quite close, but how can I get this to work? I think that in the compile command $(CXX) $(CXXFLAGS) -c $< -o $# I need something else than $< for the input file, but I am not sure what.
In your first makefile:
SRC_DIR := ../src
...
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
...
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
...
%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
Yes, this "creates the .o files next to the sources". If you have a source foo.cpp, the variable OBJS will contain ../src/foo.o, and the rule will build it.
In your second attempt you have changed the object, but you haven't changed the rule, so the only way Make knows to build ../tmp/linux_gcc/Job.o is from ../tmp/linux_gcc/Job.cpp, which doesn't exist.
On your third attempt you have the right idea, but there's a flaw in your rule:
$(OBJS): $(SRCS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#
The variable $(OBJS) is a list of objects, $(SRCS) is a list of sources, so each object depends on all sources. And the automatic variable $< expands to the first item in the prerequisite list, which in this case is ../src/Job.cpp, so no matter which object you choose, Make will try to build it by compiling that source.
This is a job for a static pattern rule:
$(OBJS): $(TMP_DIR)/%.o: $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) -c $< -o $#

How to link libraries on Raspberry Pi cross compiler?

I followed this guide to build a cross compiler for Raspberry Pi ARMv7. It works fine (compiles ok hello world) but the problem is I can't use Raspberry Pi libraries such as wiringpi, sqlite etc.
This is my Makefile.
CC = /opt/cross-pi-gcc/bin/arm-linux-gnueabihf-g++
QUOTE := "
CFLAGS = -g -lwiringPi -pthread -lpthread
PROGRAM = lora
OBJDIR = obj
CPP_SRCS += \
src/main.cpp \
src/radio/sx1276/sx1276.cpp \
src/radio/radio.cpp \
OBJ_FILES += \
$(OBJDIR)/main.o \
$(OBJDIR)/sx1276.o \
$(OBJDIR)/radio.o \
all: make_dir $(OBJ_FILES)
$(CC) $(OBJ_FILES) $(CFLAGS) -o $(PROGRAM)
make_dir:
mkdir -p $(OBJDIR)
$(OBJDIR)/main.o: src/main.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/service.o: src/service/service.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/sx1276.o: src/radio/sx1276/sx1276.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(OBJDIR)/radio.o: src/radio/radio.cpp
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm $(PROGRAM)
rm -rf $(OBJDIR)
The error I'm getting:
/opt/cross-pi-gcc/lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lwiringPi
I copied some libraries from my Pi into a folder on my home dir with this command.
rsync -vR --progress -rl --delete-after --safe-links pi#192.168.1.PI:/{lib,usr,opt/vc/lib} $HOME/raspberrypi/rootfs
Which I found it here.
But I'm not sure how to link them. Did I overlook something?
Note: The piece of code I'm trying to compile was compiling fine on Windows's cross-compiler.
I'm trying to setup a tool-chain on my Linux desktop. I'm using Manjaro.
You have to tell the linker where to look for the libraries.
You can add the flag -L$HOME/raspberrypi/rootfs/usr/lib, or wherever libwiringPi.so is located.
You have to point the compiler to the right headers as well. For that you use the -I flag. E.g. -I$HOME/raspberrypi/rootfs/usr/include. This goes in the CFLAGS of the targets that include wiringPi.h.
Also, -lwiringPi -pthread -lpthread don't belong in the CFLAGS, they are linker flags. You only need them in the target that builds PROGRAM. You could add a separate variable LDFLAGS, for example.

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.

Makefile export .o file to a different path than .cpp

So my task is simple, I have created the makefile (New with makefiles) and I want to keep my .o files in a different folder to have a cleaner directory and allow the usage of .o files by others.
I searched and found many solution pointing to using -o $< $#
However, it is giving me that g++: cannot specify -o with -c or -S with multiple files
This is what I want to do:
$(OBJECT_PATH)/file1.o: $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp
$(CC) $(CFLAGS) $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp -o $#
file1.cpp has #include "file1.h", so from what I read I should include file1.cpp in the dependencies. However, now I can't export to a different directory.
Is there a solution? Or do I have the concept wrong?
Use make -d or even better remake -x to understand what commands are invoked.
Run also make -p to understand what builtin rules are used.
We cannot help you more, because we have no idea if you redefined CFLAGS.
And C++ compilation should better be done with g++ that is CXX and CXXFLAGS, e.g. with (I am extracting this from my make -p output)
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
CXX = g++
%.o: %.cc
$(COMPILE.cc) $(OUTPUT_OPTION) $<
I strongly suggest to have CXXFLAGS= -Wall -g at least during the development phase. Learn also to use gdb and valgrind.
You could have the following in your Makefile
CXXFLAGS= -g -Wall
SOURCES=f1.cc f2.cc
SOURCE_PATH=yoursourcedir/
OBJECT_PATH=yourobjectdir/
SRCFILES=$(patsubst %.cc,$(SOURCE_PATH)/%.cc,$(SOURCES))
OBJFILES=$(patsubst %.cc,$(OBJECT_PATH)/%.o,$(SOURCES))
PROGFILE=$(OBJECT_PATH)
.PHONY: all clean
all: $(PROGFILE)
$(PROGFILE): $(OBJFILES)
$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $#
$(OBJECT_PATH)/%.o: $(SOURCE_PATH)/%.cc
$(COMPILE.cc) $(OUTPUT_OPTION) $<
clean:
$(RM) $(OBJECT_PATH)/*.o $(PROGFILE)
try
$(OBJECT_PATH)/file1.o: $(SOURCE_PATH)/file2.cpp $(SOURCE_PATH)/file1.cpp
$(CC) $(CFLAGS) $^ -c $#
and check that CFLAGS doesn't include -o -c or -s flags
also read about implicit rules. it might help you to orginzie your makefile

Qmake does not include the library path for qt

I just install qt on my slax box,
And I tried to write and compile using qmake.
But the problem is qmake does not write it's 'Makefile' to include -Lqt-mt or -Lqt.
I have to give it manually otherwise there are unresolved links are there. What I could
do for this?Any workaround on this?
And this is the 'Makefile' output by the qmake.
#############################################################################
# Makefile for building: hello
# Generated by qmake (2.01a) (Qt 4.5.3) on: Tue Feb 2 04:04:03 2010
# Project: hello_world.pro
# Template: app
# Command: /usr/bin/qmake -unix -o Makefile hello_world.pro
#############################################################################
####### Compiler, tools and options
CC = gcc
CXX = g++
DEFINES =
CFLAGS = -pipe $(DEFINES)
CXXFLAGS = -pipe $(DEFINES)
INCPATH = -I/usr/lib/qt-3.3.8b/mkspecs/linux-g++ -I.
LINK = g++
LFLAGS =
LIBS = $(SUBLIBS)
AR = ar cqs
RANLIB =
QMAKE = /usr/bin/qmake
TAR = tar -cf
COMPRESS = gzip -9f
COPY = cp -f
SED = sed
COPY_FILE = $(COPY)
COPY_DIR = $(COPY) -r
INSTALL_FILE = $(COPY_FILE)
INSTALL_DIR = $(COPY_DIR)
INSTALL_PROGRAM = $(COPY_FILE)
DEL_FILE = rm -f
SYMLINK = ln -sf
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
####### Output directory
OBJECTS_DIR = ./
####### Files
SOURCES = hello_world.cpp
OBJECTS = hello_world.o
DIST = hello_world.pro
QMAKE_TARGET = hello
DESTDIR =
TARGET = hello
first: all
####### Implicit rules
.SUFFIXES: .o .c .cpp .cc .cxx .C
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$#" "$<"
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$#" "$<"
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$#" "$<"
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$#" "$<"
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o "$#" "$<"
####### Build rules
all: Makefile $(TARGET)
$(TARGET): $(OBJECTS)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
Makefile: hello_world.pro /usr/lib/qt-3.3.8b/mkspecs/linux-g++/qmake.conf
$(QMAKE) -unix -o Makefile hello_world.pro
qmake: FORCE
#$(QMAKE) -unix -o Makefile hello_world.pro
dist:
#$(CHK_DIR_EXISTS) .tmp/hello1.0.0 || $(MKDIR) .tmp/hello1.0.0
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/hello1.0.0/ && (cd `dirname .tmp/hello1.0.0` && $(TAR) hello1.0.0.tar hello1.0.0 && $(COMPRESS) hello1.0.0.tar) && $(MOVE) `dirname .tmp/hello1.0.0`/hello1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/hello1.0.0
clean:compiler_clean
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
####### Sub-libraries
distclean: clean
-$(DEL_FILE) $(TARGET)
-$(DEL_FILE) Makefile
compiler_clean:
####### Compile
hello_world.o: hello_world.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o hello_world.o hello_world.cpp
####### Install
install: FORCE
uninstall: FORCE
FORCE:
And here is my .pro file that I used.
TEMPLATE=app
CONFIG+= qt warn_on release
HEADERS=
SOURCES=hello_world.cpp
TARGET=hello
I already set the $QTDIR and I think everything is in place.
Where I missed? Why I have to give it manually? Why qmake does not work in first
place?
EDIT:
There in makefile
LIBS = $(SUBLIBS)
What I did is change it to,
LIBS = $(SUBLIBS) -lqt-mt
After I changed everything works fine ! The problem is again , why I have to do such
a thing manually?
FOR #Frank Osterfeld
I think I'm using correct 'qmake' because ,
When I hit, qmake --version , I do get this.
QMake version 2.01a
Using Qt version 4.5.3 in /usr/lib/qt/lib
--Thanks in advance--
When there are multiple Qt installations on a machine, it's important the environment has been set-up properly to point to the right Qt version. The following are important environment variables to check:
$QTDIR -- should point to the base directory for the Qt installation.
$QMAKESPEC -- should point to a make specification directory under $QTDIR (e.g. $QTDIR/mkspecs/linux-g++).
$QT_PLUGIN_PATH -- should point to the plug-in directory, typically within the Qt installation (e.g. $QTDIR/plugins).
$PATH -- should have the $QTDIR/bin directory within it. The installation that you wish to use should be first within the $PATH.
If all else fails, check your full environment to ensure that the correct Qt installation is being referred to (use env on *nix, set on Windows).
If you notice directories pointing to the wrong installation within the Makefile generated by qmake, it is likely that your environment hasn't been properly set (in this case, $QMAKESPEC was the culprit).
Finally, it's important to note that the libraries from Qt3 are no longer present in Qt4: Qt3 has libqt-mt, libqui, etc. Qt4 has libQtCore, libQtGui, etc.

Resources