I was trying to revive an old program fslogger from Amit Singh’s MacOSX Internals and compile it with Xcode 3.0 when I discovered it would not compile. Sigh… If you don’t keep on top of development changes your software will rot.
I assumed at first it was because I was using the default settings on a new command line tool. I tired changing the target SDK for the project to 10.4 and 10.3.9 to no avail so I started looking at the build results a bit more closely.
First, to simplify the problem I stripped down the source code to a bare minimum command line project that looked like this.
// fslogger.c
#include ‹stdio.h›
int main(int argc, char **argv) {
printf(”Hello world”);
}
Just for a sanity check on a basic project. This compiled fine so I added in the needed libraries.
// fslogger.c
#include ‹stdio.h›
#include ‹string.h›
#include ‹fcntl.h›
#include ‹stdlib.h›
#include ‹unistd.h›
#include ‹sys/ioctl.h›
#include ‹sys/types.h›
#include ‹sys/sysctl.h›
#include ‹sys/fsevents.h›
#include ‹pwd.h›
#include ‹grp.h›
int main(int argc, char **argv) {
printf(”Hello world”);
}
This is where I immediately ran into the problem. The build was returning:
CompileC build/fslogger.build/Release/fslogger.build/Objects-normal/i386/main.o /Users/davec/fslogger/main.c normal i386 c com.apple.compilers.gcc.4_0
cd /Users/davec/fslogger
/Developer/usr/bin/gcc-4.0 -x c -arch i386 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -Os -mdynamic-no-pic -Wreturn-type -Wunused-variable -fmessage-length=0 -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-generated-files.hmap -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-own-target-headers.hmap -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-all-target-headers.hmap -iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-project-headers.hmap -F/Users/davec/fslogger/build/Release -I/Users/davec/fslogger/build/Release/include -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/DerivedSources -isysroot /Developer/SDKs/MacOSX10.5.sdk -c /Users/davec/fslogger/main.c -o /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/Objects-normal/i386/main.o
/Users/davec/fslogger/main.c:11:26: error: sys/fsevents.h: No such file or directory
Ah ha, I forgot to set the header search path! Or so I thought. I added in
HEADER_SEARCH_PATHS = ~/Sources/xnu/bsd/sys
to the build options for the project which is where I had my xnu sources where fsevents.h was located and tried again. This time I got a different error:
CompileC build/fslogger.build/Release/fslogger.build/Objects-normal/i386/main.o /Users/davec/fslogger/main.c normal i386 c com.apple.compilers.gcc.4_0
cd /Users/davec/fslogger
/Developer/usr/bin/gcc-4.0 -x c -arch i386 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -Os -mdynamic-no-pic -Wreturn-type -Wunused-variable -fmessage-length=0 -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-generated-files.hmap -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-own-target-headers.hmap -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-all-target-headers.hmap -iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-project-headers.hmap -F/Users/davec/fslogger/build/Release -I/Users/davec/fslogger/build/Release/include -I/Users/davec/Sources/xnu/bsd/sys -I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/DerivedSources -isysroot /Developer/SDKs/MacOSX10.5.sdk -c /Users/davec/fslogger/main.c -o /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/Objects-normal/i386/main.o
In file included from /Users/davec/fslogger/main.c:9:
/Developer/SDKs/MacOSX10.5.sdk/usr/include/sys/types.h:141: error: syntax error before ‘ino64_t’
/Users/davec/fslogger/main.c:11:26: error: sys/fsevents.h: No such file or directory
It looked like to me that it was trying to use the default system path instead of my path so I copied the command into an test.sh file and started reading up on the gcc options.
test.sh
#!/bin/bash
cd /Users/davec/fslogger
/Developer/usr/bin/gcc-4.0 -x c -arch i386 -pipe -H -Wno-trigraphs -fpascal-strings \
-fasm-blocks -Os -mdynamic-no-pic -Wreturn-type -Wunused-variable -fmessage-length=0 \
-fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 \
-iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-generated-files.hmap \
-I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-own-target-headers.hmap \
-I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-all-target-headers.hmap \
-iquote /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/fslogger-project-headers.hmap \
-F/Users/davec/fslogger/build/Release \
-I/Users/davec/fslogger/build/Release/include \
-I/Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/DerivedSources \
-isysroot /Developer/SDKs/MacOSX10.5.sdk \
-I/Users/davec/Sources/xnu/bsd/sys \
-c /Users/davec/fslogger/main.c \
-o /Users/davec/fslogger/build/fslogger.build/Release/fslogger.build/Objects-normal/i386/main.o
I discovered in the man pages for gcc this little tidbit.
-isystem dir
Search dir for header files, after all directories specified by -I
but before the standard system directories. Mark it as a system
directory, so that it gets the same special treatment as is applied
to the standard system directories.
This sounded to me just what I was looking for so I changed the -I/Users/davec/Sources/xnu/bsd to read -isystem/Users/davec/Sources/xnu/bsd and tried again. Same error! Still can’t find the fsevents.h file! Looking at the source I realized the include files which began with
// fslogger.c
#include ‹stdio.h›
#include ‹string.h›
#include ‹fcntl.h›
#include ‹stdlib.h›
#include ‹unistd.h›
#include ‹ioctl.h›
#include ‹types.h›
#include ‹sysctl.h›
#include ‹fsevents.h›
#include ‹pwd.h›
#include ‹grp.h›
int main(int argc, char **argv) {
printf(”Hello world”);
}
Viola! It compiled! So all I have to do now is tell Xcode to use -isystem instead of -I for my xnu headers. Poking around in the docs I found you can specify individual settings for source files if you bring up the info window for the file. Sure enough, there is a Build tab so I put in -isystem/Users/davec/Sources/xnu/bsd and tried building from Xcode.
Bingo! It compiled! Finally!
Hot damn, it even runs!
