In the last month my work is somewhat related to Solaris and since I really got used to tmux I kind of miss it. Unfortunately it turns out Solaris is not the happy Linux land I am used to. One does not simply dowload, ./configure and make install stuff in Solaris. Not without the proper spells 🙂 So here is an attempt to document my experience to build static tmux binary, that doesn’t require libevent or ncurses shared libraries. I used a VM I had with gcc installed from openCSW.
First thing libevent, download and unpack it. Then:
$ cd libevent-2.0.21-stable
$ ./configure --prefix=/tmp/tmux-install
$ make && make install
Next goes ncurses, download and unpack. Then:
$ export AR=gar
$ ./configure --prefix=/tmp/tmux-install --without-cxx-binding
$ make && make install
And finally we can compile tmux itself. This is abit trickier , as it seems tmux doesn’t directly support Solaris. Download and unpack. You need to apply the following patch:
diff -ur tmux-1.8/client.c tmux-1.8-patched/client.c
--- tmux-1.8/client.c Sun Mar 17 16:03:37 2013
+++ tmux-1.8-patched/client.c Mon Nov 18 22:29:59 2013
@@ -33,6 +33,39 @@
#include "tmux.h"
+/* BEGIN SOLARIS 11 FIX */
+#ifndef LOCK_SH
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* don’t block when locking */
+#define LOCK_UN 8 /* unlock */
+#endif
+int flock(int fd, int cmd);
+void cfmakeraw(struct termios *termios_p);
+int
+flock(int fd, int cmd)
+{
+ struct flock f;
+ memset(&f, 0, sizeof (f));
+ if (cmd & LOCK_UN)
+ f.l_type = F_UNLCK;
+ if (cmd & LOCK_SH)
+ f.l_type = F_RDLCK;
+ if (cmd & LOCK_EX)
+ f.l_type = F_WRLCK;
+ return fcntl(fd, (cmd & LOCK_NB) ? F_SETLK : F_SETLKW, &f);
+}
+void
+cfmakeraw(struct termios *termios_p)
+{
+ termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ termios_p->c_oflag &= ~OPOST;
+ termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ termios_p->c_cflag &= ~(CSIZE|PARENB);
+ termios_p->c_cflag |= CS8;
+}
+/* END SOLARIS 11 FIX */
+
struct imsgbuf client_ibuf;
struct event client_event;
struct event client_stdin;
diff -ur tmux-1.8/server-client.c tmux-1.8-patched/server-client.c
--- tmux-1.8/server-client.c Tue Mar 26 21:22:31 2013
+++ tmux-1.8-patched/server-client.c Mon Nov 18 22:34:13 2013
@@ -25,7 +25,20 @@
#include
#include
#include
+#include
+#ifndef timersub
+# define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
#include "tmux.h"
void server_client_check_focus(struct window_pane *);
Use gpatch, obviuosly patch in Solaris carries some braindead Unix legacy which I don’t even want to know about:
$ gpatch -p1 < ../tmux-1.8-solaris.patch
Then we setup the CPP/LDFLAGS, ./configure and make:
$ export LIBEVENT_CFLAGS=-I/tmp/tmux-install/include
$ export LIBEVENT_LIBS="-lsendfile /tmp/tmux-install/lib/libevent.a -L/tmp/tmux-install/include"
$ CPPFLAGS="-D_XPG6" LDFLAGS="-D_XPG6" ./configure --prefix=/tmp/tmux-install/
$ make
Thats it 🙂 In the tmux source directory we have a tmux binary that depends only on system libraries so you can copy it to other Solaris boxes and use it there.
$ ldd tmux
libxnet.so.1 => /lib/libxnet.so.1
libsocket.so.1 => /lib/libsocket.so.1
libnsl.so.1 => /lib/libnsl.so.1
libcurses.so.1 => /lib/libcurses.so.1
libsendfile.so.1 => /lib/libsendfile.so.1
librt.so.1 => /lib/librt.so.1
libresolv.so.2 => /lib/libresolv.so.2
libc.so.1 => /lib/libc.so.1
libmp.so.2 => /lib/libmp.so.2
libmd.so.1 => /lib/libmd.so.1
libscf.so.1 => /lib/libscf.so.1
libaio.so.1 => /lib/libaio.so.1
libdoor.so.1 => /lib/libdoor.so.1
libuutil.so.1 => /lib/libuutil.so.1
libgen.so.1 => /lib/libgen.so.1
libm.so.2 => /lib/libm.so.2