2

I'm trying to build a project I have done for Windows, Visual Studio under OSX using Xcode 6.1.1.

I'm running into an issue where in a file that needs to include #include <string.h>. However, in the same folder as the file that does this there is also a file that is named string.h.

Under my Visual Studio project this still resolves file, the system paths are searched first.

In the Xcode project I have made sure to set up my own paths under "User Header Search Paths" - Xcode expand to the correct path. I also set "Always Search User Paths" to No - which according to the docs says that the system paths should be searched first: https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW110

But yet the #include <string.h> seem to be treated as #include "string.h" for some reason.

The config is defined in the project and I've made sure the targets doesn't override this.

Is this some Xcode/OSX thing where system includes <> search the path of the including file first?

Search path config

My local string.h file is located at ruby/api/string.h relative to the include path in my User Header Search Path.


Results of https://gist.github.com/thomthom/034b539bede38dd68261: https://gist.github.com/thomthom/034b539bede38dd68261

thomthom
  • 2,854
  • 1
  • 23
  • 53
  • Try using `#import ` perhaps, or rename the file `string.h` in your project to something else. `<>` vs `""` indicates standard lib path or user header path usually. – l'L'l Mar 03 '15 at 22:42
  • Isn't `#import` an Objective C thing? And while renaming would work around it - this appear to me to be wrong behaviour and I'd prefer to find the source of the problem instead of renaming a bunch of files. – thomthom Mar 03 '15 at 22:44
  • Yes mostly; it can work in conjunction with `C++`, `C`, etc. though. My confusion with your question is are you trying to use the standard library or specifically the "string.h" in your project — or both? – l'L'l Mar 03 '15 at 22:48
  • Both - where I need my own `string.h` I use `#include "ruby/api/string.h"` - and when I need the system header (actually it's used by the Ruby headers I include) this is used: `#include ` But the latter doesn't work in Xcode - while it does work in Visual Studio. Xcode seem to look up files for `#include <>` in the same folder as the including file before looking in the system folders. – thomthom Mar 03 '15 at 22:52
  • It sounds like the directory containing your header is in your include path. `""` does a relative search (so you can be like "..\..\some_folder\string.h" where `<>` searches for files in the directories specified in your include path. You probably need to tweak your project settings, or hide your header files in another directory so you can do something like `` for cstring, or `` for your string stuff. – scaryrawr Mar 03 '15 at 22:56
  • That's the thing, my `string.h` file is located in `ruby/api/string.h` relative to the source root. I set the source root only in **User Header Search Path**. I have not put any paths in the **Header Search Path**. So I'm very confused by `#include ` is resolved to the user path variant. – thomthom Mar 03 '15 at 23:03
  • Are you using `ifndef` in your `string.h`? Also make sure under `Search Paths` that `ALWAYS_SEARCH_USER_PATHS` is `NO` – l'L'l Mar 03 '15 at 23:05
  • @l'L'l - I have set "Always Search User Path" to no - as per described. I updated with a screenshot. I wonder if there could be some recursive flag set somewhere...? – thomthom Mar 03 '15 at 23:09
  • I don't have `Sub-Directories to Exclude in Recursive Searches` when I create an XCode `C++` project, so maybe try removing those. – l'L'l Mar 03 '15 at 23:12
  • I checked my paths, there are no recursive. And that is just a list of folders *not* no search in - live conversioning control and system folders. – thomthom Mar 03 '15 at 23:14
  • You could also try setting `SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES`. – l'L'l Mar 03 '15 at 23:27
  • Firstly, it's better to include system files via rather than since certain IDEs would also look in your user files as well. If you made a custom file, then it would be "string.h"; but I'd avoid name collusions such as this. Try renaming the header file to something else and see if that resolves your issue. If Xcode still can't find it, then you should add an include path for Xcode to find it. – Poriferous Mar 03 '15 at 23:58
  • 1
    The `` was used by a third party lib I was using - can't change that. Changing my own "ruby/api/string.h` to 'ruby/api/string.hpp` did work around the name clash. – thomthom Mar 04 '15 at 00:01
  • Here is the same issue: http://stackoverflow.com/questions/30851695/library-tries-to-include-string-h-but-includes-string-h-from-my-project-how Did you find solution? Could you share it? – Maxim Kholyavkin Jul 20 '16 at 05:04
  • @Speakus - see my previous comment - I ended up just renaming my own `string.h` to `string.hpp` - as I found to other solution to it. – thomthom Jul 20 '16 at 11:04

3 Answers3

2

The paths searched to satisfy an #include directive and the order in which they are searched are implementation defined. That includes whether any user-specified include paths (if even supported) are searched before, after, or instead of any default paths.

That's the case for both forms of #include directive. In particular, although it is common for implementations to perform some kind of relative search to find a file specified using the double-quoted include syntax, C does not require that. It requires only that if the implementation-defined mechanism used for resolving double-quoted includes fails, the compiler must fall back on the implementation-defined method used for resolving angle-bracketed includes.

Moreover, C specifies behavior only for the case that the given header name uniquely identifies a file to include. Depending on how one construes "uniquely", one might claim that C does not define any behavior at all in the situation you describe, on the basis that you have not uniquely identified the header you want to include. That's a bit wild, though -- I think it's better to interpret "uniquely" in light of the implementation-defined method for locating headers.

Your best bet is to avoid header names that collide with standard header names. One version of that would be to put them in a subdirectory that will lend its name as a prefix. For example, put string.h in src/myapp/, and include it as

#include "myapp/string.h"

To make that as safe as possible, ensure that directory src/ is in the include search path.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • My `string.h` file is nested under sub-folders: `ruby/api/string.h` and I include it as such: `#include "ruby/api/string.h"`. But `#include ` seem to resolve to the same file. - So you are saying that `#include ` might be hard coded for the compiler I use with Xcode to first look in the current folder - regardless? Is there any way to override this and force it to look in the system folders first? – thomthom Mar 03 '15 at 23:17
  • @thomthom, that your header is in a nested subdirectory already in no way changes my advice. If the resulting name can be recognized as a header when compiling sources that do not provide such a header themselves, then you have a name conflict which would be better avoided. You can still do that by pushing it into a subdirectory, i.e. `myapp/ruby/api/string.h`. If you do not want to change the name, then you'll have to consult the documentation for each compiler you use to figure out how to handle this issue. – John Bollinger Mar 03 '15 at 23:24
  • I'm a little confused by this " You can still do that by pushing it into a subdirectory" - but I fail to see how that sub-folder is different from the current sub folder it is in. I do find this in the CLang docs: "A #include directive which finds a file relative to the current directory is treated as including a system header if the including file is treated as a system header." though - I don't see how the including file is being treated as a system header. I guess I eventually have to forfeit and simply rename. Had hoped to find the definitive cause though. – thomthom Mar 03 '15 at 23:29
  • @thomthom, the point is to change the name by which your sources refer to the internal header to one that does not collide with a system header. Moving the header to a subdirectory (or changing its name in any other way) must be combined with changing the `#include` directives in your sources, as already described in my answer. – John Bollinger Mar 04 '15 at 13:59
1

Upon viewing your gist I noticed a discrepancy from your screenshot:

HEADER_SEARCH_PATHS = /Users/thomas/SourceTree/SUbD/SUbD/../ThirdParty/include/ruby/mac /Users/thomas/SourceTree/SUbD/SUbD/../ThirdParty/include/ruby/mac/universal-darwin12.5.0

This should be:

HEADER_SEARCH_PATHS = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
l'L'l
  • 44,951
  • 10
  • 95
  • 146
  • Those where from my target. Adding `$(inherit)` into the list before those paths didn't affect anything. Renaming my `ruby/api/string.h` to `ruby/api/string.hpp` did work around it. But still, it bugs me when I cannot find a definitive answer. – thomthom Mar 03 '15 at 23:53
  • `HEADER_SEARCH_PATHS` shouldn't contain your user includes paths though, that is what `USER_HEADER_SEARCH_PATHS` is supposed to contain. – l'L'l Mar 03 '15 at 23:55
  • Those paths are third party libs. – thomthom Mar 03 '15 at 23:57
  • Yes, which should be in `USER_HEADER_SEARCH_PATHS` **not** `HEADER_SEARCH_PATHS`. **This is why the standard library is not being used.** – l'L'l Mar 03 '15 at 23:58
  • hmm... so I reverted my file rename to test this. I then moved the third party includes to user includes, making sure there was no lingering config. But I still get the same behaviour. – thomthom Mar 04 '15 at 01:38
  • How are you checking to see if the standard library is not being used at all? It may require you set `ifndef` for your "string.h" file as I mentioned earlier. – l'L'l Mar 04 '15 at 01:43
  • 1
    One additional suggestion would be to try setting `USE_HEADERMAP = NO` [more info](http://stackoverflow.com/a/2598519/499581) – l'L'l Mar 04 '15 at 01:52
  • 1
    Appeared logical. But it didn't work. It doesn't appear to be in `USER_HEADER_SEARCH_PATHS` or `HEADER_SEARCH_PATHS`. I also had a similar discrepancy. Tried moving user path to USER_* and put system path in HEADER_*. That didn't help. If the user directory is in any of paths, Xcode is picking that first :(. – kiranpradeep Sep 22 '16 at 11:10
0

Have same issue with file <assert.h> in Xcode 13.4.

I fixed by set "No" for build setting "Search Paths" > "Use Header Maps".

Maybe help someone.