Skip to content

Commit

Permalink
Fix issues with compiling for different platforms
Browse files Browse the repository at this point in the history
Fixes #9.
  • Loading branch information
Juici committed Aug 9, 2021
1 parent a49463a commit 864b75c
Show file tree
Hide file tree
Showing 11 changed files with 421 additions and 105 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[package]
name = "wchar"
version = "0.10.1"
version = "0.11.0"
authors = ["Juici <[email protected]>"]
description = "Procedural macros for compile time UTF-16 and UTF-32 wide strings."
edition = "2018"
license = "MIT OR Apache-2.0"
readme = "README.md"
build = "build.rs"

repository = "https://github.com/Juici/wchar-rs"
documentation = "https://docs.rs/wchar"
Expand All @@ -18,7 +19,7 @@ default = []
unstable = ["wchar-impl/unstable"]

[dependencies]
wchar-impl = { version = "0.10.0", path = "impl" }
wchar-impl = { version = "0.11.0", path = "impl" }

[dev-dependencies]
anyhow = "1.0"
Expand Down
294 changes: 294 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
use std::collections::HashMap;

macro_rules! consts {
($($arch:ident),* $(,)?) => {
$(
#[allow(non_upper_case_globals, dead_code)]
pub const $arch: &str = stringify!($arch);
)*
};
}

mod arch {
consts! {
aarch64,
arm,
hexagon,
mips,
mips64,
powerpc,
powerpc64,
riscv32,
riscv64,
sparc,
sparc64,
s390x,
xtensa,
x86,
x86_64,
}
}

mod os {
consts! {
android,
dragonfly,
emscripten,
freebsd,
fushia,
haiku,
hermit,
illumos,
ios,
linux,
l4re,
macos,
netbsd,
openbsd,
psp,
redox,
solaris,
switch,
vxworks,
wasi,
windows,
}
}

mod family {
consts! {
unix,
windows,
wasm,
}
}

mod env {
consts! {
gnu,
musl,
mvsc,
new_lib,
sgx,
uclibc,
wasi,
}
}

mod vendor {
consts! {
fortanix,
}
}

struct Cfg {
vars: HashMap<String, String>,
}

impl Cfg {
fn from_env() -> Cfg {
let vars: HashMap<String, String> = std::env::vars()
.filter(|(key, _)| key.starts_with("CARGO_CFG"))
.collect();

Cfg { vars }
}

fn cfg(&self, cfg: &str) -> Option<&str> {
let mut cfg = format!("CARGO_CFG_{}", cfg);
cfg["CARGO_CFG_".len()..].make_ascii_uppercase();

self.vars.get(&cfg).map(|s| s.as_str())
}

fn unix(&self) -> bool {
self.family() == Some(family::unix)
}

fn windows(&self) -> bool {
self.family() == Some(family::windows)
}

fn family(&self) -> Option<&str> {
self.cfg("target_family")
}

fn os(&self) -> Option<&str> {
self.cfg("target_os")
}

fn arch(&self) -> Option<&str> {
self.cfg("target_arch")
}

fn vendor(&self) -> Option<&str> {
self.cfg("target_vendor")
}

fn env(&self) -> Option<&str> {
self.cfg("target_env")
}

// fn pointer_width(&self) -> Option<&str> {
// self.cfg("target_pointer_width")
// }
//
// fn endian(&self) -> Option<&str> {
// self.cfg("target_endian")
// }
//
// fn feature(&self, value: &str) -> bool {
// self.features().any(|feature| feature == value)
// }
//
// fn features(&self) -> impl Iterator<Item = &str> {
// self.cfg("target_feature").unwrap_or_default().split(',')
// }
}

enum WChar {
U16,
U32,
I32,
Unknown,
}

fn main() {
let wchar_t = match get_platform_wchar() {
WChar::U16 => Some("u16"),
WChar::U32 => Some("u32"),
WChar::I32 => Some("i32"),
WChar::Unknown => None,
};

match wchar_t {
Some(wchar_t) => println!("cargo:rustc-cfg=wchar_t=\"{}\"", wchar_t),
None => println!("cargo:warning=unknown platform wchar_t"),
}
}

fn get_platform_wchar() -> WChar {
let cfg = Cfg::from_env();

if cfg.windows() {
return WChar::U16;
}

match cfg.os() {
Some(os::fushia) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
},
Some(os::switch) => WChar::U32,
Some(os::psp) => WChar::Unknown, // TODO: No info in libc.
Some(os::vxworks) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::x86 | arch::x86_64) => WChar::I32,
Some(arch::powerpc | arch::powerpc64) => WChar::U32,
_ => WChar::Unknown,
},
os if cfg.unix() => get_unix_wchar(&cfg, os),
Some(os::hermit) => get_hermit_wchar(&cfg),
os => {
let env = cfg.env();
if env == Some(env::sgx) || cfg.vendor() == Some(vendor::fortanix) {
WChar::Unknown // TODO: No info in libc.
} else if env == Some(env::wasi) || os == Some(os::wasi) {
WChar::I32
} else {
WChar::Unknown
}
}
}
}

fn get_unix_wchar(cfg: &Cfg, os: Option<&str>) -> WChar {
#[allow(non_upper_case_globals)]
const c_int: WChar = WChar::I32;
#[allow(non_upper_case_globals)]
const c_uint: WChar = WChar::U32;

let env = cfg.env();

if let Some(env::new_lib) = env {
return match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::powerpc) => c_int,
Some(arch::xtensa) => WChar::U32,
_ => WChar::Unknown,
};
}

match os {
Some(os::emscripten) => WChar::I32,
Some(os::linux | os::l4re) => match env {
Some(env::uclibc) => match cfg.arch() {
Some(arch::arm) => c_uint,
Some(arch::mips | arch::mips64) => WChar::I32,
Some(arch::x86_64) => c_int,
_ => WChar::Unknown,
},
Some(env::musl) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::hexagon) => WChar::U32,
Some(arch::mips) => c_int,
Some(arch::mips64) => WChar::I32,
Some(arch::powerpc | arch::powerpc64) => WChar::I32,
Some(arch::s390x) => WChar::I32,
Some(arch::x86 | arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
},
Some(env::gnu) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::mips | arch::mips64) => WChar::I32,
Some(arch::powerpc | arch::powerpc64) => WChar::I32,
Some(arch::riscv32 | arch::riscv64) => c_int,
Some(arch::sparc | arch::sparc64) => WChar::I32,
Some(arch::s390x) => WChar::I32,
Some(arch::x86 | arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
},
_ => WChar::Unknown,
},
Some(os::android) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::x86 | arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
},

Some(os::ios | os::macos) => WChar::I32,
Some(os::openbsd | os::netbsd) => WChar::I32,
Some(os::dragonfly) => WChar::I32,
Some(os::freebsd) => match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::arm) => WChar::U32,
Some(arch::powerpc64) => WChar::I32,
Some(arch::x86 | arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
},

Some(os::solaris | os::illumos) => c_int,

Some(os::haiku) => WChar::I32,

Some(os::hermit) => get_hermit_wchar(cfg),

Some(os::redox) => WChar::I32,

_ => WChar::Unknown,
}
}

fn get_hermit_wchar(cfg: &Cfg) -> WChar {
match cfg.arch() {
Some(arch::aarch64) => WChar::U32,
Some(arch::x86_64) => WChar::I32,
_ => WChar::Unknown,
}
}
4 changes: 1 addition & 3 deletions impl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wchar-impl"
version = "0.10.0"
version = "0.11.0"
authors = ["Juici <[email protected]>"]
description = "Internal implementation of wchar."
edition = "2018"
Expand All @@ -19,5 +19,3 @@ unstable = ["proc-macro2/nightly"]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", default-features = false, features = ["parsing", "printing", "proc-macro"] }

libc = { version = "0.2.94", default-features = false }
33 changes: 15 additions & 18 deletions impl/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use syn::{Error, LitChar, Result};

use crate::parse::WCharType;

pub fn expand_char(ty: Option<WCharType>, c: LitChar) -> Result<TokenStream> {
pub fn expand_char(ty: WCharType, c: LitChar) -> Result<TokenStream> {
fn quote_char<T: Encode>(c: LitChar) -> Result<TokenStream> {
match T::encode_char(c.value()) {
Some(c) => Ok(quote::quote! { #c }),
Expand All @@ -22,41 +22,38 @@ pub fn expand_char(ty: Option<WCharType>, c: LitChar) -> Result<TokenStream> {
}

match ty {
Some(WCharType::U16(_)) => quote_char::<u16>(c),
Some(WCharType::U32(_)) => quote_char::<u32>(c),
Some(WCharType::I16(_)) => quote_char::<i16>(c),
Some(WCharType::I32(_)) => quote_char::<i32>(c),
None => quote_char::<libc::wchar_t>(c),
WCharType::U16(_) => quote_char::<u16>(c),
WCharType::U32(_) => quote_char::<u32>(c),
WCharType::I16(_) => quote_char::<i16>(c),
WCharType::I32(_) => quote_char::<i32>(c),
}
}

pub fn expand_str(ty: Option<WCharType>, text: &str) -> TokenStream {
pub fn expand_str(ty: WCharType, text: &str) -> TokenStream {
fn quote_str<T: Encode>(text: &str) -> TokenStream {
let chars = T::encode_str(text);
quote::quote! { &[#(#chars),*] }
}

match ty {
Some(WCharType::U16(_)) => quote_str::<u16>(text),
Some(WCharType::U32(_)) => quote_str::<u32>(text),
Some(WCharType::I16(_)) => quote_str::<i16>(text),
Some(WCharType::I32(_)) => quote_str::<i32>(text),
None => quote_str::<libc::wchar_t>(text),
WCharType::U16(_) => quote_str::<u16>(text),
WCharType::U32(_) => quote_str::<u32>(text),
WCharType::I16(_) => quote_str::<i16>(text),
WCharType::I32(_) => quote_str::<i32>(text),
}
}

pub fn expand_str_c(ty: Option<WCharType>, text: &str) -> TokenStream {
pub fn expand_str_c(ty: WCharType, text: &str) -> TokenStream {
fn quote_str_c<T: Encode>(text: &str) -> TokenStream {
let chars = T::encode_str_c(text);
quote::quote! { &[#(#chars),*] }
}

match ty {
Some(WCharType::U16(_)) => quote_str_c::<u16>(text),
Some(WCharType::U32(_)) => quote_str_c::<u32>(text),
Some(WCharType::I16(_)) => quote_str_c::<i16>(text),
Some(WCharType::I32(_)) => quote_str_c::<i32>(text),
None => quote_str_c::<libc::wchar_t>(text),
WCharType::U16(_) => quote_str_c::<u16>(text),
WCharType::U32(_) => quote_str_c::<u32>(text),
WCharType::I16(_) => quote_str_c::<i16>(text),
WCharType::I32(_) => quote_str_c::<i32>(text),
}
}

Expand Down
Loading

0 comments on commit 864b75c

Please sign in to comment.