makefile how can I generate obj files in a subfolder? - makefile

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.

Related

How to create this makefile? Sources in subdirectories, separate output path, linking objects in subdirectories

Is there a way to create a makefile that does this?
I gave up after trying to follow the docs and lots of trial and error so I'll just post a description of what the makefile should do.
general directory structure:
src/ - contains c source files in various subdirectories (written manually by maintainer)
inc/ - contains h header files in subdirectories matching src (written manually by maintainer)
obj/ - contains o header files in subdirectories matching src (autogenerated by a make call)
bin/ - should contain binary (autogenerated by a make call)
makefile
so for example at a given point of time the project might look like
src/
main.c
sub1/
other1.c
other2.c
sub2/
sub3/
other3.c
inc/
sub1/
other1.h
other2.h
sub2/
sub3/
other3.h
obj/
main.o
sub1/
other1.o
other2.o
sub2/
sub3/
other3.o
bin/
release
makefile
(probably not relevant: Note that main doesn't have a header file but most likely every other c file will have a matching h file.)
I want to be able to call make, and have it:
use gcc to recompile only changed c files into respective o files in obj/, generating missing subdirectories if needed.
for example, from the above state, if I add a new subdirectory sub4 inside src/sub1/, and then create other4.c inside src/sub1/sub4/, I would like make to generate sub4 inside obj/sub1/ and then generate other4.o inside obj/sub1/sub4/
create a binary at bin/release by linking all object files (from all subdirectories in obj/)
I don't want to have to change the makefile each time I add directories in src
I don't want to manually have to create directories in obj, the makefile should take care of it. if this is not possible, maybe have it rename all obj o files to a flat naming pattern? i.e. obj/sub2_sub3_other3.o instead of obj/sub2/sub3/other3.o (although this can cause issues)
probably not relevant here, but the C files use include statements in this format:
#include "sub2/sub3/other3.h"
so -I./inc would be included in the gcc call. Whereas the linker would receive inputs like -s -O3. I want to make sure those options (compiler options, linker options) are listed at the top of the makefile in variables (CFLAGS, LDFLAGS, etc) and not passed incorrectly to the targets.
is this even possible? if not, what's the closest possible?
Also, can this makefile be made to work on both POSIX systems and on Windows based systems? e.g. work the same on linux/gcc and win/mingw

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.

How to force compiler to compile same source file every time used in different shared libraries in cmake? [duplicate]

I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).

How do you specify that a FreeBSD Makefile place the objects (*.o) into a different directory?

If I have some source files in another directory and I want to make some libraries using the source files, I want to have the *.o, *.po, and *.So files in the local directory. It isn't clear how to accomplish this. The transformation rules in bsd.lib.mk always point the .o into the source directory.
How do I get the results of the ${CC} -c to be in the local directory?
The file bsd.lib.mk inclused bsd.obj.mak, so you can use the MAKEOBJDIR environment variable.
Edit: If you cannot control how make is called, then don't use bsd.lib.mk and make explicit dependencies in your Makefile;
foo.o: ../bar/foo.c

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...

Resources