Skip to content

Commit

Permalink
Support building projects for FreeBSD
Browse files Browse the repository at this point in the history
This adds basic FreeBSD support. Basic, because it works for my few
cases. There are two major differences from how things works for Linux
and rest platforms:

The first is that there is no custom suffix for produced `.so` files
and `imp.get_suffixes()` confirms that.

The second is more complicated. There is no universal platform tag which
covers some OS release. In fact, it includes information about:
- OS version (11_2, 12_0),
- release type (RELEASE, STABLE)
- and patch set (p1, p7, etc).

While first two are pretty well known and could be simply hardcoded
to maintain support for a many years, patch set is very generic and
changes once any security or system fixes get issued for specific
release. From point of FreeBSD it's the same system with the same
compatibility guarantees. From point of Python it's a completely
different platform which is not compatible with the others patches
for the same OS version and release.

That means that wheels need to be rebuild (or just renamed) if system
receives any patch set update.
  • Loading branch information
kxepal committed Aug 19, 2019
1 parent 0bc3dda commit f6352ea
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 17 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ cbindgen = { version = "0.9.0", default-features = false }
walkdir = "2.2.8"
flate2 = "1.0.9"
tar = "0.4.26"
platform-info = "0.0.1"

[dev-dependencies]
indoc = "0.3.3"
Expand Down
16 changes: 13 additions & 3 deletions src/python_interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ pub struct PythonInterpreter {
///
/// See PEP 261 and PEP 393 for details
pub abiflags: String,
/// Currently just the value of [Target::os()], i.e. "windows", "linux" or
/// "macos"
/// Currently just the value of [Target::os()], i.e. "windows", "linux",
/// "macos" or "freebsd"
pub target: Target,
/// Path to the python interpreter, e.g. /usr/bin/python3.6
///
Expand Down Expand Up @@ -308,6 +308,7 @@ fn fun_with_abiflags(
"win32" | "win_amd64" => target.is_windows(),
"linux" | "linux2" | "linux3" => target.is_linux(),
"darwin" => target.is_macos(),
"freebsd11" | "freebsd12" | "freebsd13" => target.is_freebsd(),
_ => false,
};

Expand Down Expand Up @@ -420,6 +421,7 @@ impl PythonInterpreter {
/// Linux: steinlaus.cpython-35m-x86_64-linux-gnu.so
/// Windows: steinlaus.cp35-win_amd64.pyd
/// Mac: steinlaus.cpython-35m-darwin.so
/// FreeBSD: steinlaus.cpython-35m.so
///
/// For pypy3, we read sysconfig.get_config_var("EXT_SUFFIX").
///
Expand All @@ -430,7 +432,15 @@ impl PythonInterpreter {
Interpreter::CPython => {
let platform = self.target.get_shared_platform_tag();

if self.target.is_unix() {
if self.target.is_freebsd() {
format!(
"{base}.cpython-{major}{minor}{abiflags}.so",
base = base,
major = self.major,
minor = self.minor,
abiflags = self.abiflags,
)
} else if self.target.is_unix() {
format!(
"{base}.cpython-{major}{minor}{abiflags}-{platform}.so",
base = base,
Expand Down
51 changes: 37 additions & 14 deletions src/target.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use failure::{bail, format_err, Error};
use platform_info::*;
use platforms;
use platforms::target::Arch;
use serde::{Deserialize, Serialize};
Expand All @@ -14,6 +15,7 @@ enum OS {
Linux,
Windows,
Macos,
FreeBSD,
}

/// Decides how to handle manylinux compliance
Expand Down Expand Up @@ -60,6 +62,7 @@ impl Target {
"linux" => OS::Linux,
"windows" => OS::Windows,
"macos" => OS::Macos,
"freebsd" => OS::FreeBSD,
unsupported => panic!("The platform {} is not supported", unsupported),
};

Expand Down Expand Up @@ -89,6 +92,7 @@ impl Target {
platforms::target::OS::Linux => OS::Linux,
platforms::target::OS::Windows => OS::Windows,
platforms::target::OS::MacOS => OS::Macos,
platforms::target::OS::FreeBSD => OS::FreeBSD,
unsupported => bail!("The operating system {:?} is not supported", unsupported),
};

Expand Down Expand Up @@ -120,6 +124,11 @@ impl Target {
self.os == OS::Linux
}

/// Returns true if the current platform is freebsd
pub fn is_freebsd(&self) -> bool {
self.os == OS::FreeBSD
}

/// Returns true if the current platform is mac os
pub fn is_macos(&self) -> bool {
self.os == OS::Macos
Expand All @@ -131,22 +140,35 @@ impl Target {
}

/// Returns the platform part of the tag for the wheel name for cffi wheels
pub fn get_platform_tag(&self, manylinux: &Manylinux) -> &'static str {
pub fn get_platform_tag(&self, manylinux: &Manylinux) -> String {
match (&self.os, self.is_64_bit, manylinux) {
(&OS::Linux, true, Manylinux::Off) => "linux_x86_64",
(&OS::Linux, false, Manylinux::Off) => "linux_i686",
(&OS::Linux, true, Manylinux::Manylinux1) => "manylinux1_x86_64",
(&OS::Linux, true, Manylinux::Manylinux1Unchecked) => "manylinux1_x86_64",
(&OS::Linux, true, Manylinux::Manylinux2010) => "manylinux2010_x86_64",
(&OS::Linux, true, Manylinux::Manylinux2010Unchecked) => "manylinux2010_x86_64",
(&OS::Linux, false, Manylinux::Manylinux1) => "manylinux1_i686",
(&OS::Linux, false, Manylinux::Manylinux1Unchecked) => "manylinux1_i686",
(&OS::Linux, false, Manylinux::Manylinux2010) => "manylinux2010_i686",
(&OS::Linux, false, Manylinux::Manylinux2010Unchecked) => "manylinux2010_i686",
(&OS::Windows, true, _) => "win_amd64",
(&OS::Windows, false, _) => "win32",
(&OS::Macos, true, _) => "macosx_10_7_x86_64",
(&OS::Linux, true, Manylinux::Off) => "linux_x86_64".to_string(),
(&OS::Linux, false, Manylinux::Off) => "linux_i686".to_string(),
(&OS::Linux, true, Manylinux::Manylinux1) => "manylinux1_x86_64".to_string(),
(&OS::Linux, true, Manylinux::Manylinux1Unchecked) => "manylinux1_x86_64".to_string(),
(&OS::Linux, true, Manylinux::Manylinux2010) => "manylinux2010_x86_64".to_string(),
(&OS::Linux, true, Manylinux::Manylinux2010Unchecked) => {
"manylinux2010_x86_64".to_string()
}
(&OS::Linux, false, Manylinux::Manylinux1) => "manylinux1_i686".to_string(),
(&OS::Linux, false, Manylinux::Manylinux1Unchecked) => "manylinux1_i686".to_string(),
(&OS::Linux, false, Manylinux::Manylinux2010) => "manylinux2010_i686".to_string(),
(&OS::Linux, false, Manylinux::Manylinux2010Unchecked) => {
"manylinux2010_i686".to_string()
}
(&OS::Windows, true, _) => "win_amd64".to_string(),
(&OS::Windows, false, _) => "win32".to_string(),
(&OS::Macos, true, _) => "macosx_10_7_x86_64".to_string(),
(&OS::Macos, false, _) => panic!("32-bit wheels are not supported for mac os"),
(&OS::FreeBSD, true, _) => {
let info = match PlatformInfo::new() {
Ok(info) => info,
Err(error) => panic!(error),
};
let release = info.release().replace(".", "_").replace("-", "_");
format!("freebsd_{}_amd64", release)
}
(&OS::FreeBSD, false, _) => panic!("32-bit wheels are not supported for FreeBSD"),
}
}

Expand All @@ -169,6 +191,7 @@ impl Target {
}
}
OS::Macos => "darwin",
OS::FreeBSD => "", // according imp.get_suffixes(), there are no such
OS::Windows => {
if self.is_64_bit {
"win_amd64"
Expand Down

0 comments on commit f6352ea

Please sign in to comment.