Adding Runtime Features

How to add a new class or feature to sharp-runtime following project conventions.

Before You Start

Step 1: Choose the Owning Module

Choose an existing physical module before creating files. The module owns the feature's public headers, implementation, tests, and dependency declaration. For example, a new fundamental System type normally belongs in modules/core/; an I/O type belongs in modules/io/.

If no existing module owns the API area, add a new module directory, register it once in cmake/SharpRuntimeModules.cmake, and declare its dependencies in its local CMakeLists.txt. Do not add new shared top-level include/, src/, or tests/ trees.

Step 2: Create the Header

For a core type, create modules/core/include/System/[Namespace]/ClassName.hpp:

// SPDX-License-Identifier: MIT
// Copyright (C) 2024 Robert Vokac
// Based on .NET Runtime (MIT License)
#pragma once
#include <System/Object.hpp>
#include <SharpRuntime/Prop.hpp>

namespace System {
// Or: namespace System::IO etc.

/**
 * @brief One-line description.
 * @status Partial
 */
class MyClass : public Object {
public:
    MyClass();
    DDATA(int, SomeProperty)
    void SomeMethod(const std::string& arg);
    GetTypeNameHPP();
};

} // namespace System

Step 3: Create the Implementation

Create modules/core/src/System/[Namespace]/MyClass.cpp in the same owning module:

// SPDX-License-Identifier: MIT
// Copyright (C) 2024 Robert Vokac
// Based on .NET Runtime (MIT License)
#include <System/MyClass.hpp>

namespace System {

GetTypeNameCPP(MyClass, "System.MyClass")
IDATA(MyClass, int, SomeProperty)

MyClass::MyClass() : someProperty_(0) {}

void MyClass::SomeMethod(const std::string& arg) {
    // implementation
}

} // namespace System
Module-scoped discovery
sharp_runtime_register_module() discovers src/*.cpp and tests/*.cpp only inside the owning module. You do not need to edit its CMakeLists.txt for another file in that module, but you must declare dependencies correctly and register a genuinely new module.

Step 4: Write Tests

Create modules/core/tests/System/MyClassTest.cpp (or the matching test path in the owning module):

// SPDX-License-Identifier: MIT
#include <gtest/gtest.h>
#include <System/MyClass.hpp>

using namespace System;

TEST(MyClassTest, ConstructorDefault) {
    MyClass obj;
    EXPECT_EQ(obj.getSomePropertyProperty(), 0);
}

TEST(MyClassTest, SomeMethod) {
    MyClass obj;
    obj.SomeMethod("test");
    // assert expected state
}

TEST(MyClassTest, GetTypeName) {
    MyClass obj;
    EXPECT_EQ(obj.GetTypeName(), "System.MyClass");
}
Test requirement
Your new class must have focused tests. Build its component test target and run its executable; for a repository-wide change, configure All and use scripts/run_component_tests.sh build.

Step 5: Platform Guards (if needed)

If your implementation uses platform-specific APIs:

Step 6: Update Status

Update the @status Doxygen comment in the header file as the implementation progresses:

Checklist