Friday, December 1, 2017
Here is a quick recipe to rebuild a macOS SPICE client from scratch. There are two methods, one using autotools, one using c3d/build. The autotools approach is presently complicated on macOS due to a bug in autotools and to differences between Apple and GNU tools.
Building with make and c3d/build
This approach is still experimental (as in "published today"), but it is significantly faster than autotools (as in about 16 times faster).
- Install Homebrew as follows:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- Install the required dependencies for building:
brew install pkg-config gettext intltool pixman gtk+3 gtk-doc gstreamer gstreamermm libjpeg-turbo gst-plugins-good gst-plugins-bad gst-libav
Note that installing XQuartz is not necessary for the SPICE client, only for the SPICE streaming agent, but this ensures that all SPICE components build successfully. Also, this step is only used as a quick way to install the /usr/X11 directory. If you have that directory on your system, you can skip the brew cask install xquartz step.brew cask install xquartz
- Clone the top-level directory for SPICE and go to that directory:
git clone https://github.com/c3d/spice cd spice
- Tell pkg-config where to find packages installed by brew:
export PKG_CONFIG_PATH=/usr/local/opt/jpeg-turbo/lib/pkgconfig:/usr/local/Cellar/openssl/1.0.2m/lib/pkgconfig:$PKG_CONFIG_PATH
Make sure that you adjust the path for openssl to match what brew actually installed. The OpenSSL package is not seen by default by pkg-config because it conflicts with Apple's own versions. - Run the actual build:
make -j
- If there is no error, you should be able to run spicy:
./spicy -h some-host -p 5900
Building using autotools
The steps are somewhat similar, but there is an additional requirement to patch the current version of autotools. This is also more likely to run into relatively mysterious errors, so make sure to check the Possible errors section below if you have a problem.
- Install Homebrew as follows:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- Install the required dependencies for building:
brew install pkg-config autoconf automake gettext intltool pixman gtk+3 gtk-doc gstreamer gstreamermm libjpeg-turbo gst-plugins-good gst-plugins-bad gst-libav
brew cask install xquartz
- After verifying the version for OpenSSL installed by brew, setup
the environment for building as follows:
export PKG_CONFIG_PATH=/usr/local/opt/jpeg-turbo/lib/pkgconfig:/usr/local/Cellar/openssl/1.0.2m/lib/pkgconfig:$PKG_CONFIG_PATH export PATH=$PATH:/usr/local/Cellar/gettext/0.19.8.1/bin:/usr/local/Cellar/automake/1.15.1/bin export CFLAGS='-ObjC'
- Clone the spice-protocol repository and go there:
cd ~/my-build-directory git clone git://anongit.freedesktop.org/spice/spice-protocol cd spice-protocol
- Run auto-configuration in spice-protocol (it may be a good time
to take some coffee):
./autogen.sh
- Build and install spice-protocol:
make install
- Clone the top-level directory for the SPICE GTK viewer, and go to
that directory:
cd ~/my-build-directory git clone git://anongit.freedesktop.org/spice/spice-gtk cd spice-gtk
- Run the auto-configuration for spice-gtk, and go grab another coffee:
./autogen.sh
- You may need to run configure manually, because the default configuration is
Possible errors
- Dependency on Objective-C headers:
The CFLAGS='-ObjC' is required because one of the keyboard mapping
files includes a header that uses Objective-C syntax. Without it, you
will get something like:
In file included from vncdisplaykeymap.c:95:
In file included from /usr/local/Cellar/gtk+3/3.22.24/include/gtk-3.0/gdk/gdkquartz.h:23: In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:10: In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:8: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:506:9: error: unknown type name 'NSString'; did you mean 'GString'? typedef NSString * NSRunLoopMode NS_EXTENSIBLE_STRING_ENUM; ^
- Autoconf bug in error reporting: While running
auto-configuration, you may end up with a helpful error message that looks
something like that:
autoreconf: running: aclocal --force -I m4 Use of uninitialized value $msg in concatenation (.) or string at /usr/local/Cellar/autoconf/2.69/bin/autom4te line 1026. Use of uninitialized value $stacktrace in pattern match (m//) at /usr/local/Cellar/autoconf/2.69/bin/autom4te line 1026. unknown channel m4trace: -1- AS_VAR_APPEND(ac_configure_args, " '$ac_arg'") at /usr/local/Cellar/autoconf/2.69/share/autoconf/Autom4te/Channels.pm line 638. Autom4te::Channels::msg('m4trace: -1- AS_VAR_APPEND(ac_configure_args, " '$ac_arg'")x{a}', undef, 'warning: ', 'partial', 0) called at /usr/local/Cellar/autoconf/2.69/bin/autom4te line 1026 aclocal: error: echo failed with exit status: 1 autoreconf: aclocal failed with exit status: 1
If you see this, then you need to patch autom4te as explained in this comment. You can for example run:sudo vi /usr/local/Cellar/autoconf/2.69/bin/autom4te
then search for the message # Trace with arguments, and insert the following text just above it:# Traces without file/line next if (m{^m4trace: -(d+)- ([^(]+)((.*)$});
In other words, you need to apply the following patch:diff --git a/usr/local/Cellar/autoconf/2.69/bin/autom4te.old b/usr/local/Cellar/autoconf/2.69/bin/autom4te --- a/usr/local/Cellar/autoconf/2.69/bin/autom4te.old +++ b/usr/local/Cellar/autoconf/2.69/bin/autom4te @@ -821,6 +821,8 @@ EOF my $traces = new Autom4te::XFile ("< " . open_quote ($tcache . $req->id)); while ($_ = $traces->getline) { + # Traces without file/line + next if (m{^m4trace: -(d+)- ([^(]+)((.*)$}); # Trace with arguments, as the example above. We don't try # to match the trailing parenthesis as it might be on a # separate line.
Once you have applied the patch, you will see the actual error that the autoconf bug was trying to report but failed to, for example:configure: error: Package requirements (spice-protocol >= 0.12.13) were not met: No package 'spice-protocol' found Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables SPICE_PROTOCOL_CFLAGS and SPICE_PROTOCOL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.
- Configuration errors. For some reason, autogen.sh may
leave you with an invalid configuration if you don't run it
manually. In that case, you get this:
make install
If you see this, simply run ./configure manually.echo 0.34.23-0381-dirty > .version-t && mv .version-t .version /Library/Developer/CommandLineTools/usr/bin/make install-recursive Making install in spice-common make[2]: *** No rule to make target `install'. Stop. make[1]: *** [install-recursive] Error 1 make: *** [install] Error 2
- Forced errors for warnings: You may see an error like:
channel-display-mjpeg.c:117:2: error: "You should consider building with libjpeg-turbo" [-Werror,-W#warnings] #warning "You should consider building with libjpeg-turbo" ^ 1 error generated.
There were apparently recent changes in the Homebrew-installed jpeg-turbo, which make the version incompatible with the regular JPEG version. For now, simply remove the #warning.
In the end...
Let me conclude with a personal opinion...
On my machine, the complete build with c3d/build takes about 15 seconds for a debug build and about 30 seconds for an optimized build. With autotools, it takes roughly 3 minutes, that's about 16 times slower.
The description of what's required to build SPICE with c3d/build is presently about 800 lines of standard Makefile. By contrast, with autotools, it takes about 5x as much, 1303 lines for configure.ac files, 2428 lines of Makefile.am (granted, at present, building very slightly more, e.g. documentation)
Autotools: Complex non-solutions to simple non-problems.
As far as I know, there is nothing autotools makes that make cannot do as well and faster. QED.