Add Version number to XCode Command Line Utility C++ Project - objective-c

I have created a Command Line Utility C++ tool in XCode using Objective-C. I want the version number to be displayed in the Info of the created executable. So I have added the version number 1.0.0.0 in the Current Project Version field in the Build settings. However, when I build it, the version number does not get added to the created 'Unix Executable File'.
Am I missing something?
Thanks for the help.

Unfortunately, Xcode will not embed the current project version into the executable by itself, as of version 3. I'm not sure if this has changed in Xcode 4.
I ran into this problem a couple of years ago. It turns out that:
Version numbers displayed in the Finder come from applications’ Info.plists. In the case of an application bundle, Info.plist is a file. In the case of an executable, it must be embedded in a __TEXT section. The format of the Info.plist is the same either way.
Xcode does not have one-click support for embedding Info.plists into executables, but it is possible.
Xcode doesn’t preprocess Info.plist files unless they’re going into an application bundle (e.g. to insert the value of CURRENT_PROJECT_VERSION).
I hacked up a solution, but it’s unpolished and probably doesn’t represent best practices.
First, I created a new, stock Info.plist file called Info_template.plist. I set CFBundleVersion to ${CURRENT_PROJECT_VERSION}, and CFBundleShortVersionString to ${CURRENT_MARKETING_VERSION}.
Then, I added a Run Script phase called “Preprocess Info.plist” at the beginning of the build, using /bin/sh as the shell, with this script:
set -u
if ! [[ ${CURRENT_PROJECT_VERSION:-""} && ${CURRENT_MARKETING_VERSION:-""} ]]; then
echo "Version numbers are not set" >&2
exit 1
fi
# Ghetto environment variable expansion, since Xcode does not appear to have built-in expansion for arbitrary files
{ echo "cat <<EOF"
cat ${SRCROOT}/Info_template.plist
echo "EOF"
} | sh > ${DERIVED_FILES_DIR}/Info.plist
I added $(DERIVED_FILE_DIR)/Info.plist to its output files.
Then, I opened the target’s build settings, and added this to Other Linker Flags:
-sectcreate __TEXT __info_plist ${DERIVED_FILE_DIR}/Info.plist
This asks the linker to roll the generated Info.plist file into the executable.
Let me know how this works for you, or if I left anything out!

Related

How to properly wrap a C library in a Cocoa application

I want to include the GNU Scientific Library (GSL) in my Cocoa app so that the user needs not installing it locally first. Like most GNU packages, it's the standard configure / make / make install routine. But this won't work:
./configure --prefix ~/libgsl
make
make install
Since the prefix is local to my computer. And neither is this:
./configure --prefix (path to build folder)/libgsl
make
make install
What I want is essentially the GSL being contained entirely in my application, and I can call its functions without the users downloading anything else.
I'm rather new to Xcode 4 and the build system for Clang/GCC, having coming over from .NET. Any help is much appreciated.
Assuming there is not a framework-style build of the library, the way this is typically done when bundling with 3rd party libraries is to build the package as normal, install it in /usr/local, and configure your project to include and link from there. Building is the easy part though.
The tricky part is bundling up the .app correctly. You need to add a custom build stage (after the others) which first copies all the dependent .dylib files into your app bundle's Frameworks folder (using the environment variables to help; see Xcode docs). Then you need to use install_name_tool to get the app binary to look in the framework dir (as the embedded soname still thinks it is in /usr/local). This part is very fiddly and not well documented.
I've just extracted this from a working project where I use GSL. Just add this as an extra build phase in your XCode project as a Custom Script:
# Framework folder for Example.app
FRAMEWORKS_DIR=${TARGET_BUILD_DIR}/Example.app/Contents/Frameworks
# Create path if it doesn't exsit
mkdir -p ${FRAMEWORKS_DIR}
# Find the original linked path for libgsl
GSLLIB=`otool -L ${TARGET_BUILD_DIR}/Example.app/Contents/MacOS/Example | grep libgsl | cut -d" " -f1`
GSLPATH=`dirname $GSLLIB`
# Copy the dylibs into your app
cp /usr/local/lib/lib{gsl,gslcblas}.0.dylib ${FRAMEWORKS_DIR}
# Update embedded paths
install_name_tool \
-change ${GSLPATH}/libgsl.0.dylib \
#executable_path/../Frameworks/libgsl.0.dylib \
${TARGET_BUILD_DIR}/Example.app/Contents/MacOS/Example
This should work with a simple substitution of your app name.
This is basically the same as what you need to do to build a standalone Qt app, so the docs here are very relevant:
Deploying Qt on the Mac
It is worth reading up on bundles, frameworks and packaging. For example:
Mac OS X Framework Reference
This post is also relevant:
How do I link libraries in Xcode 4?
Note that GSL is published under the GPL, so your app would need to be similarly published in order to respect the license. Shipping the source is necessary, but not sufficient for compliance.

Is there any way to change the dynamic library search path in Xcode

Below is my scenario,
In my Application i had to make use of libopus library , i downloaded and install, compile --> install procedure is normal as its for any other open source library,
I linked libopus.a with my application, the way i did is , by default it will get installed in /usr/local/lib, so i drag from there and add it to my application,
Worked fine and no error on my machine,
On Another machine, i was expecting it to be run smoothly as i included this library statically, but its throwing error as
dyld: Library not loaded: /usr/local/lib/libopus.0.dylib
so i concluded, libopus.a somehow including libopus.0.dylib also dynamically,
Now i am able ot add a copy phase in my build setting , so it will get copied in ../Framework folder
if i do otool -L libpus.a then it shows following result
otool -L /usr/local/lib/libopus.a
Archive : /usr/local/lib/libopus.a
/usr/local/lib/libopus.a(bands.o):
/usr/local/lib/libopus.a(celt.o):
/usr/local/lib/libopus.a(cwrs.o):
/usr/local/lib/libopus.a(entcode.o):
/usr/local/lib/libopus.a(entdec.o):
/usr/local/lib/libopus.a(entenc.o):
/usr/local/lib/libopus.a(repacketizer.o):
It doesn't show as its depend upon the dylib library
Now my Question is
How to tell Application to look into this path first
I tried following option,
install_name_tool but it seems it will work on other machine , so the user need to run this script NOT DEVELOPER,
trying to set the some option in the xcode to set the RUNTIME Search path to locate that particular dylib but not getting succeed so far
install_name_tool is run by the developer during the build process, not by the user.
If you're building the library, you should use libtool(1) with the option -install_name #rpath; otherwise, you can use install_name_tool(1) with -id #rpath to do the same thing on the dylib. Then, when you're building your application, set the "Runpath search paths" to the path where you will install the library.
Apple has some good documentation on this in their Mach-O Programming Topics and Dynamic Library Programming Topics.

Xcode - UUID mismatch with framework dSYMs

I have an OSX desktop Xcode project which includes another Xcode project (a framework) as a dependency. When I build an archive of the app, it generates two dSYM packages - one for the app and one for the framework.
When I symbolicate crashes received from the app, symbols from the app package show up correctly (with file names and line numbers). However, symbols from the framework don't symbolicate at all - they just show the Framework name and memory address. Is there a way to symbolicate the parts of the stack trace involving the framework code?
Looking at the archive that I generated the.app package from, the UUID of the framework's dSYM doesn't match the one that gets copied into the "Frameworks" folder in the .app:
The HCCommon framework inside the .app package in the archive file:
/path/to/HipChat.xcarchive $ dwarfdump --uuid Products/Applications/HipChat.app/Contents/Frameworks/HCCommon.framework/HCCommon
UUID: 84891A9C-19DB-3E16-BE7E-9D4056FFFB97 (x86_64) Products/Applications/HipChat.app/Contents/Frameworks/HCCommon.framework/HCCommon
vs the dSYM of the HCCommon framework (in the dSYMs directory in the archive file):
/path/to/HipChat.xcarchive $ dwarfdump --uuid dSYMs/HCCommon.framework.dSYM/Contents/Resources/DWARF/HCCommon
UUID: 767F2D97-9E0B-3C4D-8337-FDF5A9CA2D81 (x86_64) dSYMs/HCCommon.framework.dSYM/Contents/Resources/DWARF/HCCommon
I'm not sure why your build is resulting in inconsistent dSYM UUIDs. When we do these kinds of builds (having spot-checked a few now), we have consistent UUIDs.
However, in answer to your question about how you can symbolicate the crash reports you've already received given the .dSYMs you already have (assuming for the moment that although the UUIDs match, they refer to identical code, and thus would work).
I have found the following to work well if you have to force the specific dsym:
atos -arch x86_64 -o <path_to_dsym_within_package> -l <offset_of_framework>
It's certainly not as pretty and generally I run the individual addresses through atos manually, but the result is a valid routine/line combination (assuming that you match the correct versions, etc.)
The <path_to_dsym_within_package> refers to foo.framework.dSYM/Contents/Resources/DWARF/foo followed by your binary name, where foo is the name of the framework. For us this works for any kind of plugin as well.
The <offset_of_framework> is from offset column in the crash log, where:
0 libsystem_kernel.dylib 0x7fff8e785ce2 0x7fff8e76f000 + 93410
1 libsystem_c.dylib 0x7fff871afa7a 0x7fff8716e000 + 268922
2 CTUtils 0x104e26c62 0x104e17000 + 64610
In this case, the first hex number is the address, the second hex number is the starting offset for the particular framework, and the + value is the decimal offset within the framework.
You'll need the second number (hex offset) for the command line above, and the first number to find the specific routine/line number.
In a worst-case scenario, there's always using dwarfdump directly, by using:
dwarfdump <path_to_dSYM> --arch x86_64 --lookup <offset>
<path_to_dSYM> is the path to the top level ".dSYM" folder (unlike the atos command above), and <offset> is the offset within the module, which isn't as convenient as atos.
P.S. atos should be installed in /usr/bin/atos if you have the dev tools installed.
I encountered this problem too. After some investigation, it turned out that Xcode was copying debug framework builds into release builds, but, apparently, creating dSYMs from the correct release binaries.
This was despite using Xcode to add the framework dependencies from the workspace. Eventually I found out why: the frameworks were included the project with their location "Relative to Group" for some reason. After I made sure all were "Relative to Build Product", it solved the problem for me. Not saying it is the only possible cause, but it's worth double-checking all the paths in the build log, because Xcode won't warn about anything in this case.

Too much exported symbols for a project compiled with CMake and MinGW

I'm trying to compile libzint (a barcode generator) for Windows using CMake and MinGW. The aim is to avoid Visual Studio dependencies. All run fine except that the generated .dll file contains too much exported symbols. I should have only ZBarcode_* functions but in fact pretty much anything that is declared as a variable/constant gets exported (and the resulting .dll file have no version information, I think this is strange.)
Here's how I did the job :
git clone from github repository in D:\Projects\Zint
installed cmake in C:\CMake
installed mingw in C:\MinGW
started cmake-gui, browsed to D:\Projects\Zint
clicked "Configure", choosed "MinGW Makefiles" in the list and "specify native compilers", next I specified the full path to c:\mingw\bin\mingw32-gcc.exe (to be sure...)
Clicked "Configure". It succeeded but it added some variables in red because dependencies where not met (PNG and QT but I don't want them and zint is fine without them)
clicked "Configure" again, everything turned white
clicked "Generate"
closed the cmake-gui
started a console prompt
overrode the path variable environment to C:\mingw\bin only
went to "D:\Projects\Zint" and ran "mingw32-make" then "mingw32-make install"
the libzint.dll and zint.exe were deployed to "C:\Program Files\zint-package\bin"
I used Dependency Walker to have a look at the exported functions and saw that in addition to few ZBarcode_* functions there were also around 400 other symbols and given the source code I saw that these symbols are in fact constants, arrays and other internals of libzint.
Do you know how to configure or tweak things to avoid all these exports ?
Many thanks for your help, regards.
Look in the headers for any macros that contain dllexport. If you find one or more, check that it's not malfunctioning.
Another possibility is that all classes are being exported, instead of just the few functions that are necessary.
If you have grep, do grep -nr dllexport *. This will recursively look in all files. For every hit, it will print the file name, line number, and contents of the line.

XCode Build Results: why is it so amazingly complex even for a hello world console app?

I have looked at build result for a simple hello world console app to see command line for compilation. Why is it so complex ? How can I then automate things if it is such complex ?
If you intend to automate builds of Xcode projects, use xcodebuild(1).
Your xcodeproj file contains all of the settings that you would need to specify on the command line if you were to call gcc directly. If you run xcodebuild all you need to do is specify your xcodeproj file, the target, the configuration, and the SDK to use. Everything else is done automatically.
Run "man xcodebuild" for more information.
XCode specifies an immense number of command line options for the compiler and linker with fully qualified path names. When working at the command line you'll frequently use defaults instead of specifying all the options the IDE does. Make or some other build tool is your friend for automation.