 +        "  <{}_H>0x{}</{}_H>".format(attribute_name_upper, attribute[0:16], attribute_name_upper),
 +    ])
 +
-+def _sgx_enclave_configuration(ctx):
++def _sgx_full_enclave_configuration_impl(ctx):
 +    """Implementation of enclave signing configuration file formatting."""
 +    xml_file = ctx.actions.declare_file(ctx.label.name + ".xml")
 +
-+    _validate_kss_attribute(ctx.attr.isvfamilyid, "isvfamilyid", ctx.attr.kss)
-+    _validate_kss_attribute(ctx.attr.isvextprodid, "isvextprodid", ctx.attr.kss)
++    # Let base be None if there is no base.
++    base = ctx.attr.base and ctx.attr.base[SGXEnclaveConfigInfo]
++    config = SGXEnclaveConfigInfo(
++        prodid = ctx.attr.prodid or (base and base.prodid),
++        isvsvn = ctx.attr.isvsvn or (base and base.isvsvn),
++        stack_max_size = ctx.attr.stack_max_size or (base and base.stack_max_size),
++        heap_max_size = ctx.attr.heap_max_size or (base and base.heap_max_size),
++        tcs_num = ctx.attr.tcs_num or (base and base.tcs_num),
++        tcs_policy = ctx.attr.tcs_policy or (base and base.tcs_policy),
++        disable_debug = ctx.attr.disable_debug or (base and base.disable_debug),
++        provision_key = ctx.attr.provision_key or (base and base.provision_key),
++        # False is falsy yet also what we want to use instead of None.
++        kss = ctx.attr.kss if ctx.attr.kss != None else (base and base.kss),
++        # The "" default value is Falsy, so None must be explicitly tested.
++        isvfamilyid = ctx.attr.isvfamilyid if ctx.attr.isvfamilyid != None else (base and base.isvfamilyid),
++        isvextprodid = ctx.attr.isvextprodid if ctx.attr.isvextprodid != None else (base and base.isvextprodid),
++        misc_select = ctx.attr.misc_select or (base and base.misc_select),
++        misc_mask = ctx.attr.misc_mask or (base and base.misc_mask),
++    )
++
++    if config.prodid == None:
++        fail("prodid must be specified")
++    if config.isvsvn == None:
++        fail("isvsvn must be specified")
++    if config.stack_max_size == None:
++        fail("stack_max_size must be specified")
++    if config.heap_max_size == None:
++        fail("heap_max_size must be specified")
++    if config.tcs_num == None:
++        fail("tcs_num must be specified")
++    if config.tcs_policy == None:
++        fail("tcs_poly must be specified")
++    if config.disable_debug == None:
++        fail("disable_debug must be specified")
++    if config.kss == None:
++        fail("kss must be specified")
++    if config.isvfamilyid == None:
++        fail("isvfamilyid must be specified")
++    if config.isvextprodid == None:
++        fail("isvextprodid must be specified")
++    if config.misc_select == None:
++        fail("misc_select must be specified")
++    if config.misc_mask == None:
++        fail("misc_mask must be specified")
++
++    _validate_kss_attribute(config.isvfamilyid, "isvfamilyid", config.kss)
++    _validate_kss_attribute(config.isvextprodid, "isvextprodid", config.kss)
 +
 +    content = "\n".join([
 +        "<EnclaveConfiguration>",
-+        "  <ProdID>%s</ProdID>" % ctx.attr.prodid,
-+        "  <ISVSVN>%s</ISVSVN>" % ctx.attr.isvsvn,
-+        "  <StackMaxSize>%s</StackMaxSize>" % ctx.attr.stack_max_size,
-+        "  <HeapMaxSize>%s</HeapMaxSize>" % ctx.attr.heap_max_size,
-+        "  <TCSNum>%s</TCSNum>" % ctx.attr.tcs_num,
-+        "  <TCSPolicy>%s</TCSPolicy>" % ctx.attr.tcs_policy,
-+        "  <DisableDebug>%s</DisableDebug>" % ctx.attr.disable_debug,
-+        "  <ProvisionKey>%s</ProvisionKey>" % ctx.attr.provision_key,
-+        "  <EnableKSS>%s</EnableKSS>" % ("1" if ctx.attr.kss else "0"),
-+        _kss_attribute_xml_tag(ctx.attr.isvfamilyid, "ISVFAMILYID"),
-+        _kss_attribute_xml_tag(ctx.attr.isvextprodid, "ISVEXTPRODID"),
-+        "  <MiscSelect>%s</MiscSelect>" % ctx.attr.misc_select,
-+        "  <MiscMask>%s</MiscMask>" % ctx.attr.misc_mask,
-+        "</EnclaveConfiguration>\n\n",
++        "  <ProdID>%s</ProdID>" % config.prodid,
++        "  <ISVSVN>%s</ISVSVN>" % config.isvsvn,
++        "  <StackMaxSize>%s</StackMaxSize>" % config.stack_max_size,
++        "  <HeapMaxSize>%s</HeapMaxSize>" % config.heap_max_size,
++        "  <TCSNum>%s</TCSNum>" % config.tcs_num,
++        "  <TCSPolicy>%s</TCSPolicy>" % config.tcs_policy,
++        "  <DisableDebug>%s</DisableDebug>" % config.disable_debug,
++        "  <ProvisionKey>%s</ProvisionKey>" % config.provision_key,
++        "  <EnableKSS>%s</EnableKSS>" % ("1" if config.kss else "0"),
++        _kss_attribute_xml_tag(config.isvfamilyid, "ISVFAMILYID"),
++        _kss_attribute_xml_tag(config.isvextprodid, "ISVEXTPRODID"),
++        "  <MiscSelect>%s</MiscSelect>" % config.misc_select,
++        "  <MiscMask>%s</MiscMask>" % config.misc_mask,
++        "</EnclaveConfiguration>",
 +    ])
 +
 +    # Strip any empty lines created by optional attributes that do not have

+    )
+
+    kwargs = {k: v for k, v in kwargs.items() if k in ["visibility"]}
+    _sgx_debug_sign_enclave(
+        name = name,
+        unsigned = unsigned_name,
+        tags = sgx_tags(),
+        config = config,
+        testonly = testonly,
+        **kwargs
+    )

 bool is_valid_sp(uintptr_t sp);
--- /dev/null
+++ BUILD
@@ -0,0 +1,1336 @@
+# linux-sgx is the Intel SGX SDK
+
+load(
+    ":sgx_sdk.bzl",
+    "sgx_enclave",
+    "sgx_full_enclave_configuration",
+    "sgx_enclave_configuration",
+)
+
