infodan

Tuesday, 10 November 2009

Creating an universal static OpenCV library in (Snow) Leopard

More that a year ago i wrote a post about creating a fat OpenCV 1.0.0 static lib for OS X 10.5.

It seems it attracted some attention and it seems that some people found it useful. Unfortunately I have not been working directly with OpenCV for quite a lot of time, until recently, when I found myself in need of recompiling it for Snow Leopard.

So I created for myself a shell script that neatly compiles OpenCV 1.0.0 (of which you can download the source from Sourceforge). It creates the libs for Leopard or Snow Leopard with i386, x86_64 and ppc architectures.

I have no time to contribute the iPhone part but if someone is willing to submit it I will add it to the script.

To use it first, unpack the OpenCV 1.0.0 sources in a folder, open a terminal window and cd to the folder you unpacked the sources: the 'ls' command will list a 'opencv-1.0.0' directory in it. Then select the text below and in the terminal launch the 'pico opencv-build-mac.sh' command, paste the text, exit pico (with ctrl-x) and execute with 'bash opencv-build-mac.sh'.
#!/bin/bash

# Download opencv-1.0.0.tar.gz from http://sourceforge.net/projects/opencvlibrary/
# Unpack it in the same directory where this file resides.
# Execute this file from a terminal with the command "bash opencv-build-mac.sh"
#
# Compiles for Leopard by default.


#set -x

ROOTDIR=$(pwd)
SRCDIR="${ROOTDIR}/opencv-1.0.0"

# Leopard
SYSROOT="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5"
SUFFIX="-macosx10.5"

# Snow Leopard
#SYSROOT="-isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6"
#SUFFIX="-macosx10.6"

I686DIR="$ROOTDIR/i686"
PPCDIR="$ROOTDIR/ppc"
X86_64DIR="$ROOTDIR/x86_64"

CONFFLAGS="--without-imageio --without-python --without-swig --disable-apps \
--disable-dependency-tracking --without-carbon --without-quicktime \
--enable-shared=no --without-gtk"

#
# i686
#
build_i686() {

rm -rf $I686DIR
mkdir -p $I686DIR
pushd $I686DIR

${SRCDIR}/configure ${CONFFLAGS} CXXFLAGS="${SYSROOT} -arch i686" --target=i686-apple-darwin10 || exit 1
make || exit 1
popd
}

#
# x86_64
#
build_x86_64 () {

rm -rf $X86_64DIR
mkdir -p $X86_64DIR
pushd $X86_64DIR

${SRCDIR}/configure ${CONFFLAGS} CXXFLAGS="${SYSROOT} -arch x86_64" --target=x86_64-apple-darwin10 || exit 1
make || exit 1
popd
}

#
# ppc
#
build_ppc () {

rm -rf $PPCDIR
mkdir -p $PPCDIR
pushd $PPCDIR

${SRCDIR}/configure ${CONFFLAGS} CXXFLAGS="${SYSROOT} -arch ppc" --host=i686-apple-darwin10 --target=ppc-apple-darwin10 || exit 1
make || exit 1
popd
}


#
# creating fat lib
#
create_fat_lib() {

lipo -create $I686DIR/cv/src/.libs/libcv.a \
$X86_64DIR/cv/src/.libs/libcv.a \
$PPCDIR/cv/src/.libs/libcv.a \
-output libcv${SUFFIX}.a || exit 1

lipo -create $I686DIR/cxcore/src/.libs/libcxcore.a \
$X86_64DIR/cxcore/src/.libs/libcxcore.a \
$PPCDIR/cxcore/src/.libs/libcxcore.a \
-output libcxcore${SUFFIX}.a || exit 1

lipo -create $I686DIR/cvaux/src/.libs/libcvaux.a \
$X86_64DIR/cvaux/src/.libs/libcvaux.a \
$PPCDIR/cvaux/src/.libs/libcvaux.a \
-output libcvaux${SUFFIX}.a || exit 1

lipo -create $I686DIR/ml/src/.libs/libml.a \
$X86_64DIR/ml/src/.libs/libml.a \
$PPCDIR/ml/src/.libs/libml.a \
-output libml${SUFFIX}.a || exit 1

lipo -create $I686DIR/otherlibs/highgui/.libs/libhighgui.a \
$X86_64DIR/otherlibs/highgui/.libs/libhighgui.a \
$PPCDIR/otherlibs/highgui/.libs/libhighgui.a \
-output libhighgui${SUFFIX}.a || exit 1
}

#
# main
#

cd ${ROOTDIR}
rm *.a

build_i686
build_x86_64
build_ppc
create_fat_lib

Monday, 22 June 2009

Managing static versioned libraries in OS X

The Mac OS X offers great tools to developers in order to manage libraries with many versions: Frameworks.

Anyway sometimes you may want to use static libraries instead. Maybe just as a means of (psycologically) obfuscating your preciuos code you don't want to put in a framework for the world to know...

I'm currently experimenting with an idea that should make easier to selectively link different libraries versions to your application. The trivial idea is to create a folder for each of your libraries, for example in your Library home folder, named after their version:

/home/dan/Library/ACME/MySecretLib-1.0.0/
/home/dan/Library/ACME/MySecretLib-1.0.1/

Inside each folder there is your library archive (or archives if you want debug and release flavours) and a Headers folder. Your client projects will simply include the headers and link the library archive.

I will show you how to obtain this with Xcode. Refer to the Apple Xcode Build System Guide and to the Xcode Build Settings Reference if you're not at home with the (complex) Xcode build stuff.

Open the library Project Info window and in the Build tab define, for all configurations, the user-defined build settings:
  • ACME_LIBRARY_DIR = $(USER_LIBRARY_DIR)/ACME
  • ACME_LIBRARY_NAME = MySecretLib
  • ACME_LIBRARY_VERSION = 1.0.0
Then open your static library Target Info window and in the Build tab edit the settings:
  • DEPLOYMENT_LOCATION = YES
  • PRODUCT_NAME = $(ACME_LIBRARY_NAME)
  • DSTROOT = $(ACME_LIBRARY_DIR)
  • INSTALL_PATH = /$(ACME_LIBRARY_NAME)-$(ACME_LIBRARY_VERSION)
  • PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH)/Headers
Then add a Copy Headers Build Phase to your target and copy your public headers to it. Remember to set their Role to Public.

If you need a debug library with symbols simply add a "debug" line to the BUILD_VARIANTS setting.

To link your library you will define the following build settings:
  • ACME_SECRETLIBRARY_DIR = $(USER_LIBRARY_DIR)/ACME/MySecretLib-1.0.0
  • ACME_SECRETLIBRARY_NAME = libMySecretLib
  • HEADER_SEARCH_PATHS = $(ACME_SECRETLIBRARY_DIR)/Headers
  • OTHER_LDFLAGS = $(ACME_SECRETLIBRARY_DIR)/$(ACME_SECRETLIBRARY_DIR).a
changing the .a to .da if you're using the debug/release flavours.

Wednesday, 19 November 2008

Failing snapshots in XCode

Did it ever happened to you that the XCode "File > Make Snaphot" fails miserably with a Cannot-change-permissions-somewhere-down-over-/tmp/XY!$%^ ?

Well if so check the permissions of your project file, they must be writable by the owner only. To fix the problem launch a terminal, go in the project folder and use the
chmod -Rv g-w,o-w *
command. Of course double check you really are in the project folder and you really don't need those writing permissions in place.

Wednesday, 5 November 2008

Importing the OmniGroup Frameworks into your Subversion repository

This is a quick reference based on the Vendor Branches of the "Version Control with Subversion" book.

So you want to use the wonderful code that the Omni Group gives you for free. Good, just follow the following instructions.

Create a vendor branch in your repository:
myRepo/trunk
myRepo/branches
myRepo/tags
myRepo/vendor/OmniFrameworks
then download the frameworks distribution from the Omni Group site, unpack it in the, say, tmp folder of your home. It will have a structure like:
tmp/OmniGroup/Configurations
tmp/OmniGroup/Frameworks
tmp/OmniGroup/Scripts
Now use the svn_load_dirs.pl program to import the distribution to the repository.

svn_load_dirs.pl -t 2008-09-09 \
http://example.com/myRepo/vendor/OmniFrameworks \
current \
~/tmp/OmniGroup
You will have the code loaded to the current and 2008-09-09 directories.
myRepo/trunk
myRepo/branches
myRepo/tags
myRepo/vendor/OmniFrameworks/current
myRepo/vendor/OmniFrameworks/2008-09-09
The next time you import a new version of the frameworks, do the same steps as above. According to the Subversion Book everything will be all right ;)

Thursday, 3 July 2008

Creating an universal static OpenCV library with iPhone support

This post has been updated here. Sorry I have no time to upgrade the iPhone part, I hope someone will share this knowledge ;)

We will create a minimal static universal OpenCV 1.0.0 library with 4 architectures: Intel, PowerPC, x86_64 and Arm for the iPhone. I've been testing it on Leopard and Snow Leopard but it should work on any Mac OS X version.

First checkout or untar the OpenCV sources in the opencv-1.0.0 directory. Then, on the same level (not inside) create a build directory with 4 subdirectories: ppc, i386, x86_64 and arm. (Download the code from Sourceforge)

Then set the global configure settings:
$ export CONFFLAGS="--without-imageio --without-python --without-swig --disable-apps --disable-dependency-tracking --without-carbon --without-quicktime --enable-shared=no --without-gtk"
in the ppc dir:
$ ../../opencv-1.0.0/configure ${CONFFLAGS} --target=ppc-apple-darwin9
$ make CXXFLAGS="-arch ppc"
in the i386 dir:
$ ../../opencv-1.0.0/configure ${CONFFLAGS} --target=i386-apple-darwin9
$ make CXXFLAGS="-arch i386"
in the x86_64 dir:
$ ../../opencv-1.0.0/configure ${CONFFLAGS} --target=x86_64-apple-darwin9
$ make CXXFLAGS="-arch x86_64"

in the arm dir:
$ ../../opencv-1.0.0/configure ${CONFFLAGS} --host =arm-apple-darwin9 CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin9-g++-4.2.1 CXXFLAGS="-arch armv6 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk" CXXCPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cpp
$ make
the last one is tough, so let's see the variables one by one:
CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin9-g++-4.2.1
CXXFLAGS="-arch armv6 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk"
CXXCPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cpp
Ok. Now for the universal static libs:
$ lipo -create i386/cv/src/.libs/libcv.a x86_64/cv/src/.libs/libcv.a ppc/cv/src/.libs/libcv.a armv6/cv/src/.libs/libcv.a -output libcv.a
$ lipo -create i386/cxcore/src/.libs/libcxcore.a x86_64/cxcore/src/.libs/libcxcore.a ppc/cxcore/src/.libs/libcxcore.a armv6/cxcore/src/.libs/libcxcore.a -output libcxcore.a
$ lipo -create i386/cvaux/src/.libs/libcvaux.a x86_64/cvaux/src/.libs/libcvaux.a ppc/cvaux/src/.libs/libcvaux.a armv6/cvaux/src/.libs/libcvaux.a -output libcvaux.a
$ lipo -create i386/ml/src/.libs/libml.a x86_64/ml/src/.libs/libml.a ppc/ml/src/.libs/libml.a armv6/ml/src/.libs/libml.a -output libml.a
$ lipo -create i386/otherlibs/highgui/.libs/libhighgui.a x86_64/otherlibs/highgui/.libs/libhighgui.a ppc/otherlibs/highgui/.libs/libhighgui.a armv6/otherlibs/highgui/.libs/libhighgui.a -output libhighgui.a

That's all. Oh, try
$ make -j 2

Tuesday, 24 June 2008

pkgutil

Try pkgutil!

Tuesday, 5 February 2008

How to uninstall Mac Os X packages (.pkg)

Mac OS X keeps track of applications installed via the .pkg native installer in the /Library/Receipts folder.

.pkgs appear as files in the Finder but in reality are bundles. Apple nicely conceals information on installed files in the .bom ("bill-of-materials") proprietary binary files. But also ships a lsbom command that reads them (and a mkbom to create them).

So, supposing you want to uninstall a .pkg-distributed file (say... cmake) you have to:

1) check that it ships only files and simbolic links
lsbom Archive.bom | less

2) list the files you are going to delete (checking there is no system file!)
lsbom Archive.bom -f -l -s Archive.bom | less

3) delete them by hand or with the following command as administrator
lsbom -f -l -s -pf Archive.bom | (cd /; xargs -n 1 rm)


Er, you know in advance that if something goes wrong with the command above you wipe out your entire system, don't you?

Thanks to ths Macworld post

:)