Dr. Brian Robert Callahan

academic, developer, with an eye towards a brighter techno-social life



[prev]
[next]

2024-01-01
FreeBSD has a new C compiler: Oracle Developer Studio 12.6

As announced, I have once again accomplished something no one was asking for, and probably no one wants. This time, it's getting Oracle Developer Studio 12.6 C compiler to produce native binaries for FreeBSD. For those uninitiated, Oracle Developer Studio is the current name for the Sun compilers.

There is some history here. A long time ago, a FreeBSD port of the Intel C++ Compiler was created. However, the version of the compiler you get from that package is version 8.1, released in September 2004, and is only supported on FreeBSD/i386.

Let's continue this rich history of proprietary compilers on FreeBSD.

Word of warning: if you try this for yourself and you break it, you get to keep both pieces.

Setup

I started by installing FreeBSD 14.0-RELEASE, specifically the amd64 release. Once logged into the newly installed system, I downloaded the Oracle Linux/Red Hat Linux Oracle Developer Studio 12.6 tarball. Though it says it's x86, they are 64-bit binaries.

I untarred the tarball and moved the resulting developerstudio12.6 directory to /opt/oracle so that the C compiler is found at /opt/oracle/developerstudio12.6/bin/cc.

Linuxulator

FreeBSD includes Linux binary compatibility through its Linuxulator. Following the FreeBSD Handbook, the commands I needed to get things going were:

# sysrc linux_enable="YES"
# service linux start
# pkg install linux_base-c7 linux-c7-elfutils-libelf

This CentOS 7 base seems to be a little old; it appears the libraries date from 2009. It looks like you can get a modern Debian/Ubuntu userland by following the other set of directions in the handbook. But as I didn't experience any issues, I didn't try to do anything more than this simple setup. The only issue of note is that Oracle Developer Studio binaries need a libelf library, and that isn't included in the linux_base-c7 package, hence the need for the second linux-c7-elfutils-libelf package.

The easy way

At this point, you could say that if you install the Linux headers and the GNU linker targeting Linux then you can build all the Linux binaries you want and FreeBSD will be able to run those binaries through the Linuxulator. And yes, that will work. That's the easy way. So if that's what you want, you're done at this step.

However, we never do things the easy way here.

Getting started on the hard way

No, instead I want Oracle Developer Studio to produce native FreeBSD binaries. This is going to take more work.

The first thing we will need to do is understand what Oracle Developer Studio attempts to do when compiling code. Let's start by writing the POSIX true utility in C:

int
main(void)
{

	return 0;
}

And saving it as true.c. We can use the -# flag to get verbose output. Running /opt/oracle/developerstudio12.6/bin/cc -# true.c gives this output:

### cc: Note: NLSPATH = /opt/oracle/developerstudio12.6/bin/../lib/locale/%L/LC_MESSAGES/%N.cat:/opt/oracle/developerstudio12.6/bin/../../lib/locale/%L/LC_MESSAGES/%N.cat
###     command line files and options (expanded):
### -# true.c
/opt/oracle/developerstudio12.6/lib/compilers/bin/acomp -Qy -std=gnu11 -i true.c -D__SUNPRO_C=0x5150 -D__unix -D__unix__ -D__linux -D__linux__ -D__gnu__linux__ -D__x86_64 -D__x86_64__ -D__amd64 -D__amd64__ -D_LP64 -D__LP64__ -D__ORDER_LITTLE_ENDIAN__=1234 -D__ORDER_BIG_ENDIAN__=4321 -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__ -D__BUILTIN_VA_STRUCT -D__C11FEATURES__ -D__C99FEATURES__ -D__PRAGMA_REDEFINE_EXTNAME -Dunix -Dlinux -D__RESTRICT -D__FLT_EVAL_METHOD__=0 -D__SUN_PREFETCH "-D__SIZE_TYPE__=unsigned long" -I-xbuiltin -I/opt/oracle/developerstudio12.6/lib/compilers/include/cc -I/opt/oracle/developerstudio12.6/lib/compilers/rtlibs/usr/include -xbuiltin=%none -fsimple=0 -m64 -fparam_ir -fparam_ir -xdebuginfo=%none -xF=%none -xdbggen=dwarf+usedonly+incl -xldscope=global -xivdep=loop -xanalyze=code -c99OS -xir_types "-g/opt/oracle/developerstudio12.6/bin/cc " -destination_ir=iropt -r /tmp/acomp.1704138652.42577.01.ir
cat /tmp/acomp.1704138652.42577.01.ir >/tmp/acomp.1704138652.42577.02.ir
/opt/oracle/developerstudio12.6/lib/compilers/bin/previse -Qy -O3 -fstore -xarch=sse2 -m64 -xchip=generic -xcache=generic -xdebuginfo=%none -depend -xbuiltin=%none -xprefetch=auto,explicit -xprefetch_level=1 -xprefetch_auto_type=no%indirect_array_access -o /tmp/iropt.1704138652.42577.03.ir "-Astatic_err_check:previse_iropt=on:umr=on:aob=on:free=on:nulld=on:nullc=on:msg_ctl_level=0:analytics=off:stderr_output=on" /tmp/acomp.1704138652.42577.02.ir
/opt/oracle/developerstudio12.6/lib/compilers/bin/ube -Qy -verbose -xcheck=noreturn -fstore -comdat -m64 -xarch=sse2 -xchip=generic -xcache=generic -xannotate=yes -fsimple=0 -ZW -fstore -xdebuginfo=%none -xbuiltin=%none -xprefetch=auto,explicit -s -fbe /opt/oracle/developerstudio12.6/bin/fbe -asm_init " -Qy -m64 -xchip=generic -warn=%none -s" -ir /tmp/acomp.1704138652.42577.01.ir -o true.o
### cc: Note: LD_LIBRARY_PATH = (null)
### cc: Note: LD_LIBRARY_PATH_64 = (null)
### cc: Note: LD_RUN_PATH     = (null)
### cc: Note: LD_OPTIONS      = (null)
/opt/oracle/developerstudio12.6/lib/compilers/postopt -optlevel=0 -xbinopt=prepare -xarch=amd64 -# -Qy -startldline /usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o a.out -Y "/opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64" -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o -stopldline
/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o /tmp/a.outSbCXv5 -q -Y /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64 -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o 
Writing extracted .o list to: (null)
DIRECT_LINK: invoked argc 27 argv 0x7fffffffb6c8
/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o a.out -Y /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64 -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o 
ld: error: unknown argument '-Y'
ld: error: unknown argument '-Qy'
ld: error: cannot open /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64: No such file or directory
ld: error: unable to find library -lc
postopt: error: ld failed to link the binary
rm /tmp/a.outSbCXv5
cc: postopt failed for a.out

Right now, we're going to ignore the linker step, though it does look like we successfully get to the linker step. There are a few things that stand out to me in this output. First is the -std=gnu11 flag indicating that we are a C11 compiler by default; that's nice and modern enough for me. Second is all the Linux defines; as we're on FreeBSD, we want the __FreeBSD__ preprocessor define. Let's see what happens if we run /opt/oracle/developerstudio12.6/bin/cc -# -D__FreeBSD__=14 true.c:

### cc: Note: NLSPATH = /opt/oracle/developerstudio12.6/bin/../lib/locale/%L/LC_MESSAGES/%N.cat:/opt/oracle/developerstudio12.6/bin/../../lib/locale/%L/LC_MESSAGES/%N.cat
###     command line files and options (expanded):
### -# -D__FreeBSD__=14 true.c
/opt/oracle/developerstudio12.6/lib/compilers/bin/acomp -D__FreeBSD__=14 -Qy -std=gnu11 -i true.c -D__SUNPRO_C=0x5150 -D__unix -D__unix__ -D__linux -D__linux__ -D__gnu__linux__ -D__x86_64 -D__x86_64__ -D__amd64 -D__amd64__ -D_LP64 -D__LP64__ -D__ORDER_LITTLE_ENDIAN__=1234 -D__ORDER_BIG_ENDIAN__=4321 -D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__ -D__BUILTIN_VA_STRUCT -D__C11FEATURES__ -D__C99FEATURES__ -D__PRAGMA_REDEFINE_EXTNAME -Dunix -Dlinux -D__RESTRICT -D__FLT_EVAL_METHOD__=0 -D__SUN_PREFETCH "-D__SIZE_TYPE__=unsigned long" -I-xbuiltin -I/opt/oracle/developerstudio12.6/lib/compilers/include/cc -I/opt/oracle/developerstudio12.6/lib/compilers/rtlibs/usr/include -xbuiltin=%none -fsimple=0 -m64 -fparam_ir -fparam_ir -xdebuginfo=%none -xF=%none -xdbggen=dwarf+usedonly+incl -xldscope=global -xivdep=loop -xanalyze=code -c99OS -xir_types "-g/opt/oracle/developerstudio12.6/bin/cc -D__FreeBSD__='14' " -destination_ir=iropt -r /tmp/acomp.1704139050.42614.01.ir
cat /tmp/acomp.1704139050.42614.01.ir >/tmp/acomp.1704139050.42614.02.ir
/opt/oracle/developerstudio12.6/lib/compilers/bin/previse -Qy -O3 -fstore -xarch=sse2 -m64 -xchip=generic -xcache=generic -xdebuginfo=%none -depend -xbuiltin=%none -xprefetch=auto,explicit -xprefetch_level=1 -xprefetch_auto_type=no%indirect_array_access -o /tmp/iropt.1704139050.42614.03.ir "-Astatic_err_check:previse_iropt=on:umr=on:aob=on:free=on:nulld=on:nullc=on:msg_ctl_level=0:analytics=off:stderr_output=on" /tmp/acomp.1704139050.42614.02.ir
/opt/oracle/developerstudio12.6/lib/compilers/bin/ube -Qy -verbose -xcheck=noreturn -fstore -comdat -m64 -xarch=sse2 -xchip=generic -xcache=generic -xannotate=yes -fsimple=0 -ZW -fstore -xdebuginfo=%none -xbuiltin=%none -xprefetch=auto,explicit -s -fbe /opt/oracle/developerstudio12.6/bin/fbe -asm_init " -Qy -m64 -xchip=generic -warn=%none -s" -ir /tmp/acomp.1704139050.42614.01.ir -o true.o
### cc: Note: LD_LIBRARY_PATH = (null)
### cc: Note: LD_LIBRARY_PATH_64 = (null)
### cc: Note: LD_RUN_PATH     = (null)
### cc: Note: LD_OPTIONS      = (null)
/opt/oracle/developerstudio12.6/lib/compilers/postopt -optlevel=0 -xbinopt=prepare -xarch=amd64 -# -Qy -startldline /usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o a.out -Y "/opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64" -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o -stopldline
/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o /tmp/a.out5Ljflq -q -Y /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64 -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o 
Writing extracted .o list to: (null)
DIRECT_LINK: invoked argc 27 argv 0x7fffffffb6b8
/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --enable-new-dtags /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/values-xa.o true.o -o a.out -Y /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64 -Qy -lc /opt/oracle/developerstudio12.6/lib/compilers/amd64/libc_supp.a /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o 
ld: error: unknown argument '-Y'
ld: error: unknown argument '-Qy'
ld: error: cannot open /opt/oracle/developerstudio12.6/lib/compilers/staticlib/amd64:/opt/oracle/developerstudio12.6/lib/compilers/amd64:/lib64:/usr/lib64: No such file or directory
ld: error: unable to find library -lc
postopt: error: ld failed to link the binary
rm /tmp/a.out5Ljflq
cc: postopt failed for a.out

So it looks like preprocessor defines we specify on the command line go at the end of the compiler invocation. This is actually excellent, as it means we can also undefine all the Linux preprocessor defines.

The third thing to note is that Oracle Developer Studio hardcodes -dynamic-linker /lib64/ld-linux-x86-64.so.2. Of course, that is the Linux dynamic linker. If we want the FreeBSD dynamic linker, we will need to add -Wl,-dynamic-linker,/libexec/ld-elf.so.1. Like the preprocessor defines, what we define comes after the hardcoded flags, so we will always overwrite the Linux dynamic linker with the FreeBSD dynamic linker. Additionally, the linker does not know where libraries are on the system, so we can help it out with -Wl,-L/usr/lib (or -Wl,-L/usr/lib32 when linking 32-bit code). This is getting us much closer.

A linker connundrum

It appears that Oracle Developer Studio hardcodes the location of the linker to /usr/bin/ld. I could not find an option like -fuse-ld= to change the linker used. On FreeBSD, /usr/bin/ld is LLVM lld, which, as the error messages helpfully keep pointing out, does not understand the -Qy and -Y flags. At one point, lld did silently ignore -Qy, but this was subsequently removed. As far as I can tell, -Y has never been supported in lld. This is a bit of a shame, as it means we either need to develop support for -Y in lld ourselves or switch to using the GNU linker. I chose to switch to the GNU linker, even though that is the less ideal choice. You can do that with:

# pkg install binutils
# rm /usr/bin/ld
# ln -s /usr/local/bin/ld.bfd /usr/bin/ld

And don't worry—you haven't deleted lld: /usr/bin/ld.lld is still around if you'd like to switch back.

Building real programs the hard way

Now we are all set up to start building real programs. Let's start with a Hello world program:

#include <stdio.h>

int
main(void)
{

	puts("Hello world");

	return 0;
}

This compilation crashes pretty quickly, as Oracle Developer Studio is missing some built-in defines that the FreeBSD headers use: __SIZEOF_LONG__, __SIZEOF_POINTER__, __SIZEOF_SIZE_T__, and __SIZEOF_PTRDIFF_T__. On FreeBSD, the value of all of these is 8 when building for 64-bit.

It was at this point I began writing a convenience script at /usr/bin/suncc to make all this easier. At the end of our journey, it will look like this:

#!/bin/sh

size=8
lib="lib"

for flag in "$@" ; do
  if test "x$flag" = "x-m32" ; then
    size=4
    lib="lib32"
  fi
  if test "x$flag" = "x-m64" ; then
    size=8
    lib="lib"
  fi
done

/opt/oracle/developerstudio12.6/bin/cc -D__SIZEOF_LONG__=$size -D__SIZEOF_POINTER__=$size -D__SIZEOF_SIZE_T__=$size -D__SIZEOF_PTRDIFF_T__=$size -D'__aligned(x)=__attribute__((__aligned__(x)))' -D'__sym_compat(x)=' -D__FreeBSD__=14 -U__linux -U__linux__ -U__gnu__linux__ -Wl,-dynamic-linker,/libexec/ld-elf.so.1 -Wl,-L/usr/$lib "$@"

We see the -D'__aligned(x)=__attribute__((__aligned__(x)))' and -D'__sym_compat(x)=' defines because our early attempts to compile more substantial programs would always error out over __aligned and __sym_compat, so we define them to be something Oracle Developer Studio understands in the case of __aligned or remove it in the case of __sym_compat.

Oracle Developer Studio can also produce 32-bit code when passed the -m32 flag. I happened to install the FreeBSD lib32 compat back at installation time, so I could test to see if Oracle Developer Studio could also be a multilib compiler on FreeBSD; spoiler: it can.

But that still wasn't quite enough to start compiling real programs. We will need to do a few more modifications.

Patching headers

We will need to patch a few headers. Not all that many. The entire diff looks like this:

--- /opt/oracle/developerstudio12.6/lib/compilers/include/cc/features.h.orig	2023-12-31 00:36:03.344232000 -0500
+++ /opt/oracle/developerstudio12.6/lib/compilers/include/cc/features.h	2023-12-31 00:36:14.575092000 -0500
@@ -5,8 +5,8 @@
 #ifndef _FEATURES_H
 /*
  * Include GNU's features.h
- */
 #include_next <features.h>
+ */
 
 /* 
  * features.h defines __GLIBC_HAVE_LONG_LONG macro only for select
--- /opt/oracle/developerstudio12.6/lib/compilers/include/cc/stddef.h.orig	2024-01-01 10:56:43.965370000 -0500
+++ /opt/oracle/developerstudio12.6/lib/compilers/include/cc/stddef.h	2024-01-01 12:32:26.153224000 -0500
@@ -83,10 +83,13 @@
 #ifndef _WCHAR_T
 #define	_WCHAR_T
 #if !defined(__GNUG__)		/* g++ has wchar_t as a built-in type */
+#ifndef _WCHAR_T_DECLARED
+#define _WCHAR_T_DECLARED
 #if defined(_LP64)
 typedef int	wchar_t;
 #else
 typedef long    wchar_t;
+#endif
 #endif
 #endif	/* !__GNUG__ */
 #endif  /* !_WCHAR_T */
--- /opt/oracle/developerstudio12.6/lib/compilers/include/cc/va_impl.h.orig	2023-12-31 01:02:49.652704000 -0500
+++ /opt/oracle/developerstudio12.6/lib/compilers/include/cc/va_impl.h	2023-12-31 01:05:35.095230000 -0500
@@ -126,14 +126,20 @@
 #if defined(__amd64)	/* processor */
 
 #if __SUNPRO_CC_COMPAT=='G'
+#ifndef _VA_LIST_DECLARED
     typedef __builtin_va_list __va_list;
+#define _VA_LIST_DECLARED
+#endif
 #else
+#ifndef _VA_LIST_DECLARED
 typedef struct __va_list_element {
 	unsigned int __va_gp_offset;
 	unsigned int __va_fp_offset;
 	void *__va_overflow_arg_area;
 	void *__va_reg_sve_area;
 } __va_list[1];
+#define _VA_LIST_DECLARED
+#endif
 #endif
 
 /* Other ISA __va_list structures added here under #elif */
--- /usr/include/stdio.h.orig	2023-12-31 01:01:14.509417000 -0500
+++ /usr/include/stdio.h	2024-01-01 12:21:29.078007000 -0500
@@ -73,7 +73,20 @@
 
 #if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
 #ifndef _VA_LIST_DECLARED
+#ifdef __SUNPRO_C
+#ifdef __amd64
+typedef struct __va_list_element {
+	unsigned int __va_gp_offset;
+	unsigned int __va_fp_offset;
+	void *__va_overflow_arg_area;
+	void *__va_reg_sve_area;
+} __va_list[1];
+#else
+typedef void *__va_list;
+#endif
+#else
 typedef	__va_list	va_list;
+#endif
 #define	_VA_LIST_DECLARED
 #endif
 #endif
--- /usr/include/sys/_types.h.orig	2023-12-31 00:47:50.148686000 -0500
+++ /usr/include/sys/_types.h	2023-12-31 00:48:16.397954000 -0500
@@ -206,10 +206,12 @@
  * Types for varargs. These are all provided by builtin types these
  * days, so centralize their definition.
  */
+#ifndef __SUNPRO_C
 typedef	__builtin_va_list	__va_list;	/* internally known to gcc */
 #if !defined(__GNUC_VA_LIST) && !defined(__NO_GNUC_VA_LIST)
 #define __GNUC_VA_LIST
 typedef __va_list		__gnuc_va_list;	/* compatibility w/GNU headers*/
+#endif
 #endif
 
 /*
--- /usr/include/wchar.h.orig	2023-12-31 10:44:36.510683000 -0500
+++ /usr/include/wchar.h	2024-01-01 12:21:47.258300000 -0500
@@ -78,7 +78,20 @@
 
 #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
 #ifndef _VA_LIST_DECLARED
+#ifdef __SUNPRO_C
+#ifdef __amd64
+typedef struct __va_list_element {
+	unsigned int __va_gp_offset;
+	unsigned int __va_fp_offset;
+	void *__va_overflow_arg_area;
+	void *__va_reg_sve_area;
+} __va_list[1];
+#else
+typedef void *__va_list;
+#endif
+#else
 typedef	__va_list	va_list;
+#endif
 #define	_VA_LIST_DECLARED
 #endif
 #endif
--- /usr/include/xlocale/_ctype.h.orig	2023-12-31 00:52:49.391999000 -0500
+++ /usr/include/xlocale/_ctype.h	2023-12-31 00:53:12.788098000 -0500
@@ -28,6 +28,7 @@
  * SUCH DAMAGE.
  */
 
+#include <runetype.h>
 
 #if	(defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_WCTYPE_H)) || \
 	(!defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_CTYPE_H))

It seems the main issue was around redefinitions of varargs. I am willing to bet there is a more elegant way to solve this issue, but what we have here works fine and does not disturb any other C compiler, so good enough to ship.

One last change: the C startup routines.

C startup routines

The linker stage also hardcodes the locations of the C startup routines. This is for the most part OK, as those are going to be Linux routines and we need to replace them anyway with the FreeBSD routines. We might as well put them in the same place. I'm also going to save copies of the Linux routines in case they ever are useful:

# mv /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o.orig
# mv /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o.orig
# mv /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o.orig
# mv /opt/oracle/developerstudio12.6/lib/compilers/crt1x.o /opt/oracle/developerstudio12.6/lib/compilers/crt1x.o.orig
# mv /opt/oracle/developerstudio12.6/lib/compilers/crti.o /opt/oracle/developerstudio12.6/lib/compilers/crti.o.orig
# mv /opt/oracle/developerstudio12.6/lib/compilers/crtn.o /opt/oracle/developerstudio12.6/lib/compilers/crtn.o.orig
# cp /usr/lib/crt1.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crt1x.o
# cp /usr/lib/crti.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crti.o
# cp /usr/lib/crtn.o /opt/oracle/developerstudio12.6/lib/compilers/amd64/crtn.o
# cp /usr/lib32/crt1.o /opt/oracle/developerstudio12.6/lib/compilers/crt1x.o
# cp /usr/lib32/crti.o /opt/oracle/developerstudio12.6/lib/compilers/crti.o
# cp /usr/lib32/crtn.o /opt/oracle/developerstudio12.6/lib/compilers/crtn.o

Note that FreeBSD crt1.o gets renamed crt1x.o on the Oracle Developer Studio side.

With this, Oracle Developer Studio 12.6 is all set up to produce native FreeBSD binaries.

Using our new C compiler

Whenever you link something, you will get this output from the GNU linker:

/usr/bin/ld: warning: true.o: missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker

You can ignore these warnings. Since 2017, lld has unconditionally added PT_GNU_STACK unless explicitly told not to with -z execstack. I'm not sure what direction the GNU linker will take, but for now it does not matter.

And just for completeness, here is our true utility compiled with Oracle Developer Studio:

$ file true
true: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/ld-elf.so.1, for FreeBSD 14.0 (1400097), FreeBSD-style, with debug_info, not stripped

Conclusion

There are probably still some subtle bugs lying around. But this really is good enough to have Oracle Developer Studio 12.6 produce native binaries for FreeBSD, both 64-bit and 32-bit.

I built two copies of GNU Bash 5.2.21: 64-bit and 32-bit. They are statically linked binaries, so they're a little large but hopefully usable and portable for a while. I used -xO4 -xspace -fPIC for the CFLAGS, which as I understand the documentation, is likely the most sensible optimization flags for most compiles. If you run readelf -x .comment bash, you will see all the comments Oracle Developer Studio leaves behind.

That was fun. And probably useless. And no, I didn't really try the C++ compiler. Things broke immediately and getting the C compiler working was enough for me.

Maybe NetBSD will be next?

Top

RSS