gnu make spaces in directory names vpath - c++

We've been trying unsuccessfully to make VPATH or vpath search directories containing space characters.
My makefile contains:
vpath %cpp RTW/ModelRTW RTW/StandardTests RTW/TestFramework RTW/TestFromFile ../../../CommonCode ../04_Model/DLib/ ../04 Model/ELib/
make -p returns:
.
.
vpath %cpp RTW/ModelRTW:RTW/StandardTests:RTW/TestFramework:RTW/TestFromFile:../../../CommonCode:../04_Model/DLib
I have tried quoting, escaping '\ ' and several other incarnations to no avail.
Any help would be greatfully accepted.
Ed

Sadly, it is a very old known defect, #712, and people have looked in to it a few times since it was reported in 2002.
GNU make doesn't handle spaces in names, and never has.
If you do attempt to patch it you will have a serious challenge ahead, since an enormous number of projects rely on it. Those who need whitespace support move to more advanced build systems. Over the decades there have been many build script tools, but make still sticks around despite many major problems. The make format of tabs and spaces has been annoying developers for almost 40 years.
The source is available, feel free to attempt to patch it if you want. Most developers who try end up giving up or making yet another build script system.

The best way is to write an m-script to copy the file(s) to the build directory where path is space-free.
If you use Simulink then the m-script is invoked at "before_make" hook.

Related

How can I quickly search all included header files in a project for a specific symbol?

Here's a problem I've had recently that just HAS to be a common pain to others here.
I'm working with someone else's legacy C code and need to find where a function or macro was defined. The code #includes a bunch of different standard system libraries in addition to those from the specific project.
Is there a tool or technique to quickly find where a specific function, macro, (or other global for that matter) was defined?
I tried:
grep -R 'function' /usr/lib
and other similar *nix/bash-fu with only limited success and lots of annoying chaff to cull. One of you sage coders out there must have a good solution to this seemingly common scenario.
I was very surprised to not find another question on this particular pain here or in my searches of the interwebs. (I'm sure there will be angry comments if I missed one... ;-))
Thanks in advance for any tips!
Use etags/ctags from the exuberant ctags project in conjunction with an editor (emacs, vim) that understands them, or GNU GLOBAL.
Oh, and if you happen to use automake it generates a target TAGS. So no need for complicated manual calls to {c,e}tags.
Use ctags/cscope + vim/emacs
you can google for their detail use.
if you use ctags + vim, you can :
1.go to the /usr/include directory, excute ctags -f tags1 -R . generate the tags
2.generate tags for your code in your code directory ctags -f tags2 -R.
3.run :set path+=tags1,tags2 in your vim
4.under a function or marco try CTRL+]
Here is what you can do, assuming you use gcc, if not just modify it accordingly.
gcc -E myfile.c | grep '^#' | cut -f 3 -d ' ' | sort |uniq | xargs -n 1 grep -l "MYMACROORFUNCTIONNAME"
You can use Eclipse CDT. For example here is described how to setup CDT project to navigate Linux kernel source - HowTo use the CDT to navigate Linux kernel source.
vim + ctags is the way to go. You can jump to and definition of functions, global variables, macros, etc. etc.
FYI, browsing programs with tags
Also, if you want to quickly switch between .c and .h files, please refer to this blog
you can use cscope or emacs/vim + xcscope.el to do that easily. I think it's batter than ctage and etage.
Provided the correct headers are included that directly or indirectly define what you look for, most IDEs have a jump-to-definition-functionality that works.
The tags-approaches are of course nice because they don't depend on correctly included headers.

Using Eclipse CDT from command line

I need to have some of my C++ classes, functions and namespaces renamed as a part of my build script, which is runned by my CI system.
Unfortunatly a simple sad/awk/gsar/... technique is not enough, and I need smart rename refactoring, that carefully analyses my code.
Actually I found out, that CDT C/C++ rename refactoring does, what I need. But it does it from Eclipse IDE. So I need to find a way to start it from command line, and to make it a part of my CI build script.
I know that Eclipse has eclipsec executable, that allowes running some Eclipse functions from command line (see e.g. here).
But I can't find any suitable documentation for functions, CDT exports to command line. The only thing, I found is the this. But it doesn't solve my problem.
So, I need help to run CDT rename refactoring from command line (or someway like that). If it is not possible, may be someone will advice another tool, that can do rename refactoring for C++ from command line ?
Pragmatic Approach
"I need to have renamed as a part of my build script"
This sounds a bit like a design problem. However, I remember having been guilty of the same sin once writing a C++ application on AIX/Win32: most notably, I wanted to be able to link 'conflicting' versions of shared objects. I solved it using a simple preprocessor hack like this:
# makefile
#if($(ALTERNATIVE))
CPPFLAGS+=-DLIBNAMESPACE=MYLIB_ALTERNATIVE
#else
CPPFLAGS+=-DLIBNAMESPACE=MYLIB
#endif
./obj64/%.o: %cpp
xlC++ $(CPPFLAGS) $^ -o %#
Sample source/header file:
namespace MYLIB
{
class LibService :
{
};
}
As you can see, this required only a single
find -iname '*.[hc]pp' -o -iname '*.[hc]' -print0 |
xargs -0 sed -i 's/OldNamespace/MYLIB/g'
Eclipse Automation
You could have a look at eclim, which does most, if not all, of what you describe, however it targets the vim editor.
What eclim boasts, is full eclipse intergration (completion, refactoring, usage search etc.) from an external program. I'm not fully up to speed with the backend of eclim, but I do know that it works with a eclimd server process that exposes the service interface used by the vim plugin.
I suspect you should be able to reuse the code from eclimd if not just use eclim for your purposes.
We are completing a command-line rename tool for C++, that uses compiler accurate parsing and name resolution, including handling of shadowed names. Contact me (see bio) for further details or if you might be interested in a beta.

C++ Make compile errors with Poco Library - Path Name containing spaces

I'm attempting to build/install/use the Poco C++ Libraries. I'm running Ubututu (Natty). I've compiled the static libraries which are working fine, but when I set the env var PROJECT_BASE to a path containing spaces, I get errors:
make
/bin/sh: Syntax error: Unterminated quoted string
/bin/sh: Syntax error: Unterminated quoted string
/home/username/Documents/poco-1.4.1p1/build/rules/global:62: *** Current working directory not under $PROJECT_BASE. Stop.
I've set PROJECT_BASE to:
/files/Dropbox/Myname\'s\ Work/C++\ Work
which I believe should be escaped correctly? Adding a trailling backspace gives me the alternate error of:
make
/bin/sh: Syntax error: Unterminated quoted string
awk: line 1: runaway string constant "/files/Dro ...
/home/username/Documents/poco-1.4.1p1/build/rules/global:62: *** Current working directory not under $PROJECT_BASE. Stop.
I might be missing something basic, but I've been wrestling for a few days now to get the Poco C++ Library build system set up how I want it to no avail :S I know the README said something about SYMBLINKS screwing up the PROJECT_BASE, but I'm no using any :S /files is an ext4 mount (same hdd, seperate partition) if that's relevant at all.
Thanks for your help!
For anyone else getting the: "* Current working directory not under $PROJECT_BASE. Stop." error, I found a solution that maybe sounds obscure.
Basically, if any of the parent directories are symlinks, it will generate this error.
IMPORTANT: Make sure that the path to the build directory does not
contain symbolic links. Furthermore, on Mac OS X (or other systems
with case insensitive filesystems), make sure that the characters in
the path have the correct case. Otherwise you'll get an error saying
"Current working directory not under $PROJECT_BASE.".
http://pocoproject.org/docs/00200-GettingStarted.html
In my case, I was compiling the library 5 levels deep and the second directory was a symlink. Changing it to a directory resolved the issue.
HTH
It requires great care and deliberate effort to make systems such as makefiles handle pathnames with spaces accurately. It can be done; it is not trivial. It is fairly clear that this package has not been so modified; it is like the majority of such packages.
If you really want to make life hell for yourself, use a pathname such as:
/home/mine/He said, "Don't do it!"/poco-1.4.1
Spaces, single and double quotes -- at least it doesn't include backquotes, dollars, parentheses, newlines, etc.
In the meantime, bow to the inevitable - use a pathname without spaces etc in it.
If your problem is not with symlinks, as in my case, you probably are not specifying a full path, but instead a relative one, as indicated in the following blog post.
http://fatalfeel.blogspot.com/2013/09/poco-with-cocos2d-in-android-and-ios.html

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

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.