Create Custom Builds of an Xcode Project - objective-c

I am going to build a Mac application written in Obj-C with Xcode. For argument's sake let's say it will have 10 optional features. I need a way to enable or disable those features to create custom builds of the application. These builds would be automated (most likely through the Mac OS X Terminal) so I would need a way to state which of these features are enabled/disabled at build time (a configuration file or CLI arguments would be ideal.)
So what is the best way to accomplish this? I'm trying to plan this out before I start coding so that there is proper separation in my code base to allow for these features to come and go. Ideally the custom build would only contain compiled code for the features it should have. In other words I don't want to always compile all the features and condition them out at runtime.

You can use Xcode configurations for this purpose; for each configuration you could include a different prefix header, for example. Then you can trigger builds form the command line via xcodebuild.
If you'd prefer the config file approach, you can use a .xcconfig file instead to define any of the Xcode build settings.
The Xcode Build System Guide describes both of these approaches.

use #ifdef and the -D flag under the compiler flags to control whether stuff is compiled in or out. You can set up lots of different configs this way if you want, and just have the xcode build configurations work nicely.
#include <stdio.h>
int
main (void)
{
#ifdef TEST
printf ("Test mode\n");
#endif
printf ("Running...\n");
return 0;
}
output 1:
$ gcc -Wall -DTEST dtest.c
$ ./a.out
Test mode
Running...
output 2:
$ gcc -Wall dtest.c
$ ./a.out
Running...
source: http://www.network-theory.co.uk/docs/gccintro/gccintro_34.html

Related

metrics from compilation with the make command

I use CMake to generate some makefiles that will compile multiple targets using G++ on Linux.
I would like to create some metrics about the compilation such as :
Time needed to build each target
G++ warnings and errors
The only solution I came up with so far is to redirect the output of make and parse the whole file but this seems really heavy. I cannot use the G++ flag -fdiagnostics-format=json feature since I cannot upgrade to GCC-9.
Any suggestions? Thank you very much
Something you could do is set the compiler to be a program or shell script that wraps the G++ functionality and add some (similar to how some ccache integrations work):
# Makefile
CC := g++-with-metrics.sh
# g++-with-metric.sh
# 1. Start timer
# 2. Run command, save output (to variable or tmpfile)
# 3. Stop timer, log result
# 4. Parse output for warnings and errors, log result
As far as timing is concerned, consider using Ninja instead of Make. When you build it produces a file called ${CMAKE_BINARY_DIR}/.ninja_log that can be converted to a format compatible with Chrome's about:tracing flame graph format.
There's a script for doing that here: https://github.com/nico/ninjatracing

Does the main kernel "make" command also make modules internally?

I am learning how to write kernel drivers and this is my first attempt to build one. I have created a folder drivers/naveen/ for my module files - hello.c,Kconfig and Makefile. These are the contents of these files :
Kconfig
config HELLO_WORLD
tristate "Hello World support"
default m
---help---
This option enables printing hello world
Makefile
obj-$(CONFIG_HELLO_WORLD) += hello.o
hello.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init hello_init(void)
{
printk(KERN_ERR "This is NAVEEN module");
return 0;
}
static int __exit hello_exit(void)
{
printk(KERN_ERR "NAVEEN exiting module");
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Naveen");
MODULE_LICENSE("GPL");
Also, I have added the following line in drivers/Makefile :
obj-$(CONFIG_HELLO_WORLD) += naveen/
and the following line in drivers/Kconfig :
source "drivers/naveen/Kconfig"
My generated .config contains CONFIG_HELLO_WORLD=m.
I did make ARCH=x86_64 -j16 and I can see hello.ko generated. Why? I was expecting to get it generated only when I had done make modules as its set to be as modular with m inside the .config, and not to be compiled with just make. Can someone please explain the behaviour to me or what wrong I am doing?
Does that mean that make also does make modules. I can see from make help that make actually means make all and hence it should do make modules as well internally, and so there should be no need to do make modules once make is successful.
Linux kernel consists of 2 parts - core kernel and modules. When we do simply make, it means make all which means make vmlinux && make modules. Hence, if we have done make, we need not do make modules again and we can simply run the command make modules_install without doing make modules.
You are doing nothing wrong. The modules target has been a dependency of the all target since kernel version 2.6.0 (actually since kernel version 2.5.60 I think).
The way you are adding your module is to add it to the kernel source tree. It is also possible to build custom modules outside the kernel source tree - so called "out-of-tree" kernel modules. Typically, those don't need a Kconfig file and the obj-$(CONFIG_HELLO_WORLD) would be replaced with obj-m in the Makefile.
Here is a Makefile for an "out-of-tree" version of your "hello" module:
ifneq ($(KERNELRELEASE),)
# Kbuild part of Makefile
obj-m += hello.o
else
# Normal part of Makefile
#
# Kernel build directory specified by KDIR variable
# Default to running kernel's build directory if KDIR not set externally
KDIR ?= "/lib/modules/`uname -r`/build"
all:
$(MAKE) -C "$(KDIR)" M=`pwd` modules
clean:
$(MAKE) -C "$(KDIR)" M=`pwd` clean
endif
This Makefile uses a common trick so that the same Makefile can be invoked as a "normal" Makefile and as a "kbuild" Makefile. The "normal" part between the else and endif lines invokes $(MAKE) on the kernel's Makefile (the location of which is specified by the KDIR variable), telling it to build the modules target in the current directory (specified by M=`pwd`). The "kbuild" part is between the ifneq($(KERNELRELEASE),) and else lines and is in the normal "kbuild" format for building parts of the kernel.
That trick depends on the KERNELRELEASE variable being initially unset or empty. It will be set to a non-empty value by the kernel's Makefile rules.

Plugin with own library kills Browser

I am new to C++ and plugin development. I am working with/for Unix and for the Firefox browser. So here we go:
I have a plugin which uses some classes from a own library. The problem is: it kills my browser asap. I cant even start my browser as soon as MyPlugin.so is in the plugin folder of the Firefox. The library is build and doesn't kill a desktop application that uses it.
My guess is that I failed at linking my library with CMake or forgot to include some stuff from FireBreath. So here are the two things I assume are wrong, maybe someone can help me out.
1) (wrong?) linking with Cmake:
I added some of these at the end of the CMakeLists.txt of my project. The paths are where the library is.
add_definitions(-L${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/bin)
add_definitions(-I${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/src)
add_definitions(-lcoala64) [name of the library]
add_definitions(-Wl,-rpath=${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/bin)
add_definitions(-pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/harfbuzz -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0)
And used the prepmake.sh to generate my build files. Then I followed up with adding flags manually (because I dont know a better solution) to the in the /buid/projects/MyPlugin/CMakeFiles/MyPlugin.dir/link.txt
-L/home/username/swp/dev/lib/bin
-I/home/username/swp/dev/lib/src
-lcoala64 -Wl,-rpath=/home/username/swp/dev/lib/bin
Afterwards I could build the plugin. It builds, so one could assume I have linked correctly. But said crashes appear as soon as I want to use it.
2) Do I use the library wrong?
I include like this in MyPluginAPI.h:
#include <string>
#include <sstream>
#include <boost/weak_ptr.hpp>
#include <boost/smart_ptr.hpp>
#include "JSAPIAuto.h"
#include "BrowserHost.h"
#include "X11/X11KryptoKoala.h"
//Include from my own library:
#include "../../../lib/src/Key.hpp"
As soon as I add the following line to MyPlugin.cpp I get the mentioned crashes while the same line works without a problem in the desktop application that uses the same library:
Key key(password_);
Now I hope this isn't a too big wall of text and someone is willing to investigate and answer to me.
You shouldn't use add_definitions() in that way. CMake allows to differentiate your directives in different categories, so that they only go in the necessary command line. You should use:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
include_directories(/usr/include/gtk-2.0
/usr/include/cairo
etc. etc.
)
add_library(the_name_of_your_target gtk-x11-2.0 gdk-x11-2.0 ETC. ETC.)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/bin)
Furthermore, there are FindPackage functionalities that can help you setting automatically variables containing the name of your libraries, their directories, their include path.
Most information can be found here and here
Then: What is then prepmake.sh? Are you running cmake at all? Can you use cmake-gui, and then select one canonical build system, like make or ninja?
Finally: It could be that you have a crash because your library are not in your library path. I assume you are under linux, here are some ideas: LD_LIBRARY_PATH vs LIBRARY_PATH and LD_LIBRARY_PATH

Unable to Compile Objective C using Gnustep on windows

Hi i am a beginner learning objective c.
i am finding an error "hello.m:1:34: Foundation/Foundation.h: No such file or directory"
i came to know that i need to make a make file
may i know how to make the make file please
No need to create a makefile. If you start MinGW from "All Programs -> GNUstep -> Shell" as Pax indicates above, you can just compile your .m file.
My GNUstep installation is in c:\GNUstep\GNUstep\System. If yours is different, you should change the import of Foundation.h accordingly.
I did this:
Create c:\myprogs\obj-c\hello\hello.m that looks like this:
//---------- Hello.m
#import <../../GNUstep/System/Library/Headers/Foundation/Foundation.h>
int main(int argc, const char* argv[])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Hello from Hello.m!");
[pool release];
return 0;
}
//----------
Start MinGW shell. (See above.)
On shell command line, change to directory where program code is located. (Note that, since this is not Unix, the Windows drive letter must be included.):
cd /c/myprogs/obj-c/hello
Compile the program:
gcc -o hello hello.m -I/c/GNUstep/GNUstep/System/Library/Headers \
-L /c/GNUstep/GNUstep/System/Library/Libraries -lobjc -lgnustep-base \
-fconstant-string-class=NSConstantString
(Note that "\" character allows us to extend command to multiple lines.)
I get the following informational messages when I compile:
Info: resolving ___objc_class_name_NSAutoreleasePool by linking to __imp____objc_class_name_NSAutoreleasePool (auto-import)
Info: resolving ___objc_class_name_NSConstantString by linking to __imp____objc_class_name_NSConstantString (auto-import)
Running resulting hello.exe gives me this:
2009-06-03 14:44:59.483 hello[1240] Hello from Hello.m!
That problem just looks like you haven't instructed gcc on where to find the relevant include files (i.e., the directory in which Foundation/Foundation.h resides).
Are you running gcc from under MinGW or from the command prompt. You should have a "All Programs -> GNUstep -> Shell" on your Start menu which brings up this shell.
A makefile for this should be as simple as:
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = YourProg
YourProg_OBJC_FILES = source_code.m
include $(GNUSTEP_MAKEFILES)/tool.make
If you will put your source codes into home directory in GNUStep, you don't need to provide relative location of Foundation framework.
Using a makefile such as the one specified by paxdiablo is probably the easiest, because rather than trying to remember an arcane command line each time, you set up the makefile and then call make from the source folder.
However, my experience under Windows suggested that GNUStep and Windows, even with the shell, won't build using that because it can't find all the make files it needs - add an environment variable GNUSTEP_MAKEFILES with a value of /GNUstep/System/Library/Makefiles and restart that shell, and then any errors from it being unable to find the standard makefiles should be history.
(I had tried using full paths to the makefiles, but found that this included the specific makefiles but then failed when trying to include further ones, hence going the easy route and adding an environment variable.)

Build System and portability

I'm wondering how i can make a portable build system (step-by-step), i currently use cmake because it was easy to set up in the first place, with only one arch target, but now that i have to package the library I'm developing I'm wondering how is the best way to make it portable for arch I'm testing.
I know I need a config.h to define things depending on the arch but I don't know how automatic this can be.
Any other way to have a build system are warmly welcome!
You can just use CMake, it's pretty straightforward.
You need these things:
First, means to find out the configuration specifics. For example, if you know that some function is named differently on some platform, you can use TRY_COMPILE to discover that:
TRY_COMPILE(HAVE_ALTERNATIVE_FUNC
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/alternative_function_test.cpp
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=xxx
)
where alternative_function_test.cpp is a file in your source directory that compiles only with the alternative definition.
This will define variable HAVE_ALTERNATIVE_FUNC if the compile succeeds.
Second, you need to make this definition affect your sources. Either you can add it to compile flags
IF(HAVE_TR1_RANDOM)
ADD_DEFINITIONS(-DHAVE_TR1_RANDOM)
ENDIF(HAVE_TR1_RANDOM)
or you can make a config.h file. Create config.h.in with the following line
#cmakedefine HAVE_ALTERNATIVE_FUNCS
and create a config.h file by this line in CMakeLists.txt (see CONFIGURE_FILE)
CONFIGURE_FILE(config.h.in config.h #ONLY)
the #cmakedefine will be translated to #define or #undef depending on the CMake variable.
BTW, for testing edianness, see this mail
I have been using the GNU autoconf/automake toolchain which has worked well for me so far. I am only really focussed on Linux/x86 (and 64bit) and the Mac, which is important if you are building on a PowerPC, due to endian issues.
With autoconf you can check the host platform with the macro:
AC_CANONICAL_HOST
And check the endianness using:
AC_C_BIGENDIAN
Autoconf will then add definitions to config.h which you can use in your code.
I am not certain (have never tried) how well the GNU autotools work on Windows, so if Windows is one of your targets then you may be better off finding similar functionality with your existing cmake build system.
For a good primer on the autotools, have a look here:
http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool