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

Update to make it work with more recent gl_generator crate #3

Merged
merged 1 commit into from
Sep 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
[package]
name = "epoxy"
version = "0.0.2"
authors = ["Maxwell Koo <[email protected]>"]
build = "build/main.rs"
description = "Rust bindings for libepoxy, an OpenGL function pointer manager."
repository = "https://github.com/mjkoo/epoxy-rs"
license = "Apache-2.0"
keywords = ["epoxy", "libepoxy", "opengl", "gl", "gtk"]
build = "build/main.rs"
license = "Apache-2.0"
name = "epoxy"
repository = "https://github.com/mjkoo/epoxy-rs"
version = "0.0.2"

[build-dependencies]
gl_generator = "^0.1"
khronos_api = "^0"
gl_generator = "0.5.3"

[dependencies]
libc = "^0.1"
gl = "0.6.2"
gl_common = "^0.1"
libc = "^0.2"
shared_library = "0.1.5"

[features]
default = ["gl_generator/unstable_generator_utils"]
debug_marker = []
136 changes: 75 additions & 61 deletions build/epoxy_gen.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
// Based on StaticGenerator from `gl_generator` crate, original copyright below:
//
// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -15,39 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate gl_generator;

use gl_generator::registry::{Registry, Ns};
use std::io;

use gl_generator::{Cmd, Generator, Registry};
use gl_generator::generators::{gen_enum_item, gen_parameters, gen_symbol_name, gen_types};

#[allow(missing_copy_implementations)]
pub struct EpoxyGenerator;

impl gl_generator::generators::Generator for EpoxyGenerator {
fn write<W>(&self, registry: &Registry, ns: Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
impl Generator for EpoxyGenerator {
fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
where W: io::Write
{
try!(write_header(dest));
try!(write_metaloadfn(dest));
try!(write_type_aliases(&ns, dest));
try!(write_type_aliases(registry, dest));
try!(write_enums(registry, dest));
try!(write_fns(registry, dest));
try!(write_fnptr_struct_def(dest));
try!(write_ptrs(registry, dest));
try!(write_fn_mods(registry, &ns, dest));
try!(write_error_fns(&ns, dest));
try!(write_fn_mods(registry, dest));
try!(write_error_fns(dest));
try!(write_load_fn(registry, dest));
try!(write_get_proc_addr(registry, &ns, dest));
try!(write_get_proc_addr(registry, dest));
Ok(())
}
}

/// Creates a `__gl_imports` module which contains all the external symbols that we need for the bindings.
fn write_header<W>(dest: &mut W) -> io::Result<()> where W: io::Write {
writeln!(dest, r#"
/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
/// bindings.
fn write_header<W>(dest: &mut W) -> io::Result<()>
where W: io::Write
{
writeln!(dest,
r#"
mod __gl_imports {{
pub extern crate gl_common;
pub extern crate libc;
pub use std::mem;
pub use std::ptr;
pub use std::os::raw;
pub use std::process::exit;
}}
"#)
Expand All @@ -58,43 +62,46 @@ fn write_metaloadfn<W>(dest: &mut W) -> io::Result<()> where W: io::Write {
writeln!(dest, r#"
fn metaloadfn<F>(mut loadfn: F,
symbol: &str,
fallbacks: &[&str]) -> *const *const __gl_imports::libc::c_void
where F: FnMut(&str) -> *const __gl_imports::libc::c_void {{
fallbacks: &[&str]) -> *const *const __gl_imports::raw::c_void
where F: FnMut(&str) -> *const __gl_imports::raw::c_void {{
let mut ptr = loadfn(symbol);
if ptr.is_null() {{
for &sym in fallbacks.iter() {{
ptr = loadfn(sym);
if !ptr.is_null() {{ break; }}
}}
}}
ptr as *const *const __gl_imports::libc::c_void
ptr as *const *const __gl_imports::raw::c_void
}}
"#)
}

/// Creates a `types` module which contains all the type aliases.
///
/// See also `generators::gen_type_aliases`.
fn write_type_aliases<W>(ns: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
try!(writeln!(dest, r#"
/// See also `generators::gen_types`.
fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
where W: io::Write
{
try!(writeln!(dest,
r#"
pub mod types {{
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
#![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
"#));

try!(gl_generator::generators::gen_type_aliases(ns, dest));
try!(gen_types(registry.api, dest));

writeln!(dest, "
writeln!(dest,
"
}}
")
}

/// Creates all the `<enum>` elements at the root of the bindings.
fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
for e in registry.enum_iter() {
try!(gl_generator::generators::gen_enum_item(e, "types::", dest));
fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
where W: io::Write
{
for enm in &registry.enums {
try!(gen_enum_item(enm, "types::", dest));
}

Ok(())
Expand All @@ -105,7 +112,7 @@ fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W:
/// The function calls the corresponding function pointer stored in the `storage` module created
/// by `write_ptrs`.
fn write_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
for c in registry.cmd_iter() {
for c in &registry.cmds {
if let Some(v) = registry.aliases.get(&c.proto.ident) {
try!(writeln!(dest, "/// Fallbacks: {}", v.join(", ")));
}
Expand All @@ -117,30 +124,41 @@ fn write_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io
(*storage::{name}.pf)({idents})
}}"#,
name = c.proto.ident,
params = gl_generator::generators::gen_parameters(c, true, true).join(", "),
typed_params = gl_generator::generators::gen_parameters(c, false, true).join(", "),
return_suffix = gl_generator::generators::gen_return_type(c),
idents = gl_generator::generators::gen_parameters(c, true, false).join(", "),
params = gen_parameters(c, true, true).join(", "),
typed_params = gen_parameters(c, false, true).join(", "),
return_suffix = gen_return_type(c),
idents = gen_parameters(c, true, false).join(", "),
));
}

Ok(())
}

fn gen_return_type(cmd: &Cmd) -> String {
// turn the return type into a Rust type
let ty = &cmd.proto.ty;

// ... but there is one more step: if the Rust type is `c_void`, we replace it with `()`
if ty == "__gl_imports::raw::c_void" {
return "()".to_string();
}

ty.to_string()
}

/// Creates a `FnPtr` structure which contains the store for a single binding.
fn write_fnptr_struct_def<W>(dest: &mut W) -> io::Result<()> where W: io::Write {
writeln!(dest, "
#[allow(missing_copy_implementations)]
pub struct FnPtr {{
/// Pointer to the entry in libepoxy's dispatch table
pf: *const *const __gl_imports::libc::c_void,
pf: *const *const __gl_imports::raw::c_void,
/// True if the pointer points to a real function, false if points to an error fn
is_loaded: bool,
}}

impl FnPtr {{
/// Creates a `FnPtr` from a load attempt.
pub fn new(ptr: *const *const __gl_imports::libc::c_void) -> FnPtr {{
pub fn new(ptr: *const *const __gl_imports::raw::c_void) -> FnPtr {{
if ptr.is_null() {{
FnPtr {{
pf: &PMISSING_FN_EXIT,
Expand All @@ -158,11 +176,11 @@ fn write_fnptr_struct_def<W>(dest: &mut W) -> io::Result<()> where W: io::Write
fn write_ptrs<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
try!(writeln!(dest,
"mod storage {{
#![allow(non_snake_case)]
#![allow(non_snake_case, non_upper_case_globals)]
use super::PMISSING_FN_EXIT;
use super::FnPtr;"));

for c in registry.cmd_iter() {
for c in &registry.cmds {
try!(writeln!(dest,
"pub static mut {name}: FnPtr = FnPtr {{
pf: &PMISSING_FN_EXIT,
Expand All @@ -179,34 +197,32 @@ fn write_ptrs<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: i
///
/// Each module contains `is_loaded` and `load_with` which interact with the `storage` module
/// created by `write_ptrs`.
fn write_fn_mods<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
for c in registry.cmd_iter() {
fn write_fn_mods<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
for c in &registry.cmds {
let fallbacks = match registry.aliases.get(&c.proto.ident) {
Some(v) => {
let names = v.iter().map(|name| format!(r#""{}""#,
gl_generator::generators::gen_symbol_name(ns, &name[..]))).collect::<Vec<_>>();
gen_symbol_name(registry.api, &name[..]))).collect::<Vec<_>>();
format!("&[{}]", names.join(", "))
},
None => "&[]".to_string(),
};
let fnname = &c.proto.ident[..];
let symbol = gl_generator::generators::gen_symbol_name(ns, &c.proto.ident[..]);
let symbol = gen_symbol_name(registry.api, &c.proto.ident[..]);
let symbol = &symbol[..];

try!(writeln!(dest, r#"
#[allow(non_snake_case)]
pub mod {fnname} {{
use super::{{storage, metaloadfn}};
use super::FnPtr;

#[inline]
#[allow(dead_code)]
pub fn is_loaded() -> bool {{
unsafe {{ storage::{fnname}.is_loaded }}
}}

#[allow(dead_code)]
pub fn load_with<F>(loadfn: F) where F: FnMut(&str) -> *const super::__gl_imports::libc::c_void {{
pub fn load_with<F>(loadfn: F) where F: FnMut(&str) -> *const super::__gl_imports::raw::c_void {{
unsafe {{
storage::{fnname} = FnPtr::new(metaloadfn(loadfn, "epoxy_{symbol}", {fallbacks}))
}}
Expand All @@ -224,15 +240,14 @@ fn write_fn_mods<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> io::Result<()
/// Creates a `missing_fn_exit` function.
///
/// This function is the mock that is called if the real function could not be called.
fn write_error_fns<W>(ns: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
fn write_error_fns<W>(dest: &mut W) -> io::Result<()> where W: io::Write {
writeln!(dest, r#"
#[inline(never)]
extern fn missing_fn_exit() {{
println!("{ns} function was not loaded");
println!("function was not loaded");
__gl_imports::exit(1);
}}
const PMISSING_FN_EXIT: *const __gl_imports::libc::c_void = missing_fn_exit as *const __gl_imports::libc::c_void;"#,
ns = ns,
const PMISSING_FN_EXIT: *const __gl_imports::raw::c_void = missing_fn_exit as *const __gl_imports::raw::c_void;"#,
)
}

Expand All @@ -242,38 +257,37 @@ fn write_error_fns<W>(ns: &Ns, dest: &mut W) -> io::Result<()> where W: io::Writ
fn write_load_fn<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
try!(writeln!(dest, r#"
#[allow(dead_code)]
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const __gl_imports::libc::c_void {{
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const __gl_imports::raw::c_void {{
"#));

for c in registry.cmd_iter() {
for c in &registry.cmds {
try!(writeln!(dest, "{name}::load_with(|s| loadfn(s));",
name = &c.proto.ident[..]));
}

writeln!(dest, "
}}

#[allow(dead_code)]
pub fn load<T: __gl_imports::gl_common::GlFunctionsSource>(loader: &T) {{
load_with(|name| loader.get_proc_addr(name));
load_with(|name| loader.get_proc_addr(name) as _);
}}
")
}

/// Creates the `get_proc_addr` function.
///
/// The function adds in a layer of indirection, but allows compatibility with the `gl` crate
fn write_get_proc_addr<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> io::Result<()> where W: io::Write {
fn write_get_proc_addr<W>(registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write {
try!(writeln!(dest, r#"
#[allow(dead_code)]
pub fn get_proc_addr(symbol: &str) -> *const __gl_imports::libc::c_void {{
pub fn get_proc_addr(symbol: &str) -> *const __gl_imports::raw::c_void {{
match &symbol[..] {{
"#));

for c in registry.cmd_iter() {
for c in &registry.cmds {
try!(writeln!(dest, r#"
"{symbol}" => {name} as *const __gl_imports::libc::c_void,"#,
symbol = gl_generator::generators::gen_symbol_name(ns, &c.proto.ident[..]),
"{symbol}" => {name} as *const __gl_imports::raw::c_void,"#,
symbol = gen_symbol_name(registry.api, &c.proto.ident[..]),
name = &c.proto.ident[..],
));
}
Expand Down
Loading