multi-directory "make" in linux programming - c++

suppose we have a file-list:
src
a
b
c
Makefile
and there are many .cc & .h files in each folders.
how to write the Makefile??
when I write a path like this
./a/a.cc or ../a/a.cc
errors will be occurred.
but when i put the files on the same directory
and write as a.cc.
everything is ok.
I run it on cygwin.
could anyone help me?

The wildcard function is what you are looking for: http://www.gnu.org/software/make/manual/html_node/Wildcards.html
On Linux I would prefer Automake/Autoconf build systems: http://de.wikipedia.org/wiki/GNU_Build_System
An alternative could be CMake: http://www.cmake.org/

From the not-so-clear directory graph, it seems that you are missing the src/ directory prefix in your Makefile. E.g. to compile src/a/a.cc, use:
src/a/a.o: src/a/a.cc
$(CXX) $(CXXFLAGS) -c -o $# $<
BUT: Do yourself a favour, and use a real build system, such as CMake. It is cross-platform, can generate IDE project files (e.g. for Visual Studio, Xcode, Eclipse, CodeBlocks, etc.), is much higher level and does automatic dependency tracking for you.

You've left out a lot of details (e.g. where you want to put the object files), but VPATH is probably what you're looking for.
VPATH = src/a src/b src/c
# Now you can write rules as if the .cc & .h files were in the current directory.
%.o: %.cc
do something with $<
foo.o: foo.cc bar.h
do something special with $<

Related

ECLIPSE makefile for C++ projects -- source directory

In Eclipse platform (Windows 10, MinGW toolchain), I'm trying to create a makefile to compile a project with .cpp and .hpp files.
To do that, I choose to create a new project:
File ->
(popup) New Project
C/C++ -> C/C++ Project => NEXT -> C++ Managed Build => MakefileProject -> Hello World C++ MakefileProject
This example compiles and links perfectly.
But I want to move the .cpp file into a src directory, then in the Project Explorer window, over the name of the project, I select to create a "Source
Folder", naming it as "src". Then I move the .cpp file inside the directory, and try to build the project without success.
How must I modify the makefile included with this example? I've tried everything but without luck. I get this error:
*19:51:33 **** Incremental Build of configuration Default for project CE_SEP ****
make all
make: *** No rule to make target CE_SEP.o', needed byCE_SEP.exe'. Stop*
Thanks for your support in advance!
Stop depending on an IDE. There is an actual "Makefile" that you can go in and edit. You likely just have to modify the path to the source file in the Makefile and/or add another Makefile in the "src" folder.
If you don't know Makefile syntax, google a brief tutorial.
Or save yourself some time in the long run and just learn CMake which is just a scripting type language to write platform-portable build systems -- it will generate Makefiles, MSVC projects, Xcode projects, Ninja build files, etc.
I have solved it. I had written wrongly the name of the file, and I have modified the Makefile adding "src\" before the name of the object an exe file:
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = src\CE.o
LIBS =
TARGET = src\CE.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
But I rather will learn some of CMake as "jonrobm" suggested me.
Thank you again!

How to recompile source file every time while using cmake 2.8.2 in single build for c++11 and c++98 for shared library creation?

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

Structuring Makefiles with multiple directories

I am trying to compile my project which has the following structure
Project:
MakeFile
Executable
Source1
.cxx
.h
Source2
.cxx
.h
Build
*.o
And I'm having difficulty writting a Makefile to compile. I currently have commands like:
Src1 = $(wildcard $(SRCDIR1)/*.cxx)
Obj1 = $(patsubst $(SRCDIR1)/%.cxx, $(OBJDIR)/%.o, $(Src1))
But then I have difficulty making the compile rules for the object files a) Because I can no longer do:
$(Obj1): %.cxx
$(CXX) $(CFLAGS) -c $(#:.o=.cxx) -o $#
Because the '$#' command now includes the path of the build directory and b) because the prerequisites now include the build path and I should have a source path. I have read large bits of the make manual to try and find a solution but no luck.
Any help towards a solution appreciated!
Jack
From personal experience, after playing around a bit with "raw" Makefiles, I'd really recommend using some tool building the Makefiles for you, like automake or cmake.
You'll still have to specify all the source files manually - but at least I prefer that to manually fiddling around with the Makefiles.
One option I prefer is building an isomorphic directory structure in the build directory. That is, a source file ${src_dir}/project_x/main.cxx builds into ${build_dir}/project_x/main.o. This way you are protected from name clashes when there are source files with the same name in different source directories. The compiler rule would look something like:
${obj_dir}/%.o : ${src_dir}/%.cxx # % includes directory name, e.g. project_x/main
#-mkdir -p ${#D}
${CXX} -c -o $# ${CPPFLAGS} ${CXXFLAGS} $<
Notice how in the above it creates the target directory on the fly. This is a bit simplistic, in a real-world build system object files depend (using order-only dependency) on its directory, so that make automatically creates the destination directory if it does not exist instead of speculatively trying to create them for each target object file even if it already exists.

Which build system will do this the most 'naturally'?

Instead of the flat structure my code currently has, I want to organize it into modules contained in sub-folders (and perhaps sub-sub folders if the modules get big enough).
Each module will have one or more translation units which will each produce a .o file.
The final target would be to mash up all these object files into a static library (for now).
I am using plain 'make' and it is already complicated enough.
Is there a system in which the specified model comes naturally or with much less effort compared to writing makefiles by hand ?
(If you are going to recommend cmake, I need some hints as I have already tried and could not come up with a good solution.)
Some paraphrased bits from my current project's makefile that may help you out with good old fashioned GNU make:
SOURCEDIR := dir1 dir2/subdir1 dir3 dir4 dir5/subdir1 dir6/subdir1
SOURCES := $(foreach srcdir,$(SOURCEDIR),$(wildcard $(srcdir)/*.c))
OBJECTS := $(patsubst %.c,build/%.o,$(SOURCES))
OBJDIRS := $(addprefix build/,$(SOURCEDIR))
MAKEDEPS := $(patsubst %.c,build/%.d,$(SOURCES))
all: example
$(OBJDIRS):
-mkdir -p $#
build: $(OBJDIRS)
build/%.o : %.c | build
cc -MMD -c -o $# $<
example: $(OBJECTS)
cc -o $# $(OBJECTS)
-include $(MAKEDEPS)
In essence, it builds all of the source files found in the designated directories into object files located in subdirectories of the build directory in a hierarchy that parallels their source directory layout (important if multiple source files have the same name) and then links the results into an executable example.
As a bonus, dynamic dependency generation and inclusion via the MAKEDEPS variable and clang's -MMD flag.
It really depends upon your purposes: Build packages are generally intended for the audience rather than the performer. Often, they take into consideration the disparate environments into which people deploy. I played around with 'tup,' which seemed more a way of generating an executable as quickly as possible after an edit. 'Premake' seems to shoot at multiple platforms, but I found specifying compiler options no more enlightened than with Cmake.
It looks as though you've found a good Makefile tutor, so I'll leave my observations at that.

Portably Compile Entire Directory

Is there a clean/portable way to descend recursively from a given directory, compiling all found .cpp files into a single output file? I'm not sure if makefiles are capable of this sort of thing, or if it's a job for some kind of build script, but I'd like to avoid maintaining various IDEs' project files along with my code.
There are different things that you can do here. I would suggest that you use a multiplatform build system, and follow the documentation for it. I have used CMake in the past, but I wouldn't know how to tell it to compile all files in a directory.
The advantage is that the user can use CMake to generate project files for most common IDEs, so it would allow VisualStudio users to generate VS solutions, MacOSX users to generate Xcode projects, Eclipse CDK projects in pretty much any environment, Makefiles...
There's the wildcard function which can be used to match a pattern like so:
CXX_FILES = $(wildcard src/*.cpp) # All .cpp files in the directory
This is not recursive, but will at least save you from having to manually specify the files in a certain directory. The rule for building them would look something like this:
CXX_FILES = $(wildcard src/*.cpp) # All .cpp files in the directory
OBJ_FILES = $(CXX_FILES:src/%.cpp=$(OBJ_DIR)/%.o) # Corresponding .o files
# Rules
all: $(OBJ_FILES)
g++ $(OBJ_FILES) -o output_filename
$(OBJ_DIR)/%.o: src/%.cpp
g++ -c $< -o $#
Oh, and to answer your question, this method is completely portable.