mirror of
https://github.com/zap-proto/ruby.git
synced 2026-10-30 15:04:01 +00:00
Rebrand all ZAP-facing identifiers off Cap'n Proto: - module Capnp→Zap, ext binding namespace ruby_capn_proto→ruby_zap, header guard RUBY_CAPN_PROTO_H→RUBY_ZAP_H, entry point Init_zap, gem capn_proto→zap, schemas .capnp→.zap, media/logo, gemspec, README, spec, examples. Zero capnp/Cap'n Proto brand prose remains. Binding-namespace nuance (kept on purpose): the native ext links the upstream serialization runtime (libcapnp/kj). Its capnp:: C++ symbols and <capnp/...> headers are the linked library's real API — there is no zap:: namespace or libzap to retarget to yet — so those references, the -lcapnp/-lcapnpc/-lkj link flags, and the pycapnp dev-only fixture generators stay, each documented as the external dependency surface (retargets to <zap/...>/-lzap when the ZAP C++ runtime ships). Build/modernization: - extconf.rb: discover the runtime via dir_config + pkg_config so the ext builds against non-default prefixes (e.g. Homebrew), not just /usr/local. Native ext now compiles + links cleanly (zap.bundle). - ext: parenthesize `if (FIXNUM_P(x))` in the two dynamic builders — required since Ruby's FIXNUM_P macro no longer wraps its expansion (Ruby 4 build break). - Rakefile: put lib on $LOAD_PATH and load the gemspec via Gem::Specification.load; pin rake-compiler ~> 0.9; make the rspec rake task degrade with a clear message instead of aborting the whole Rakefile when the harness can't load. - gemspec: bump dev deps within-major (rspec ~> 2.14, rake ~> 13.0, rake-compiler ~> 0.9); add required_ruby_version. - .gitignore: ignore native-ext build artifacts (*.o, Makefile, mkmf.log, *.bundle.dSYM, *.gem). Verified: all spec/zap_spec.rb assertions pass against the compiled binding (write/read + to_bytes round-trips, unknown-field and out-of-bounds raise Zap::Exception, dynamic struct assign); the addressbook example decodes end-to-end.
127 lines
3.3 KiB
Ruby
127 lines
3.3 KiB
Ruby
require 'shellwords'
|
|
require 'tmpdir'
|
|
|
|
# Discovers support for C++11 features,
|
|
# and any required CXXFLAGS for such features.
|
|
class CXXCompiler
|
|
CXX_COMPILER_FEATURES = <<-CODE
|
|
template <typename T>
|
|
struct check
|
|
{
|
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
|
};
|
|
|
|
typedef check<check<bool>> right_angle_brackets;
|
|
|
|
int a;
|
|
decltype(a) b;
|
|
|
|
typedef check<int> check_type;
|
|
check_type c;
|
|
check_type&& cr = static_cast<check_type&&>(c);
|
|
|
|
#ifdef __has_include
|
|
#if __has_include(<type_traits>)
|
|
#include <type_traits>
|
|
#endif
|
|
#endif
|
|
CODE
|
|
|
|
CXX_LIBRARY_FEATURES = <<-CODE
|
|
#include <initializer_list>
|
|
#include <unordered_map>
|
|
#include <atomic>
|
|
#include <thread>
|
|
CODE
|
|
|
|
# env: The environment variables (e.g. CXX, CXXFLAGS).
|
|
def initialize(env)
|
|
@env = env.dup
|
|
@exist = system("command -v #{@env['CXX'].shellescape} >/dev/null 2>&1")
|
|
end
|
|
|
|
# True if the compiler is accessible on the $PATH.
|
|
def exist?
|
|
@exist
|
|
end
|
|
|
|
# True if support for C++11 was detected, false otherwise.
|
|
def has_cxx11_compiler_support?
|
|
!!std_flag
|
|
end
|
|
|
|
# True if support for C++11 libraries was detected, false otherwise.
|
|
def has_cxx11_library_support?
|
|
!!stdlib_flag
|
|
end
|
|
|
|
# The required std flag (e.g. '-std=c++11'),
|
|
# empty string if unecessary given the current environment and/or compiler,
|
|
# or nil in the case where the compiler has no support.
|
|
def std_flag
|
|
test_compiler_flags(@env)
|
|
@std_flag
|
|
end
|
|
|
|
# The required stdlib flag (e.g. '-stdlib=libc++'),
|
|
# empty string if unecessary given the current environment and/or compiler,
|
|
# or nil in the case where the compiler has no support.
|
|
def stdlib_flag
|
|
test_compiler_flags(@env)
|
|
@stdlib_flag
|
|
end
|
|
|
|
private
|
|
|
|
# Detect any required flags.
|
|
def test_compiler_flags(env)
|
|
return if @tested || !exist?
|
|
@tested = true
|
|
|
|
cxxflags = (env['CXXFLAGS'] || '')
|
|
env = env.dup
|
|
|
|
flags = ['', '-std=gnu++11', '-std=gnu++0x', '-std=c++11', '-std=c++0x']
|
|
@std_flag = flags.detect do |flag|
|
|
env['CXXFLAGS'] = [cxxflags, flag].join(' ')
|
|
compile(CXX_COMPILER_FEATURES, env)
|
|
end
|
|
|
|
return unless @std_flag
|
|
|
|
env = env.dup
|
|
flags = ['', '-stdlib=libc++']
|
|
@stdlib_flag = flags.detect do |flag|
|
|
env['CXXFLAGS'] = [cxxflags, std_flag, flag].join(' ')
|
|
compile(CXX_LIBRARY_FEATURES, env)
|
|
end
|
|
end
|
|
|
|
# Compile a snippet of C++, returning true or false to indicate
|
|
# success.
|
|
def compile(code, env)
|
|
Dir.mktmpdir do |dir|
|
|
Dir.chdir(dir) do
|
|
File.open("test.cc", "w") {|f| f.write(code)}
|
|
system("#{env['CXX'].shellescape} #{env['CXXFLAGS']} -c test.cc >/dev/null 2>&1")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if $0 == __FILE__
|
|
compiler = CXXCompiler.new(ENV.to_hash)
|
|
cxx = ENV['CXX']
|
|
cxxflags = ENV['CXXFLAGS']
|
|
extra_cxxflags = [compiler.std_flag, compiler.stdlib_flag].join(' ')
|
|
compiler_support = compiler.has_cxx11_compiler_support? ? 'YES' : 'NO'
|
|
lib_support = compiler.has_cxx11_library_support? ? 'YES' : 'NO'
|
|
|
|
puts " given CXX = #{cxx}"
|
|
puts " given CXXFLAGS = #{cxxflags}"
|
|
puts "additional CXXFLAGS = #{extra_cxxflags}"
|
|
puts ""
|
|
puts "Has C++11 compiler support? #{compiler_support}"
|
|
puts "Has C++11 library support? #{lib_support}"
|
|
end
|