Makefile count how many files - c++

I am making a makefile that compiles some .cpp files but i want it to be "beautiful".
So i try to add current index compiling:
(eg: Compiling 10nth out of 150 total files.)
I successfully did the 10nth out of part, but i cannot find a way to get how many total files are in makefile's directory (in my case how many .cpp's).
What i want is to get this 150 number.
So my Question (and i am really curious WHY no one has ever asked) is, how to get how many .cpp files are in this (makefile's) directory.
I hope this question helps other people as well in the future.

You can do something like this using GNU Make:
SOURCES := $(wildcard src/*.cpp)
NO_OF_FILES := $(words $(SOURCES))
Various text processing functions are documented here

Related

How to use *.o and *.d files?

I ma trying to run examples using a library. In the documentation to the library it is written that I need to copy all the files into my directory and than type make. After that I need to go to the "Debug" folder and type ./lib_examples to run the examples.
I performed this sequence. As a result I have a lot of *.o and *.d files in the "Debug" subdirectory. Among them there is lib_examples.o and lib_examples.h files. But there is no lib_example file that I am supposed to execute.
Does anybody know what was supposed to happen and where it went wrong. Should I do one more step to be able to use *.o and *.d files?
The ".o" files are likely intermediate files from which the actual executable program should have been created.
The ".d" files are likely internal state used by the makefile, only important if you are making changes to the source code and then rebuilding "incrementally".
If, after running make, you have only these files but not the executable file, then the most likely explanation is that make encountered an error in creating the executable. If that's the case, then the last few lines of output generated by make should tell you more.

Is there a way to get the * command to ignore certain entries?

I have a lot of a files in one of my folders that I need *.c to compile them in my Makefile, but I want to exclude one of them for now. Is there anyway to still use *.c but ignore a specific file?
How about:
SOURCES := $(filter-out foo.c,$(wildcard *.c))

Using make for my program

I have a bunch of files in different folders:
/ai/client.cpp # contains the main function
/ai/utils/geometry.h
/ai/utils/geometry.cpp
/ai/world/world.h
/ai/world/world.cpp
/ai/world/ball.h
/ai/world/ball.cpp
/ai/world/bat.h
/ai/world/bat.cpp
How do I write a makefile to compile this program? I'm using Ubuntu.
Make is a versatile tool, and there are many different subtleties to using it. However, you can keep things simple:
OBJ := ai/utils/geometry.o ai/world/world.o ai/world/ball.o ai/world/bat.o
all: ai/client
.PHONY: all # specific to GNU make, which is what Ubuntu provides
ai/client: ai/client.o $OBJ
# this rule means each .cpp file depends on its corresponding header
# and, since the .o files depend on .cpp files (a builtin make rule),
# they will be recompiled if the headers change
#
# you can also get more complex and generate dependencies automatically
# look at the -MM option for gcc, for example
%.cpp: %.h
you should check out that you have installed g++ and build-essential
here is some insight into the makefile black magic consorsium
I think that make1 is directory aware so typing mydirectory/myfile.cpp should work well
the rest is basic g++ commands but the tutorial on 1 should be enough :)
1 the program that executes makefiles
its working thank you every1 for your valuable comments
specially for the links
on the previous post i forgot to write the client.cpp file on line 6
but my mistake was that i had included one header with a mistake in the client.cpp and it could never find it.
First result in google: http://www.opussoftware.com/tutorial/TutMakefile.htm
Seems to be a pretty good tutorial. Should be pretty simple to understand, note that they talk about the GNU version of make, which is what is most commonly used. There is also the BSD version though if you use a BSD-based OS(such as OpenBSD, NetBSD, or FreeBSD.. anyone know about Mac OSX?)

Help with rake dependency mapping

I'm writing a Rakefile for a C++ project. I want it to identify #includes automatically, forcing the rebuilding of object files that depend on changed source files. I have a working solution, but I think it can be better. I'm looking for suggestions for:
Suggestions for improving my function
Libraries, gems, or tools that do the work for me
Links to cool C++ Rakefiles that I should check out that do similar things
Here's what I have so far. It's a function that returns the list of dependencies given a source file. I feed in the source file for a given object file, and I want a list of files that will force me to rebuild my object file.
def find_deps( file )
deps = Array.new
# Find all include statements
cmd = "grep -r -h -E \"#include\" #{file}"
includes = `#{cmd}`
includes.each do |line|
dep = line[ /\.\/(\w+\/)*\w+\.(cpp|h|hpp)/ ]
unless dep.nil?
deps << dep # Add the dependency to the list
deps += find_deps( dep )
end
end
return deps
end
I should note that all of my includes look like this right now:
#include "./Path/From/Top/Level/To/My/File.h" // For top-level files like main.cpp
#include "../../../Path/From/Top/To/My/File.h" // Otherwise
Note that I'm using double quotes for includes within my project and angle brackets for external library includes. I'm open to suggestions on alternative ways to do my include pathing that make my life easier.
Use the gcc command to generate a Make dependency list instead, and parse that:
g++ -M -MM -MF - inputfile.cpp
See man gcc or info gcc for details.
I'm sure there are different schools of thought with respect to what to put in #include directives. I advise against putting the whole path in your #includes. Instead, set up the proper include paths in your compile command (with -I). This makes it easier to relocate files in the future and more readable (in my opinion). It may sound minor, but the ability to reorganize as a project evolves is definitely valuable.
Using the preprocessor (see #greyfade) to generate the dependency list has the advantage that it will expand the header paths for you based on your include dirs.
Update: see also the Importing Dependencies section of the Rakefile doc for a library that reads the makefile dependency format.

Can I have one makefile to build a hierarchical project?

I have several hundred files in a non-flat directory structure. My Makefile lists each sourcefile, which, given the size of the project and the fact that there are multiple developers on the project, can create annoyances when we forget to put a new one in or take out the old ones. I'd like to generalize my Makefile so that make can simply build all .cpp and .h files without me having to specify all the filenames, given some generic rules for different types of files.
My question: given a large number of files in a directory with lots of subfolders, how do I tell make to build them all without having to specify each and every subfolder as part of the path? And how do I make it so that I can do this with only one Makefile in the root directory?
EDIT: this almost answers my question, but it requires that you specify all filenames :\
I'm sure a pure-gmake solution is possible, but using an external command to modify the makefile, or generate an external one (which you include in your makefile) is probably much simpler.
Something along the lines of:
all: myprog
find_sources:
zsh -c 'for x in **/*.cpp; echo "myprog: ${x/.cpp/.o}" >> deps.mk'
include deps.mk
and run
make find_sources && make
note: the exact zsh line probably needs some escaping to work in a make file, e.g. $$ instead of $. It can also be replaced with bash + find.
One way that would be platform independent (I mean independent from shell being in Windows or Linux) is this:
DIRS = relative/path1\
relative/path2
dd = absolute/path/to/subdirectories
all:
#$(foreach dir, $(DIRS), $(MAKE) -C $(dd)$(dir) build -f ../../Makefile ;)
build:
... build here
note that spaces and also the semicolon are important here, also it is important to specify the absolute paths, and also specify the path to the appropriate Makefile at the end (in this case I am using only one Makefile on grandparent folder)
But there is a better approach too which involves PHONY targets, it better shows the progress and errors and stops the build if one folder has problem instead of proceeding to other targets:
.PHONY: subdirs $(DIRS)
subdirs: $(DIRS)
$(DIRS):
$(MAKE) -C $# build -f ../../Makefile
all : prepare subdirs
...
build :
... build here
Again I am using only one Makefile here that is supposed to be applicable to all sub-projects. For each sub-project in the grandchild folder the target "build" is created usinf one Makefile in the root.
I would start by using a combination of the wildcard function:
http://www.gnu.org/software/make/manual/make.html#Wildcard-Function
VPATH/vpath
http://www.gnu.org/software/make/manual/make.html#Selective-Search
and the file functions
http://www.gnu.org/software/make/manual/make.html#File-Name-Functions
For exclusion (ie: backups, as Jonathan Leffler mentioned), use a seperate folder not in the vpath for backups, and use good implicit rules.
You will still need to define which folders to do to, but not each file in them.
I'm of two minds on this one. On one hand, if your Make system compiles and links everything it finds, you'll find out in a hurry if someone has left conflicting junk in the source directories. On the other hand, non-conflicting junk will proliferate and you'll have no easy way of distinguishing it from the live code...
I think it depends on a lot of things specific to your shop, such as source source control system and whether you plan to ever have another project with an overlapping code base. That said, if you really want to compile every source file below a given directory and then link them all, I'd suggest simple recursion: to make objects, compile all source files here, add the resultant objects (with full paths) to a list in the top source directory, recurse into all directories here. To link, use the list.