Class: Rubycc::Rmake::CLI
- Inherits:
-
Object
- Object
- Rubycc::Rmake::CLI
- Defined in:
- lib/rubycc/rmake/cli.rb
Overview
The command-line front end to rmake (M3 / ROADMAP ยง6 B6). It exists so
RubyGems can drive rubycc's builds by setting ENV["MAKE"] to this program:
Gem::Ext::Builder invokes $(MAKE) as three separate processes shaped like
rmake DESTDIR= sitearchdir=<tmp> sitelibdir=<tmp> clean
rmake DESTDIR= sitearchdir=<tmp> sitelibdir=<tmp> (default goal)
rmake DESTDIR= sitearchdir=<tmp> sitelibdir=<tmp> install
so the argument grammar it must accept is: command-line variable definitions
(VAR=value, which override the Makefile's own assignments), zero or more
target names (an absent target builds the default goal) and, though RubyGems
does not pass them, the -j/-f options make users expect. Because rmake is
rubycc's build-only make, tool substitution ($(CC)/$(LDSHARED) routed to
rubycc's Driver) is always on โ a CC = gcc left in the Makefile is still
built by rubycc.
It is a plain method object rather than an OptionParser front end: the mkmf invocation shape is fixed and narrow, so hand-parsing keeps the accepted grammar explicit (and the "everything routes to rubycc" contract obvious).
Constant Summary collapse
- DEFAULT_MAKEFILE =
"Makefile"
Class Method Summary collapse
-
.run(argv, dir: Dir.pwd, out: $stdout, err: $stderr) ⇒ Object
Run rmake with
argvindir, returning the process exit status (0 success, 2 for any make-level failure โ the code GNU make uses).
Instance Method Summary collapse
-
#initialize(dir:, out:, err:) ⇒ CLI
constructor
A new instance of CLI.
- #run(argv) ⇒ Object
Constructor Details
#initialize(dir:, out:, err:) ⇒ CLI
Returns a new instance of CLI.
37 38 39 40 41 |
# File 'lib/rubycc/rmake/cli.rb', line 37 def initialize(dir:, out:, err:) @dir = dir @out = out @err = err end |
Class Method Details
.run(argv, dir: Dir.pwd, out: $stdout, err: $stderr) ⇒ Object
Run rmake with argv in dir, returning the process exit status
(0 success, 2 for any make-level failure โ the code GNU make uses). out
and err are injectable so the CLI can be exercised without spawning.
33 34 35 |
# File 'lib/rubycc/rmake/cli.rb', line 33 def self.run(argv, dir: Dir.pwd, out: $stdout, err: $stderr) new(dir: dir, out: out, err: err).run(argv) end |
Instance Method Details
#run(argv) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rubycc/rmake/cli.rb', line 43 def run(argv) = parse_argv(argv) makefile_path = File.([:file] || DEFAULT_MAKEFILE, @dir) unless File.file?(makefile_path) @err.puts("rmake: #{[:file] || DEFAULT_MAKEFILE}: No such file") return 2 end mk = Makefile.parse(File.read(makefile_path), dir: @dir, overrides: [:overrides], defaults: { "MAKE" => make_default }) goals = [:targets].empty? ? [nil] : [:targets] # Tool substitution is always on: rmake is rubycc's build CLI, so the # compiler/linker words in every recipe are handed to rubycc's Driver. goals.each { |goal| mk.run(goal, out: @out, err: @err, tools: :rubycc, jobs: [:jobs]) } 0 rescue RmakeError => e @err.puts("rmake: #{e.}") 2 end |