Compare commits

..

3 commits

8 changed files with 628 additions and 44 deletions

View file

@ -1,11 +1,8 @@
module; module;
#include <RmlUi/Core/Context.h>
#include <RmlUi/Core/Input.h>
#include <RmlUi/Core/Types.h>
export module rutile.core.ui.backend.rmlui_input_handler; export module rutile.core.ui.backend.rmlui_input_handler;
import wrappers.rmlui.core;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile

View file

@ -3,15 +3,13 @@
module; module;
#include <RmlUi/Core/Core.h> #include <cassert>
#include <RmlUi/Core/FileInterface.h>
#include <RmlUi/Core/RenderInterface.h>
#include <RmlUi/Core/Types.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
export module rutile.core.ui.backend.rmlui_render_interface; export module rutile.core.ui.backend.rmlui_render_interface;
import std; import std;
import wrappers.rmlui.core;
import wrappers.sdl; import wrappers.sdl;
import wrappers.sdl_image; import wrappers.sdl_image;
@ -152,7 +150,7 @@ export namespace rutile
const Rml::Vector2i source_dimensions const Rml::Vector2i source_dimensions
) override ) override
{ {
RMLUI_ASSERT( assert(
source.data() && source.size() == static_cast<size_t>(source_dimensions.x * source_dimensions.y * 4) source.data() && source.size() == static_cast<size_t>(source_dimensions.x * source_dimensions.y * 4)
); );

View file

@ -3,14 +3,13 @@
module; module;
#include <RmlUi/Core/StringUtilities.h>
#include <RmlUi/Core/SystemInterface.h>
#include <RmlUi/Core/Types.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
export module rutile.core.ui.backend.rmlui_system_interface; export module rutile.core.ui.backend.rmlui_system_interface;
import std;
import utils.memory; import utils.memory;
import wrappers.rmlui.core;
import wrappers.sdl; import wrappers.sdl;
// Shorthand for a unique pointer to an SDL_Cursor // Shorthand for a unique pointer to an SDL_Cursor

View file

@ -1,8 +1,6 @@
module; module;
#include <cassert> #include <cassert>
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
export module rutile.core.ui.ui_server; export module rutile.core.ui.ui_server;
@ -10,6 +8,8 @@ import std;
import rutile.core.ui.backend.rmlui_render_interface; import rutile.core.ui.backend.rmlui_render_interface;
import rutile.core.ui.backend.rmlui_system_interface; import rutile.core.ui.backend.rmlui_system_interface;
import rutile.core.ui.backend.rmlui_input_handler; import rutile.core.ui.backend.rmlui_input_handler;
import wrappers.rmlui.core;
import wrappers.rmlui.debugger;
import wrappers.sdl; import wrappers.sdl;
export namespace rutile export namespace rutile

View file

@ -1,7 +1,6 @@
module; module;
#include <cassert> #include <cassert>
#include <RmlUi/Core/ElementDocument.h>
export module rutile.game.game; export module rutile.game.game;
@ -11,6 +10,7 @@ import rutile.core.drawing.tile_map;
import rutile.core.drawing.tile_set; import rutile.core.drawing.tile_set;
import rutile.core.engine; import rutile.core.engine;
import rutile.core.render_server; import rutile.core.render_server;
import wrappers.rmlui.core;
import wrappers.sdl; import wrappers.sdl;
import wrappers.sdl_image; import wrappers.sdl_image;

View file

@ -0,0 +1,530 @@
module;
#include <RmlUi/Core.h>
export module wrappers.rmlui.core;
export
{
namespace Rml
{
using Rml::Animation;
using Rml::AnimationList;
using Rml::Any;
using Rml::Array;
using Rml::ArrayDefinition;
using Rml::Assert;
using Rml::AttributeNameList;
using Rml::BasePointerDefinition;
using Rml::BaseXMLParser;
using Rml::BlendMode;
using Rml::Box;
using Rml::BoxArea;
using Rml::BoxDirection;
using Rml::BoxEdge;
using Rml::BoxShadow;
using Rml::BoxShadowList;
using Rml::CallbackTexture;
using Rml::CallbackTextureFunction;
using Rml::CallbackTextureInterface;
using Rml::CallbackTextureSource;
using Rml::Character;
using Rml::ClipMaskGeometry;
using Rml::ClipMaskGeometryList;
using Rml::ClipMaskOperation;
using Rml::ColorFormat;
using Rml::ColorStop;
using Rml::ColorStopList;
using Rml::Colour;
using Rml::Colourb;
using Rml::ColourbPremultiplied;
using Rml::Colourf;
using Rml::ColumnMajorMatrix4f;
using Rml::ColumnMajorStorage;
using Rml::CompiledFilter;
using Rml::CompiledFilterHandle;
using Rml::CompiledGeometryHandle;
using Rml::CompiledShader;
using Rml::CompiledShaderHandle;
using Rml::ComputedValues;
using Rml::ContainerBox;
using Rml::Context;
using Rml::ContextInstancer;
using Rml::ContextPtr;
using Rml::ConvolutionFilter;
using Rml::CornerSizes;
using Rml::CreateContext;
using Rml::CreateString;
using Rml::DataAddress;
using Rml::DataAddressEntry;
using Rml::DataController;
using Rml::DataControllerInstancer;
using Rml::DataControllerPtr;
using Rml::DataEventFunc;
using Rml::DataGetFunc;
using Rml::DataModel;
using Rml::DataModelConstructor;
using Rml::DataModelHandle;
using Rml::DataSetFunc;
using Rml::DataTransformFunc;
using Rml::DataTypeGetFunc;
using Rml::DataTypeRegister;
using Rml::DataTypeSetFunc;
using Rml::DataVariable;
using Rml::DataVariableType;
using Rml::DataView;
using Rml::DataViewInstancer;
using Rml::DataViewPtr;
using Rml::Decorator;
using Rml::DecoratorDataHandle;
using Rml::DecoratorDeclaration;
using Rml::DecoratorDeclarationList;
using Rml::DecoratorInstancer;
using Rml::DecoratorInstancerInterface;
using Rml::DecoratorPtrList;
using Rml::DecoratorsPtr;
using Rml::DefaultActionPhase;
using Rml::DefaultStyleSheetParsers;
using Rml::Dictionary;
using Rml::DirtyVariables;
using Rml::DocumentHeader;
using Rml::EdgeSizes;
using Rml::EffectSpecification;
using Rml::Element;
using Rml::ElementAnimation;
using Rml::ElementAnimationList;
using Rml::ElementAttributes;
using Rml::ElementBackgroundBorder;
using Rml::ElementDefinition;
using Rml::ElementDocument;
using Rml::ElementForm;
using Rml::ElementFormControl;
using Rml::ElementFormControlInput;
using Rml::ElementFormControlSelect;
using Rml::ElementFormControlTextArea;
using Rml::ElementInstancer;
using Rml::ElementInstancerElement;
using Rml::ElementInstancerGeneric;
using Rml::ElementInstancerText;
using Rml::ElementList;
using Rml::ElementMeta;
using Rml::ElementProgress;
using Rml::ElementPtr;
using Rml::ElementScroll;
using Rml::ElementStyle;
using Rml::ElementTabSet;
using Rml::ElementText;
using Rml::ElementUtilities;
using Rml::EnableObserverPtr;
using Rml::Event;
using Rml::EventDispatcher;
using Rml::EventId;
using Rml::EventInstancer;
using Rml::EventListener;
using Rml::EventListenerInstancer;
using Rml::EventPhase;
using Rml::EventPtr;
using Rml::EventSpecification;
using Rml::Factory;
using Rml::Family;
using Rml::FamilyBase;
using Rml::FamilyId;
using Rml::FileHandle;
using Rml::FileInterface;
using Rml::Filter;
using Rml::FilterDeclaration;
using Rml::FilterDeclarationList;
using Rml::FilterHandleList;
using Rml::FilterInstancer;
using Rml::FilterOperation;
using Rml::FiltersPtr;
using Rml::FocusFlag;
using Rml::FontEffect;
using Rml::FontEffectInstancer;
using Rml::FontEffectList;
using Rml::FontEffects;
using Rml::FontEffectsHandle;
using Rml::FontEffectsPtr;
using Rml::FontEngineInterface;
using Rml::FontFaceHandle;
using Rml::FontGlyph;
using Rml::FontGlyphMap;
using Rml::FontMetrics;
using Rml::FormatString;
using Rml::FromString;
using Rml::FuncDefinition;
using Rml::Function;
using Rml::Geometry;
using Rml::Get;
using Rml::GetContext;
using Rml::GetFileInterface;
using Rml::GetFontEngineInterface;
using Rml::GetIf;
using Rml::GetNumContexts;
using Rml::GetRenderInterface;
using Rml::GetSystemInterface;
using Rml::GetTextInputHandler;
using Rml::GetTextureSourceList;
using Rml::GetVersion;
using Rml::Hash;
using Rml::Initialise;
using Rml::InlineLevelBox;
using Rml::InputType;
using Rml::IsVoidMemberFunc;
using Rml::KeyframeBlock;
using Rml::Keyframes;
using Rml::KeyframesMap;
using Rml::LayerHandle;
using Rml::LayoutEngine;
using Rml::List;
using Rml::LoadFontFace;
using Rml::Log;
using Rml::MakeLiteralIntVariable;
using Rml::MakeMoveIterator;
using Rml::MakeShared;
using Rml::MakeUnique;
using Rml::Matrix4;
using Rml::Matrix4f;
using Rml::MatrixStorageBase;
using Rml::MediaBlock;
using Rml::MediaBlockList;
using Rml::MediaQueryId;
using Rml::MediaQueryModifier;
using Rml::MemberGetFunc;
using Rml::MemberGetFuncDefinition;
using Rml::MemberGetterFunc;
using Rml::MemberObjectDefinition;
using Rml::MemberScalarGetSetFuncDefinition;
using Rml::MemberSetFunc;
using Rml::MemberSetterFunc;
using Rml::Mesh;
using Rml::MeshUtilities;
using Rml::ModalFlag;
using Rml::NamedDecorator;
using Rml::NamedDecoratorMap;
using Rml::NavigationSearchDirection;
using Rml::NonCopyMoveable;
using Rml::NumericValue;
using Rml::ObserverPtr;
using Rml::OwnedElementList;
using Rml::Pair;
using Rml::ParameterMap;
using Rml::Plugin;
using Rml::PointerDefinition;
using Rml::PointerTraits;
using Rml::PropertiesIterator;
using Rml::PropertiesIteratorView;
using Rml::Property;
using Rml::PropertyDefinition;
using Rml::PropertyDictionary;
using Rml::PropertyId;
using Rml::PropertyIdNameMap;
using Rml::PropertyIdSet;
using Rml::PropertyIdSetIterator;
using Rml::PropertyMap;
using Rml::PropertyParser;
using Rml::PropertySource;
using Rml::PropertySpecification;
using Rml::Queue;
using Rml::Rectangle;
using Rml::Rectanglef;
using Rml::Rectanglei;
using Rml::RegisterEventType;
using Rml::RegisterPlugin;
using Rml::RelativeTarget;
using Rml::Releasable;
using Rml::ReleaseCompiledGeometry;
using Rml::ReleaseFontResources;
using Rml::ReleaseRenderManagers;
using Rml::ReleaseTexture;
using Rml::ReleaseTextures;
using Rml::Releaser;
using Rml::ReleaserBase;
using Rml::RemoveContext;
using Rml::RenderBox;
using Rml::RenderInterface;
using Rml::RenderManager;
using Rml::RenderManagerAccess;
using Rml::RenderState;
using Rml::ReplacedBox;
using Rml::ResolveValue;
using Rml::ResolveValueOr;
using Rml::RowMajorMatrix4f;
using Rml::RowMajorStorage;
using Rml::ScalarDefinition;
using Rml::ScalarFuncDefinition;
using Rml::ScriptInterface;
using Rml::ScriptInterfacePtr;
using Rml::ScriptObject;
using Rml::ScrollAlignment;
using Rml::ScrollBehavior;
using Rml::ScrollController;
using Rml::ScrollIntoViewOptions;
using Rml::ScrollParentage;
using Rml::SetFileInterface;
using Rml::SetFontEngineInterface;
using Rml::SetRenderInterface;
using Rml::SetSystemInterface;
using Rml::SetTextInputHandler;
using Rml::SharedPtr;
using Rml::ShorthandDefinition;
using Rml::ShorthandId;
using Rml::ShorthandIdNameMap;
using Rml::ShorthandType;
using Rml::Shutdown;
using Rml::SmallOrderedMap;
using Rml::SmallOrderedSet;
using Rml::SmallUnorderedMap;
using Rml::SmallUnorderedSet;
using Rml::Span;
using Rml::Sprite;
using Rml::SpriteDefinitionList;
using Rml::SpriteMap;
using Rml::Spritesheet;
using Rml::SpritesheetList;
using Rml::StableMap;
using Rml::StableUnorderedMap;
using Rml::StableVector;
using Rml::StableVectorIndex;
using Rml::Stack;
using Rml::StackingContextChild;
using Rml::Stream;
using Rml::String;
using Rml::StringIteratorU8;
using Rml::StringList;
using Rml::StringView;
using Rml::StructDefinition;
using Rml::StructHandle;
using Rml::StyleSheet;
using Rml::StyleSheetContainer;
using Rml::StyleSheetIndex;
using Rml::StyleSheetNode;
using Rml::StyleSheetParser;
using Rml::StyleSheetSpecification;
using Rml::SystemInterface;
using Rml::TextInputHandler;
using Rml::TextShapingContext;
using Rml::Texture;
using Rml::TextureDatabase;
using Rml::TextureFileIndex;
using Rml::TextureHandle;
using Rml::TextureSource;
using Rml::TexturedMesh;
using Rml::TexturedMeshList;
using Rml::ToString;
using Rml::Touch;
using Rml::TouchId;
using Rml::TouchList;
using Rml::Transform;
using Rml::TransformFuncRegister;
using Rml::TransformPrimitive;
using Rml::TransformPtr;
using Rml::TransformState;
using Rml::Transition;
using Rml::TransitionList;
using Rml::Tween;
using Rml::TypeConverter;
using Rml::URL;
using Rml::UniquePtr;
using Rml::UniqueReleaserPtr;
using Rml::UniqueRenderResource;
using Rml::Unit;
using Rml::Units;
using Rml::UnorderedMap;
using Rml::UnorderedMultimap;
using Rml::UnorderedSet;
using Rml::UnregisterPlugin;
using Rml::VariableDefinition;
using Rml::Variant;
using Rml::VariantList;
using Rml::Vector2;
using Rml::Vector2f;
using Rml::Vector2i;
using Rml::Vector3;
using Rml::Vector3f;
using Rml::Vector3i;
using Rml::Vector4;
using Rml::Vector4f;
using Rml::Vector4i;
using Rml::Vector;
using Rml::Vertex;
using Rml::VoidMemberFunc;
using Rml::WeakPtr;
using Rml::WidgetDropDown;
using Rml::WidgetScroll;
using Rml::WidgetTextInputMultiLine;
using Rml::XMLAttributes;
using Rml::XMLDataType;
using Rml::XMLNodeHandler;
using Rml::XMLParser;
using Rml::byte;
using Rml::is_builtin_data_scalar;
using Rml::voidPtr;
namespace Input
{
using Rml::Input::KeyIdentifier;
using Rml::Input::KeyModifier;
}
namespace Math
{
using Rml::Math::ACos;
using Rml::Math::ASin;
using Rml::Math::ATan2;
using Rml::Math::Absolute;
using Rml::Math::Clamp;
using Rml::Math::Cos;
using Rml::Math::DecomposeFractionalIntegral;
using Rml::Math::DegreesToRadians;
using Rml::Math::Exp;
using Rml::Math::ExpandToPixelGrid;
using Rml::Math::HexToDecimal;
using Rml::Math::IsCloseToZero;
using Rml::Math::Lerp;
using Rml::Math::Log2;
using Rml::Math::Max;
using Rml::Math::Min;
using Rml::Math::NormaliseAngle;
using Rml::Math::RadiansToDegrees;
using Rml::Math::RandomBool;
using Rml::Math::RandomInteger;
using Rml::Math::RandomReal;
using Rml::Math::Round;
using Rml::Math::RoundDown;
using Rml::Math::RoundDownToInteger;
using Rml::Math::RoundToInteger;
using Rml::Math::RoundUp;
using Rml::Math::RoundUpToInteger;
using Rml::Math::RoundedLerp;
using Rml::Math::Sin;
using Rml::Math::SnapToPixelGrid;
using Rml::Math::SquareRoot;
using Rml::Math::Tan;
using Rml::Math::ToPowerOfTwo;
}
namespace StringUtilities
{
using Rml::StringUtilities::BytesUTF8;
using Rml::StringUtilities::ConvertByteOffsetToCharacterOffset;
using Rml::StringUtilities::ConvertCharacterOffsetToByteOffset;
using Rml::StringUtilities::DecodeRml;
using Rml::StringUtilities::EncodeRml;
using Rml::StringUtilities::EndsWith;
using Rml::StringUtilities::ExpandString;
using Rml::StringUtilities::IsWhitespace;
using Rml::StringUtilities::JoinString;
using Rml::StringUtilities::LengthUTF8;
using Rml::StringUtilities::Replace;
using Rml::StringUtilities::SeekBackwardUTF8;
using Rml::StringUtilities::SeekForwardUTF8;
using Rml::StringUtilities::StartsWith;
using Rml::StringUtilities::StringCompareCaseInsensitive;
using Rml::StringUtilities::StripWhitespace;
using Rml::StringUtilities::ToCharacter;
using Rml::StringUtilities::ToLower;
using Rml::StringUtilities::ToUTF8;
using Rml::StringUtilities::ToUpper;
using Rml::StringUtilities::TrimTrailingDotZeros;
}
namespace Style
{
using Rml::Style::AlignContent;
using Rml::Style::AlignItems;
using Rml::Style::AlignSelf;
using Rml::Style::Bottom;
using Rml::Style::BoxSizing;
using Rml::Style::Clear;
using Rml::Style::Clip;
using Rml::Style::CommonValues;
using Rml::Style::ComputedValues;
using Rml::Style::Direction;
using Rml::Style::Display;
using Rml::Style::Drag;
using Rml::Style::FlexBasis;
using Rml::Style::FlexDirection;
using Rml::Style::FlexWrap;
using Rml::Style::Float;
using Rml::Style::Focus;
using Rml::Style::FontKerning;
using Rml::Style::FontStyle;
using Rml::Style::FontWeight;
using Rml::Style::Height;
using Rml::Style::InheritedValues;
using Rml::Style::JustifyContent;
using Rml::Style::Left;
using Rml::Style::LengthPercentage;
using Rml::Style::LengthPercentageAuto;
using Rml::Style::LineHeight;
using Rml::Style::Margin;
using Rml::Style::MaxHeight;
using Rml::Style::MaxWidth;
using Rml::Style::MinHeight;
using Rml::Style::MinWidth;
using Rml::Style::Nav;
using Rml::Style::NumberAuto;
using Rml::Style::OriginX;
using Rml::Style::OriginY;
using Rml::Style::Overflow;
using Rml::Style::OverscrollBehavior;
using Rml::Style::Padding;
using Rml::Style::PerspectiveOrigin;
using Rml::Style::PointerEvents;
using Rml::Style::Position;
using Rml::Style::RareValues;
using Rml::Style::Right;
using Rml::Style::TabIndex;
using Rml::Style::TextAlign;
using Rml::Style::TextDecoration;
using Rml::Style::TextOverflow;
using Rml::Style::TextTransform;
using Rml::Style::Top;
using Rml::Style::TransformOrigin;
using Rml::Style::VerticalAlign;
using Rml::Style::Visibility;
using Rml::Style::WhiteSpace;
using Rml::Style::Width;
using Rml::Style::WordBreak;
using Rml::Style::ZIndex;
}
namespace Transforms
{
using Rml::Transforms::DecomposedMatrix4;
using Rml::Transforms::Matrix2D;
using Rml::Transforms::Matrix3D;
using Rml::Transforms::Perspective;
using Rml::Transforms::ResolvedPrimitive;
using Rml::Transforms::Rotate2D;
using Rml::Transforms::Rotate3D;
using Rml::Transforms::RotateX;
using Rml::Transforms::RotateY;
using Rml::Transforms::RotateZ;
using Rml::Transforms::Scale2D;
using Rml::Transforms::Scale3D;
using Rml::Transforms::ScaleX;
using Rml::Transforms::ScaleY;
using Rml::Transforms::ScaleZ;
using Rml::Transforms::Skew2D;
using Rml::Transforms::SkewX;
using Rml::Transforms::SkewY;
using Rml::Transforms::Translate2D;
using Rml::Transforms::Translate3D;
using Rml::Transforms::TranslateX;
using Rml::Transforms::TranslateY;
using Rml::Transforms::TranslateZ;
using Rml::Transforms::UnresolvedPrimitive;
}
namespace Utilities
{
using Rml::Utilities::HashCombine;
}
}
using ::rmlui_dynamic_cast;
using ::rmlui_static_cast;
using ::rmlui_type_name;
}

View file

@ -0,0 +1,14 @@
module;
#include <RmlUi/Debugger.h>
export module wrappers.rmlui.debugger;
export namespace Rml::Debugger
{
using Rml::Debugger::Initialise;
using Rml::Debugger::IsVisible;
using Rml::Debugger::SetContext;
using Rml::Debugger::SetVisible;
using Rml::Debugger::Shutdown;
}

View file

@ -10,7 +10,6 @@
############################################ ############################################
import argparse import argparse
import copy
import json import json
import shlex import shlex
import subprocess import subprocess
@ -18,7 +17,7 @@ import sys
from collections import namedtuple from collections import namedtuple
from dataclasses import asdict, dataclass, field from dataclasses import asdict, dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any, Self
import yaml import yaml
@ -60,6 +59,38 @@ class TargetConfig:
return f"{self.linker_args or ''} {self.linker_args_extra or ''}".strip() return f"{self.linker_args or ''} {self.linker_args_extra or ''}".strip()
@dataclass(kw_only=True)
class MergedTargetConfig(TargetConfig):
cpp_compiler: str = ''
cpp_standard: str = ''
cpp_flags: str = ''
cpp_flags_extra: str = ''
linker_flags: str = ''
linker_flags_extra: str = ''
linker_args: str = ''
linker_args_extra: str = ''
output_file: str = ''
run_command: str = ''
@classmethod
def create_from(cls, target_defaults: TargetConfig, target_config: TargetConfig) -> Self:
merged_config = cls()
merged_config.update(asdict(target_defaults))
merged_config.update(asdict(target_config))
return merged_config
def validate(self) -> None:
# Validate that all required fields are set
if not self.cpp_compiler:
raise ConfigValidationException('cpp_compiler must be set')
if not self.cpp_standard:
raise ConfigValidationException('cpp_standard must be set')
if not self.output_file:
raise ConfigValidationException('output_file must be set')
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ShurikenConfig: class ShurikenConfig:
__path_fields = ['source_dir', 'build_dir'] __path_fields = ['source_dir', 'build_dir']
@ -72,9 +103,6 @@ class ShurikenConfig:
defaults: TargetConfig = field(default_factory=lambda: TargetConfig( defaults: TargetConfig = field(default_factory=lambda: TargetConfig(
cpp_compiler='clang++', cpp_compiler='clang++',
cpp_standard='c++20', cpp_standard='c++20',
cpp_flags='',
linker_flags='',
linker_args='',
)) ))
enable_import_std: bool = False enable_import_std: bool = False
@ -82,6 +110,9 @@ class ShurikenConfig:
default_target: str = '' default_target: str = ''
targets: dict[str, TargetConfig] = field(default_factory=dict) targets: dict[str, TargetConfig] = field(default_factory=dict)
# Merged target configs, generated from defaults and targets
_merged_target_configs = {}
def update(self, data: dict) -> None: def update(self, data: dict) -> None:
for key, value in data.items(): for key, value in data.items():
# Ignore unknown config keys # Ignore unknown config keys
@ -116,6 +147,10 @@ class ShurikenConfig:
else: else:
setattr(self, key, str(value)) setattr(self, key, str(value))
# Generate merged target configs (we generate all of them so that we can validate the full config)
for target_name, target_config in self.targets.items():
self._merged_target_configs[target_name] = MergedTargetConfig.create_from(self.defaults, target_config)
def update_from_yaml(self, file_path: Path) -> None: def update_from_yaml(self, file_path: Path) -> None:
with file_path.open('r') as file: with file_path.open('r') as file:
self.update(yaml.safe_load(file)) self.update(yaml.safe_load(file))
@ -137,23 +172,18 @@ class ShurikenConfig:
raise ConfigValidationException('default_target is not defined in targets') raise ConfigValidationException('default_target is not defined in targets')
# Validate individual build targets # Validate individual build targets
for target_name, target_config in self.targets.items(): for target_name, merged_target_config in self._merged_target_configs.items():
if not target_config.cpp_compiler and not self.defaults.cpp_compiler: try:
raise ConfigValidationException(f'Target "{target_name}": cpp_compiler must be set') merged_target_config.validate()
if not target_config.cpp_standard and not self.defaults.cpp_standard: except ConfigValidationException as exc:
raise ConfigValidationException(f'Target "{target_name}": cpp_standard must be set') raise ConfigValidationException(f'Target "{target_name}": {str(exc)}')
if not target_config.output_file and not self.defaults.output_file:
raise ConfigValidationException(f'Target "{target_name}": output_file must be set')
def get_ninja_file_path(self, target: str) -> Path: def get_ninja_file_path(self, target: str) -> Path:
return self.build_dir / f'build.{target}.ninja' return self.build_dir / f'build.{target}.ninja'
def get_merged_target_config(self, target: str) -> TargetConfig: def get_merged_target_config(self, target: str) -> MergedTargetConfig:
assert target in self.targets, f'Target "{target}" not defined!' assert target in self.targets, f'Target "{target}" not defined!'
return self._merged_target_configs[target]
merged_config = copy.deepcopy(self.defaults)
merged_config.update(asdict(self.targets[target]))
return merged_config
class ShurikenArgumentParser: class ShurikenArgumentParser:
@ -570,7 +600,25 @@ class NinjaFileGenerator:
config = self.config config = self.config
target = self.target target = self.target
target_config = self.target_config target_config = self.target_config
build_dir = self.config.build_dir build_dir = config.build_dir
ninja_file_path = config.get_ninja_file_path(config.default_target)
cpp_compiler = target_config.cpp_compiler
# Generate list of all source input files to be used as implicit dependencies for the dyndep file
dyndep_file_implicit_inputs = ' '.join(sorted(
t.src for t in self.compile_targets_cpp + self.compile_targets_cppm
))
# Generate list of all .dep files that are generated implicitly during dyndep file generation.
# This is mostly necessary so that Ninja can create the directories for these files beforehand.
dyndep_file_implicit_outputs = ' '.join(sorted(
f'{t.obj}.dep' for t in self.compile_targets_cpp + self.compile_targets_cppm
))
# Generate list of generated source files (currently just the copied std module file)
generated_source_files = ' '.join(sorted(
t.generated_src for t in self.compile_targets_std_module
))
# Generate Ninja file # Generate Ninja file
return f""" return f"""
@ -596,19 +644,21 @@ rule copy
# Rule to compile a .cpp file to a .o file # Rule to compile a .cpp file to a .o file
rule cpp rule cpp
command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out depfile = $out.dep
command = {cpp_compiler} $cpp_flags -MMD -MF $out.dep -c $in -o $out
# Rule to compile a .cppm file (C++20 module) to a .o file ($out) and a .pcm file ($pcm_out) # Rule to compile a .cppm file (C++20 module) to a .o file ($out) and a .pcm file ($pcm_out)
rule cppm rule cppm
command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out -fmodule-output=$pcm_out depfile = $out.dep
command = {cpp_compiler} $cpp_flags -MMD -MF $out.dep -c $in -o $out -fmodule-output=$pcm_out
# Rule to compile a standard library module to a .pcm file (e.g. "import std") # Rule to compile a standard library module to a .pcm file (e.g. "import std")
rule std_module rule std_module
command = {target_config.cpp_compiler} $cpp_std_module_flags --precompile $in -o $out command = {cpp_compiler} $cpp_std_module_flags --precompile $in -o $out
# Rule to link several .o files to an executable # Rule to link several .o files to an executable
rule link rule link
command = {target_config.cpp_compiler} $linker_flags -o $out $in $linker_args command = {cpp_compiler} $linker_flags -o $out $in $linker_args
# Rule to generate a compilation database (JSON file) from the build targets defined in a Ninja file # Rule to generate a compilation database (JSON file) from the build targets defined in a Ninja file
rule generate_compdb rule generate_compdb
@ -622,13 +672,13 @@ rule generate_dyndeps
# -- STATIC BUILD TARGETS # -- STATIC BUILD TARGETS
# Generate compilation database from default target Ninja file # Generate compilation database from default target Ninja file
build $compdb_file: generate_compdb {self.config.get_ninja_file_path(config.default_target)} | generate_source_files build $compdb_file: generate_compdb {ninja_file_path} | generate_source_files
# Shortcut alias to generate compilation database # Shortcut alias to generate compilation database
build compdb: phony $compdb_file build compdb: phony $compdb_file
# Generate Ninja dyndep file from compilation database # Generate Ninja dyndep file from compilation database
build $dyndep_file: generate_dyndeps $compdb_file build $dyndep_file | {dyndep_file_implicit_outputs}: generate_dyndeps $compdb_file | {dyndep_file_implicit_inputs}
# -- GENERATED BUILD TARGETS # -- GENERATED BUILD TARGETS
@ -638,17 +688,13 @@ build $builddir/{target_config.output_file}: link {' '.join(self.link_target_obj
default $builddir/{target_config.output_file} default $builddir/{target_config.output_file}
# Phony target that depends on all generated source files # Phony target that depends on all generated source files
build generate_source_files: phony {self.list_generated_source_files()} build generate_source_files: phony {generated_source_files}
{self.render_compile_targets()} {self.render_compile_targets()}
# End of build.{target}.ninja # End of build.{target}.ninja
""".strip() """.strip()
def list_generated_source_files(self) -> str:
generated_files = [target.generated_src for target in self.compile_targets_std_module]
return ' '.join(generated_files)
def render_compile_targets(self) -> str: def render_compile_targets(self) -> str:
rendered_targets = list(map(self.render_compile_target_std_module, self.compile_targets_std_module)) rendered_targets = list(map(self.render_compile_target_std_module, self.compile_targets_std_module))
rendered_targets += list(map(self.render_compile_target_cpp, self.compile_targets_cpp)) rendered_targets += list(map(self.render_compile_target_cpp, self.compile_targets_cpp))