Skip to content

Commit

Permalink
Added mrbgems/mruby-bin-utils
Browse files Browse the repository at this point in the history
The document was converted from Japanese by https://www.deepl.com/.
  • Loading branch information
dearblue committed Sep 21, 2023
1 parent 39d805e commit 2c54c70
Show file tree
Hide file tree
Showing 6 changed files with 152 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
43 changes: 43 additions & 0 deletions mrbgems/mruby-bin-utils/README.md
@@ -0,0 +1,43 @@
# 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.

```ruby
# in your build configuration file

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

Building with this configuration will generate several executable programs.
To each of those programs, you can add switches depending on the corresponding source code and compiler.

For example, `mruby-cc` takes C source code and generates an executable file.
If the toolchain used to build mruby is "gcc", you can use the gcc switches, and if the toolchain is "visualcpp", you can use the VisualC++ switches.

For mruby built with the gcc toolchain, you can use `mruby-cc` as follows

```console
$ bin/mruby-cc yourcode.c # Compile to generate a.out
$ bin/mruby-cc -o exec yourcode.c # Compile to generate exec
$ bin/mruby-cc -o exec yourcode.c -lzip # Compile and link with libzip to generate exec
```

## Generated programs and corresponding files

| Program name | File type
| ----------------- | --------
| `bin/mruby-cc` | C source file
| `bin/mruby-c++` | C++ source file
| `bin/mruby-as` | Assembly source file
| `bin/mruby-objc` | Objective-C source file
| `bin/mruby-ld` | Object file
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
82 changes: 82 additions & 0 deletions mrbgems/mruby-bin-utils/mrbgem.rake
@@ -0,0 +1,82 @@
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 2c54c70

Please sign in to comment.