Skip to content

Commit

Permalink
Added mrbgems/mruby-bin-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
dearblue committed Sep 18, 2023
1 parent 39d805e commit e8d5b7a
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 0 deletions.
3 changes: 3 additions & 0 deletions mrbgems/default.gembox
Expand Up @@ -22,4 +22,7 @@ MRuby::GemBox.new do |conf|

# Generate mruby-config command
conf.gem :core => "mruby-bin-config"

# Generate mruby-cc and other commands
conf.gem :core => "mruby-bin-utils"
end
29 changes: 29 additions & 0 deletions mrbgems/mruby-bin-utils/README.md
@@ -0,0 +1,29 @@
# mruby-bin-utils

This is a command line program that serves as a wrapper to compile and link source code requiring libmruby.

The name is a play on GNU Binutils.

## How to build and use it

Add this mruby-bin-utils to your build configuration file and build mruby.

```ruby
# in your build configuration file

MRuby::Build.new do |conf|
...
conf.gem core: "mruby-bin-utils"
...
end
```

Then compile and link your code in the generated command line program.

```console
$ bin/mruby-cc yourcode.c
$ bin/mruby-c++ yourcode.cxx
$ bin/mruby-as yourcode.s
$ bin/mruby-objc yourcode.m
$ bin/mruby-ld ...
```
14 changes: 14 additions & 0 deletions mrbgems/mruby-bin-utils/bintest/test.rb
@@ -0,0 +1,14 @@
require "pathname"

cc_command = File.join(ENV["BUILD_DIR"], "bin/mruby-cc")
testdata = Pathname(__dir__).parent + "testdata"

assert "C compile" do
system *%W(#{cc_command} #{testdata + "test1.c"})
assert_true $?.success?
end

assert "C compile (failing)" do
system *%W(#{cc_command} #{testdata + "test2.c"}), err: File::NULL
assert_false $?.success?
end
84 changes: 84 additions & 0 deletions mrbgems/mruby-bin-utils/mrbgem.rake
@@ -0,0 +1,84 @@
#!ruby

MRuby::Gem::Specification.new("mruby-bin-utils") do |spec|
spec.summary = "one-shot mruby C/C++ compiler and utilities"
spec.license = "MIT"
spec.author = "mruby developers"
spec.add_dependency "mruby-bin-config", core: "mruby-bin-config"

if ENV["OS"] =~ /windows/i
msvc = build.toolchains.find { |e| e == "visualcpp" } ? true : false
binext = ".bat"
bingen = ->(bin, cflags, ldflags) {
(cflags, ldflags) = [cflags, ldflags].map { |flags|
flags.map { |f|
varname = %(mrbc_#{f.sub(/^--/, "").gsub(/[^\w]+/, "_")})
extractor = %(for /f "usebackq delims=" %%i in (`%mrbconfig% #{f}`) do set #{varname}=%%i)
["%#{varname}%", extractor]
}
}

withlink = "/link " if msvc && bin != "mruby-ld"

<<~CODE
@echo off
if "%1" == "" (
\techo %~n0: no files given 1>&2
\texit /b 1
)
set mrbconfig="%~dp0.\\mruby-config.bat"
#{cflags.map { |v, e| e }.join("\n")}
#{ldflags.map { |v, e| e }.join("\n")}
call #{cflags.map { |v, e| v }.join(" ")} %* #{withlink}#{ldflags.map { |v, e| v }.join(" ")}
CODE
}
else
binext = ""
bingen = ->(bin, cflags, ldflags) {
<<~CODE
#!/bin/sh
if [ "$#" -lt 1 ]
then
\techo "$(basename "$0"): no files given" 1>&2
\texit 1
fi
mrbconfig="$(dirname "$0")/mruby-config"
$("$mrbconfig" #{cflags.join(" ")}) "$@" $("$mrbconfig" #{ldflags.join(" ")})
CODE
}
end

if spec.build.kind_of?(MRuby::CrossBuild)
destdir = "#{build.build_dir}/host-bin"
addbin = ->(dest) { build.products << dest }
else
destdir = "#{build.build_dir}/bin"
addbin = ->(dest) { build.bins << File.basename(dest) }
end

[
["mruby-cc", %w(--cc --cflags), %w(--ldflags --ldflags-before-libs --libs)],
["mruby-c++", %w(--cxx --cxxflags), %w(--ldflags --ldflags-before-libs --libs)],
["mruby-as", %w(--as --asflags), %w(--ldflags --ldflags-before-libs --libs)],
["mruby-objc", %w(--objc --objcflags), %w(--ldflags --ldflags-before-libs --libs)],
["mruby-ld", %w(--ld), %w(--ldflags --ldflags-before-libs --libs)],
].each do |bin, cflags, ldflags|
destpath = File.join(destdir, "#{bin}#{binext}")

addbin.call(destpath)

file destpath => __FILE__ do |t|
_pp "GEN", destpath.relative_path
mkdir_p destdir

# NOTE: No line break code is specified, so text appropriate to the environment is output
File.write(destpath, bingen.call(bin, cflags, ldflags), perm: 0755)
end
end
end
9 changes: 9 additions & 0 deletions mrbgems/mruby-bin-utils/testdata/test1.c
@@ -0,0 +1,9 @@
#include <mruby.h>

int
main(int argc, char **argv)
{
mrb_state *mrb = mrb_open();
mrb_close(mrb);
return 0;
}
1 change: 1 addition & 0 deletions mrbgems/mruby-bin-utils/testdata/test2.c
@@ -0,0 +1 @@
#error "INTENTIONAL ERROR FOR FAILING!"

0 comments on commit e8d5b7a

Please sign in to comment.