Background:
I was writing a "Hello Rectangle" OpenGL application. I want it to be a standalone .app
instead of just a "UNIX executable." The code runs fine from Terminal.app.
I didn't use Xcode; I'm very tight on disk space and I'm not doing iOS dev.
Instead I'm using brewed toolchain, including gcc-8
, glfw
and glew
.
I structured my release dir according to this SO question as follows:
Contents
├── Frameworks
│ ├── libGLEW.2.1.dylib
│ ├── libgcc_s.1.dylib
│ ├── libglfw.3.dylib
│ └── libstdc++.6.dylib
├── MacOS
│ ├── hello-rect <- the actual binary
│ └── launcher.sh <- entry wrapper for working dir as the above link suggests
├── Resources
│ ├── rect.frag
│ └── rect.vert
└── Info.plist
I also modified the reference to dylibs in binary. But it won't run.
After a few hours of Googling, this SO answer and this SO question and several others convinced me that I should use CoreFoundation
to read those two shader files (text file) in Resources
.
Problem:
I tried following code (pasted from the link above with slight modification), but it gets segfault:
const char* textFileReadCF(const char *&filename){
// Get a reference to the main bundle
CFBundleRef mainBundle = CFBundleGetMainBundle();
// Get a reference to the file's URL
CFStringRef filenameHandle = CFStringRef(filename);
// ------ segfault 11 here ------
CFURLRef fileURL = CFBundleCopyResourceURL(mainBundle, filenameHandle, NULL, NULL);
// Convert the URL reference into a string reference
CFStringRef filePath = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle);
// Get the system encoding method
CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
// Convert the string reference into a C string
const char *path = CFStringGetCStringPtr(filePath, encodingMethod);
// the real read function, read in file and returns all as a big char* arr
return textFileRead(path);
}
// this runs fine before packing and I didn't change,
// just for the sake of completeness
const char *textFileRead(const char *filename){
std::ifstream shaderFile(filename);
std::ostringstream shaderBuffer;
shaderBuffer << shaderFile.rdbuf();
std::string shaderBufferStr = shaderBuffer.str();
// Warning: safe only until shaderBufferStr is destroyed or modified
char * ret = new char[shaderBufferStr.size()];
std::strcpy(ret, shaderBufferStr.c_str());
return ret;
}
textFileReadCF
will be called twice with "rect.vert"
and "rect.vert"
(not literal, but const char*
holding them).
I have no idea why it goes segfault. I made sure there is one mainBundle
through assert
(omitted), and that filenameHandle
is valid as I can tell, but otherwise I don't know where to look.