views:

114

answers:

5

Hi!

I have a project that was compiling ok within g++(I can't see the version right now) and now on xCode it is not.
I think that I got the problem now... I have a String.h file in my project and it seems tha the xCode compiler(that is gcc) is trying to add my own string file from the < cstring >... I am not sure of it, but take a look at this picture
http://www.jode.com.br/Joe/xCode1.png

from what it looks like, it is including my own instead of the system file, I was wondering... shouldn't #include < file > be a system include? because of the < > ? and shouldn't the system include a file within its own path and not the original path of my application?
As I said, I am not sure if this is what happening because I am just migrating to osx these past 2 days...
I was going to change my class and file name to not conflict, so it would work, if this is really the problem, but I was wondering, there should be another way to do this, because now my project isn't that big so I can do this in some time, but what if the project was bigger? it would be dificult to change all includes and class names...

Any help is appreciated

Thanks,
Jonathan

+1  A: 

On OSX the filesystem is case insensitive - so String.h you can wind up with conflicts like that. String.h == string.h

jskaggz
I presume it was case insensitive also with g++...
Lorenzo
Oh, i thought you we're migrating the project from linux. It was working on osx before?
jskaggz
Hmm actually in the question the source OS is not specified, so you might be right!
Lorenzo
g++ within linux
Jonathan
Thats totally it - it sees your String.h first, and includes it. This wouldn't happen on linux because the filesystem is case sensitive. Try building it from the command line on osx - in the same way you do on linux to eliminate xcode from the picture, I bet you'll see the same results.
jskaggz
but that makes no sense, since the std library is including it's own string.h and not mine. I mean, makes no sense for a developer to create his files thinking of what names he can't use, for an instance, lets say I change my String.h to Text.h(I already did, I need to work and this is not letting me) ad somehow I had to include another templated library that has a include called Text.h, would I have to change my text.h again or not use this new library? there should be an alternative. Or shouldn't it?
Jonathan
+3  A: 

Yes, if you use

#include "file"

the local directory is looked first and

#include <file>

only the system include folders are looked.

Notice the word first only in the first case. This means that every time is included your local version should never be reached (unless you have included your source path within the INCLUDE directive).

Said that, my dummy suggestion is to rename your local file with an unambiguous name...

Lorenzo
A: 

it worked by changing the name from String.h to Text.h

but that makes no sense, since the std library is including it's own string.h and not mine.
I mean, makes no sense for a developer to create his files thinking of what names he can't use, for an instance, lets say I change my String.h to Text.h(I already did, I need to work and this is not letting me) ad somehow I had to include another templated library that has a include called Text.h, would I have to change my text.h again or not use this new library? there should be an alternative.
Or shouldn't it?

thanks for the help so far,
Jonathan

Jonathan
Well, there' no possible solution. If the system is aware of two files with the same name, it has to pick *one* of them. If it preferred your file over the standard library, you'd risk breaking a lot of third-party code. Imagine another standard library header which attempts to include string.h. Now, with your rule, it includes *your* string.h instead of the standard library one. And then the standard library no longer compiles.The standard library defines a fixed set of headers, and it's up to you to avoid conflicts with those.
jalf
You can use `include "file"` instead of `<file>` to make the compiler search local folders first, which will normally make your headers take precedence over the system ones. You could also modify the compiler's include path.
jalf
+1  A: 

Naming your headers with the same name as standard headers like string.h and including them simply with #include <String.h> is asking for trouble (the difference in casing makes no difference on some platforms).

As you said, however, it would be difficult to try to figure out what those are in advance when naming your headers. Thus, the easiest way to do this is to set to set your include path one directory level outside of a sub-directory in which your headers reside, ex:

#include <Jonathan/String.h>

Now you don't have to worry about whether the String.h file name conflicts with something in one the libraries you are using unless they happen to also be including <Jonathan/String.h> which is unlikely. All decent third-party libraries do this as well. We don't include <function.hpp> in boost, for instance, but instead include <boost/function.hpp>. Same with GL/GL.h instead of simply GL.h. This practice avoids conflicts for the most part and you don't have to work around problems by renaming String.h to something like Text.h.

my problem was that the cstring was including my String.h instead of te string.h of the system, will this what u said solve this too?
Jonathan
Yes, if you put your String.h header in a Jonathan subdirectory, then <cstring> will not be able to include it since it will have to specify <Jonathan/String.h>.
A: 

Two things you're running into:

  1. As noted above, the filesystem on Mac OS is case-insensitive unless you specifically set up your filesystem to be case-sensitive.
  2. gcc does not distinguish all that much between local and system header include paths. When you specify a directory to be added to the path via -I, that directory will be used to locate both local and system includes. Only when you use -iquote or -I- does a directory get skipped for locating system includes. Further, the builtin "system include" directories on the compiler's search path are always searched for local includes.
    • Note that the current directory is used for local but not system includes. In this case, I believe it's picking up String.h because the project settings explicitly add the top-level project directory to the include path.

The workaround I would suggest, rather than renaming your includes, is to put your utilities into a directory whose name is unique for your project, and specify that directory in your include directive. For example:

#include "Josk/String.h"

and make sure Josk/ itself isn't in your include search path. This way you aren't stuck with an awkward rename, though you may have to shuffle some files around in your project. You may also need to edit your project settings to make sure the parent directory of that utility directory is in your include path.

Another possibility to try is, if you see the top-level project directory added to your project's include path, remove it. This ought to keep items in your top-level project directory from being searched for system includes.

Finally, you may also be able to avoid this problem in this specific case by changing the case sensitivity of your file system. This can break some Mac applications, though, so research the issue before you embark on this – or pick a volume that nothing else is using.

Owen S.