def compile_model(
    model: _Union["_proto.Model_pb2.Model", str],
    destination_path: _Optional[str] = None,
) -> str:
    """
    Compiles a Core ML model.

    Parameters
    ----------
    model: Model_pb2 | str
        Either a Core ML model specification (protobuf object) or a path to a saved model (.mlmodel or .mlpackage) file.

    destination_path: str
        Path where the compiled model will be saved.

    Returns
    -------

    str : Path to compiled model directory
        If the ``destination_path`` is specified, that is the value that will be returned.

    Examples
    --------
    .. sourcecode:: python

        from coremltools.models import CompiledMLModel
        from coremltools.models.utils import compile_model
        from coremltools.proto import Model_pb2

        spec = Model_pb2.Model()
        spec.specificationVersion = 1

        input_ = spec.description.input.add()
        input_.name = "x"
        input_.type.doubleType.MergeFromString(b"")

        output_ = spec.description.output.add()
        output_.name = "y"
        output_.type.doubleType.MergeFromString(b"")
        spec.description.predictedFeatureName = "y"

        lr = spec.glmRegressor
        lr.offset.append(0.1)
        weights = lr.weights.add()
        weights.value.append(2.0)

        compiled_model_path = compile_model(spec)
        model = CompiledMLModel(compiled_model_path)
        y = model.predict({"x": 2})

    See Also
    --------
    coremltools.models.CompiledMLModel
    """
    def is_valid_model_file(source_path: str) -> bool:
        extension = source_path.rstrip("/")
        return extension.endswith(".mlpackage") or extension.endswith(".mlmodel")

    # Check environment
    if _macos_version() < (10, 13):
        raise Exception("Compiling a Core ML models is only support on macOS 10.13 or higher.")
    try:
        from ..libcoremlpython import _MLModelProxy
    except:
        raise Exception("Unable to compile any Core ML models.")

    source_model_path = None
    # Check model parameter
    if isinstance(model, str):
        if is_valid_model_file(model):
            source_model_path = model
        else:
            raise ValueError(
                f"Invalid model file path: '{model}'."
                "Expected a file with .mlpackage or .model extension. "
            )

    if source_model_path is None:
        if isinstance(model, _ct.models.MLModel):
            raise TypeError(
                'This model has already been compiled. Call "get_compiled_model_path"'
                " to get the compiled model."
            )

        if not isinstance(model, _proto.Model_pb2.Model):
            raise TypeError(
                'Unrecognized input for "model" parameter. It should be a spec or model file path.'
            )

    # Check file extension of destination_path parameter
    if destination_path is not None and not destination_path.rstrip('/').endswith(".mlmodelc"):
        raise Exception("\"destination_path\" parameter must have \".mlmodelc\" file extension.")

    # Compile model
    if source_model_path is None:
        with _tempfile.TemporaryDirectory() as save_dir:
            spec_file_path = save_dir + "/spec.mlmodel"
            save_spec(model, spec_file_path)
            original_compiled_model_path = _MLModelProxy.compileModel(spec_file_path)
    else:
        original_compiled_model_path = _MLModelProxy.compileModel(source_model_path)

    # Move the compiled model if needed
    if destination_path is None:
        return original_compiled_model_path
    _shutil.move(original_compiled_model_path, destination_path)

    return destination_path

    Compiles a Core ML model.

    Parameters
    ----------
    model: Model_pb2 | str
        Either a Core ML model specification (protobuf object) or a path to a saved model (.mlmodel or .mlpackage) file.

    destination_path: str
        Path where the compiled model will be saved.

    Returns
    -------

    str : Path to compiled model directory
        If the ``destination_path`` is specified, that is the value that will be returned.

    Examples
    --------
    .. sourcecode:: python

        from coremltools.models import CompiledMLModel
        from coremltools.models.utils import compile_model
        from coremltools.proto import Model_pb2

        spec = Model_pb2.Model()
        spec.specificationVersion = 1

        input_ = spec.description.input.add()
        input_.name = "x"
        input_.type.doubleType.MergeFromString(b"")

        output_ = spec.description.output.add()
        output_.name = "y"
        output_.type.doubleType.MergeFromString(b"")
        spec.description.predictedFeatureName = "y"

        lr = spec.glmRegressor
        lr.offset.append(0.1)
        weights = lr.weights.add()
        weights.value.append(2.0)

        compiled_model_path = compile_model(spec)
        model = CompiledMLModel(compiled_model_path)
        y = model.predict({"x": 2})

    See Also
    --------
    coremltools.models.CompiledMLModel
    
coremltools/models/utils.py