rbxx 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +72 -0
- data/exe/rbxx +6 -0
- data/ext-cmake/FindRuby.cmake +42 -0
- data/ext-cmake/rbxx-config.cmake +25 -0
- data/include/rbxx/arg.hpp +347 -0
- data/include/rbxx/callback.hpp +54 -0
- data/include/rbxx/class.hpp +630 -0
- data/include/rbxx/data_object.hpp +221 -0
- data/include/rbxx/detail/ruby_include.hpp +36 -0
- data/include/rbxx/exception.hpp +116 -0
- data/include/rbxx/extension.hpp +23 -0
- data/include/rbxx/function.hpp +463 -0
- data/include/rbxx/module.hpp +69 -0
- data/include/rbxx/nogvl.hpp +146 -0
- data/include/rbxx/object.hpp +68 -0
- data/include/rbxx/operators.hpp +31 -0
- data/include/rbxx/policies.hpp +36 -0
- data/include/rbxx/protect.hpp +72 -0
- data/include/rbxx/rbxx.hpp +20 -0
- data/include/rbxx/registry.hpp +145 -0
- data/include/rbxx/stl/array.hpp +40 -0
- data/include/rbxx/stl/chrono.hpp +26 -0
- data/include/rbxx/stl/detail.hpp +60 -0
- data/include/rbxx/stl/filesystem.hpp +21 -0
- data/include/rbxx/stl/map.hpp +49 -0
- data/include/rbxx/stl/optional.hpp +23 -0
- data/include/rbxx/stl/set.hpp +30 -0
- data/include/rbxx/stl/tuple.hpp +74 -0
- data/include/rbxx/stl/variant.hpp +35 -0
- data/include/rbxx/stl/vector.hpp +34 -0
- data/include/rbxx/stl.hpp +11 -0
- data/include/rbxx/type_caster.hpp +247 -0
- data/include/rbxx/value.hpp +63 -0
- data/include/rbxx/version.hpp +14 -0
- data/lib/rbxx/cli.rb +127 -0
- data/lib/rbxx/mkmf.rb +144 -0
- data/lib/rbxx/rake_tasks.rb +44 -0
- data/lib/rbxx/version.rb +5 -0
- data/lib/rbxx.rb +8 -0
- data/single_include/rbxx/rbxx.hpp +3211 -0
- data/templates/CMakeLists.txt.erb +14 -0
- data/templates/Gemfile.erb +10 -0
- data/templates/README.md.erb +11 -0
- data/templates/Rakefile.erb +23 -0
- data/templates/ci.yml.erb +21 -0
- data/templates/extconf.rb.erb +5 -0
- data/templates/extconf_cmake.rb.erb +5 -0
- data/templates/extension.cpp.erb +23 -0
- data/templates/gemspec.erb +16 -0
- data/templates/lib.rb.erb +4 -0
- data/templates/release.yml.erb +21 -0
- data/templates/test.rb.erb +12 -0
- data/templates/version.rb.erb +5 -0
- metadata +99 -0
data/lib/rbxx/mkmf.rb
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
require "rbconfig"
|
|
5
|
+
require "shellwords"
|
|
6
|
+
|
|
7
|
+
module Rbxx
|
|
8
|
+
# Shared mkmf and CMake configuration for extensions built with rbxx.
|
|
9
|
+
module Mkmf
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def include_dir
|
|
13
|
+
File.expand_path("../../include", __dir__)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def cmake_config_dir
|
|
17
|
+
File.expand_path("../../ext-cmake", __dir__)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_makefile(target, include_path: include_dir, debug: debug?, sanitize: sanitize?)
|
|
21
|
+
configure_cpp_flags(include_path, debug:, sanitize:)
|
|
22
|
+
super_create_makefile(target)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create_cmake_makefile(target, source_dir: __dir__, build_dir: "cmake-build")
|
|
26
|
+
target_name = File.basename(target)
|
|
27
|
+
configure, build = cmake_commands(source_dir, build_dir)
|
|
28
|
+
extension = "#{target_name}.#{RbConfig::CONFIG.fetch('DLEXT')}"
|
|
29
|
+
windows = RUBY_PLATFORM.include?("mingw")
|
|
30
|
+
makefile = cmake_makefile(configure, build, build_dir, extension, windows:)
|
|
31
|
+
File.write("Makefile", makefile)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def cmake_commands(source_dir, build_dir, cxx: RbConfig::CONFIG.fetch("CXX"),
|
|
35
|
+
platform: RUBY_PLATFORM)
|
|
36
|
+
compiler, *compiler_flags = Shellwords.split(cxx)
|
|
37
|
+
raise ArgumentError, "rbxx: Ruby C++ compiler is not configured" unless compiler
|
|
38
|
+
|
|
39
|
+
configure = ["cmake", "-S", File.expand_path(source_dir), "-B", build_dir,
|
|
40
|
+
"-Drbxx_DIR=#{cmake_config_dir}", "-DRuby_EXECUTABLE=#{RbConfig.ruby}",
|
|
41
|
+
"-DCMAKE_CXX_COMPILER=#{compiler}"]
|
|
42
|
+
configure << "-DCMAKE_CXX_FLAGS_INIT=#{compiler_flags.join(' ')}" unless compiler_flags.empty?
|
|
43
|
+
build = ["cmake", "--build", build_dir, "--config", "Release"]
|
|
44
|
+
|
|
45
|
+
configure.push("-G", "MinGW Makefiles") if platform.include?("mingw")
|
|
46
|
+
|
|
47
|
+
[configure, build]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def cmake_makefile(configure, build, build_dir, extension, windows: false)
|
|
51
|
+
built_extension = File.join(build_dir, extension)
|
|
52
|
+
install_copy = if windows
|
|
53
|
+
shell_join(["cmake", "-E", "copy", extension,
|
|
54
|
+
"$(sitearchdir)/#{extension}"], windows: true)
|
|
55
|
+
else
|
|
56
|
+
"cmake -E copy #{Shellwords.escape(extension)} $(sitearchdir)/#{extension}"
|
|
57
|
+
end
|
|
58
|
+
lines = [
|
|
59
|
+
".PHONY: all clean install", "", "all:", "\t#{shell_join(configure, windows:)}",
|
|
60
|
+
"\t#{shell_join(build, windows:)}",
|
|
61
|
+
"\t#{shell_join(['cmake', '-E', 'copy', built_extension, extension], windows:)}", "",
|
|
62
|
+
"install: all", "\tcmake -E make_directory $(sitearchdir)",
|
|
63
|
+
"\t#{install_copy}", "", "clean:",
|
|
64
|
+
"\t#{shell_join(['cmake', '-E', 'remove_directory', build_dir], windows:)}",
|
|
65
|
+
"\t#{shell_join(['cmake', '-E', 'rm', '-f', extension], windows:)}", ""
|
|
66
|
+
]
|
|
67
|
+
lines.unshift("unexport MAKE", "") if windows
|
|
68
|
+
lines.join("\n")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def shell_join(arguments, windows: false)
|
|
72
|
+
return Shellwords.join(arguments) unless windows
|
|
73
|
+
|
|
74
|
+
arguments.map { |argument| windows_shell_escape(argument) }.join(" ")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def windows_shell_escape(argument)
|
|
78
|
+
value = argument.to_s
|
|
79
|
+
return value if value.match?(%r{\A[A-Za-z0-9_+.,:/\\=@-]+\z})
|
|
80
|
+
|
|
81
|
+
escaped = value.gsub(/(\\*)"/) { "#{Regexp.last_match(1) * 2}\\\"" }
|
|
82
|
+
%("#{escaped.sub(/(\\+)\z/) { |slashes| slashes * 2 }}")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def debug?
|
|
86
|
+
ENV["RBXX_DEBUG"] == "1"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def sanitize?
|
|
90
|
+
ENV["RBXX_SANITIZE"] == "1"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def configure_cpp_flags(include_path, debug:, sanitize:)
|
|
94
|
+
compiler_flags(include_path, debug:, sanitize:).each do |name, flags|
|
|
95
|
+
append_global(name, flags)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def compiler_flags(include_path, debug:, sanitize:, compiler: msvc? ? :msvc : :gnu)
|
|
100
|
+
return msvc_flags(include_path, debug:) if compiler == :msvc
|
|
101
|
+
|
|
102
|
+
cppflags = " -I#{Shellwords.escape(include_path)}"
|
|
103
|
+
cppflags += " -DRBXX_DEBUG=1" if debug
|
|
104
|
+
optimization = debug ? "-O0 -g" : RbConfig::CONFIG.fetch("optflags", "-O2")
|
|
105
|
+
cxxflags = " #{optimization} -std=c++20 -Wall -Wextra -fvisibility=hidden"
|
|
106
|
+
cxxflags += " -fsanitize=address,undefined -fno-omit-frame-pointer" if sanitize
|
|
107
|
+
ldflags = sanitize ? " -fsanitize=address,undefined" : ""
|
|
108
|
+
{ cppflags:, cxxflags:, ldflags: }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def msvc_flags(include_path, debug:)
|
|
112
|
+
cppflags = %( /I"#{include_path}")
|
|
113
|
+
cppflags += " /DRBXX_DEBUG=1" if debug
|
|
114
|
+
optimization = debug ? "/Od /Zi" : "/O2"
|
|
115
|
+
{ cppflags:, cxxflags: " #{optimization} /std:c++20 /EHsc /utf-8 /W4", ldflags: "" }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# mkmf exposes compiler configuration exclusively through these globals.
|
|
119
|
+
# rubocop:disable Style/GlobalVars
|
|
120
|
+
def append_global(name, suffix)
|
|
121
|
+
$CPPFLAGS = $CPPFLAGS.to_s + suffix if name == :cppflags
|
|
122
|
+
$CXXFLAGS = $CXXFLAGS.to_s + suffix if name == :cxxflags
|
|
123
|
+
$LDFLAGS = $LDFLAGS.to_s + suffix if name == :ldflags
|
|
124
|
+
end
|
|
125
|
+
# rubocop:enable Style/GlobalVars
|
|
126
|
+
|
|
127
|
+
def msvc?
|
|
128
|
+
compiler = File.basename(RbConfig::CONFIG.fetch("CC", "").split.first.to_s)
|
|
129
|
+
compiler.match?(/\Acl(?:\.exe)?\z/i) || RUBY_PLATFORM.include?("mswin")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def super_create_makefile(target)
|
|
133
|
+
TOPLEVEL_BINDING.receiver.send(:create_makefile, target)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def create_rbxx_makefile(target, **options)
|
|
139
|
+
Rbxx::Mkmf.create_makefile(target, **options)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def create_rbxx_cmake_makefile(target, **options)
|
|
143
|
+
Rbxx::Mkmf.create_cmake_makefile(target, **options)
|
|
144
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake"
|
|
4
|
+
|
|
5
|
+
module Rbxx
|
|
6
|
+
# Reusable rake-compiler-dock tasks for the supported native gem platforms.
|
|
7
|
+
module RakeTasks
|
|
8
|
+
extend Rake::DSL
|
|
9
|
+
|
|
10
|
+
PLATFORMS = %w[
|
|
11
|
+
x86_64-linux
|
|
12
|
+
aarch64-linux
|
|
13
|
+
x86_64-darwin
|
|
14
|
+
arm64-darwin
|
|
15
|
+
x64-mingw-ucrt
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
module_function
|
|
19
|
+
|
|
20
|
+
def install(namespace: :precompiled, command: "bundle install && rake native:%<platform>s gem")
|
|
21
|
+
namespace(namespace) do
|
|
22
|
+
desc "Print precompiled gem build commands without starting containers"
|
|
23
|
+
task :dry_run do
|
|
24
|
+
PLATFORMS.each { |platform| puts build_description(platform, command) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
PLATFORMS.each do |platform|
|
|
28
|
+
desc "Build the #{platform} native gem with rake-compiler-dock"
|
|
29
|
+
task platform do
|
|
30
|
+
require "rake_compiler_dock"
|
|
31
|
+
RakeCompilerDock.sh(format(command, platform:), platform:)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "Build native gems for all supported platforms"
|
|
36
|
+
task all: PLATFORMS
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def build_description(platform, command)
|
|
41
|
+
"RCD_PLATFORM=#{platform} #{format(command, platform:)}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/rbxx/version.rb
ADDED