Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated POSIX/C bindings + FreeBSD support #2442

Merged
merged 11 commits into from
May 5, 2016
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ SOURCES := $(shell find src -name '*.cr')
SPEC_SOURCES := $(shell find spec -name '*.cr')
FLAGS := $(if $(release),--release )$(if $(stats),--stats )$(if $(threads),--threads $(threads) )
EXPORTS := $(if $(release),,CRYSTAL_CONFIG_PATH=`pwd`/src)
SHELL = /bin/bash
LLVM_CONFIG := $(shell command -v llvm-config-3.6 llvm-config-3.5 llvm-config | head -n 1)
SHELL = bash
LLVM_CONFIG := $(shell command -v llvm-config-3.6 llvm-config36 llvm-config-3.5 llvm-config35 llvm-config | head -n 1)
LLVM_EXT_DIR = src/llvm/ext
LLVM_EXT_OBJ = $(LLVM_EXT_DIR)/llvm_ext.o
LIB_CRYSTAL_SOURCES = $(shell find src/ext -name '*.c')
Expand Down
38 changes: 29 additions & 9 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,42 @@
Vagrant.configure("2") do |config|
%w(precise trusty vivid).product([32, 64]).each do |dist, bits|
box_name = "#{dist}#{bits}"
config.vm.define(box_name) { |c| c.vm.box = "ubuntu/#{box_name}" }

config.vm.define(box_name) do |c|
c.vm.box = "ubuntu/#{box_name}"

c.vm.provision :shell, inline: %(
curl -s http://dist.crystal-lang.org/apt/setup.sh | bash
apt-get install -y crystal git libgmp3-dev zlib1g-dev libedit-dev libxml2-dev libssl-dev libyaml-dev libreadline-dev g++
curl -s http://crystal-lang.s3.amazonaws.com/llvm/llvm-3.5.0-1-linux-`uname -m`.tar.gz | tar xz -C /opt
echo 'export LIBRARY_PATH="/opt/crystal/embedded/lib"' > /etc/profile.d/crystal.sh
echo 'export PATH="$PATH:/opt/llvm-3.5.0-1/bin"' >> /etc/profile.d/crystal.sh
)
end
end

config.vm.define "freebsd" do |c|
c.ssh.shell = "csh"
c.vm.box = "freebsd/FreeBSD-10.2-RELEASE"

c.vm.network "private_network", type: "dhcp"
c.vm.synced_folder ".", "/vagrant", type: "nfs"

# to build boehm-gc from git repository:
#c.vm.provision :shell, inline: %(
# pkg install -y libtool automake autoconf libatomic_ops
#)

c.vm.provision :shell, inline: %(
pkg install -y git gmake pkgconf pcre libunwind clang36 libyaml gmp libevent2
)
end

config.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.cpus = 2
end

config.vm.provision :shell, inline: %(
curl -s http://dist.crystal-lang.org/apt/setup.sh | bash
apt-get install -y crystal git libgmp3-dev zlib1g-dev libedit-dev libxml2-dev libssl-dev libyaml-dev libreadline-dev g++
curl -s http://crystal-lang.s3.amazonaws.com/llvm/llvm-3.5.0-1-linux-`uname -m`.tar.gz | tar xz -C /opt
echo 'export LIBRARY_PATH="/opt/crystal/embedded/lib"' > /etc/profile.d/crystal.sh
echo 'export PATH="$PATH:/opt/llvm-3.5.0-1/bin"' >> /etc/profile.d/crystal.sh
)

config.vm.provision :shell, privileged: false, inline: %(
git clone /vagrant crystal
)
Expand Down
37 changes: 36 additions & 1 deletion bin/crystal
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,47 @@ remove_path_item() {

##############################################################################

# required to build Crystal 0.16.0 with Crystal 0.15.0 (because the previous
# compiler won't append the target folder).
# TODO: remove this + the CRYSTAL_PATH injection below once 0.16.0 is released!

LLVM_CONFIG=`command -v llvm-config-3.6 lllvm-config36 lvm-config-3.5 llvm-config35 llvm-config`
TARGET_TRIPLE=`$LLVM_CONFIG --host-target`

if (echo $TARGET_TRIPLE | grep -q "x86_64-"); then
if (echo $TARGET_TRIPLE | grep -q "linux-"); then
if (echo $TARGET_TRIPLE | grep -q "gnu"); then
TRIPLE=x86_64-linux-gnu
elif (echo $TARGET_TRIPLE | grep -q "musl"); then
TRIPLE=x86_64-linux-musl
fi
elif (echo $TARGET_TRIPLE | grep -q "darwin"); then
TRIPLE=x86_64-macosx-darwin
elif (echo $TARGET_TRIPLE | grep -q "freebsd"); then
TRIPLE=x86_64-portbld-freebsd
fi
elif (echo $TARGET_TRIPLE | egrep -q "(i[3456]86)-"); then
if (echo $TARGET_TRIPLE | grep -q "linux-"); then
if (echo $TARGET_TRIPLE | grep -q "gnu"); then
TRIPLE=i686-linux-gnu
elif (echo $TARGET_TRIPLE | grep -q "musl"); then
TRIPLE=i686-linux-musl
fi
#elif (echo $TARGET_TRIPLE | grep -q "darwin"); then
# TRIPLE=i686-macosx-darwin
#elif (echo $TARGET_TRIPLE | grep -q "freebsd"); then
# TRIPLE=i686-portbld-freebsd
fi
fi

##############################################################################

SCRIPT_PATH="$(realpath "$0")"
SCRIPT_ROOT="$(dirname "$SCRIPT_PATH")"
CRYSTAL_ROOT="$(dirname "$SCRIPT_ROOT")"
CRYSTAL_DIR="$CRYSTAL_ROOT/.build"

export CRYSTAL_PATH=$CRYSTAL_ROOT/src:libs
export CRYSTAL_PATH=$CRYSTAL_ROOT/src:$CRYSTAL_ROOT/src/lib_c/$TRIPLE:libs

if [ -x "$CRYSTAL_DIR/crystal" ]
then
Expand Down
12 changes: 6 additions & 6 deletions spec/std/socket_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,14 @@ describe UDPSocket do
server.local_address.port.should eq(port)
server.local_address.address.should eq("::")

client = UDPSocket.new(Socket::Family::INET)
client.connect("127.0.0.1", port)
client = UDPSocket.new(Socket::Family::INET6)
client.connect("::1", port)

client.local_address.family.should eq(Socket::Family::INET)
client.local_address.address.should eq("127.0.0.1")
client.remote_address.family.should eq(Socket::Family::INET)
client.local_address.family.should eq(Socket::Family::INET6)
client.local_address.address.should eq("::1")
client.remote_address.family.should eq(Socket::Family::INET6)
client.remote_address.port.should eq(port)
client.remote_address.address.should eq("127.0.0.1")
client.remote_address.address.should eq("::1")

client << "message"
server.gets(7).should eq("message")
Expand Down
1 change: 1 addition & 0 deletions src/big/big_float.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "c/string"
require "./big"

# A BigInt can represent arbitrarily large floats.
Expand Down
1 change: 1 addition & 0 deletions src/big/big_int.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require "c/string"
require "./big"

# A BigInt can represent arbitrarily large integers.
Expand Down
28 changes: 27 additions & 1 deletion src/compiler/crystal/crystal_path.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,34 @@ module Crystal

@crystal_path : Array(String)

def initialize(path = CrystalPath.default_path)
def initialize(path = CrystalPath.default_path, target_triple = LLVM.default_target_triple)
@crystal_path = path.split(':').reject &.empty?
add_target_path(target_triple)
end

private def add_target_path(target_triple = LLVM.default_target_triple)
triple = target_triple.split('-')
triple.delete(triple[1]) if triple.size == 4 # skip vendor

if %w(i386 i486 i586).includes?(triple[0])
triple[0] = "i686"
end

target = if triple.any?(&.includes?("macosx"))
{triple[0], "macosx", "darwin"}.join('-')
elsif triple.any?(&.includes?("freebsd"))
{triple[0], triple[1], "freebsd"}.join('-')
else
triple.join('-')
end

@crystal_path.each do |path|
_path = File.join(path, "lib_c", target)
if Dir.exists?(_path)
@crystal_path << _path unless @crystal_path.includes?(_path)
return
end
end
end

def find(filename, relative_to = nil)
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/crystal/program.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ module Crystal
@global_vars = {} of String => MetaTypeVar
@requires = Set(String).new
@temp_var_counter = 0
@crystal_path = CrystalPath.new
@vars = MetaVars.new
@def_macros = [] of Def
@splat_expansions = {} of UInt64 => Type
Expand Down Expand Up @@ -174,6 +173,10 @@ module Crystal
define_primitives
end

private def crystal_path
@crystal_path ||= CrystalPath.new(target_triple: target_machine.triple)
end

def add_def(node : Def)
if file_module = check_private(node)
file_module.add_def node
Expand Down
1 change: 1 addition & 0 deletions src/compiler/crystal/semantic/flags.cr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Crystal::Program
private def parse_flags(flags_name)
set = flags_name.map(&.downcase).to_set
set.add "darwin" if set.any?(&.starts_with?("macosx"))
set.add "freebsd" if set.any?(&.starts_with?("freebsd"))
set.add "i686" if set.any? { |flag| %w(i586 i486 i386).includes?(flag) }
set
end
Expand Down
42 changes: 4 additions & 38 deletions src/dir.cr
Original file line number Diff line number Diff line change
@@ -1,40 +1,6 @@
lib LibC
type Dir = Void*

ifdef darwin
struct DirEntry
d_ino : Int32
reclen : UInt16
type : UInt8
namelen : UInt8
name : UInt8[1024]
end
elsif linux
struct DirEntry
d_ino : UInt64
d_off : Int64
reclen : UInt16
type : UInt8
name : UInt8[256]
end
end

fun getcwd(buffer : UInt8*, size : SizeT) : UInt8*
fun chdir = chdir(path : UInt8*) : Int
fun opendir(name : UInt8*) : Dir*
fun closedir(dir : Dir*) : Int

fun mkdir(path : UInt8*, mode : LibC::ModeT) : Int
fun rmdir(path : UInt8*) : Int

ifdef darwin
fun readdir(dir : Dir*) : DirEntry*
elsif linux
fun readdir = readdir64(dir : Dir*) : DirEntry*
end

fun rewinddir(dir : Dir*)
end
require "c/dirent"
require "c/unistd"
require "c/sys/stat"

# Objects of class Dir are directory streams representing directories in the underlying file system.
# They provide a variety of ways to list directories and their contents. See also `File`.
Expand Down Expand Up @@ -111,7 +77,7 @@ class Dir
Errno.value = 0
ent = LibC.readdir(@dir)
if ent
String.new(ent.value.name.to_unsafe)
String.new(ent.value.d_name.to_unsafe)
elsif Errno.value != 0
raise Errno.new("readdir")
else
Expand Down
31 changes: 3 additions & 28 deletions src/dl.cr
Original file line number Diff line number Diff line change
@@ -1,32 +1,7 @@
@[Link("dl")]
lib LibDL
LAZY = 1
GLOBAL = 8

struct Info
fname : LibC::Char*
fbase : Void*
sname : LibC::Char*
saddr : Void*
end

fun dladdr(addr : Void*, info : Info*) : LibC::Int
fun dlsym(handle : Void*, symbol : LibC::Char*) : Void*
fun dlopen(path : LibC::Char*, mode : LibC::Int) : Void*

ifdef darwin
RTLD_NEXT = Pointer(Void).new(-1)
RTLD_DEFAULT = Pointer(Void).new(-2)
RTLD_SELF = Pointer(Void).new(-3)
RTLD_MAIN_ONLY = Pointer(Void).new(-5)
else
RTLD_NEXT = Pointer(Void).new(-1)
RTLD_DEFAULT = Pointer(Void).new(0)
end
end
require "c/dlfcn"

module DL
def self.dlopen(path, mode = LibDL::LAZY | LibDL::GLOBAL) : Void*
LibDL.dlopen(path, mode)
def self.dlopen(path, mode = LibC::RTLD_LAZY | LibC::RTLD_GLOBAL) : Void*
LibC.dlopen(path, mode)
end
end
7 changes: 1 addition & 6 deletions src/env.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
lib LibC
$environ : Char**
fun getenv(name : Char*) : Char*?
fun setenv(name : Char*, value : Char*, overwrite : Int) : Int
fun unsetenv(name : Char*) : Int
end
require "c/stdlib"

# `ENV` is a hash-like accessor for environment variables.
#
Expand Down
Loading