The Journey of a C Developer in FreeBSD’s World (Part 1)

Moving from Linux to FreeBSD involves quite a number of changes; some gains and some losses. As a developer, for most of the programming languages, especially the high level ones, there are no meaningful disturbing changes. But for languages like C (and its sibling C++), if you want to port your softwares, libraries, etc, some points might need to be considered.

JourneyCDev_what you will learn

As is often the case with C, it is not especially straightforward; the code itself might need some changes, minus the pure POSIX part. Let’s say your program needs to use some known network functions.

#include <sys/param.h> ? BSD defined, FreeBSD current
version etc …
#if defined(BSD)
#include <netinet/in.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
main(int argc, char *argv[])
{
…
struct in_addr in;
const char *ip = argv[1];
if (inet_pton(AF_INET, ip, &in) == -1)
...
}

Here we have a more complex case; for example, how do we get the MAC Address of an interface?

int
main(int argc, char *argv[])
{…
struct ifreq if;
char hwaddr[6] = { 0 };
...
#if defined(__linux__)
if (ioctl(clsock, SIOCGIFHWADDR, &if) == 0)
memcpy(hwaddr, if.ifr_hwaddr.sa_data, sizeof(hwaddr));
...
#else if defined(BSD)
struct sockaddr_dl *cl = (struct sockaddr_dl *)(if.ifa_
addr);
unsigned char *p = (unsigned char *)LLADDR(cl);
memcpy(hwaddr, p, sizeof(hwaddr));
#endif
…}

In addition, FreeBSD provides a bunch of specific functions like strlcpy/strlcat (safer versions of strcpy/strcat) and strtonum family functions, all of which are available in the base whereas Linux must install the separate BSD library to have them. If you have any doubts about any functions, all manpages are available and very well written.

The environment

FreeBSD is shipped by default with clang whereas Linux relies on GCC suite. If you heavily use OpenMP, clang does not provide it yet so you might need to install GCC from ports. Somehow, clang mostly compiles faster and provides more informative warning and error messages. Fortunately, they share a significant amount of common flags.

On Linux, you may use a custom memory allocator during your development like jemalloc. It’s a very handy and useful library which allows you to generate statistics, to fill freed memory with specific values, and to spot corrupted memory usage.

Good news! You do not need to install it—FreeBSD libc’s malloc (aka phkmalloc) uses jemalloc internally. To print statistics from your application, for example, you need to include malloc_np.h instead of jemalloc/jemalloc.h.

As for the makefiles, this is the BSD format which differs from GNU style:

A basic makefile for a library:

…
LIB= mylib
SHLIB_MAJOR= 1
SHLIB_MINOR= 0
=> In addition to the static (profiled and non profiled
one), it will compile the shared version
SRCS= mylib.c
.include <bsd.lib.mk>
…
PROG= myprog => will compile an app called myprog
SRCS= main.c prog.c
CFLAGS+= -I${.CURDIR}/../mylib
=> always concatenate cflags, some like fstack-protector,
-Qunused-arguments … are added automatically
LDADD= -lutil -lmylib
DPADD= ${LIBUTIL}
=> linked to libutil.a ${.CURDIR}/../mylib/libmylib.a
.include <bsd.prog.mk>

FreeBSD can handle GNU via (gnu)make, libtool, etc via the ports.

Or to save the effort of porting this part, it might be more handy to use cmake or scons.

The publication

You might want to publish your library / application in pure FreeBSD’s path. You can make a port which can provide some options for the user. It can download the source and compile it with its dependencies in a natural manner. In addition, you can build a binary package to facilitate the distribution. Example of a port Makefile:

PORTNAME= mylib
PORTVERSION= 1
PORTREVISION= 0
MAINTAINER= john.doe@email.com
LICENSE= BSD
OPTIONS_DEFINE= CURL_SUPPORT
CURL_SUPPORT_DESC= Enable Curl support
=> Will display to the user the curl support then will add
a flag during compilation
.if ${PORT_OPTIONS:MCURL_SUPPORT}
CFLAGS+= -DCURL
.endif
.include <bsd.port.mk>

For instance, you can put the archive .tar.gz of the library in /usr/ports/distfiles, then type make checksum. Then, make install will compile and install it in /usr/local. The handbook of making ports is very useful to read.

Furthermore, you can build a binary version of this port to facilitate its distribution. Simply as it is, pkg create mylib. It will create a txz archive in the current folder. In the end, pkg install mylib will install it.

The conclusion

Developing under FreeBSD is not the extreme challenge you might think it is. Even better, from coding to publishing, everything is thought out and made in a constant way without any external dependencies. If you even want to go further, like kernel development, again it is easy and in base. So there is no real reason to stay away from FreeBSD anymore, you are more than welcome.


 

DAVID CARLIER

David Carlier has been working as a software developer since 2001. He used FreeBSD for more than 10 years and starting from this year, he became involved with the HardenedBSD project and performed serious developments on FreeBSD. He worked for a mobile product company that provides C++ APIs for two years in Ireland. From this, he became completely inspired to develop on FreeBSD.

ESG Labs: TrueNAS Technical Report
Download Enterprise Storage Guide Button
iXsystems values privacy for all visitors. Learn more about how we use cookies and how you can control them by reading our Privacy Policy.