GNU* Autoconf* is a popular build system that sees extensive use for Linux* source code packages. It produces a consistent, easy-to-use, and well-understood configuration script that allows end users and systems integrators to tailor software packages for their installation environments, almost always without any manual intervention. To create a configure script, the software developer creates a template file consisting of a series of macros that define the software package configuration needs, and then processes it with the Autoconf utility. GNU Autoconf provides convenient automation and standardization for common, and often tedious, tasks such as building Makefiles and configurable header files.
One of the key features of the Autoconf system is that it is extensible. Software developers can create macros that expand its functionality in order to support customized build and configuration needs. In this article, we introduce a set of macros and Makefile templates that do exactly this: Extend the functionality of Autoconf to simplify the process of building software that makes use of Intel® Software Guard Extensions (Intel® SGX). The templates themselves, along with a sample application source tree that makes use of them, are provided as a download.
Overview
The Intel SGX templates for the GNU Autoconf package contain four files:
- README
- aclocal.m4
- sgx-app.mk.in
- sgx-enclave.mk.in
README
The README file has detailed information on the Autoconf macros and Makefile rules and variables that make up the templates. It is a reference document, while this article functions more as a “how to” guide.
aclocal.m4
This is where the macros for extending Autoconf are defined. This file can be used as-is, appended to an existing aclocal.m4, or renamed for integration with GNU Automake*.
sgx-app.mk.in
This file builds to “sgx-app.mk” and contains Makefile rules and definitions for building Intel SGX applications. It is intended to be included (via an “include” directive) from the Makefile(s) that produce an executable object that includes one or more Intel SGX enclaves.
sgx-enclave.mk.in
This file builds to “sgx-enclave.mk” and contains Makefile rules and definitions for building Intel SGX enclaves. It must be included (via an “include” directive) from Makefiles that produce an Intel SGX enclave object (*.signed.so file in Linux).
Because this file contains build targets, you should place the include directive after the default build target in the enclave’s Makefile.in.
Creating configure.ac
Start by including the macro SGX_INIT
in your configure.ac. This macro is required in order to set up the build system for Intel SGX, and it does the following:
- Adds several options to the final configure script that let the user control aspects of the build.
- Attempts to discover the location of the Intel SGX SDK.
- Creates sgx_app.mk from sgx_app.mk.in.
SGX_INIT
also defines a number of Makefile substitution variables. The ones most likely to be needed by external Makefiles are:
enclave_libdir | Installation path for enclave libraries/objects. Defaults to $EPREFIX/lib. |
SGX_URTS_LIB | The untrusted runtime library name. When the project is built in simulation mode it automatically includes the _sim suffix. |
SGX_UAE_SERVICE_LIB | The untrusted AE service library name. When the project is built in simulation mode it automatically includes the _sim suffix. |
SGXSDK | The location of the Intel® SGX SDK. |
SGXSDK_BINDIR | The directory containing Intel SGX SDK utilities. |
SGXSDK_INCDIR | The location of Intel SGX SDK header files. |
SGXSDK_LIBDIR | The directory containing the Intel SGX SDK libraries needed during linking. |
The SGX_INIT
macro does not take any arguments.
AC_INIT(sgxautosample, 1.0, john.p.mechalas@intel.com) AC_PROG_CC() AC_PROG_CXX() AC_PROG_INSTALL() AC_CONFIG_HEADERS([config.h]) SGX_INIT() AC_CONFIG_FILES([Makefile]) AC_OUTPUT()
Next, define the enclaves. Each enclave is expected to have a unique name, and should be located in a subdirectory that is named after it. Specify the enclaves using the SGX_ADD_ENCLAVES
macro. It takes one or two arguments:
- (required) The list of enclave names.
- (optional) The parent directory where the enclave subdirectories can be found. This defaults to “.”, the current working directory, if omitted.
Note that you can invoke this macro multiple times if your project has multiple enclaves and they do not share a common parent directory. Enclave names should not include spaces or slashes.
AC_INIT(sgxautosample, 1.0, john.p.mechalas@intel.com) AC_PROG_CC() AC_PROG_CXX() AC_PROG_INSTALL() AC_CONFIG_HEADERS([config.h]) SGX_INIT() # Add enclave named “EnclaveHash” in the EnclaveHash/ directory SGX_ADD_ENCLAVES([EnclaveHash]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT()
In addition to defining the enclaves, this macro does the following:
- Builds sgx_enclave.mk from sgx_enclave.mk.in.
- Builds the Makefiles in each enclave subdirectory from their respective Makefile.in sources.
Enclave Makefiles
Each enclave’s Makefile needs to include the global sgx_enclave.mk rules file in order to inherit the rules, targets, and variables that automate enclave builds. Each Enclave must abide by the following rules:
- The enclave must be in its own subdirectory.
- The name of the subdirectory must match the name of the enclave (for example, an enclave named EnclaveCrypto must be placed in a subdirectory named EnclaveCrypto).
- The EDL file for the enclave must also match the enclave name (for example, EnclaveCrypto.edl).
- The Makefile must define the name of the enclave in a variable named ENCLAVE (for example,
ENCLAVE=EnclaveCrypto
).
The sgx_enclave.mk file defines a number of variables for you to use in the enclave’s Makefile:
ENCLAVE_CLEAN | A list of files that should be removed during 'make clean'. |
ENCLAVE_CPPFLAGS | C preprocessor flags. |
ENCLAVE_CXXFLAGS | C++ compiler flags necessary for building an enclave. |
ENCLAVE_DISTCLEAN | A list of files that should be removed during 'make distclean'. |
ENCLAVE_LDFLAGS | Linker flags for generating the enclave .so. |
ENCLAVE_TOBJ | The trusted object file $(ENCLAVE)_t.o that is auto-generated by the sgx_edger8r tool. Include this in your enclave link line and the enclave build dependencies. |
Here’s the Makefile.in for the enclave in the sample application included with the templates:
CC=@CC@ CFLAGS=@CFLAGS@ CPPFLAGS=@CPPFLAGS@ LDFLAGS=@LDFLAGS@ INSTALL=@INSTALL@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ enclave_libdir=@enclave_libdir@ ENCLAVE=EnclaveHash OBJS=$(ENCLAVE).o %.o: %.c $(CC) $(CPPFLAGS) $(ENCLAVE_CPPFLAGS) $(CFLAGS) $(ENCLAVE_CFLAGS) -c $< all: $(ENCLAVE).so install: all $(INSTALL) -d $(enclave_libdir) $(INSTALL) -t $(enclave_libdir) $(ENCLAVE_SIGNED) include ../sgx_enclave.mk $(ENCLAVE).so: $(ENCLAVE_TOBJ) $(OBJS) $(CC) $(CFLAGS) -o $@ $(ENCLAVE_TOBJ) $(OBJS) $(LDFLAGS) $(ENCLAVE_LDFLAGS) clean: rm -f $(OBJS) $(ENCLAVE_CLEAN) distclean: clean rm -f Makefile $(ENCLAVE_DISTCLEAN)
Application Makefiles
Application components that reference enclaves need to include sgx_app.mk in their Makefile. It defines a number of rules, targets, and variables to assist with the build.
To get a list of all the enclaves in the project, the Makefile must define a list variable from the @SGX_ENCLAVES@
substitution variable that is set by Autoconf:
SGX_ENCLAVES:=@SGX_ENCLAVES@
This should be included as a build target as well, to ensure that all enclaves are built along with the application.
all: enclavetest $(SGX_ENCLAVES)
The variables most likely to be needed by the application’s Makefile are:
ENCLAVE_CLEAN | A list of files that should be removed during 'make clean'. |
ENCLAVE_UOBJS | The untrusted object files $(ENCLAVE)_u.o that are auto-generated by the sgx_edger8r tool. Include these in your application link line and the enclave build dependencies. |
ENCLAVE_UDEPS | The untrusted source and header files that are auto-generated by the sgx_edger8r tool. Include these in your compilation dependencies when building your application. |
Here’s the Makefile for the sample application that is bundled with the templates:
SGX_ENCLAVES:=@SGX_ENCLAVES@ CC=@CC@ CFLAGS=@CFLAGS@ -fno-builtin-memsetqq CPPFLAGS=@CPPFLAGS@ LDFLAGS=@LDFLAGS@ -L$(SGXSDK_LIBDIR) LIBS=@LIBS@ INSTALL=@INSTALL@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ enclave_libdir=@enclave_libdir@ APP_OBJS=main.o %.o: %.c $(CC) -c $(CPPFLAGS) $(CFLAGS) -I$(SGXSDK_INCDIR) $< all: enclavetest $(SGX_ENCLAVES) install: install-program install-enclaves install-program: all $(INSTALL) -d $(bindir) $(INSTALL) -t $(bindir) enclavetest install-enclaves: for dir in $(SGX_ENCLAVES); do \ $(MAKE) -C $$dir install; \ done include sgx_app.mk enclavetest: $(ENCLAVE_UOBJS) $(APP_OBJS) $(CC) -o $@ $(LDFLAGS) $(APP_OBJS) $(ENCLAVE_UOBJS) $(LIBS) -l$(SGX_URTS_LIB) clean: clean_enclaves rm -f enclavetest $(APP_OBJS) $(ENCLAVE_CLEAN) distclean: clean distclean_enclaves rm -rf Makefile config.log config.status config.h autom4te.cache rm -rf sgx_app.mk sgx_enclave.mk
Note that the link line for the application references the sgx_urts library via the Makefile variable $(SGX_URTS_LIB)
. This is to support builds made in simulation mode: The variable will automatically append the _sim suffix to the library names so that the Makefile doesn’t have to define multiple build targets. Always use the variables $(SGX_URTS_LIB)
and $(SGX_UAE_SERVICE_LIB)
in your Makefile instead of the actual library names.
Running the Configure Script
When the configure.ac file is processed by Autoconf, the resulting configure script will have some additional command-line options. These are added by the SGX_INIT
macro:
--enable-sgx-simulation
Build the project in simulation mode. This is for running and testing Intel SGX applications on hardware that does not support Intel SGX instructions.
--with-enclave-libdir-path=path
Specify where enclave libraries should be installed, and set the enclave_libdir
substitution variable in Makefiles. The default is $EPREFIX/lib
.
--with-sgx-build=debug|prerelease|release
Specify whether to build the Intel SGX application in debug, prerelease, or release mode. The default is to build in debug mode.
See the Intel SGX SDK for information on the various build modes. Note that you cannot mix release or prerelease modes with the --enable-sgx-simulation
option.
--with-sgxsdk=path
Specify the Intel SGX SDK installation directory. This overrides the auto-detection procedure.
Summary and Future Work
These templates simplify the process of integrating the GNU build system with Intel SGX projects. They eliminate tedious, redundant coding, relieve the developer of the burden of remembering and entering the numerous libraries and compiler and linker flags needed to build Intel SGX enclaves, and automate the execution of supporting tools such as sgx_edger8r and sgx_sign.
While this automation and integration is valuable, there is still a non-trivial amount of effort required to set up the project environment. Further automation might be possible through the use of GNU Automake, which is designed to generate the Makefile templates that are in turn processed by Autoconf.
The build environment for Intel SGX applications can be complicated. Integration with build systems such as GNU Autoconfig, and potentially Automake, can save the developer considerable time and make their projects less prone to errors.