Skip to content

Commit 15e6e11

Browse files
committed
Add tool checking and support for all compilable languages
1 parent 789eb70 commit 15e6e11

12 files changed

+1253
-6
lines changed

builder_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ func TestBuilderFactory(t *testing.T) {
1616

1717
// Test that all expected builders are registered
1818
builders := factory.ListBuilders()
19-
if len(builders) != 5 {
20-
t.Errorf("Expected 5 builders, got %d", len(builders))
19+
expectedCount := 11 // 5 original + 3 new specific + 3 generic language builders
20+
if len(builders) != expectedCount {
21+
t.Errorf("Expected %d builders, got %d", expectedCount, len(builders))
2122
}
2223

2324
// Test builder detection for each type

cargo_builder.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ func (b *CargoBuilder) Name() string {
2424
return "Cargo"
2525
}
2626

27+
// RequiredTools returns the tools needed for Cargo builds
28+
func (b *CargoBuilder) RequiredTools() []ToolRequirement {
29+
return []ToolRequirement{
30+
{
31+
Name: "cargo",
32+
Purpose: "Rust package manager and build tool",
33+
},
34+
{
35+
Name: "rustc",
36+
Purpose: "Rust compiler",
37+
},
38+
}
39+
}
40+
41+
// CheckTools verifies that Cargo and Rust toolchain are available
42+
func (b *CargoBuilder) CheckTools() error {
43+
return CheckRequiredTools(b.RequiredTools())
44+
}
45+
2746
// CanBuild checks if this builder can handle the extension file
2847
func (b *CargoBuilder) CanBuild(extensionFile string) bool {
2948
return MatchesPattern(extensionFile, `Cargo\.toml$`)

cmake_builder.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,32 @@ func (b *CmakeBuilder) Name() string {
2525
return "CMake"
2626
}
2727

28+
// RequiredTools returns the tools needed for CMake builds
29+
func (b *CmakeBuilder) RequiredTools() []ToolRequirement {
30+
return []ToolRequirement{
31+
{
32+
Name: "cmake",
33+
Purpose: "CMake build system generator",
34+
},
35+
{
36+
Name: "gcc",
37+
Alternatives: []string{"clang", "cl"},
38+
Purpose: "C/C++ compiler",
39+
},
40+
{
41+
Name: "make",
42+
Alternatives: []string{"gmake", "ninja", "nmake"},
43+
Optional: true,
44+
Purpose: "Build backend (CMake auto-detects if not specified)",
45+
},
46+
}
47+
}
48+
49+
// CheckTools verifies that CMake and build tools are available
50+
func (b *CmakeBuilder) CheckTools() error {
51+
return CheckRequiredTools(b.RequiredTools())
52+
}
53+
2854
// CanBuild checks if this builder can handle the extension file
2955
func (b *CmakeBuilder) CanBuild(extensionFile string) bool {
3056
return MatchesPattern(extensionFile, `CMakeLists\.txt$`)

configure_builder.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,32 @@ func (b *ConfigureBuilder) Name() string {
1818
return "Configure"
1919
}
2020

21+
// RequiredTools returns the tools needed for configure-based builds
22+
func (b *ConfigureBuilder) RequiredTools() []ToolRequirement {
23+
return []ToolRequirement{
24+
{
25+
Name: "sh",
26+
Alternatives: []string{"bash", "dash"},
27+
Purpose: "Shell to execute configure script",
28+
},
29+
{
30+
Name: "gcc",
31+
Alternatives: []string{"clang", "cc"},
32+
Purpose: "C/C++ compiler",
33+
},
34+
{
35+
Name: "make",
36+
Alternatives: []string{"gmake"},
37+
Purpose: "Build automation tool",
38+
},
39+
}
40+
}
41+
42+
// CheckTools verifies that shell and make are available
43+
func (b *ConfigureBuilder) CheckTools() error {
44+
return CheckRequiredTools(b.RequiredTools())
45+
}
46+
2147
// CanBuild checks if this builder can handle the extension file
2248
func (b *ConfigureBuilder) CanBuild(extensionFile string) bool {
2349
return MatchesPattern(extensionFile, `configure$`) || MatchesPattern(extensionFile, `configure\.sh$`)

extconf_builder.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,31 @@ func (b *ExtConfBuilder) Name() string {
1818
return "ExtConf"
1919
}
2020

21+
// RequiredTools returns the tools needed for extconf.rb builds
22+
func (b *ExtConfBuilder) RequiredTools() []ToolRequirement {
23+
return []ToolRequirement{
24+
{
25+
Name: "ruby",
26+
Purpose: "Ruby interpreter for extconf.rb",
27+
},
28+
{
29+
Name: "gcc",
30+
Alternatives: []string{"clang", "cc", "cl"},
31+
Purpose: "C/C++ compiler for native extensions",
32+
},
33+
{
34+
Name: "make",
35+
Alternatives: []string{"gmake", "nmake"},
36+
Purpose: "Build automation tool",
37+
},
38+
}
39+
}
40+
41+
// CheckTools verifies that Ruby and C compiler are available
42+
func (b *ExtConfBuilder) CheckTools() error {
43+
return CheckRequiredTools(b.RequiredTools())
44+
}
45+
2146
// CanBuild checks if this builder can handle the extension file
2247
func (b *ExtConfBuilder) CanBuild(extensionFile string) bool {
2348
return MatchesPattern(extensionFile, `extconf\.rb$`)

factory.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,48 @@ type BuilderFactory struct {
4949
// NewBuilderFactory creates a factory with all standard builders registered.
5050
//
5151
// The standard builders are registered in this order:
52-
// 1. ExtConfBuilder - extconf.rb files
53-
// 2. ConfigureBuilder - configure scripts
52+
//
53+
// Traditional Ruby builders:
54+
// 1. ExtConfBuilder - extconf.rb files (C/C++)
55+
// 2. ConfigureBuilder - configure scripts (autotools)
5456
// 3. RakeBuilder - Rakefile and mkrf_conf.rb
55-
// 4. CmakeBuilder - CMakeLists.txt
56-
// 5. CargoBuilder - Cargo.toml
57+
//
58+
// Modern build systems:
59+
// 4. CMakeBuilder - CMakeLists.txt
60+
// 5. CargoBuilder - Cargo.toml (Rust)
61+
// 6. MakefileBuilder - Plain Makefile
62+
// 7. GoBuilder - Go with CGO
63+
// 8. JavaBuilder - Java/JRuby extensions
64+
//
65+
// Modern languages (generic builders):
66+
// 9. CrystalBuilder - Crystal language
67+
//
68+
// 10. ZigBuilder - Zig language
69+
// 11. SwiftBuilder - Swift language
5770
//
5871
// This is the recommended way to create a BuilderFactory for most use cases.
72+
// Builders are checked in registration order, so more specific builders
73+
// should be registered first.
5974
func NewBuilderFactory() *BuilderFactory {
6075
factory := &BuilderFactory{}
6176

6277
// Register all standard builders in priority order
78+
// Traditional Ruby builders first (most common)
6379
factory.Register(&ExtConfBuilder{})
6480
factory.Register(&ConfigureBuilder{})
6581
factory.Register(&RakeBuilder{})
82+
83+
// Modern build systems
6684
factory.Register(&CmakeBuilder{})
6785
factory.Register(&CargoBuilder{})
86+
factory.Register(&MakefileBuilder{})
87+
factory.Register(&GoBuilder{})
88+
factory.Register(&JavaBuilder{})
89+
90+
// Modern languages via generic builders
91+
factory.Register(NewCrystalBuilder())
92+
factory.Register(NewZigBuilder())
93+
factory.Register(NewSwiftBuilder())
6894

6995
return factory
7096
}

0 commit comments

Comments
 (0)