taucs on Mac OS X

Alec Jacobson

July 13, 2010

weblog/

Yesterday I spent way too long trying to get taucs compiled and linking on a Mac machine running OS X 10.6. Because my Qt is compiling for 32 bits I needed a 32-bit/i386 libtaucs.a, this was not so easy. I began hoping to compile a universal library, but couldn't manage to do it. I've previously posted about how to compile a 64-bit version of taucs on a mac 10.6 machine (this was not so bad). Update: Thanks to the useful comment below, I've modify these steps so that the result is a unviersal (32-bit and 64-bit) libtaucs.a

Part one: Compiling libtaucs.a (universal)

In the taucs directory (here on out [taucs] issue the following:
cp config/darwin.mk config/darwin10.0.mk
Then open up config/darwin10.0.mk and edit the following lines to look like this:
CFLAGS    = -arch i386 -arch x86_64 -O3 -faltivec
LIBBLAS   = -framework Accelerate
LIBLAPACK = -framework Accelerate
LIBMETIS  = -lmetis
LIBF77 = -lf2c
Now, this part is really messy but hopefully I'll remember everything I did. Before compiling libtaucs.a we need to compile libf2c.a and libmetis.a, and we need to do it so that both are at least i386. I think I managed to get mine to both be universal (i386 and x86_64). So, I've stripped these commands out of the buildf2c.sh script. Issue them in a terminal:
curl http://netlib.sandia.gov/cgi-bin/netlib/netlibfiles.tar?filename=netlib/f2c -o "f2c.tar"
tar -xvf f2c.tar
gunzip -rf f2c/*
cd f2c
unzip libf2c.zip -d libf2c
cd ..
sed 's/CC = cc/CC = \/usr\/bin\/cc/' f2c/libf2c/makefile.u > f2c/libf2c/makefile
sed 's/CC = cc/CC = \/usr\/bin\/cc/' f2c/src/makefile.u > f2c/src/makefile
At this point we need to edit the makefiles to make sure that they build universal libraries: In libf2c/makefile edit the following lines to look like this:
CFLAGS = -arch x86_64 -arch i386 -O
LDFLAGS += -arch x86_64 -arch i386

# compile, then strip unnecessary symbols
.c.o:
        $(CC) -c -DSkip_f2c_Undefs $(CFLAGS) $*.c
#        ld $(LDFLAGS) -r -x -o $*.xxx $*.o
#        mv $*.xxx $*.o
AND AGAIN in src/makefile edit the following lines to look like this:
CFLAGS = -arch x86_64 -arch i386 -O
LDFLAGS += -arch x86_64 -arch i386

# compile, then strip unnecessary symbols
.c.o:
        $(CC) -c -DSkip_f2c_Undefs $(CFLAGS) $*.c
#        ld $(LDFLAGS) -r -x -o $*.xxx $*.o
#        mv $*.xxx $*.o
Note: Be sure to comment out the ld ... and mv ... lines above. Now back to compiling:
cd f2c/libf2c
make f2c.h
if test ! -d /usr/local/include; then
    sudo mkdir -p /usr/local/include
fi
sudo cp f2c.h /usr/local/include/
make
if test ! -d /usr/local/lib; then
    sudo mkdir -p /usr/local/lib
fi
sudo cp libf2c.a /usr/local/lib/
sudo ranlib /usr/local/lib/libf2c.a
cd ../src
make
if test ! -d /usr/local/bin; then
    sudo mkdir -p /usr/local/bin
fi
sudo cp f2c /usr/local/bin/
cd ..
chmod +x fc
sudo cp fc /usr/local/bin
sudo ln  -s /usr/local/bin/fc /usr/local/bin/f77
sudo chmod +x /usr/local/bin/f77
Following the rest of the buildf2c.sh on your own to build the executables. Next, we need to compile libmetis.a. Download and unzip the source then in the metis folder edit Makefile.in:
# What options to be used by the compiler
COPTIONS = -arch i386 -arch x86_64

# What options to be used by the loader
LDOPTIONS = -arch i386 -arch x86_64
Then issue:
make
and then
sudo cp libmetis.a /usr/local/lib/
Now, finally, go back to [taucs]. Here you can issue:
./configure
make
This should produce a universal libtaucs.a library.

Part two: Using libtaucs.a

You should have no problem compiling any of the examples, like those in [taucs]/progs, as long as you include the right headers and the library. For example I can issue the following (be sure to replace the [taucs]s):
cc -arch i386 -o direct [taucs]/progs/direct.c \
-I[taucs]/src/ -I[taucs]/build/darwin10.0/ \
-L[taucs]/lib/darwin10.0/ -ltaucs -framework \
Accelerate -lmetis -lf2c
or
cc -arch x86_64 -o direct [taucs]/progs/direct.c \
-I[taucs]/src/ -I[taucs]/build/darwin10.0/ \
-L[taucs]/lib/darwin10.0/ -ltaucs -framework \
Accelerate -lmetis -lf2c
Though I do get the warning:
In file included from taucs_with_LU/src/taucs.h:7,
                 from taucs_with_LU/progs/direct.c:17:
taucs_with_LU/build/darwin10.0/taucs_config_build.h:5:24: warning: missing whitespace after the macro name
This is because of a #define that uses darwin10.0 and periods are not allowed. Update: If you are using a mac then taucs will try to define a macro called OSTYPE and set it to an invalid c value: darwin10.0 (invalid because of the period). As a result whenever you include taucs.h you'll get hundreds of warnings. I fix this by opening [taucs]/build/taucs_config_build.h and commenting out the following lines before I make:
/* This is an automatically generated file */
/* Configuration name: anonymous */
//#define TAUCS_OSTYPE darwin10.0
...
//#define OSTYPE_darwin10.0
...
You should also be able to compile this simple c program, saved in taucs_super_simple.c:
#include <taucs.h>
int main(int argc, char* argv[])
{
  double x = taucs_get_nan();
  return 1;
}
I can compile and run this with:
cc -arch i386 -o taucs_super_simple taucs_super_simple.c \
-I[taucs]/src/ -I[taucs]/build/darwin10.0/ \
-L[taucs]/lib/darwin10.0/ -ltaucs -framework Accelerate
./taucs_super_simple
Now if you try the same simple program, naively translated to cpp like this, saved in taucs_super_simple.cpp:
extern "C"{
#include <taucs.h>
}
int main(int argc, char* argv[])
{
  double x = taucs_get_nan();
  return 1;
}
and you try to compile with something like this:
c++ -arch i386 -o taucs_super_simple taucs_super_simple.cpp \
-I[taucs]/src/ -I[taucs]/build/darwin10.0/ \
-L[taucs]/lib/darwin10.0/ -ltaucs -framework Accelerate
You'll get a bagillion of these errors:
/usr/include/c++/4.2.1/complex:1104: error: template with C linkage
That's because taucs.h uses some complex library that is weird. Not sure why exactly you have to do this, but just add:
#include <complex>
above
extern "C"{
#include <taucs.h>
}
Do this anytime you include taucs. This should now compile with the above command.