Make Xcode build a C file generated by processing a file with a custom extension - ios

I'm trying to set up Xcode to build generated .c files just like it does for files generated by yacc (*.y) and lex (*.l) files.
Say I have input files with a *.corn extension that are meant to be processed by a tool of mine to create C source files. I then want these C source files to be compiled and linked using the rest of Xcode's mechanisms.
This is exactly what happens to my .y and .l files for yacc and lex. The project target contains only the .y and .l files and the rest happens automatically. Generated .c files get put in the derived files directory and those get compiled and linked automatically.
Here's what I've tried so far:
-If I just add a .corn file to my target, Xcode copies it into the bundle at build time presuming it is a resource. Okay, whatever.
-I then create a custom build rule to handle
Source files with names matching: *.corn
Using Custom Script:
#!/bin/sh
cp "${INPUT_FILE_PATH}" "${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.c"
I have to give it an output file so:
OutputFiles:
${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.c
Note in this case I'm just copying the file as I rename it with .c extension. (As I'm playing around, the .corn file just contains C source.)
So now before the bundle directory even gets created I get the following warning:
unexpected C compiler invocation with specified outputs: 'blahblahblah/Build/Products/Debug-iphonesimulator/MyApp.app/foo.c' (for input: 'blahblahblah/Build/Intermediates.noindex/MyApp.build/Debug-iphonesimulator/MyApp.build/DerivedSources/foo.c')
Then after the link phase (sheesh!), the script above runs and I do end up with my foo.c in DERIVED_FILES_DIR. It doesn't get compiled however and notably, foo.corn didn't get copied into the bundle anymore so there's hope.
I've tried a bunch of other stuff, but this is the cleanest I can describe that others can try. Please what is the magic incantation to make this work?!
Note that I've also tried using DERIVED_SOURCES_DIR instead of DERIVED_FILES_DIR.

So I missed two things:
I needed to add the .corn files to the "Compile Sources" build phase.
By adding .corn files to the project/target before the adding the custom build rule, Xcode added the .corn files to the "Copy Bundle Resources" build phase which broke the build.

Related

Automate the process of including generated proto files into an Xcode project

Our iOS app currently is using Google protobuffer gRPC as our API layer to communicate between App and backend. And so we have these .proto files in our backend directory which will be converting to .grpc.swift and .pb.swift files by gRPC-Swift-Plugins and then consumed by the App.
This works okay, but the process of converting is very tedious, and we would like to automate the whole process.
Below is how we're doing it:
Delete previously copied directory, and copy all .proto files from backend (.proto files are maintained by backend devs) to App directory named "Protos" via a shell script
We already set up Build rules and include .proto files in Compile Sources. Following the steps from an answer here on SO
Screenshot of the current setup in Xcode Build Rules:
Whenever we build the project, .pb.swift and .grpc.swift are generated and putting into a directory named "generated" under the "Protos" folder.
Here are the problems:
If the backend added a new .proto files into the source directory, my script will only copy the files into the Protos directory but not included news files in the Compile Sources list.
Similar to the first problem, we need to manually set up Compile Sources in Xcode and that means if a new dev joins our team, he/she also needs to do the same setup again.
We sometimes need to refer to the .grpc.swift and .ph.swift files while coding. But If we add these files into Xcode and build the project again, Xcode will complain that these generated files are there like (Sorry, we're working on a private repo, so the project name and file names are replaced):
Multiple commands produce '${user_path}/${proto_name}.pb.o':
Target '${my_project_name}' (project '${my_project_name}') has compile command for Swift source files
Target '${my_project_name}' (project '${my_project_name}') has compile command for Swift source files
Any answers or comments and suggestions are greatly appreciated!
It's interesting I didn't have those problems with Swift if I use the $DERIVED_FILE_DIR
protoc "$INPUT_FILE_NAME" --swift_out="$DERIVED_FILE_DIR" --proto_path="Your/proto/path"
I don't use the plugin because I've got the plugin installed in my /usr/local/bin
But I have exactly those problems when we use the output for cpp files.

Header files are not found while archiving the build in xcode

I have a sub project that has been developed as dynamic lib and included that sub project into my main project and been set as target dependency.
When I run my main project, .a file for my sub project has been created successfully and the corresponding header files are created in the build directory such as (build/release-iphoneos/include). I have mentioned path using MACRO
In my main project, I mentioned header search path as the same that i mentioned above using MACRO.
But when I try to archive the build it throws the run time error file not found in the import statement
#import <subproject/myfile.h>
But it is getting build and run successfully even though it displays the file not found error in the xcode editor in compile time.
My question is
Is this because of the build directory will be empty while archieving?
I solved the problem as below
1. The header files were private so changed them as public so they are exposed to main project. (To build & run successfully)
2. I copied the header files and created a directory and add them into my main project and set the header search path to point that directory (To archive successfully)

Include files in bundle only for simulator

I have a couple test files I'd like be included in the bundle but ONLY when the project is compiled to be run in the simulator.
Is there a flag/target/setting somewhere in Xcode to indicate certain files shouldn't be included in the bundle for different schemes?
What you need to do is not include the files in the standard build phase "Copy Files" block, but write a custom build script that examines the current platform (EFFECTIVE_PLATFORM_NAME -iphonesimulator), and copies the files only in that case. Create a custom Run Script and the variables get printed out to the build log - you can examine all your options there.

Can't compile plcrashreporter in Xcode 4

I can use the prebuilt framework provided on the plcrashreporter project page when compiling for the device, but not for the simulator. I have the same problem described here.
I assume the prebuilt framework does not support the simulator's architecture, so I downloaded out the plcrashreporter source. I opened the Xcode project and selected the CrashReporter-iOS-Simulator > iPhone 4.3 Simulator target. When I try to build the project, I get this error:
libtool: unknown option character `D' in: -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000
I get the same error when I try to build most of the other targets (such as for device).
My next step was to try adding the source files to my project. I no longer have the aforementioned problem; however, I get this error when I try to compile:
fatal error: 'crash_report.pb-c.h' file not found [2]
#import "crash_report.pb-c.h"
^
1 error generated.
Command clang failed with exit code 1
The crash_report.pb-c.h file which is mentioned in the error message simply does not exist; I've searched the plcrashreporter source tree and the internet. Therefore, I have to assume that this file is supposed to be generated somehow, but I cannot figure out how.
(Commenting out the line in PLCrashReport.m on which crash_report.pb-c.h is included results in numerous other compilation errors.)
You are correct in that the file does not exist normally, nor does crash_report.pb-c.c exist, which will be your next error after this one.
The crash_report.pb.h and crash_report.pb.c files are generated at compile time through a build rule. You need to add a custom script to your build process to make them.
First, make sure you have protoc-c in the plcrashreporter folder of your project (plcrashreporter-1.0/Dependencies/protobuf-2.0.3/bin/protoc-c). They buried it deep. This is what your script will be running.
Then find your crash_report.proto file. This is the main input that protoc-c will be using to create your missing files. You can take this directory and put it manually into your script, OR you can make a rule to run the script on every *.proto file. I do the latter.
Then edit your build rules to include a script that runs protoc-c with the flag --c_out="${DERIVED_FILES_DIR}" and your crash_report.proto file as two inputs, this will output crash_report.pb-c.h and crash_report.pb-c.c into the same directory as where your crash_report.proto file is, which should already be accessible in your project.
The build rules in Xcode 4 (and above) are under your project's target's build rules tab. You add a build rule before all your other build rules. Here's what mine looks like in Xcode:
You'll probably have to fiddle with the directory

Xcode linked project header files not found

Here is the situation I have:
ProjectA - Xcode static library project.
ProjectA contains logical code group ExternLib with file ExternLib.h. ExternLib.h itself is in the folder Classes/lib/ExternLib (relative to ProjectA folder). Within ProjectA, I use ExternLib.h simply as: #import "ExternLib.h". This works fine.
Next I have ProjectB. This includes ProjectA as a linked Xcode project. The target has been added correctly etc. However, when I include a file in ProjectB which in turn includes ExternLib.h, upon building ProjectB, I get an error saying that the file ExternLib.h cannot be found.
I have tried adding the path to ExternLib.h to the header search path (all types: relative, absolute, with recursion etc.) but to no avail. I have checked that static library target has the copy headers step and the file ExternLib.h is included in it.
Anybody able to shed some light on how to get around this?
Add a Run Script Build Phase to the target for ExternLib that executes
mkdir -p "${BUILT_PRODUCTS_DIR}ExternLibHeaders"
Add a Copy Files build phase that copies the ExternLib header files into ${BUILT_PRODUCTS_DIR}ExternLibHeaders, and add all of ExternLib's headers into that phase.
In the app target for ProjectB, add ${BUILT_PRODUCTS_DIR}/ExternLibHeaders/ to the Header Search Paths for all configurations.
In Xcode > Preferences > Build, set the Build Products Directory to some common location.
The fourth step is crucial; it ensures that BUILT_PRODUCTS_DIR is the same for both projects.
It's really hard to say what might have gone wrong.
I'd start from scratch with a tutorial on building and using static libraries, and see if any of the steps jog any ideas out of you.

Resources