mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #5928 from dearblue/task/install
Improved `rake install`
This commit is contained in:
@@ -31,6 +31,7 @@ load "#{MRUBY_ROOT}/tasks/presym.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/test.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/benchmark.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/doc.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/install.rake"
|
||||
|
||||
##############################
|
||||
# generic build targets, rules
|
||||
@@ -67,34 +68,6 @@ task :deep_clean => %w[clean doc:clean] do
|
||||
puts "Cleaned up mrbgems build folder"
|
||||
end
|
||||
|
||||
PREFIX = ENV['PREFIX'] || ENV['INSTALL_PREFIX'] || '/usr/local'
|
||||
|
||||
desc "install compiled products"
|
||||
task :install => :install_bin do
|
||||
if host = MRuby.targets['host']
|
||||
install_D host.libmruby_static, File.join(PREFIX, "lib", File.basename(host.libmruby_static))
|
||||
# install mruby.h and mrbconf.h
|
||||
Dir.glob(File.join(MRUBY_ROOT, "include", "*.h")) do |src|
|
||||
install_D src, File.join(PREFIX, "include", File.basename(src))
|
||||
end
|
||||
Dir.glob(File.join(MRUBY_ROOT, "include", "mruby", "*.h")) do |src|
|
||||
install_D src, File.join(PREFIX, "include", "mruby", File.basename(src))
|
||||
end
|
||||
Dir.glob(File.join(File.join(MRUBY_ROOT, "build", "host", "include", "mruby", "presym", "*.h"))) do |src|
|
||||
install_D src, File.join(PREFIX, "include", "mruby", "presym", File.basename(src))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "install compiled executable (on host)"
|
||||
task :install_bin => :all do
|
||||
if host = MRuby.targets['host']
|
||||
Dir.glob(File.join(MRUBY_ROOT, "bin", "*")) do |src|
|
||||
install_D src, File.join(PREFIX, "bin", File.basename(src))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "run all pre-commit hooks against all files"
|
||||
task :check do
|
||||
sh "pre-commit run --all-files"
|
||||
|
||||
@@ -557,6 +557,56 @@ LDFLAGS = `$(MRB_CONFIG) --ldflags`
|
||||
LIBS = `$(MRB_CONFIG) --libs`
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
To install the files in the `bin`, `include` and `lib` directories generated by the "host" build target into a system directory, do the following:
|
||||
|
||||
```console
|
||||
$ rake install
|
||||
```
|
||||
|
||||
If there are multiple build targets in the build configuration file, to install the products of all build targets, do the following:
|
||||
|
||||
```console
|
||||
$ rake install:full
|
||||
```
|
||||
|
||||
To install only one of several build targets, e.g., the "its-mine" build target, do the following:
|
||||
|
||||
```console
|
||||
$ rake install:full:its-mine
|
||||
```
|
||||
|
||||
To install only the executable files, do the following:
|
||||
|
||||
```console
|
||||
$ rake install_bin # only "host" build target
|
||||
$ rake install:bin # all build targets
|
||||
$ rake install:bin:its-mine # only "its-mine" build target
|
||||
```
|
||||
|
||||
### Installation Directory
|
||||
|
||||
The installation directory is `/usr/local` for the "host" build target and `/usr/local/mruby/<build-name>` for the others.
|
||||
To change them, you can set the environment variable `PREFIX` or use `MRuby::Build#install_prefix = dir` in your build configuration file.
|
||||
|
||||
The `PREFIX` environment variable affects all build targets and changes the `/usr/local` part.
|
||||
|
||||
The `MRuby::Build#install_prefix` can be set for each individual build target.
|
||||
In this case, the environment variable `PREFIX` is ignored.
|
||||
|
||||
Also, if the environment variable `DESTDIR` is set, it will prepend to the path obtained by `install_prefix` to determine the final write directory.
|
||||
This is intended for temporary file expansion by the user's package work.
|
||||
|
||||
---
|
||||
|
||||
To summarize:
|
||||
|
||||
- The default value of the environment variable `PREFIX` is `/usr/local`.
|
||||
- For the "host" build target, the default value of `MRuby::Build#install_prefix` is `<PREFIX>`.
|
||||
- For a build target other than "host", the default value of `MRuby::Build#install_prefix` is `<PREFIX>/mruby/<build-name>`.
|
||||
- If the environment variable `DESTDIR` is set, the actual write directory is `<DESTDIR>/<MRuby::Build#install_prefix>`.
|
||||
|
||||
## Tips
|
||||
|
||||
- If you see compilation troubles, try `rake clean` first.
|
||||
|
||||
+52
-3
@@ -1,12 +1,16 @@
|
||||
require "mruby/core_ext"
|
||||
require "mruby/build/load_gems"
|
||||
require "mruby/build/command"
|
||||
autoload :Find, "find"
|
||||
|
||||
module MRuby
|
||||
autoload :Gem, "mruby/gem"
|
||||
autoload :Lockfile, "mruby/lockfile"
|
||||
autoload :Presym, "mruby/presym"
|
||||
|
||||
INSTALL_PREFIX = ENV['PREFIX'] || ENV['INSTALL_PREFIX'] || '/usr/local'
|
||||
INSTALL_DESTDIR = ENV['DESTDIR'] || ''
|
||||
|
||||
class << self
|
||||
def targets
|
||||
@targets ||= {}
|
||||
@@ -97,6 +101,7 @@ module MRuby
|
||||
@file_separator = '/'
|
||||
@build_dir = "#{build_dir}/#{@name}"
|
||||
@gem_clone_dir = "#{build_dir}/repos/#{@name}"
|
||||
@install_prefix = nil
|
||||
@defines = []
|
||||
@cc = Command::Compiler.new(self, %w(.c), label: "CC")
|
||||
@cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp), label: "CXX")
|
||||
@@ -370,14 +375,35 @@ EOS
|
||||
end
|
||||
end
|
||||
|
||||
def define_installer(src)
|
||||
dst = "#{self.class.install_dir}/#{File.basename(src)}"
|
||||
def define_installer_outline(src, dst)
|
||||
file dst => src do
|
||||
install_D src, dst
|
||||
_pp "GEN", src.relative_path, dst.relative_path
|
||||
mkdir_p(File.dirname(dst))
|
||||
yield dst
|
||||
end
|
||||
dst
|
||||
end
|
||||
|
||||
if ENV['OS'] == 'Windows_NT'
|
||||
def define_installer(src)
|
||||
dst = "#{self.class.install_dir}/#{File.basename(src)}".pathmap("%X.bat")
|
||||
define_installer_outline(src, dst) do
|
||||
File.write dst, <<~BATCHFILE
|
||||
@echo off
|
||||
call "#{src}" %*
|
||||
BATCHFILE
|
||||
end
|
||||
end
|
||||
else
|
||||
def define_installer(src)
|
||||
dst = "#{self.class.install_dir}/#{File.basename(src)}"
|
||||
define_installer_outline(src, dst) do
|
||||
File.unlink(dst) if File.exist?(dst)
|
||||
File.symlink(src, dst)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def define_installer_if_needed(bin)
|
||||
exe = exefile("#{build_dir}/bin/#{bin}")
|
||||
host? ? define_installer(exe) : exe
|
||||
@@ -485,6 +511,29 @@ EOS
|
||||
@internal
|
||||
end
|
||||
|
||||
def each_header_files(&block)
|
||||
return to_enum(__method__) unless block
|
||||
|
||||
basedir = File.join(MRUBY_ROOT, "include")
|
||||
Find.find(basedir) do |d|
|
||||
next unless File.file? d
|
||||
yield d
|
||||
end
|
||||
|
||||
@gems.each { |g| g.each_header_files(&block) }
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def install_prefix
|
||||
@install_prefix || (self.name == "host" ? MRuby::INSTALL_PREFIX :
|
||||
File.join(MRuby::INSTALL_PREFIX, "mruby/#{self.name}"))
|
||||
end
|
||||
|
||||
def install_prefix=(dir)
|
||||
@install_prefix = dir&.to_s
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :presym
|
||||
|
||||
@@ -22,6 +22,27 @@ class String
|
||||
def remove_leading_parents
|
||||
Pathname.new(".#{Pathname.new("/#{self}").cleanpath}").cleanpath.to_s
|
||||
end
|
||||
|
||||
def replace_prefix_by(dirmap)
|
||||
[self].replace_prefix_by(dirmap)[0]
|
||||
end
|
||||
end
|
||||
|
||||
class Array
|
||||
# Replace the prefix of each string that is a file path that contains in its own array.
|
||||
#
|
||||
# dirmap is a hash whose elements are `{ "path/to/old-prefix" => "path/to/new-prefix", ... }`.
|
||||
# If it does not match any element of dirmap, the file path is not replaced.
|
||||
def replace_prefix_by(dirmap)
|
||||
dirmap = dirmap.map { |older, newer| [File.join(older, "/"), File.join(newer, "/")] }
|
||||
dirmap.sort!
|
||||
dirmap.reverse!
|
||||
self.flatten.map do |e|
|
||||
map = dirmap.find { |older, newer| e.start_with?(older) }
|
||||
e = e.sub(map[0], map[1]) if map
|
||||
e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def install_D(src, dst)
|
||||
|
||||
@@ -284,6 +284,19 @@ module MRuby
|
||||
end
|
||||
end.all?
|
||||
end
|
||||
|
||||
def each_header_files(&block)
|
||||
return to_enum(__method__) unless block
|
||||
|
||||
self.export_include_paths.flatten.uniq.compact.each do |dir|
|
||||
Find.find(dir) do |d|
|
||||
next unless File.file? d
|
||||
yield d
|
||||
end
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
end # Specification
|
||||
|
||||
class Version
|
||||
|
||||
@@ -11,7 +11,16 @@ MRuby::Gem::Specification.new('mruby-bin-config') do |spec|
|
||||
else
|
||||
mruby_config_dir = "#{build.build_dir}/bin"
|
||||
end
|
||||
mruby_config = name + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
|
||||
|
||||
if ENV['OS'] == 'Windows_NT'
|
||||
suffix = '.bat'
|
||||
refvar = '%\\1%'
|
||||
else
|
||||
suffix = ''
|
||||
refvar = '${\\1}'
|
||||
end
|
||||
|
||||
mruby_config = name + suffix
|
||||
mruby_config_path = "#{mruby_config_dir}/#{mruby_config}"
|
||||
make_cfg = "#{build.build_dir}/lib/libmruby.flags.mak"
|
||||
tmplt_path = "#{__dir__}/#{mruby_config}"
|
||||
@@ -24,11 +33,16 @@ MRuby::Gem::Specification.new('mruby-bin-config') do |spec|
|
||||
|
||||
directory mruby_config_dir
|
||||
|
||||
file mruby_config_path => [mruby_config_dir, make_cfg, tmplt_path] do |t|
|
||||
file mruby_config_path => [__FILE__, mruby_config_dir, make_cfg, tmplt_path] do |t|
|
||||
config = Hash[File.readlines(make_cfg).map!(&:chomp).map! {|l|
|
||||
l.gsub!(/\$\((\w+)\)/, refvar)
|
||||
l.gsub('\\"', '"').split(' = ', 2).map! {|s| s.sub(/^(?=.)/, 'echo ')}
|
||||
}]
|
||||
tmplt = File.read(tmplt_path)
|
||||
tmplt.sub!(%r((?<=\A#!/bin/sh\n\n)), <<~SETDIR)
|
||||
MRUBY_PACKAGE_DIR=$(dirname "$(dirname "$(readlink -f "$0")")")
|
||||
|
||||
SETDIR
|
||||
File.write(t.name, tmplt.gsub(/(#{Regexp.union(*config.keys)})\b/, config))
|
||||
chmod(0755, t.name)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
@echo off
|
||||
|
||||
call :init "%~dp0."
|
||||
goto top
|
||||
|
||||
:init
|
||||
rem call init2 for treatments last directory separator
|
||||
call :init2 "%~dp1."
|
||||
goto :eof
|
||||
|
||||
:init2
|
||||
set MRUBY_PACKAGE_DIR=%~f1
|
||||
goto :eof
|
||||
|
||||
:top
|
||||
shift
|
||||
if "%0" equ "" goto :eof
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
desc "install compiled products (on host)"
|
||||
task :install => "install:full:host"
|
||||
|
||||
desc "install compiled executable (on host)"
|
||||
task :install_bin => "install:bin:host"
|
||||
|
||||
desc "install compiled products (all build targets)"
|
||||
task "install:full"
|
||||
|
||||
desc "install compiled executable (all build targets)"
|
||||
task "install:bin"
|
||||
|
||||
MRuby.each_target do |build|
|
||||
next if build.internal?
|
||||
|
||||
prefix = File.join(MRuby::INSTALL_DESTDIR, build.install_prefix)
|
||||
|
||||
task "install:full" => "install:full:#{build.name}"
|
||||
|
||||
task "install:full:#{build.name}" => "install:bin:#{build.name}" do
|
||||
Dir.glob(File.join(build.build_dir.gsub(/[\[\{\*\?]/, "\\\0"), "{include,lib}/**/*")) do |path|
|
||||
install_D path, File.join(prefix, path.relative_path_from(build.build_dir)) if File.file? path
|
||||
end
|
||||
end
|
||||
|
||||
task "install:bin" => "install:bin:#{build.name}"
|
||||
|
||||
task "install:bin:#{build.name}" => "all" do
|
||||
Dir.glob(File.join(build.build_dir.gsub(/[\[\{\*\?]/, "\\\0"), "{bin,host-bin}/**/*")) do |path|
|
||||
install_D path, File.join(prefix, path.relative_path_from(build.build_dir)) if File.file? path
|
||||
end
|
||||
end
|
||||
end
|
||||
+54
-5
@@ -8,22 +8,71 @@ MRuby.each_target do
|
||||
next unless libmruby_enabled?
|
||||
|
||||
file libmruby_static => libmruby_objs.flatten do |t|
|
||||
Rake::Task["expose_header_files"].invoke
|
||||
archiver.run t.name, t.prerequisites
|
||||
end
|
||||
|
||||
task "expose_header_files" do |t|
|
||||
# Since header files may be generated dynamically and it is hard to know all of them,
|
||||
# the task is executed depending on when libmruby.a is generated.
|
||||
|
||||
gemsbasedir = File.join(build_dir, "include/mruby/gems")
|
||||
dirmap = {
|
||||
MRUBY_ROOT => build_dir
|
||||
}
|
||||
gems.each { |g|
|
||||
dirmap[g.dir] = File.join(gemsbasedir, g.name)
|
||||
dirmap[g.build_dir] = File.join(gemsbasedir, g.name)
|
||||
}
|
||||
|
||||
dirs = each_header_files.to_a
|
||||
dirs.uniq!
|
||||
dirs.replace_prefix_by(dirmap).zip(dirs).each do |dest, src|
|
||||
if File.mtime(src).to_i > (File.mtime(dest).to_i rescue 0)
|
||||
mkpath File.dirname(dest)
|
||||
cp src, dest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libmruby_static] do |t|
|
||||
mkdir_p File.dirname t.name
|
||||
open(t.name, 'w') do |f|
|
||||
gemincs = gems.map { |g| g.export_include_paths.map { |n| g.filename(n) } }.flatten.uniq
|
||||
f.puts "MRUBY_CFLAGS = #{cc.all_flags([], gemincs)}"
|
||||
f.puts <<~FLAGS_MAKE
|
||||
# GNU make is required to use this file.
|
||||
MRUBY_PACKAGE_DIR_GNU := $(shell dirname "$(firstword $(MAKEFILE_LIST))")
|
||||
MRUBY_PACKAGE_DIR != dirname "$(MRUBY_PACKAGE_DIR_GNU)"
|
||||
FLAGS_MAKE
|
||||
|
||||
[
|
||||
[cc, "MRUBY_CC", "MRUBY_CFLAGS"],
|
||||
[cxx, "MRUBY_CXX", "MRUBY_CXXFLAGS"],
|
||||
[asm, "MRUBY_AS", "MRUBY_ASFLAGS"],
|
||||
[objc, "MRUBY_OBJC", "MRUBY_OBJCFLAGS"]
|
||||
].each do |cc, cmd, flags|
|
||||
incpaths = cc.include_paths.dup
|
||||
dirmaps = {
|
||||
MRUBY_ROOT => "$(MRUBY_PACKAGE_DIR)",
|
||||
build_dir => "$(MRUBY_PACKAGE_DIR)"
|
||||
}
|
||||
gems.each do |g|
|
||||
incpaths.concat g.export_include_paths
|
||||
dirmaps[g.dir] = "$(MRUBY_PACKAGE_DIR)/include/mruby/gems/#{g.name}"
|
||||
dirmaps[g.build_dir] = "$(MRUBY_PACKAGE_DIR)/include/mruby/gems/#{g.name}"
|
||||
end
|
||||
modcc = cc.clone
|
||||
modcc.include_paths = incpaths.replace_prefix_by(dirmaps).uniq
|
||||
|
||||
f.puts "#{cmd} = #{cc.command}"
|
||||
f.puts "#{flags} = #{modcc.all_flags}"
|
||||
end
|
||||
|
||||
f.puts "MRUBY_CC = #{cc.command}"
|
||||
f.puts "MRUBY_LD = #{linker.command}"
|
||||
|
||||
libgems = gems.reject{|g| g.bin?}
|
||||
gem_flags = libgems.map {|g| g.linker.flags }
|
||||
gem_library_paths = libgems.map {|g| g.linker.library_paths }
|
||||
f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "#{build_dir}/lib"}"
|
||||
f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "$(MRUBY_PACKAGE_DIR)/lib"}"
|
||||
|
||||
gem_flags_before_libraries = libgems.map {|g| g.linker.flags_before_libraries }
|
||||
f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ')}"
|
||||
@@ -31,7 +80,7 @@ MRuby.each_target do
|
||||
gem_libraries = libgems.map {|g| g.linker.libraries }
|
||||
f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries)}"
|
||||
|
||||
f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static}"
|
||||
f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static.replace_prefix_by(build_dir => "$(MRUBY_PACKAGE_DIR)")}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user