Xcode using per-target headers with the same name - xcode

I am using Xcode 12.4. My project builds an app with two targets, one for the Mac App Store and one for "Retail" (downloaded from my website). My project folder looks like:
-Project
--Classes
---AppStore
----MyClass.h
----MyClass.m
---Retail
----MyClass.h
----MyClass.m
---Shared
----OtherClass.h
----OtherClass.m
All six source files appear in the left side file manager of Xcode and each project has two source files, OtherClass.m and the relevant MyClass.m.
When I build, the Retail version uses the correct MyClass.m source, but when it refers to the header with #import "MyClass.h", it wants to use the header from the AppStore version. Why does Xcode not look first in the directory where the .m file is located to see if a matching .h file is in the same directory?
How can I ensure that the right header files is used for each project, especially considering that ALWAYS_SEARCH_USER_PATHS is deprecated?

Related

How does the target know which headers it should include?

I do not understand how Xcode knows which headers should be included into which target? For example if I add a new File to my Xcode Project it adds the .m File to the compile sources of the selected targets but what about the .h files? How does my target know which header files should be used?
Only .m files and resource files are part of the targets, not .h. Headers only need to be copied for a framework target, and only because they are part of the framework release (they allow users to know how to use the framework). Apps don't need the headers because they're compiled stand alone entities. The headers (and the pch file) are used during compilation but aren't required at runtime.
You want files to be members of your target when they:
Form part of the executable (e.g. implementation (.m) files or libraries), or
Are included as files in the application bundle (e.g. images).
Just to give an example via screenshot, the way we control headers in Xcode for libraries is in build phase something like this:
You may further read out this Apple Documentation for setting the visibility of header files in Xcode.

Can Xcode Use "Folder References" for Code?

Like many people, I would love to have Xcode use a folder structure that mirrors the folder-structure on disk. However, I cannot get the code in "folder references" (the cyan folders) to show up in my project targets under "Compile Sources." Is there any way to do this?
I have managed to even add a cyan folder to the "Compile Sources" build phase, but that does not result in the contents of that folder being added.
How can I use folder references for code?
The simple (and very unfortunate) answer is that Folder References under Xcode remain broken and buggy, they don't work. Tested 04-Mar-2017 in Xcode 8.2.1
Below is an example exploration so you do not have to waste your time replicating the Xcode failure.
(incidentally buggy Xcode crashed twice while I was producing this example)
Per the question, the overall desire is to use a folder reference in Xcode so Xcode picks up all the files in the folder and includes them in the project, and by proxy will update automatically based upon any Finder or Xcode changes of the folder. In this way 50 projects all leveraging the same set of common source code files do not have to be individually updated when those folders get changed. Below explores how this is broken in Xcode (tested in 8.2.1)
The example: ViewController.m includes NSError+Core.h so we want everything from the folder "NSError+Core" to be added to the project.
NSError+Core.h is in this centrally located development folder
Drag the source folder from the Finder into the Project under the "Support" group (nothing up my sleeves, simple drag)
Xcode dutifully offers to add the drag to the target, note the "Create folder references" is selected, not "Create group references". Note also it is clear that Xcode is offering and is told to add this folder and files to the targets.
Although everything looks like it should work, the compiler does not pick up the header file and a recompile yields the same results... can't find header. Ditching the DerivedData does not help either.
So doing a double check, we check the "Compile Sources" under the project and sure enough, the source file is not there either. Remember, Xcode 'added' it to the target...
So what if we drag it from the folder into the "Support" group...
It offers to add them to the project again?! Note that the settings are identical to the first time they were drug in by virtue of the parent folder drag instead of files...
And now the source file shows up in the "Compile Sources" list. Note the bizarre double listing of the files in the project.
(Xcode crashed shortly after snapping this screen shot)
And of course the compiler can now find the header file and the error clears on the import as it should have the first time we drug it in...
Did it just need a little help to "find" the file? If so, the "Create folder references" does exactly what?
So we try and tidy up and drag the files back from the parent "Supporting Files" group to their rightful folder. Without any confirmation, indication, notification, the files just vanish from the group and nothing happens in the NSError+Core folder.
Oh by the way, it really did delete them from the project too... The Compile Sources no longer has the NSError+Core.m reference.
SO to sum up, "Folder references" as implemented thus far do not seem to have any useful purpose... It would appear to be a 6+ year old dunsel on the USS Xcode.
Kevin - linked source folders, folder references, etc, are super useful for when you have a common code base shared across different IDEs, like I do for my games that I compile on Windows, Mac, iOS, Android, Linux, etc. I have 3 different IDEs all building the same shared codebase, so it's very helpful when one automatically picks up on a new file and adds it right into the project after I merely run svn update, and I svn commit from one IDE (say XCode) and my Eclipse in Windows project picks up the change. I have a different project for each because each IDE likes the project files in a certain configuration so it's easier for me to have multiple SVN directories (base-project, project-ios, project-android) that all share code in base-project than to have one mega project directory with the different IDE bits unhappily all shoved into subdirectories (which is what I tried the first time around).
Furthermore - it used to work fine in XCode 3. They seemed to not like that useful of a feature so it is no longer working in XCode 4 as I've just found out.
I just tried doing this to share code across multiple Xcode projects, and our team came to the conclusion that it's better to create an Xcode project that contains all of your shared classes, compiles them into a static/dynamic library, and then add that as a subproject to those that need the shared code. Then you can set up target dependencies and link your shared library. This will get you the "automatic updating" every time you add a new class to the shared library project.
This approach also works well with submodules or even cocoapods/carthage.
You can't. Why are you even trying? A folder reference's job is to embody a folder, without having entries for all the individual files in the folder. It's primary use is for copying an entire folder of resources verbatim into a project. If you want to compile the sources though, then those sources must be referenced in the Compile Sources build phase of the target, which requires having individual entries for each file.
Depending on what's in the folder, it might make more sense to have a Makefile or some other external build process that builds the content in the folder into a static library. This way you can invoke that build process from a Shell Script Phase, and then just link in the resulting static library. Alternatively if you're using this folder as a way to have a shared bit of code (e.g. an svn:externals or git submodule), you could give that folder its own Xcode project and then embed that project into any of your other projects which share this folder.

Xcode source code directory

Goodday!
ToDo: compile the files from a directory that is outside of my Xcode project.
How to tell Xcode the path to look for source codes to compile (like the VPATH in a makefile)?
Note1: Right-click the target and it is easy to add the search path for header files or lib, but there I havent found any option to add a new source code directory.
Note2: I havnt found an answer in the xcode build documentation for this issue.
P.S.: I hope that I can do it without copying all the files to the xcode explicitly.
Thank you!
Drag the directory containing the files into your Xcode project. The only way Xcode knows it needs to compile the files is if they are contained in the project and a part of the target.
You indicated that you wanted to use at least some of the source files in a project and intend on using some set of the same source files for other future projects.
Create a new static or dynamic library using the external collection of source files and then just link this project to it and future projects to it
The design of most build environments encourages the use of code in reusable libraries.
Davidli
By the way (for those who are still searching and have problems with this issue), i have Xcode 4.5.2 and when i drag the items they are not linked! It seems that xcode's getting worse with each new version.
In case of xcode 4.5.2 if i copied class files into the separate folder i had to do right click to the group and choose 'add files to ""'

Xcode 4 and nested projects -- header files not found

I'm having a myriad of problems with Xcode 4 and nested projects that worked just well under Xcode 3.2. Here's a very basic one I cannot solve:
I'm building a cocoa framework that requires another cocoa framework for which I have the source. So I perform the usual steps:
Drag the .xcodeproj file of the required framework into my main framework project
In my main framework under TARGETS > MyFramework > Build Phases > Target Dependencies: Add the nested project's target
Make sure the header files of the nested framework are public
In Xcode Settings > Locations > Build Location I have it set to Place build products in derived data location (recommended)
Build products path of both targets are set to ${BUILT_PRODUCTS_DIR} and tell me they are at the DerivedData/Debug (or Release) location
Architecture settings for both targets are identical
Then I hit [CMD] + B to build and it tells me that it doesn't find the header files of the nested framework. When I check the settings, User Header Search Paths contain the path to DerivedData/Debug, and inside there is the nested framework target with the header files in Versions/A/Headers.
I'm sitting here, anybody an idea what I'm doing wrong?
The issue goes away when building for Debug when I change the User header search paths to ${BUILT_PRODUCTS_DIR}/MyFramework.framework/Headers. However this doesn't work when building for Distribution as the frameworks then use their Release settings, which ends up in a different subdirectory...
My temporary solution is to also define a Distribution configuration for the nested projects. This way the headers are found and the linker can link successfully.
Here's my synthesized knowledge so far:
Forget the whole public header thing with Xcode, it's a PITA and doesn't work correctly when archiving your app. Instead, have all static library header files on the project level and tell your app where to find it.
Ease your pain by making sure all targets have the same name for the build configuration (i.e. add an "AdHoc" and "Deployment" configuration to the static libraries).
In build settings, point the Header Search Paths (if you use #include <file.h>) or User Header Search Paths (if you use #include "file.h") to the directory of the static library project. If the static library project is inside your app directory, use this:
"$(PROJECT_DIR)" (recursive enabled)
If you have a directory which contains a) the static library project and b) your app, then this should work:
"$(PROJECT_DIR)/.." (recursive enabled)
If the submodule contains compiled libraries, set your Library Search Paths to:
"$(TARGET_BUILD_DIR)"
Make sure all the static library projects that you use have Skip Install set to YES.
Again, no public header files (Build Phases » Copy Headers) in any of the static libraries, otherwise Xcode will not be able to archive an app.
Make sure to tell Xcode when to build the static libraries, as shown in this Tech Doc from Apple.
Old Answer:
I still haven't found a real solution to this problem with static libraries. What works for me is:
Create an "AdHoc" Configuration for the static library
Add $(BUILT_PRODUCTS_DIR) to User Header Search paths for the application (with recursive checked) -> this is used when running the app
In the Xcode menu, select Product > Build For > Build For Archiving
This works, the app finds the header files and builds itself, it ends up in DerivedData//Build/Products/AdHoc-iphoneos/ as an App bundle. Following these simple instructions (dead link) from TestFlightApp.com I can pack this App into an IPA and send it around. Simply selecting to Archive the app from Xcode does again not find the headers, even if they truly are in the AdHoc-iphoneos build directory.
(As of Xcode 5.1)
When the subproject is built by XCode, the subproject header files are copied into the build directory. When archiving, it seems that this copy destination directory is not added to the header/include search path. You'll want to go to your Build Settings and add
$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include
to the "Header Search Paths" for the scheme that you use for archiving.
If you're not sure which scheme is used for archiving, go to Product -> Scheme -> Edit Schemes and look for Archive in the left column.
Make sure your third party framework is added as «group» to your main project, so you can see it in your project's hierarchy...
I had the same problem here and I could solve the problem by setting "Build Location" to Place build products in locations specified by targets"
I had this problem: I could build both Debug and App Store configurations, but not Ad Hoc. Building Ad Hoc gave me errors because it couldn't find .h files needed by nested projects.
Turned out I had an expired provisioning lingering in my Release configuration. I updated that provisioning link and now I can both build Ad Hoc and use the Archive feature to package it.
Took me hours to figure it out! My mind just didn't jump from missing .h files to provisioning errors just by itself. =) There might have been an error or warning complaining about the missing provisioning, but if so it was well buried among the hundreds of .h related errors.
I was having the same issue with a Configuration named "Ad Hoc" (as per TestFlight recommendation at http://help.testflightapp.com/customer/portal/articles/402782-how-to-create-an-ipa-xcode-4) and the main project could not find some of the headers from the nested projects. I renamed the project to "AdHoc" (no spaces) and the problem went away; seems like spaces can mess up header search paths in some cases, although I haven't figured out the specifics of when that might happen and why.
I was having this issue with a nested project that built a static library. I found this doc on apples site that completely saved my life.
http://developer.apple.com/library/ios/#DOCUMENTATION/Xcode/Conceptual/ios_development_workflow/AA-Developing_a_Static_Library_and_Incorporating_It_in_Your_Application/archiving_an_application_that_uses_a_static_library.html
I'm so glad I didn't have to muck around with the derived data paths.
For me, this happened after a GIT merge, which created many conflicts, one of them related to the project file. After the merge, I'm sure the structure of the project file changed.
What I ended up doing was going into the project "Build Settings", then looking for "Always Search User Paths" and turning it to Yes.
I guess the merge turned this boolean to No, therefore the project wasn't looking in the right places for the header files.

How should I structure my Qt based project so as to have a clean qmake generated xcode project?

If I add sources and headers in my .pro file that arn't in the same directory, the resulting xcode project groups the files by it's default Sources, Headers, etc. but then puts the files in a subdir of those folders indicating the subdirectory where the files are. This make non-flat projects look exceedingly ugly when generated for xcode (notice all the Qt examples are flat).
How do I prevent it from doing that? Or am I stuck with either an ugly xcode layout, or a flat project?
You can create your own configuration features for qmake by adding a new CONFIG argument variable in a .prf file.
Check out this Qt wiki.
Also it looks like you can use different variable names to generate different group names in xcode.
I'm going to figure out both these methods and generate a nice report.

Resources