This CMake Config-file package
is provided for use with CMake's
find_package
command.
In a CMake project which is using the Open Enclave SDK, you find the package by
using the following in your CMakeLists.txt
:
find_package(OpenEnclave CONFIG REQUIRED)
This will bring in the Open Enclave targets under the openenclave::
namespace.
The targets relevant to users of the SDK are:
openenclave::oeedger8r
openenclave::oesign
openenclave::oeapkman
(only on Linux)
openenclave::oeenclave
openenclave::oelibc
openenclave::oelibcxx
openenclave::oehost
The remaining targets in openenclave-targets.cmake
are automatically included
when needed by the above.
The package will also search for (and requires) the
Threads
package.
However, the libraries crypto
and dl
will also need to be available on the
system, but due to an outstanding issue, the failure will happen at link-time if
they are unavailable.
The openenclave::oeedger8r
target is an executable that generates trusted and
untrusted C bindings from an Enclave Definition Language file. Example usage is:
# Trusted bindings for the enclave
add_custom_command(OUTPUT example_t.h example_t.c example_args.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example.edl
COMMAND openenclave::oeedger8r --trusted ${CMAKE_CURRENT_SOURCE_DIR}/example.edl)
# Untrusted bindings for the host
add_custom_command(OUTPUT example_u.h example_u.c example_args.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example.edl
COMMAND openenclave::oeedger8r --untrusted ${CMAKE_CURRENT_SOURCE_DIR}/example.edl)
Note that oeedger8r
emits files in the current working directory, which is
${CMAKE_CURRENT_BINARY_DIR}
by default, but this can be changed with the
WORKING_DIRECTORY
argument to
add_custom_command
.
To trigger the generation of the OUTPUT
files, you will need to specify them
as input source files to another target (such as an enclave and a host).
Because both the enclave(s) and host need files generated by oeedger8r
, you
probably want to use two separate commands with just the --trusted
and
--untrusted
flags respectively, even though they can be given simultaneously.
This is because the output of a CMake custom command can only be used as an
input to a CMake target in the same CMakeLists.txt
, and your enclave and host
targets are probably in separate folders. See our samples for a complete build
structure example.
There is a special case where the example_args.h
file is not generated, but it
is exceedingly rare. If the only functions specified in the EDL are of the form
void fn()
(no arguments and a void return type), then no arguments header will
be generated.
Enclave targets in CMake should use add_executable
, link to both
openenclave::oeenclave
and openenclave::oelibc
, and include the trusted EDL
code if oeedger8r
was used. An example is:
add_executable(example_enclave example.c example_t.c)
target_link_libraries(example_enclave openenclave::oeenclave openenclave::oelibc)
Technically, the openenclave::oelibc
dependency is optional. That is, if you
don't use anything from the C library (such as #include <stdio.h>
etc.), you
can exclude it, but this is very unlikely.
If the enclave uses C++ code, it must link to both openenclave::oeenclave
and
openenclave::oelibcxx
:
add_executable(example_cpp_enclave example.cpp example_t.c)
target_link_libraries(example_cpp_enclave openenclave::oeenclave openenclave::oelibcxx)
Because openenclave:oelibccxx
depends on openenclave::oelibc
, you don't have
to specify both. The latter is brought in automatically by the former. However,
openenclave:oeenclave
depends on neither of these libraries, so it must always
be included.
Note that to opt-in to our latest API version, you should also use:
target_compile_definitions(example_enclave OE_API_VERSION=2)
The openenclave::oesign
target is an executable that takes an unsigned
enclave, an enclave configuration file, and a private key, and outputs a signed
enclave. Example usage is:
# NOTE: This is a self-signed certificate only for demonstration.
add_custom_command(OUTPUT private.pem public.pem
COMMAND openssl genrsa -out private.pem -3 3072
COMMAND openssl rsa -in private.pem -pubout -out public.pem)
add_custom_command(OUTPUT example_enclave.signed
DEPENDS example_enclave example.conf private.pem
COMMAND openenclave::oesign sign -e $<TARGET_FILE:example_enclave> -c ${CMAKE_CURRENT_SOURCE_DIR}/example.conf -k private.pem)
Since oesign
is unaware of CMake information, the
CMake Generator Expression
$<TARGET_FILE:example_enclave>
is used. Given that example_enclave
is a
valid CMake target, the generator expression will replace itself with the
absolute path to the output file of that build target.
Note that oesign
emits the signed enclave next to the unsigned enclave, which
typically is in the build directory corresponding to the source directory of the
enclave. The current working directory does not affect it.
Because this is a custom command, you will need to depend on
example_enclave.signed
from a
custom target.
add_custom_target(signed_example_enclave ALL
DEPENDS example_enclave.signed)
This adds a default target to the build (by the use of ALL
) which ensures the
signing takes place. You do not want to use add_custom_target(COMMAND ...)
instead of add_custom_command
because the former would run on every build, but
the latter sets up a dependency where it only signs if the enclave is rebuilt.
Host targets in CMake should use add_executable
, link to
openenclave::oehost
, and include the untrusted EDL code if oeedger8r
was
used. An example is:
add_executable(example_host host.cpp example_u.c)
target_link_libraries(example_host openenclave::oehost)
Finally, you can run the enclave with:
./example_host /path/to/example_enclave.signed
On Linux, Alpine Linux static libraries can be installed for use within enclaves as follows:
oeapkman add sqlite-static sqlite-dev
For a complete walkthrough of using oeapkman
refer to apkman sample.