Skip to content

Instantly share code, notes, and snippets.

@pbosetti
Last active December 1, 2015 07:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pbosetti/152379270f53d2386643 to your computer and use it in GitHub Desktop.
Save pbosetti/152379270f53d2386643 to your computer and use it in GitHub Desktop.
Trying to illustrate the reason for using local includes (i.e. #include "") rather than system includes (i.e. #include <>) within public headers for mruby.
#!/usr/bin/env ruby
require 'fileutils'
include FileUtils
# This scripts tries to show why it is preferable to only use local include
# commands (#include "") within public headers of mruby when they include each
# other.
# To test it, first run this script with no arguments (it will stop on
# compilation), then with the `proposal` argument, which uses as mruby source
# the relative pull request.
# Note that the pull request does not alter in any way how users will have to
# include mruby headers with respect to the current HEAD. They only have to
# compile with a -I flag pointing to the directory containing the mruby.h main
# header.
# By using local include commands in public headers when they include each
# other, the inclusion mechanism is independent from the C header path
# resulting from compiler configuration and from the list of -I switches
# provided by the user. As such it shall be considered more robust and
# preferable.
#
# Note: it is true that if we install the mruby public headers straight within
# ./include rather than into a subdirectory the compilation problem is solved,
# but this means to needlessly force the user to adapt his directory stucture
# to assumptions made into headers.
#
i = 0
puts "\n#{i+=1}. Preparing project folders"
mkpath 'include/mruby'
mkpath 'lib'
mkpath 'src'
rm_rf 'mruby'
if ARGV.include? 'proposal' then
puts "\n#{i+=1}. Building mruby from proposal pull-request"
system 'git clone --depth 1 -b fix_include https://github.com/pbosetti/mruby.git'
else
puts "\n#{i+=1}. Building mruby from HEAD"
system 'git clone --depth 1 https://github.com/mruby/mruby.git'
end
system '(cd mruby && ./minirake)'
puts "\n#{i+=1}. Populating project folders"
cp_r Dir.glob('mruby/include/*'), 'include/mruby'
cp_r Dir.glob('mruby/build/host/lib/*'), 'lib'
puts "\n#{i+=1}. Writing example C code"
File.open('main.c', 'w') do |f|
f.print <<-EOS
#include <stdio.h>
// We have our headers installed somewhere in include path, and mruby headers
// are collectively installed within a folder named `mruby` (for isolation). See
// the example structure of the `include` dir.
// By building with -I./include, the three following lines search files within
// `./include`.
#include <mylib.h>
#include <mruby/mruby.h>
#include <mruby/mruby/compile.h>
#include <mruby/mruby/string.h>
// Silly example here:
int main(int argc, const char ** argv) {
mrb_state *mrb = mrb_open();
if (!mrb) { /* handle error */ }
puts("Executing Ruby code from C!");
mrb_load_string(mrb, "p 'hello world!'");
mrb_close(mrb);
return 0;
}
EOS
end
File.open('include/mylib.h', 'w') do |f|
f.print <<-EOS
// Header for a dummy function
#include <mruby/mruby.h>
#include <mruby/mruby/compile.h>
void dummy();
EOS
end
File.open('src/mylib.c', 'w') do |f|
f.print <<-EOS
// Implementation of the dummy function
void dummy() {}
EOS
end
puts "\n#{i+=1}. Building C code"
# Since all the headers we need are within `./include`, we only add that
# folder to the includes search path, and then we use <angled> includes in
# our source (`main.c` and `./include/mylib.h`) with paths that are relative to
# `./include`
system "gcc -I./include -lm main.c src/mylib.c lib/libmruby.a -o test"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment