C++ makefile with relative include path to parent - makefile

I've got a working project that I need to take parts from it without changing it's code and just write new main() for it.
My directory structure:
[main_dir]/[main.cpp]
[main_dir]/[dir1]/[child1]/file1.h
[main_dir]/[dir2]/[child2]/file2.h
in main.cpp I have: include "dir1/child1/file1.h"
In file1.h I have: include "dir2/child2/file2.h"
I'm compiling:
g++ main main.cpp
I'm getting "dir2/child2/file2.h" no such file or directory.
I can't change file1 to do: include "../../dir2/child2/file2.h"
Somehow in the original project something in the makefile to search for all include path relative to the [main_dir] so the include from file1.h can be found.
What should I add to the makefile in order to do it as well?

When using double-quotes to include a header file, as in
#include "dir2/child2/file2.h"
then the compiler will use the directory of the current file to search for the header file.
If you have it in your file1.h then the compiler will look for the header file [main_dir]/dir1/child1/dir2/child2/file2.h. Which isn't correct.
You can solve it by telling the compiler to add [main_dir] to the list of standard include search paths. This is done with the -I (upper-case i) option:
g++ -I [main_dir] main.cpp
Then when the compiler fails to find dir2/child2/file2.h in its first search, it will continue with the list of standard include search paths, and it should be found.

You need to manage CPPFLAGS in your Makefile.
CPPFLAGS="-I[main_dir]"
And compile application with receipt like this:
g++ $(CPPFLAGS) main.cpp -o main
Also it's recommended to read make style guides to write a good one Makefile. You can meet there tips for include folders declaration.

Related

Including a header from a parent directory

I have a situation where I am given a link to source directory which goes under the parent dir. The contents of the link cannot be modified. The link has a header and .c file. The header file includes a "Config.h" file. The Config.h can only reside in the parent dir because I cannot modify anything under the link. I have to use the sources in the link and compile the parent dir. Here is the directory structure.
ParentDir
|-TestSrc.c
|-TestSrc.h
|-Config.h
|-Makefile
|-LinkToSrcDir
|-Src.c
|-Src.h(#include "Config.h")
My makefile is very straightforward
CC = gcc
INC_DIR = -IParentDir -IParentDir/LinkToSrcDir
CFLAGS = -Wall -Wextra $(INC_DIR)
all: mybin
mybin: TestSrc.o Src.o
$(CC) $(CFLAGS) -o TestSrc.o Src.o
TestSrc.o: TestSrc.c
$(CC) $(CFLAGS) -c TestSrc.c
--- similar code for Src.o ----
Phony: clean (all the usual rm -f)
My problem is, since I cannot modify src.h, the make always complains that Config.h is not found(tried a few different ways). How do I write the Makefile to make src.h look for Config.h in parent dir?
The simplest way is to use a fully-qualified path for the compiler flags:
INC_DIR = -I$(CURDIR)/ParentDir -I$(CURDIR)/ParentDir/LinkToSrcDir
Just to be clear, when the compiler searches for header files using a relative path it always starts with the directory the source file appears in. It doesn't start with the working directory where the compiler is invoked.
From the GCC manual for example:
the preprocessor looks for header files included ... first relative to the directory of the current file
In your case, the current file is LinkToSrcDir/Src.h so all paths will be expanded relative to the directory LinkToSrcDir.
When you say a link above I assume you mean a symbolic link. In that case you may not be able to use something like -I.. because that will give you the parent of the directory linked to.
You pretty much have no alternative but to use a fully-qualified path in your -I options.

makefile how can I generate obj files in a subfolder?

I want to generate my obj files in a subfolder, I have tried this:
lib/*.o: source/*.cpp
clang++ $(CC_FLAGS) -c -Iinclude source/*.cpp
But it still generates the obj files in the project root and not in the lib/
The project tree that I'm trying to have:
Project/
source/(cpp files)
include/(header files)
lib/(obj files)
You don't show your current makefile, but my suspicion is that it's wrong. However as we can't see it, we'll leave that alone.
The compiler does not support writing multiple object files to a different directory. If you pass multiple source files along with the -c flag then it will write out multiple object files but only to the current directory... as you've discovered the -o flag can't be specified on compile lines which generate multiple output files.
You can change your recipe to look like this:
cd lib && clang++ $(CC_FLAGS) -c -I../include ../source/*.cpp
this will cause all the object files to be written to the lib directory because it's now the current directory.
However, putting this into a makefile is not simple, because make itself is designed to have a single recipe create a single target. However you have this problem with your existing makefile which you don't show, as well.

how to gcc compile with #define in multiple files

I have a project with multiple files.. I want to compile it using gcc from command line.
the directory looks like this
lib/
Comp/ contains .cpp files
Decomp/ contains .cpp files
Globals.cpp
include/
Comp/ contains .h files
Decomp/ contains .h files
Globals.h
some of these .h files are not paired with .cpp files
to compile this i use something like this :
g++ lib/Comp/* lib/Decomp/* lib/Globals.cpp -std=c++0x -o TEST
the problem is,I have to add some #defines for each .h file and i have to do it through command line. how to do this ??
also if i had to compile each file on its own and then link them. what would be the appropriate order for doing this ?
The dirtiest ugliest way is that you want to use something like:
g++ -Iinclude lib/Comp/*.cpp lib/Decomp/*.cpp lib/Globals.cpp -o test
Your .cpp files should #include <Comp/foo.h> or whatever
The correct way to manage this is to use a makefile to build each object file and then link them together:
Makefile
Create a a file called Makefile and put the following in it:
CXX=g++
CPPFLAGS=-Iinclude -DFOO -DBAR=1 -DSOME_STRING=\"My Name\"
CXXFLAGS=-O2 -g
SOURCES=lib/Comp/file1.cpp \
lib/Comp/file2.cpp \
lib/Comp/file3.cpp \
lib/Decomp/file1.cpp \
lib/Decomp/file2.cpp \
...
OBJ=$(SOURCES:%.cpp=%.o)
default: test
test: $(OBJ)
<tab> $(CXX) -o $# $(OBJ)
%.o: %.cpp
<tab> $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
NOTES
Replace file1.cpp etc. with the actual filenames in your project. DO NOT include headers in SOURCES only your .cpp or .cc files
If you are using sub-paths like #include <Comp/foo.h> or #include "Comp/foo.h" in your source files then you only need to use -Iinclude in CPPFLAGS but if you are doing something like "foo.h" and foo.h is actually in include/Comp/ then add -Iinclude/Comp and -Iinclude/Decomp to the CPPFLAGS
Where it says <tab> make sure you use the TAB key to insert a tab (don't type the word '')
Before using this Makefile blindly . Know that it will NOT work as is you have to correct the entries. It is offered as a starting point... Read up on writing Makefiles ... http://frank.mtsu.edu/~csdept/FacilitiesAndResources/make.htm has a good introduction
Defines can be provided on the compiler command line using -DVAR=VALUE (on Windows, presumably /DVAR=VALUE). Note that you can not provide different defines for different headers as in:
compiler -DX=one first.h -DX=two second.h third.cc -o third.o
In such a case, my compiler spews warning and uses the last value of X for all source code.
Anyway, in general you should not list header files on the compilation line; prefer to include them from the implementation files (.cc/.cpp or whatever) that need them.
Be careful too - if you're changing defines to modify class definitions, inline function implementation etc. you can end up with technically and/or practically undefined behaviour.
In terms of how best to decide which objects to create and link - you probably want one object per .cc/.cpp file. You can link those objects then specify them on the command line when compiling the file containing main().

Header include path in files generated by `protoc`

When I call protoc like this
protoc --cpp_out=. path/to/test.proto
the files
path/to/test.pb.cc and
path/to/test.pb.h
are generated which is what I want. But, since the cc needs the h, the h is included like this
#include "path/to/test.pb.h"
which is not what I want. The background is that my build tool (scons) calls protoc from the project's root and not from the directory which includes the source files. I found no obvious option in the manpage or the help text.
So my next idea was to consider this as "correct" and adjust my build system, but: The two files are siblings in the directory tree, so when one includes the other, no path is needed. Even compiling by hand fails.
Can someone help me with that?
Doing find-replace on generated files is most likely easier
than reorganization of your build system (use sed command on Linux/unix).
What I ended up doing for my project is as follows:
Create a pb/ directory at the same level as your include/ and src/ directories.
Put your .proto files in there, and create a makefile. Write the following in it:
CXX = g++
CXXFLAGS = -O3
PROTOBF = $(shell find ./ -name '*.proto')
SOURCES = $(subst proto,pb.cc,$(PROTOBF))
OBJECTS = $(subst proto,pb.o,$(PROTOBF))
default: $(OBJECTS)
#echo -n
$(SOURCES): %.pb.cc : %.proto
protoc --cpp_out=. $<
$(OBJECTS): %.pb.o : %.pb.cc
$(CXX) $(CXXFLAGS) -c $< -o $#
Which will essentially generate and build the protobuffer files when invoked.
In your main makefile, simply add the following include path: -Ipb/.
And when including a protocol buffer header, use #include <whatever.pb.h>.
Add the object files generated in pb/ to your linking step. Myself I used:
PB_OBJS = $(shell find pb/ -name '*.pb.o')
And gave that to the linker along with the normal object files in obj/.
Then, you can probably call the pb/ makefile from the main makefile if you want to automate it. The important point is that protoc be called from the pb/ directory or the include will be messed up.
Sorry for the ugly makefiles. At least it works, and I hope this helps you...

How to write rule to build object file when C files have different paths

I have bunch of C files, each with differnt path, so I have something like
SRC=/path1/path2/file1.c file2.c /usr/joe/files/file3.c
I want to build object file from each C file in build directory, so I did:
SRCBASE=$(notdir $(SRC))
OBJS= $(addprefix $(OBJDIR)/,$(SRCBASE:.c=.o))
This works fine, and I got the OBJS is build/file1.o build/file2.o build/file3.o
My question is how to write the implicit rule to build the object file, I tried to do:
build/%.o : %.c
gcc ....
But that seems now to work, since this rule did not catch the files with the full path.
I've tried to look at the gnu make, but did not find the answer there.
Many thanks.
You can use VPATH to locate files in other directories. Note that this does implicit searches, though, rather than using explicit paths. That is, you specify that you need file1.o through file3.o and that make should look first in ., then in /path1/path2, then in /usr/joe/files; so if . contains a file3.c you will get that one rather than the one in /usr/joe/files (or if not, but if there is one in /path1/path2, you will get that one).
It turns out that path searching is more often useful than explicit location anyway, so usually that's what you want. If you need to override something you just copy or symlink the "desired version" to the first place to be searched.

Resources