module RBuildSys
Namespace for all code for RBuildSys
Constants
- CONFIG_SYMBOLS
Stores all global symbols to configure files
- DECLARED_PROJECTS
- OPTIONS
Stores all options; will be modified through the commandline option parser @see @@optparse
- PROJECTS
Stores all projects that are defined by the user
- TOOLCHAINS
Stores all currently loaded toolchains
Private Class Methods
Loads a toolchain definition from a file. Format needs to be JSON.
@param file [String] path to the toolchain definition file
# File lib/rbuildsys.rb, line 984 def self.loadToolchain(file) if (!File.exists?(file)) then raise ArgumentError.new("Argument #1 (file) needs to be the path to an existing file"); end data = JSON.parse(File.read(file)); if (TOOLCHAINS.keys.include?(data["name"])) then raise RuntimeError.new("Cannot load toolchain '#{data["name"]}' from '#{file}': already loaded"); end TOOLCHAINS[data["name"]] = data; return data; end
# File lib/rbuildsys.rb, line 999 def self.load_default_toolchains # load builtin toolchains gemDir = File.dirname(File.expand_path(__FILE__)); toolchains = Dir.glob("#{gemDir}/toolchains/*.json"); toolchains.each {|f| self.loadToolchain(f); } # use toolchain installed for the user toolchains = Dir.glob("#{Dir.home}/.rbuildsys/toolchains/*.json"); toolchains.each {|f| self.loadToolchain(f); } end
Public Instance Methods
Tells the project that, in order to build it, the file specified at input
must be transformed to the file at output
.
@note Should only be called inside the block for {#newProject} @param input [String] The filename of the file that should be configured @param output [String] The filename that should be used to save the result, cannot be the same as the input! @param options [Hash] Some optional options
# File lib/rbuildsys.rb, line 1039 def configureFile(input, output, options = {}) if (!input.is_a?(String) || input.strip.empty?) then raise ArgumentError.new("Argument #1 (input) needs to be a string"); end if (!output.is_a?(String) || output.strip.empty?) then raise ArgumentError.new("Argument #2 (output) needs to be a string"); end if (input == output) then raise ArgumentError.new("Argument #1 (input) and #2 (output) cannot be the same"); end @@cur_proj.config_files.push({ input: File.join(@@cur_proj.baseDir, input), output: File.join(@@cur_proj.baseDir, output), options: options }); end
Shorthand for {Project#isMac?}
# File lib/rbuildsys.rb, line 1074 def isLinux?() return @@cur_proj.isLinux?; end
Shorthand for {Project#isMac?}
# File lib/rbuildsys.rb, line 1069 def isMac?() return @@cur_proj.isMac?; end
Tests if the toolchain is the given type of OS.
@param type [:win, :win32, :windows, :mac, :macos, :apple, :linux] the OS to check @return [Boolean] Returns true if OS is correct, false otherwise
# File lib/rbuildsys.rb, line 1082 def isToolchainOS?(type) if ([:win, :win32, :windows].include?(type)) then return @@cur_proj.isWindows?; end if ([:mac, :macos, :apple].include?(type)) then return @@cur_proj.isMac?(); end if ([:linux].include?(type)) then return @@cur_proj.isLinux?(); end raise ArgumentError.new("Unexpected argument: os-type '#{type}' unknown"); end
Shorthand for {Project#isWindows?}
# File lib/rbuildsys.rb, line 1064 def isWindows?() return @@cur_proj.isWindows?; end
Sets a symbol with an optional value to configure files. See {#configureFile}
@note When used inside the block for {#newProject}, the symbol is only visible for the project. If used outside of the block, the symbol is visible for everyone! @param symbol [String] The symbol that should be set @param value [String, nil] Optional value for the symbol
# File lib/rbuildsys.rb, line 1025 def set(symbol, value = nil) if (@@cur_proj == nil) then CONFIG_SYMBOLS[symbol] = value; else @@cur_proj.config_symbols[symbol] = value; end end
Private Instance Methods
Begins the build process. Should be called after you configured all your projects with {#newProject}.
# File lib/rbuildsys.rb, line 693 def build() parseARGV(); ARGV.each { |projname| proj = PROJECTS[projname]; if (proj) then if (OPTIONS[:clean]) then proj.clean(); elsif (OPTIONS[:install]) then proj.install(); else proj.build(); end end } end
Checks if this RBuildSys
is at minimum the required version. This is only for scripts that dont use systems like bundler etc. If you use bundler or similar dependency management software, you propably should use their features instead of this. @return [Boolean]
# File lib/rbuildsys.rb, line 734 def checkSysVersion(min_version) data_min = min_version.split("."); data_ver = sysVersion().split("."); if (data_ver.size != data_min.size) then return false; end if (data_ver.size == 4 && data_ver[3] != data_min[3]) then # 4th part dosnt match. Should be something like 'pre' or similar. return false; end data_min.pop(); data_ver.pop(); while (data_ver.size > 0) do a = data_min.pop(); b = data_ver.pop(); return false if (a > b); end return true; end
Declares the project's name so they can be displayed in the help text!
# File lib/rbuildsys.rb, line 720 def declareProjects(*projects) DECLARED_PROJECTS.push(*projects); end
Adds a define to the compiler call
@note Should only be called inside the block for {#newProject} @param symbol [String] Symbol that should be defined @param value [String, nil] Optional value the symbol should hold
# File lib/rbuildsys.rb, line 942 def define(symbol, value = nil) @@cur_proj.defines[symbol] = value; end
Adds a flag to the flags of the current project.
@note Should only be called inside the block for {#newProject} @note This should only be used when nothing else works, because this method dosnt ensure that the flags used are working with the current toolchain! @param flag [String] the flag to be added
# File lib/rbuildsys.rb, line 951 def flag(flag) @@cur_proj.flags.push(flag); end
Returns the install path for the current project
@note Should only be called inside the block for {#newProject}
# File lib/rbuildsys.rb, line 858 def getInstallPath() dir = OPTIONS[:installDir] || "/usr/include" if (isLinux? || isMac?); dir = OPTIONS[:installDir] || "C:/Program Files/#{@@cur_proj.outputName}" if (isWindows?); return File.expand_path(dir); end
Adds include directorys to use for the current project
@note Should only be called inside the block for {#newProject} @param dir [String, Array<String>] Directory path; root of the include path. If its a Array, each element is used in a call to {#incDir} @param more [Array<String>] Additional include paths; each element is used in a call to {#incDir}
# File lib/rbuildsys.rb, line 767 def incDir(dir, *more) if (dir.class == String) then dirPath = File.join(@@cur_proj.baseDir, dir); raise ArgumentError.new("Argument #1 is no directory: '#{dir}' ('#{dirPath}')") if (!Dir.exists?(dirPath)); @@cur_proj.inc_dirs.push(dirPath); elsif (dir.class == Array) then dir.each { |d| incDir(d) } else raise ArgumentError.new("Argument #1 must be a String or an Array"); end more.each { |d| incDir(d) } end
Sets the current project as a lib
@note Should only be called inside the block for {#newProject} @param type [:static, :dynamic, :s, :dyn, :both] The type of the library: static (*.a / *.lib) or dynamic (*.so / *.dll)
# File lib/rbuildsys.rb, line 848 def isLib(type) @@cur_proj.libType = :static if ([:static, :s].include?(type)); @@cur_proj.libType = :dynamic if ([:dynamic, :dyn, :d].include?(type)); @@cur_proj.libType = :both if (type == :both); raise ArgumentError.new("Argument #1 (type) must be one of the following: :static, :dynamic, :s, :dyn, :both") if (@@cur_proj.libType == nil) end
Creates a new project to build. Takes a block to execute, that defines the project. The block is immediately executed, and has access to the current project (that is created with this method) in {RBuildSys::@@cur_proj RBuildSys::@@cur_proj}.
@yield Block to configure the project
@param name [String] Name of the project, also used for the final output of the project @param options [Hash] Various options; for details see {Project#initialize}
# File lib/rbuildsys.rb, line 681 def newProject(name, options = {}) raise ArgumentError.new("Argument #1 (name) need to be a string") if (name.class != String); raise ArgumentError.new("Argument #2 (options) need to be an hash") if (!options.is_a?(Hash)); @@cur_proj = Project.new(name, options); yield PROJECTS[name] = @@cur_proj; @@cur_proj = nil; end
Tells the current project that it is not install-able This means that if you run an install of your projects, this one will not be installed
@note Should only be called inside the block for {#newProject}
# File lib/rbuildsys.rb, line 840 def noInstall() @@cur_proj.no_install = true; end
Adds an option to the option parser of RBuildSys
@see OptionParser#on_head
# File lib/rbuildsys.rb, line 973 def onHeadOption(*opts, &block) @@optparse.on_head(*opts, block); end
Adds an option to the option parser of RBuildSys
@see OptionParser#on
# File lib/rbuildsys.rb, line 961 def onOption(*opts, &block) @@optparse.on(*opts, block); end
Adds an option to the option parser of RBuildSys
@see OptionParser#on_tail
# File lib/rbuildsys.rb, line 967 def onTailOption(*opts, &block) @@optparse.on_tail(*opts, block); end
Parses the commandline arguments @note this should be called before any call to {#newProject} and/or {#build}!
# File lib/rbuildsys.rb, line 711 def parseARGV() @@optparse.parse! if (ARGV.length == 0) then puts @@optparse; exit(1); end end
Adds include directorys to use for projects that depends on the current project
@note Should only be called inside the block for {#newProject} @param dir [String, Array<String>] Directory path; root of the include path. If its a Array, each element is used in a call to {#publish_incDir} @param more [Array<String>] Additional include paths; each element is used in a call to {#publish_incDir}
# File lib/rbuildsys.rb, line 785 def publish_incDir(dir, *more) if (@@cur_proj.libType == nil) then raise RuntimeError.new("Can only be called when the project is configured as an library"); end if (dir.class == String) then dirPath = File.join(@@cur_proj.baseDir, dir); raise ArgumentError.new("Argument #1 is no directory: '#{dir}' ('#{dirPath}')") if (!Dir.exists?(dirPath)); @@cur_proj.public_inc_dirs.push(dirPath); elsif (dir.class == Array) then dir.each { |d| publish_incDir(d) } else raise ArgumentError.new("Argument #1 must be a String or an Array"); end more.each { |d| publish_incDir(d) } end
Adds source directorys to use for the current project
@note Should only be called inside the block for {#newProject} @param dir [String, Array<String>] Directory path; root of the source path. If its a Array, each element is used in a call to {#srcDir} @param more [Array<String>] Additional source paths; each element is used in a call to {#srcDir}
# File lib/rbuildsys.rb, line 807 def srcDir(dir, *more) if (dir.class == String) then dirPath = File.join(@@cur_proj.baseDir, dir); raise ArgumentError.new("Argument #1 is no directory: '#{dir}' ('#{dirPath}')") if (!Dir.exists?(dirPath)); @@cur_proj.src_dirs.push(dirPath); elsif (dir.class == Array) then dir.each { |d| srcDir(d) } else raise ArgumentError.new("Argument #1 must be a String or an Array"); end more.each { |d| srcDir(d) } end
Adds a source glob to use for the current project
@note Should only be called inside the block for {#newProject} @param glob [String, Array<String>] Glob to be used to find source files; If its a Array, each element is used in a call to {#srcGlob} @param more [Array<String>] Additional source globs; each element is used in a call to {#srcGlob}
# File lib/rbuildsys.rb, line 825 def srcGlob(glob, *more) if (glob.class == String) then @@cur_proj.src_globs.push(File.join(@@cur_proj.baseDir, glob)); elsif (glob.class == Array) then glob.each { |g| srcGlob(g) } else raise ArgumentError.new("Argument #1 must be a String or an Array"); end more.each { |g| srcGlob(g) } end
Returns the version of RBuildSys
@return [β1.0.0β]
# File lib/rbuildsys.rb, line 726 def sysVersion() return "1.0.0"; end
Links a RBuildSys
project to the current project. This has the effect that the given project is build before the current project, and if the given project is a lib, it is also linked to the current project
@note Should only be called inside the block for {#newProject} @param name [String] Can be a local project (inside current file) or any installed project @param linktype [:static, :dynamic] Specify wich linkage type should be used to link the project with the current one.
If the project to link dosnt support the linktype, this raises an error.
# File lib/rbuildsys.rb, line 872 def use(name, linktype) if (PROJECTS[name] == nil) then @@cur_proj.dependencys.push([name, linktype]); else # use local proj = PROJECTS[name]; if (!proj.libType) then raise ArgumentError.new("Argument #1 can't be used cause it is not a library"); end if (proj.libType != linktype && proj.libType != :both) then raise ArgumentError.new("Argument #1 can't be linked with linktype #{linktype}!"); end @@cur_proj.dependencys.push(proj); end end
Adds a external library to the current project
@note Should only be called inside the block for {#newProject} @note There is currently no check in place to verify that the given library exists @param name [String] Name of the library that should be used. in a c/c++ context, it should be without the leading βlibβ @param path [String, nil] Optional search path for this library @param options [Hash] Optional options @option options :pkgconf [Boolean] If true, search pkgconf(ig) for additional informations about the lib
# File lib/rbuildsys.rb, line 927 def useLib(name, path = nil, options = {}) if (options[:pkgconf]) then usePkgconf(name); return; end @@cur_proj.librarys.push(name); @@cur_proj.lib_dirs.push(path) if (path != nil && Dir.exists?(path)); end
Adds a external library through pkg-config. If no pkg-config is installed on the system, this functions raises an error
@note Should only be called inside the block for {#newProject} @note For retriving the flags from pkg-config, --libs
and --cflags
is used, and the output is given to {#flag} @param name [String] Name of the pkg-config package
# File lib/rbuildsys.rb, line 896 def usePkgconf(name) if (`which pkg-config` == "") then raise ArgumentError.new("Option pkgconf specified, but no pkg-config installed on system!"); end modver = `pkg-config --short-errors --modversion #{name}`; if (modver.start_with?("No package") or $?.exitstatus != 0) then raise RuntimeError.new("Could not find package '#{name}' with pkg-config!"); end linker_flags = `pkg-config --short-errors --libs #{name}`; if ($?.exitstatus != 0) then raise RuntimeError.new("Could not get linkler flags for '#{name}', plg-config error: #{linker_flags}"); end flag(linker_flags); cflags = `pkg-config --short-errors --cflags #{name}`; if ($?.exitstatus != 0) then raise RuntimeError.new("Could not get compiler flags for '#{name}', plg-config error: #{linker_flags}"); end flag(cflags); end