Remove Rust from the tree.

Part 4 for #58
This commit is contained in:
wolfbeast 2018-03-13 13:38:57 +01:00 committed by Roy Tam
commit 963560a1d2
496 changed files with 4 additions and 788702 deletions

View file

@ -1,166 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-rust', help='Include Rust language sources')
@depends('--enable-rust')
def rust_compiler_names(value):
if value:
return ['rustc']
@depends('--enable-rust')
def cargo_binary_names(value):
if value:
return ['cargo']
rustc = check_prog('RUSTC', rust_compiler_names, allow_missing=True)
cargo = check_prog('CARGO', cargo_binary_names, allow_missing=True)
@depends_if(rustc)
@checking('rustc version', lambda info: info.version)
def rustc_info(rustc):
out = check_cmd_output(rustc, '--version', '--verbose').splitlines()
info = dict((s.strip() for s in line.split(':', 1)) for line in out[1:])
return namespace(
version=Version(info.get('release', '0')),
commit=info.get('commit-hash', 'unknown'),
)
@depends_if(cargo)
@checking('cargo support for --frozen')
@imports('subprocess')
@imports('os')
def cargo_supports_frozen(cargo):
try:
lines = subprocess.check_output(
[cargo, 'help', 'build']
).splitlines()
supported = any(' --frozen' in l for l in lines)
if 'MOZ_AUTOMATION' in os.environ and not supported:
die('cargo in automation must support --frozen')
return supported
except subprocess.CalledProcessError as e:
die('Failed to call cargo: %s', e.message)
set_config('MOZ_CARGO_SUPPORTS_FROZEN', cargo_supports_frozen)
@depends('--enable-rust', rustc, rustc_info)
@imports(_from='textwrap', _import='dedent')
def rust_compiler(value, rustc, rustc_info):
if value:
if not rustc:
die(dedent('''\
Rust compiler not found.
To compile rust language sources, you must have 'rustc' in your path.
See https//www.rust-lang.org/ for more information.
'''))
version = rustc_info.version
min_version = Version('1.10')
if version < min_version:
die(dedent('''\
Rust compiler {} is too old.
To compile Rust language sources please install at least
version {} of the 'rustc' toolchain and make sure it is
first in your path.
You can verify this by typing 'rustc --version'.
'''.format(version, min_version)))
return True
set_config('MOZ_RUST', rust_compiler)
@depends(rust_compiler, rustc, target, cross_compiling)
@imports('os')
@imports('subprocess')
@imports(_from='mozbuild.configure.util', _import='LineIO')
@imports(_from='mozbuild.shellutil', _import='quote')
@imports(_from='tempfile', _import='mkstemp')
def rust_target(rust_compiler, rustc, target, cross_compiling):
if rust_compiler:
# Rust's --target options are similar to, but not exactly the same
# as, the autoconf-derived targets we use. An example would be that
# Rust uses distinct target triples for targetting the GNU C++ ABI
# and the MSVC C++ ABI on Win32, whereas autoconf has a single
# triple and relies on the user to ensure that everything is
# compiled for the appropriate ABI. We need to perform appropriate
# munging to get the correct option to rustc.
#
# The canonical list of targets supported can be derived from:
#
# https://github.com/rust-lang/rust/tree/master/mk/cfg
# Avoid having to write out os+kernel for all the platforms where
# they don't differ.
os_or_kernel = target.kernel if target.kernel == 'Linux' and target.os != 'Android' else target.os
rustc_target = {
# DragonFly
('x86_64', 'DragonFly'): 'x86_64-unknown-dragonfly',
# FreeBSD
('x86', 'FreeBSD'): 'i686-unknown-freebsd',
('x86_64', 'FreeBSD'): 'x86_64-unknown-freebsd',
# NetBSD
('x86_64', 'NetBSD'): 'x86_64-unknown-netbsd',
# OpenBSD
('x86_64', 'OpenBSD'): 'x86_64-unknown-openbsd',
# Linux
('x86', 'Linux'): 'i586-unknown-linux-gnu',
# Linux
('x86_64', 'Linux'): 'x86_64-unknown-linux-gnu',
# OS X and iOS
('x86', 'OSX'): 'i686-apple-darwin',
('x86', 'iOS'): 'i386-apple-ios',
('x86_64', 'OSX'): 'x86_64-apple-darwin',
# Android
('x86', 'Android'): 'i686-linux-android',
('arm', 'Android'): 'armv7-linux-androideabi',
# Windows
# XXX better detection of CXX needed here, to figure out whether
# we need i686-pc-windows-gnu instead, since mingw32 builds work.
('x86', 'WINNT'): 'i686-pc-windows-msvc',
('x86_64', 'WINNT'): 'x86_64-pc-windows-msvc',
}.get((target.cpu, os_or_kernel), None)
if rustc_target is None:
die("Don't know how to translate {} for rustc".format(target.alias))
# Check to see whether our rustc has a reasonably functional stdlib
# for our chosen target.
target_arg = '--target=' + rustc_target
in_fd, in_path = mkstemp(prefix='conftest', suffix='.rs')
out_fd, out_path = mkstemp(prefix='conftest', suffix='.rlib')
os.close(out_fd)
try:
source = 'pub extern fn hello() { println!("Hello world"); }'
log.debug('Creating `%s` with content:', in_path)
with LineIO(lambda l: log.debug('| %s', l)) as out:
out.write(source)
os.write(in_fd, source)
os.close(in_fd)
cmd = [
rustc,
'--crate-type', 'staticlib',
target_arg,
'-o', out_path,
in_path,
]
def failed():
die('Cannot compile for {} with {}'.format(target.alias, rustc))
check_cmd_output(*cmd, onerror=failed)
if not os.path.exists(out_path) or os.path.getsize(out_path) == 0:
failed()
finally:
os.remove(in_path)
os.remove(out_path)
# This target is usable.
return rustc_target
set_config('RUST_TARGET', rust_target)
# Until we remove all the other Rust checks in old-configure.
add_old_configure_assignment('MOZ_RUST', rust_compiler)
add_old_configure_assignment('RUSTC', rustc)
add_old_configure_assignment('RUST_TARGET', rust_target)

View file

@ -907,4 +907,3 @@ set_config('WRAP_SYSTEM_INCLUDES', wrap_system_includes)
set_config('VISIBILITY_FLAGS', visibility_flags)
include('windows.configure')
include('rust.configure')

View file

@ -1,10 +0,0 @@
# Options to enable rust in automation builds.
# Tell configure to use the tooltool rustc.
# Assume this is compiled with --enable-rpath so we don't
# have to set LD_LIBRARY_PATH.
RUSTC="$topsrcdir/rustc/bin/rustc"
CARGO="$topsrcdir/cargo/bin/cargo"
# Enable rust in the build.
ac_add_options --enable-rust

View file

@ -60,14 +60,6 @@ def Library(name):
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
@template
def SharedLibrary(name):
'''Template for shared libraries.'''

View file

@ -905,44 +905,6 @@ $(ASOBJS):
$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
endif
ifdef MOZ_RUST
ifdef RUST_LIBRARY_FILE
# Permit users to pass flags to cargo from their mozconfigs (e.g. --color=always).
cargo_build_flags = $(CARGOFLAGS)
ifndef MOZ_DEBUG
cargo_build_flags = --release
endif
ifdef MOZ_CARGO_SUPPORTS_FROZEN
cargo_build_flags += --frozen
endif
cargo_build_flags += --manifest-path $(CARGO_FILE)
cargo_build_flags += --target=$(RUST_TARGET)
cargo_build_flags += --verbose
# Enable color output if original stdout was a TTY and color settings
# aren't already present. This essentially restores the default behavior
# of cargo when running via `mach`.
ifdef MACH_STDOUT_ISATTY
ifeq (,$(findstring --color,$(cargo_build_flags)))
cargo_build_flags += --color=always
endif
endif
# Assume any system libraries rustc links against are already in the target's LIBS.
#
# We need to run cargo unconditionally, because cargo is the only thing that
# has full visibility into how changes in Rust sources might affect the final
# build.
force-cargo-build:
$(REPORT_BUILD)
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
$(RUST_LIBRARY_FILE): force-cargo-build
endif # CARGO_FILE
endif # MOZ_RUST
$(SOBJS):
$(REPORT_BUILD)
$(AS) -o $@ $(DEFINES) $(ASFLAGS) $($(notdir $<)_FLAGS) $(LOCAL_INCLUDES) -c $<

View file

@ -35,10 +35,6 @@ if CONFIG['MOZ_WEBM_ENCODER']:
'TestWebMWriter.cpp',
]
if CONFIG['MOZ_RUST']:
UNIFIED_SOURCES += ['TestRust.cpp',]
TEST_HARNESS_FILES.gtest += [
'../test/gizmo-frag.mp4',
'../test/gizmo.mp4',

View file

@ -37,13 +37,4 @@ TEST_HARNESS_FILES.gtest += [
'test_case_1351094.mp4',
]
if CONFIG['MOZ_RUST']:
UNIFIED_SOURCES += ['TestMP4Rust.cpp',]
TEST_HARNESS_FILES.gtest += [
'../../../dom/media/test/street.mp4',
]
LOCAL_INCLUDES += [
'../binding/include',
]
FINAL_LIBRARY = 'xul-gtest'

View file

@ -80,11 +80,6 @@ SOURCES += [
'system/core/libutils/VectorImpl.cpp',
]
if CONFIG['MOZ_RUST']:
EXPORTS += [
'binding/include/mp4parse.h',
]
UNIFIED_SOURCES += [
'binding/Adts.cpp',
'binding/AnnexB.cpp',

View file

@ -6060,7 +6060,6 @@ export MOZ_ZLIB_CFLAGS
export MOZ_ZLIB_LIBS
export MOZ_APP_NAME
export MOZ_APP_REMOTINGNAME
export RUSTC
export MOZILLA_CENTRAL_PATH=$_topsrcdir
export STLPORT_CPPFLAGS
export STLPORT_LIBS

View file

@ -59,7 +59,6 @@ from ..frontend.data import (
ObjdirPreprocessedFiles,
PerSourceFlag,
Program,
RustLibrary,
SharedLibrary,
SimpleProgram,
Sources,
@ -574,12 +573,6 @@ class RecursiveMakeBackend(CommonBackend):
else:
return False
elif isinstance(obj, RustLibrary):
self.backend_input_files.add(obj.cargo_file)
self._process_rust_library(obj, backend_file)
# No need to call _process_linked_libraries, because Rust
# libraries are self-contained objects at this point.
elif isinstance(obj, SharedLibrary):
self._process_shared_library(obj, backend_file)
self._process_linked_libraries(obj, backend_file)
@ -1172,10 +1165,6 @@ class RecursiveMakeBackend(CommonBackend):
if libdef.no_expand_lib:
backend_file.write('NO_EXPAND_LIBS := 1\n')
def _process_rust_library(self, libdef, backend_file):
backend_file.write_once('RUST_LIBRARY_FILE := %s\n' % libdef.import_name)
backend_file.write('CARGO_FILE := $(srcdir)/Cargo.toml')
def _process_host_library(self, libdef, backend_file):
backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
@ -1186,7 +1175,7 @@ class RecursiveMakeBackend(CommonBackend):
def _process_linked_libraries(self, obj, backend_file):
def write_shared_and_system_libs(lib):
for l in lib.linked_libraries:
if isinstance(l, (StaticLibrary, RustLibrary)):
if isinstance(l, StaticLibrary):
write_shared_and_system_libs(l)
else:
backend_file.write_once('SHARED_LIBS += %s/%s\n'
@ -1208,11 +1197,7 @@ class RecursiveMakeBackend(CommonBackend):
self._build_target_for_obj(lib))
relpath = pretty_relpath(lib)
if isinstance(obj, Library):
if isinstance(lib, RustLibrary):
# We don't need to do anything here; we will handle
# linkage for any RustLibrary elsewhere.
continue
elif isinstance(lib, StaticLibrary):
if isinstance(lib, StaticLibrary):
backend_file.write_once('STATIC_LIBS += %s/%s\n'
% (relpath, lib.import_name))
if isinstance(obj, SharedLibrary):
@ -1235,12 +1220,6 @@ class RecursiveMakeBackend(CommonBackend):
backend_file.write_once('HOST_LIBS += %s/%s\n'
% (relpath, lib.import_name))
# We have to link any Rust libraries after all intermediate static
# libraries have been listed to ensure that the Rust libraries are
# searched after the C/C++ objects that might reference Rust symbols.
if isinstance(obj, SharedLibrary):
self._process_rust_libraries(obj, backend_file, pretty_relpath)
for lib in obj.linked_system_libs:
if obj.KIND == 'target':
backend_file.write_once('OS_LIBS += %s\n' % lib)
@ -1250,23 +1229,6 @@ class RecursiveMakeBackend(CommonBackend):
# Process library-based defines
self._process_defines(obj.lib_defines, backend_file)
def _process_rust_libraries(self, obj, backend_file, pretty_relpath):
assert isinstance(obj, SharedLibrary)
# If this library does not depend on any Rust libraries, then we are done.
direct_linked = [l for l in obj.linked_libraries if isinstance(l, RustLibrary)]
if not direct_linked:
return
# We should have already checked this in Linkable.link_library.
assert len(direct_linked) == 1
# TODO: see bug 1310063 for checking dependencies are set up correctly.
direct_linked = direct_linked[0]
backend_file.write('RUST_STATIC_LIB_FOR_SHARED_LIB := %s/%s\n' %
(pretty_relpath(direct_linked), direct_linked.import_name))
def _process_final_target_files(self, obj, files, backend_file):
target = obj.install_target
path = mozpath.basedir(target, (
@ -1445,11 +1407,6 @@ class RecursiveMakeBackend(CommonBackend):
self._makefile_out_count += 1
def _handle_linked_rust_crates(self, obj, extern_crate_file):
backend_file = self._get_backend_file_for(obj)
backend_file.write('RS_STATICLIB_CRATE_SRC := %s\n' % extern_crate_file)
def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources,
unified_ipdl_cppsrcs_mapping):
# Write out a master list of all IPDL source files.

View file

@ -310,10 +310,6 @@ class LinkageWrongKindError(Exception):
"""Error thrown when trying to link objects of the wrong kind"""
class LinkageMultipleRustLibrariesError(Exception):
"""Error thrown when trying to link multiple Rust libraries to an object"""
class Linkable(ContextDerived):
"""Generic context derived container object for programs and libraries"""
__slots__ = (
@ -337,13 +333,6 @@ class Linkable(ContextDerived):
'Linkable.link_library() does not take components.')
if obj.KIND != self.KIND:
raise LinkageWrongKindError('%s != %s' % (obj.KIND, self.KIND))
# Linking multiple Rust libraries into an object would result in
# multiple copies of the Rust standard library, as well as linking
# errors from duplicate symbols.
if isinstance(obj, RustLibrary) and any(isinstance(l, RustLibrary)
for l in self.linked_libraries):
raise LinkageMultipleRustLibrariesError("Cannot link multiple Rust libraries into %s",
self)
self.linked_libraries.append(obj)
if obj.cxx_link:
self.cxx_link = True
@ -474,40 +463,6 @@ class StaticLibrary(Library):
self.no_expand_lib = no_expand_lib
class RustLibrary(StaticLibrary):
"""Context derived container object for a static library"""
__slots__ = (
'cargo_file',
'crate_type',
'dependencies',
'deps_path',
)
def __init__(self, context, basename, cargo_file, crate_type, dependencies, **args):
StaticLibrary.__init__(self, context, basename, **args)
self.cargo_file = cargo_file
self.crate_type = crate_type
# We need to adjust our naming here because cargo replaces '-' in
# package names defined in Cargo.toml with underscores in actual
# filenames. But we need to keep the basename consistent because
# many other things in the build system depend on that.
assert self.crate_type == 'staticlib'
self.lib_name = '%s%s%s' % (context.config.lib_prefix,
basename.replace('-', '_'),
context.config.lib_suffix)
self.dependencies = dependencies
# cargo creates several directories and places its build artifacts
# in those directories. The directory structure depends not only
# on the target, but also what sort of build we are doing.
rust_build_kind = 'release'
if context.config.substs.get('MOZ_DEBUG'):
rust_build_kind = 'debug'
build_dir = mozpath.join(context.config.substs['RUST_TARGET'],
rust_build_kind)
self.import_name = mozpath.join(build_dir, self.lib_name)
self.deps_path = mozpath.join(build_dir, 'deps')
class SharedLibrary(Library):
"""Context derived container object for a shared library"""
__slots__ = (

View file

@ -61,7 +61,6 @@ from .data import (
PreprocessedTestWebIDLFile,
PreprocessedWebIDLFile,
Program,
RustLibrary,
SdkFiles,
SharedLibrary,
SimpleProgram,
@ -198,7 +197,7 @@ class TreeMetadataEmitter(LoggingMixin):
def _emit_libs_derived(self, contexts):
# First do FINAL_LIBRARY linkage.
for lib in (l for libs in self._libs.values() for l in libs):
if not isinstance(lib, (StaticLibrary, RustLibrary)) or not lib.link_into:
if not isinstance(lib, StaticLibrary) or not lib.link_into:
continue
if lib.link_into not in self._libs:
raise SandboxValidationError(
@ -408,66 +407,6 @@ class TreeMetadataEmitter(LoggingMixin):
'%s %s of crate %s refers to a non-existent path' % (description, dep_crate_name, crate_name),
context)
def _rust_library(self, context, libname, static_args):
# We need to note any Rust library for linking purposes.
cargo_file = mozpath.join(context.srcdir, 'Cargo.toml')
if not os.path.exists(cargo_file):
raise SandboxValidationError(
'No Cargo.toml file found in %s' % cargo_file, context)
config = self._parse_cargo_file(cargo_file)
crate_name = config['package']['name']
if crate_name != libname:
raise SandboxValidationError(
'library %s does not match Cargo.toml-defined package %s' % (libname, crate_name),
context)
# Check that the [lib.crate-type] field is correct
lib_section = config.get('lib', None)
if not lib_section:
raise SandboxValidationError(
'Cargo.toml for %s has no [lib] section' % libname,
context)
crate_type = lib_section.get('crate-type', None)
if not crate_type:
raise SandboxValidationError(
'Can\'t determine a crate-type for %s from Cargo.toml' % libname,
context)
crate_type = crate_type[0]
if crate_type != 'staticlib':
raise SandboxValidationError(
'crate-type %s is not permitted for %s' % (crate_type, libname),
context)
# Check that the [profile.{dev,release}.panic] field is "abort"
profile_section = config.get('profile', None)
if not profile_section:
raise SandboxValidationError(
'Cargo.toml for %s has no [profile] section' % libname,
context)
for profile_name in ['dev', 'release']:
profile = profile_section.get(profile_name, None)
if not profile:
raise SandboxValidationError(
'Cargo.toml for %s has no [profile.%s] section' % (libname, profile_name),
context)
panic = profile.get('panic', None)
if panic != 'abort':
raise SandboxValidationError(
('Cargo.toml for %s does not specify `panic = "abort"`'
' in [profile.%s] section') % (libname, profile_name),
context)
dependencies = set(config.get('dependencies', {}).iterkeys())
return RustLibrary(context, libname, cargo_file, crate_type,
dependencies, **static_args)
def _handle_linkables(self, context, passthru, generated_files):
linkables = []
host_linkables = []
@ -688,11 +627,7 @@ class TreeMetadataEmitter(LoggingMixin):
'generate_symbols_file', lib.symbols_file,
[symbols_file], defines)
if static_lib:
is_rust_library = context.get('IS_RUST_LIBRARY')
if is_rust_library:
lib = self._rust_library(context, libname, static_args)
else:
lib = StaticLibrary(context, libname, **static_args)
lib = StaticLibrary(context, libname, **static_args)
self._libs[libname].append(lib)
self._linkage.append((context, lib, 'USE_LIBS'))
linkables.append(lib)

View file

@ -1,18 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[dependencies]
deep-crate = { version = "0.1.0", path = "the/depths" }
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,6 +0,0 @@
[package]
name = "shallow-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]

View file

@ -1,9 +0,0 @@
[package]
name = "deep-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[dependencies]
shallow-crate = { path = "../../shallow" }

View file

@ -1,27 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
Library('test')
DIRS += [
'rust1',
'rust2',
]
USE_LIBS += [
'rust1',
'rust2',
]

View file

@ -1,15 +0,0 @@
[package]
name = "rust1"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,4 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
RustLibrary('rust1')

View file

@ -1,15 +0,0 @@
[package]
name = "rust2"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,4 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
RustLibrary('rust2')

View file

@ -1,15 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,15 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["dylib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,12 +0,0 @@
[package]
name = "deterministic-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,12 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,12 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[profile.release]
panic = "abort"

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -1,14 +0,0 @@
[package]
name = "random-crate"
version = "0.1.0"
authors = [
"Nobody <nobody@mozilla.org>",
]
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "unwind"
[profile.release]

View file

@ -1,18 +0,0 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
@template
def Library(name):
'''Template for libraries.'''
LIBRARY_NAME = name
@template
def RustLibrary(name):
'''Template for Rust libraries.'''
Library(name)
IS_RUST_LIBRARY = True
RustLibrary('random-crate')

View file

@ -31,7 +31,6 @@ from mozbuild.frontend.data import (
LinkageMultipleRustLibrariesError,
LocalInclude,
Program,
RustLibrary,
SdkFiles,
SharedLibrary,
SimpleProgram,
@ -1021,78 +1020,6 @@ class TestEmitterBasic(unittest.TestCase):
'Only source directory paths allowed in FINAL_TARGET_PP_FILES:'):
self.read_topsrcdir(reader)
def test_rust_library_no_cargo_toml(self):
'''Test that defining a RustLibrary without a Cargo.toml fails.'''
reader = self.reader('rust-library-no-cargo-toml')
with self.assertRaisesRegexp(SandboxValidationError,
'No Cargo.toml file found'):
self.read_topsrcdir(reader)
def test_rust_library_name_mismatch(self):
'''Test that defining a RustLibrary that doesn't match Cargo.toml fails.'''
reader = self.reader('rust-library-name-mismatch')
with self.assertRaisesRegexp(SandboxValidationError,
'library.*does not match Cargo.toml-defined package'):
self.read_topsrcdir(reader)
def test_rust_library_no_lib_section(self):
'''Test that a RustLibrary Cargo.toml with no [lib] section fails.'''
reader = self.reader('rust-library-no-lib-section')
with self.assertRaisesRegexp(SandboxValidationError,
'Cargo.toml for.* has no \\[lib\\] section'):
self.read_topsrcdir(reader)
def test_rust_library_no_profile_section(self):
'''Test that a RustLibrary Cargo.toml with no [profile] section fails.'''
reader = self.reader('rust-library-no-profile-section')
with self.assertRaisesRegexp(SandboxValidationError,
'Cargo.toml for.* has no \\[profile\\.dev\\] section'):
self.read_topsrcdir(reader)
def test_rust_library_invalid_crate_type(self):
'''Test that a RustLibrary Cargo.toml has a permitted crate-type.'''
reader = self.reader('rust-library-invalid-crate-type')
with self.assertRaisesRegexp(SandboxValidationError,
'crate-type.* is not permitted'):
self.read_topsrcdir(reader)
def test_rust_library_non_abort_panic(self):
'''Test that a RustLibrary Cargo.toml has `panic = "abort" set'''
reader = self.reader('rust-library-non-abort-panic')
with self.assertRaisesRegexp(SandboxValidationError,
'does not specify `panic = "abort"`'):
self.read_topsrcdir(reader)
def test_rust_library_dash_folding(self):
'''Test that on-disk names of RustLibrary objects convert dashes to underscores.'''
reader = self.reader('rust-library-dash-folding',
extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc'))
objs = self.read_topsrcdir(reader)
self.assertEqual(len(objs), 1)
lib = objs[0]
self.assertIsInstance(lib, RustLibrary)
self.assertRegexpMatches(lib.lib_name, "random_crate")
self.assertRegexpMatches(lib.import_name, "random_crate")
self.assertRegexpMatches(lib.basename, "random-crate")
def test_multiple_rust_libraries(self):
'''Test that linking multiple Rust libraries throws an error'''
reader = self.reader('multiple-rust-libraries',
extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc'))
with self.assertRaisesRegexp(LinkageMultipleRustLibrariesError,
'Cannot link multiple Rust libraries'):
self.read_topsrcdir(reader)
def test_crate_dependency_path_resolution(self):
'''Test recursive dependencies resolve with the correct paths.'''
reader = self.reader('crate-dependency-path-resolution',
extra_substs=dict(RUST_TARGET='i686-pc-windows-msvc'))
objs = self.read_topsrcdir(reader)
self.assertEqual(len(objs), 1)
self.assertIsInstance(objs[0], RustLibrary)
def test_android_res_dirs(self):
"""Test that ANDROID_RES_DIRS works properly."""
reader = self.reader('android-res-dirs')

View file

@ -1 +0,0 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"2879af3c0512f976015d532e2d768f04ff22fdcf8745b69b955b78fda321c3fb",".travis.yml":"81545ce3c6c72111a68434464c3f9fa8df9cbe39759a081fac527628ab21ae0c","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"a7282931b50dff2e463f82baaed95a9d76636bc0fef3e921acd8ca69eab32b83","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"fbcc46b6d0a585096737f50922818b59016b69d959b05f1b29863b2af8e4da43","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"f583692d829c8dfe19b1d5b9e968ccf5c74d6733367ca183edff74041a6afedd","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"ef9e7a218fa3a4912c47f6840d32b975940d98277b6c9be85e8d7d045552eb87","src/new.rs":"161c21b7ebb5668c7cc70b46b0eb37709e06bb9c854f2fdfc6ce3d3babcbf3de"},"package":"0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"}

View file

View file

@ -1,6 +0,0 @@
.*.swp
doc
tags
build
target
Cargo.lock

View file

@ -1,15 +0,0 @@
language: rust
matrix:
include:
- rust: "nightly"
env: TEST_SUITE=suite_nightly
- rust: "beta"
env: TEST_SUITE=suite_beta
- rust: "stable"
env: TEST_SUITE=suite_stable
script:
- cargo build --verbose
- cargo test --verbose
- if [ "$TEST_SUITE" = "suite_nightly" ]; then
cargo bench --verbose;
fi

View file

@ -1,3 +0,0 @@
This project is dual-licensed under the Unlicense and MIT licenses.
You may use this code under the terms of either license.

View file

@ -1,25 +0,0 @@
[package]
name = "byteorder"
version = "0.5.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = "Library for reading/writing numbers in big-endian and little-endian."
documentation = "http://burntsushi.net/rustdoc/byteorder/"
homepage = "https://github.com/BurntSushi/byteorder"
repository = "https://github.com/BurntSushi/byteorder"
readme = "README.md"
keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
license = "Unlicense/MIT"
[lib]
name = "byteorder"
[dev-dependencies]
quickcheck = "0.2"
rand = "0.3"
[features]
default = ["std"]
std = []
[profile.bench]
opt-level = 3

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 Andrew Gallant
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -1,14 +0,0 @@
all:
echo Nothing to do...
ctags:
ctags --recurse --options=ctags.rust --languages=Rust
docs:
cargo doc
in-dir ./target/doc fix-perms
rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
push:
git push origin master
git push github master

View file

@ -1,59 +0,0 @@
This crate provides convenience methods for encoding and decoding numbers in
either big-endian or little-endian order. This is meant to replace the old
methods defined on the standard library `Reader` and `Writer` traits.
[![Build status](https://api.travis-ci.org/BurntSushi/byteorder.png)](https://travis-ci.org/BurntSushi/byteorder)
[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
### Documentation
[http://burntsushi.net/rustdoc/byteorder/](http://burntsushi.net/rustdoc/byteorder/).
The documentation includes examples.
### Installation
This crate works with Cargo and is on
[crates.io](https://crates.io/crates/byteorder). The package is regularly
updated. Add it to your `Cargo.toml` like so:
```toml
[dependencies]
byteorder = "0.5"
```
If you want to augment existing `Read` and `Write` traits, then import the
extension methods like so:
```rust
extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
```
For example:
```rust
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
// Note that we use type parameters to indicate which kind of byte order
// we want!
assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
```
### `no_std` crates
This crate has a feature, `std`, that is enabled by default. To use this crate
in a `no_std` context, add the following to your `Cargo.toml`:
```toml
[dependencies]
byteorder = { version = "0.5", default-features = false }
```

View file

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View file

@ -1,148 +0,0 @@
#![feature(test)]
extern crate byteorder;
extern crate test;
macro_rules! bench_num {
($name:ident, $read:ident, $bytes:expr, $data:expr) => (
mod $name {
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
use super::test::Bencher;
use super::test::black_box as bb;
const NITER: usize = 100_000;
#[bench]
fn read_big_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(BigEndian::$read(&buf, $bytes));
}
});
}
#[bench]
fn read_little_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(LittleEndian::$read(&buf, $bytes));
}
});
}
#[bench]
fn read_native_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(NativeEndian::$read(&buf, $bytes));
}
});
}
}
);
($ty:ident, $max:ident,
$read:ident, $write:ident, $size:expr, $data:expr) => (
mod $ty {
use std::$ty;
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
use super::test::Bencher;
use super::test::black_box as bb;
const NITER: usize = 100_000;
#[bench]
fn read_big_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(BigEndian::$read(&buf));
}
});
}
#[bench]
fn read_little_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(LittleEndian::$read(&buf));
}
});
}
#[bench]
fn read_native_endian(b: &mut Bencher) {
let buf = $data;
b.iter(|| {
for _ in 0..NITER {
bb(NativeEndian::$read(&buf));
}
});
}
#[bench]
fn write_big_endian(b: &mut Bencher) {
let mut buf = $data;
let n = $ty::$max;
b.iter(|| {
for _ in 0..NITER {
bb(BigEndian::$write(&mut buf, n));
}
});
}
#[bench]
fn write_little_endian(b: &mut Bencher) {
let mut buf = $data;
let n = $ty::$max;
b.iter(|| {
for _ in 0..NITER {
bb(LittleEndian::$write(&mut buf, n));
}
});
}
#[bench]
fn write_native_endian(b: &mut Bencher) {
let mut buf = $data;
let n = $ty::$max;
b.iter(|| {
for _ in 0..NITER {
bb(NativeEndian::$write(&mut buf, n));
}
});
}
}
);
}
bench_num!(u16, MAX, read_u16, write_u16, 2, [1, 2]);
bench_num!(i16, MAX, read_i16, write_i16, 2, [1, 2]);
bench_num!(u32, MAX, read_u32, write_u32, 4, [1, 2, 3, 4]);
bench_num!(i32, MAX, read_i32, write_i32, 4, [1, 2, 3, 4]);
bench_num!(u64, MAX, read_u64, write_u64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(i64, MAX, read_i64, write_i64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(f32, MAX, read_f32, write_f32, 4, [1, 2, 3, 4]);
bench_num!(f64, MAX, read_f64, write_f64, 8,
[1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(uint_1, read_uint, 1, [1]);
bench_num!(uint_2, read_uint, 2, [1, 2]);
bench_num!(uint_3, read_uint, 3, [1, 2, 3]);
bench_num!(uint_4, read_uint, 4, [1, 2, 3, 4]);
bench_num!(uint_5, read_uint, 5, [1, 2, 3, 4, 5]);
bench_num!(uint_6, read_uint, 6, [1, 2, 3, 4, 5, 6]);
bench_num!(uint_7, read_uint, 7, [1, 2, 3, 4, 5, 6, 7]);
bench_num!(uint_8, read_uint, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(int_1, read_int, 1, [1]);
bench_num!(int_2, read_int, 2, [1, 2]);
bench_num!(int_3, read_int, 3, [1, 2, 3]);
bench_num!(int_4, read_int, 4, [1, 2, 3, 4]);
bench_num!(int_5, read_int, 5, [1, 2, 3, 4, 5]);
bench_num!(int_6, read_int, 6, [1, 2, 3, 4, 5, 6]);
bench_num!(int_7, read_int, 7, [1, 2, 3, 4, 5, 6, 7]);
bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]);

View file

@ -1 +0,0 @@
au BufWritePost *.rs silent!make ctags > /dev/null 2>&1

View file

@ -1,802 +0,0 @@
/*!
This crate provides convenience methods for encoding and decoding numbers
in either big-endian or little-endian order.
The organization of the crate is pretty simple. A trait, `ByteOrder`, specifies
byte conversion methods for each type of number in Rust (sans numbers that have
a platform dependent size like `usize` and `isize`). Two types, `BigEndian`
and `LittleEndian` implement these methods. Finally, `ReadBytesExt` and
`WriteBytesExt` provide convenience methods available to all types that
implement `Read` and `Write`.
# Examples
Read unsigned 16 bit big-endian integers from a `Read` type:
```rust
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
// Note that we use type parameters to indicate which kind of byte order
// we want!
assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
```
Write unsigned 16 bit little-endian integers to a `Write` type:
```rust
use byteorder::{LittleEndian, WriteBytesExt};
let mut wtr = vec![];
wtr.write_u16::<LittleEndian>(517).unwrap();
wtr.write_u16::<LittleEndian>(768).unwrap();
assert_eq!(wtr, vec![5, 2, 0, 3]);
```
*/
#![crate_name = "byteorder"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]
#[cfg(feature = "std")]
extern crate core;
use core::mem::transmute;
use core::ptr::copy_nonoverlapping;
#[cfg(feature = "std")]
pub use new::{ReadBytesExt, WriteBytesExt};
#[cfg(feature = "std")]
mod new;
#[inline]
fn extend_sign(val: u64, nbytes: usize) -> i64 {
let shift = (8 - nbytes) * 8;
(val << shift) as i64 >> shift
}
#[inline]
fn unextend_sign(val: i64, nbytes: usize) -> u64 {
let shift = (8 - nbytes) * 8;
(val << shift) as u64 >> shift
}
#[inline]
fn pack_size(n: u64) -> usize {
if n < 1 << 8 {
1
} else if n < 1 << 16 {
2
} else if n < 1 << 24 {
3
} else if n < 1 << 32 {
4
} else if n < 1 << 40 {
5
} else if n < 1 << 48 {
6
} else if n < 1 << 56 {
7
} else {
8
}
}
/// ByteOrder describes types that can serialize integers as bytes.
///
/// Note that `Self` does not appear anywhere in this trait's definition!
/// Therefore, in order to use it, you'll need to use syntax like
/// `T::read_u16(&[0, 1])` where `T` implements `ByteOrder`.
///
/// This crate provides two types that implement `ByteOrder`: `BigEndian`
/// and `LittleEndian`.
///
/// # Examples
///
/// Write and read `u32` numbers in little endian order:
///
/// ```rust
/// use byteorder::{ByteOrder, LittleEndian};
///
/// let mut buf = [0; 4];
/// LittleEndian::write_u32(&mut buf, 1_000_000);
/// assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
/// ```
///
/// Write and read `i16` numbers in big endian order:
///
/// ```rust
/// use byteorder::{ByteOrder, BigEndian};
///
/// let mut buf = [0; 2];
/// BigEndian::write_i16(&mut buf, -50_000);
/// assert_eq!(-50_000, BigEndian::read_i16(&buf));
/// ```
pub trait ByteOrder {
/// Reads an unsigned 16 bit integer from `buf`.
///
/// Panics when `buf.len() < 2`.
fn read_u16(buf: &[u8]) -> u16;
/// Reads an unsigned 32 bit integer from `buf`.
///
/// Panics when `buf.len() < 4`.
fn read_u32(buf: &[u8]) -> u32;
/// Reads an unsigned 64 bit integer from `buf`.
///
/// Panics when `buf.len() < 8`.
fn read_u64(buf: &[u8]) -> u64;
/// Reads an unsigned n-bytes integer from `buf`.
///
/// Panics when `nbytes < 1` or `nbytes > 8` or
/// `buf.len() < nbytes`
fn read_uint(buf: &[u8], nbytes: usize) -> u64;
/// Writes an unsigned 16 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 2`.
fn write_u16(buf: &mut [u8], n: u16);
/// Writes an unsigned 32 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 4`.
fn write_u32(buf: &mut [u8], n: u32);
/// Writes an unsigned 64 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 8`.
fn write_u64(buf: &mut [u8], n: u64);
/// Writes an unsigned integer `n` to `buf` using only `nbytes`.
///
/// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then
/// this method panics.
fn write_uint(buf: &mut [u8], n: u64, nbytes: usize);
/// Reads a signed 16 bit integer from `buf`.
///
/// Panics when `buf.len() < 2`.
#[inline]
fn read_i16(buf: &[u8]) -> i16 {
Self::read_u16(buf) as i16
}
/// Reads a signed 32 bit integer from `buf`.
///
/// Panics when `buf.len() < 4`.
#[inline]
fn read_i32(buf: &[u8]) -> i32 {
Self::read_u32(buf) as i32
}
/// Reads a signed 64 bit integer from `buf`.
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_i64(buf: &[u8]) -> i64 {
Self::read_u64(buf) as i64
}
/// Reads a signed n-bytes integer from `buf`.
///
/// Panics when `nbytes < 1` or `nbytes > 8` or
/// `buf.len() < nbytes`
#[inline]
fn read_int(buf: &[u8], nbytes: usize) -> i64 {
extend_sign(Self::read_uint(buf, nbytes), nbytes)
}
/// Reads a IEEE754 single-precision (4 bytes) floating point number.
///
/// Panics when `buf.len() < 4`.
#[inline]
fn read_f32(buf: &[u8]) -> f32 {
unsafe { transmute(Self::read_u32(buf)) }
}
/// Reads a IEEE754 double-precision (8 bytes) floating point number.
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_f64(buf: &[u8]) -> f64 {
unsafe { transmute(Self::read_u64(buf)) }
}
/// Writes a signed 16 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 2`.
#[inline]
fn write_i16(buf: &mut [u8], n: i16) {
Self::write_u16(buf, n as u16)
}
/// Writes a signed 32 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 4`.
#[inline]
fn write_i32(buf: &mut [u8], n: i32) {
Self::write_u32(buf, n as u32)
}
/// Writes a signed 64 bit integer `n` to `buf`.
///
/// Panics when `buf.len() < 8`.
#[inline]
fn write_i64(buf: &mut [u8], n: i64) {
Self::write_u64(buf, n as u64)
}
/// Writes a signed integer `n` to `buf` using only `nbytes`.
///
/// If `n` is not representable in `nbytes`, or if `nbytes` is `> 8`, then
/// this method panics.
#[inline]
fn write_int(buf: &mut [u8], n: i64, nbytes: usize) {
Self::write_uint(buf, unextend_sign(n, nbytes), nbytes)
}
/// Writes a IEEE754 single-precision (4 bytes) floating point number.
///
/// Panics when `buf.len() < 4`.
#[inline]
fn write_f32(buf: &mut [u8], n: f32) {
Self::write_u32(buf, unsafe { transmute(n) })
}
/// Writes a IEEE754 double-precision (8 bytes) floating point number.
///
/// Panics when `buf.len() < 8`.
#[inline]
fn write_f64(buf: &mut [u8], n: f64) {
Self::write_u64(buf, unsafe { transmute(n) })
}
}
/// Defines big-endian serialization.
///
/// Note that this type has no value constructor. It is used purely at the
/// type level.
#[allow(missing_copy_implementations)] pub enum BigEndian {}
/// Defines little-endian serialization.
///
/// Note that this type has no value constructor. It is used purely at the
/// type level.
#[allow(missing_copy_implementations)] pub enum LittleEndian {}
/// Defines network byte order serialization.
///
/// Network byte order is defined by [RFC 1700][1] to be big-endian, and is
/// referred to in several protocol specifications. This type is an alias of
/// BigEndian.
///
/// [1]: https://tools.ietf.org/html/rfc1700
///
/// Note that this type has no value constructor. It is used purely at the
/// type level.
pub type NetworkEndian = BigEndian;
/// Defines system native-endian serialization.
///
/// Note that this type has no value constructor. It is used purely at the
/// type level.
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
/// Defines system native-endian serialization.
///
/// Note that this type has no value constructor. It is used purely at the
/// type level.
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;
macro_rules! read_num_bytes {
($ty:ty, $size:expr, $src:expr, $which:ident) => ({
assert!($size == ::core::mem::size_of::<$ty>());
assert!($size <= $src.len());
let mut data: $ty = 0;
unsafe {
copy_nonoverlapping(
$src.as_ptr(),
&mut data as *mut $ty as *mut u8,
$size);
}
data.$which()
});
}
macro_rules! write_num_bytes {
($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => ({
assert!($size <= $dst.len());
unsafe {
// N.B. https://github.com/rust-lang/rust/issues/22776
let bytes = transmute::<_, [u8; $size]>($n.$which());
copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
}
});
}
impl ByteOrder for BigEndian {
#[inline]
fn read_u16(buf: &[u8]) -> u16 {
read_num_bytes!(u16, 2, buf, to_be)
}
#[inline]
fn read_u32(buf: &[u8]) -> u32 {
read_num_bytes!(u32, 4, buf, to_be)
}
#[inline]
fn read_u64(buf: &[u8]) -> u64 {
read_num_bytes!(u64, 8, buf, to_be)
}
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
let mut out = [0u8; 8];
let ptr_out = out.as_mut_ptr();
unsafe {
copy_nonoverlapping(
buf.as_ptr(), ptr_out.offset((8 - nbytes) as isize), nbytes);
(*(ptr_out as *const u64)).to_be()
}
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
write_num_bytes!(u16, 2, n, buf, to_be);
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
write_num_bytes!(u32, 4, n, buf, to_be);
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
write_num_bytes!(u64, 8, n, buf, to_be);
}
#[inline]
fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
assert!(pack_size(n) <= nbytes && nbytes <= 8);
assert!(nbytes <= buf.len());
unsafe {
let bytes: [u8; 8] = transmute(n.to_be());
copy_nonoverlapping(
bytes.as_ptr().offset((8 - nbytes) as isize),
buf.as_mut_ptr(),
nbytes);
}
}
}
impl ByteOrder for LittleEndian {
#[inline]
fn read_u16(buf: &[u8]) -> u16 {
read_num_bytes!(u16, 2, buf, to_le)
}
#[inline]
fn read_u32(buf: &[u8]) -> u32 {
read_num_bytes!(u32, 4, buf, to_le)
}
#[inline]
fn read_u64(buf: &[u8]) -> u64 {
read_num_bytes!(u64, 8, buf, to_le)
}
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
let mut out = [0u8; 8];
let ptr_out = out.as_mut_ptr();
unsafe {
copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes);
(*(ptr_out as *const u64)).to_le()
}
}
#[inline]
fn write_u16(buf: &mut [u8], n: u16) {
write_num_bytes!(u16, 2, n, buf, to_le);
}
#[inline]
fn write_u32(buf: &mut [u8], n: u32) {
write_num_bytes!(u32, 4, n, buf, to_le);
}
#[inline]
fn write_u64(buf: &mut [u8], n: u64) {
write_num_bytes!(u64, 8, n, buf, to_le);
}
#[inline]
fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
assert!(pack_size(n as u64) <= nbytes && nbytes <= 8);
assert!(nbytes <= buf.len());
unsafe {
let bytes: [u8; 8] = transmute(n.to_le());
copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes);
}
}
}
#[cfg(test)]
mod test {
extern crate quickcheck;
extern crate rand;
use test::rand::thread_rng;
use test::quickcheck::{QuickCheck, StdGen, Testable};
const U64_MAX: u64 = ::std::u64::MAX;
const I64_MAX: u64 = ::std::i64::MAX as u64;
fn qc_sized<A: Testable>(f: A, size: u64) {
QuickCheck::new()
.gen(StdGen::new(thread_rng(), size as usize))
.tests(1_00)
.max_tests(10_000)
.quickcheck(f);
}
macro_rules! qc_byte_order {
($name:ident, $ty_int:ident, $max:expr,
$bytes:expr, $read:ident, $write:ident) => (
mod $name {
use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
use super::qc_sized;
#[test]
fn big_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut buf = [0; 8];
BigEndian::$write(&mut buf, n, $bytes);
n == BigEndian::$read(&mut buf[..$bytes], $bytes)
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
#[test]
fn little_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut buf = [0; 8];
LittleEndian::$write(&mut buf, n, $bytes);
n == LittleEndian::$read(&mut buf[..$bytes], $bytes)
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
#[test]
fn native_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut buf = [0; 8];
NativeEndian::$write(&mut buf, n, $bytes);
n == NativeEndian::$read(&mut buf[..$bytes], $bytes)
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
}
);
($name:ident, $ty_int:ident, $max:expr,
$read:ident, $write:ident) => (
mod $name {
use std::mem::size_of;
use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
use super::qc_sized;
#[test]
fn big_endian() {
fn prop(n: $ty_int) -> bool {
let bytes = size_of::<$ty_int>();
let mut buf = [0; 8];
BigEndian::$write(&mut buf[8 - bytes..], n);
n == BigEndian::$read(&mut buf[8 - bytes..])
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
#[test]
fn little_endian() {
fn prop(n: $ty_int) -> bool {
let bytes = size_of::<$ty_int>();
let mut buf = [0; 8];
LittleEndian::$write(&mut buf[..bytes], n);
n == LittleEndian::$read(&mut buf[..bytes])
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
#[test]
fn native_endian() {
fn prop(n: $ty_int) -> bool {
let bytes = size_of::<$ty_int>();
let mut buf = [0; 8];
NativeEndian::$write(&mut buf[..bytes], n);
n == NativeEndian::$read(&mut buf[..bytes])
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
}
);
}
qc_byte_order!(prop_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16);
qc_byte_order!(prop_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16);
qc_byte_order!(prop_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32);
qc_byte_order!(prop_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32);
qc_byte_order!(prop_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64);
qc_byte_order!(prop_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64);
qc_byte_order!(prop_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32);
qc_byte_order!(prop_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64);
qc_byte_order!(prop_uint_1, u64, super::U64_MAX, 1, read_uint, write_uint);
qc_byte_order!(prop_uint_2, u64, super::U64_MAX, 2, read_uint, write_uint);
qc_byte_order!(prop_uint_3, u64, super::U64_MAX, 3, read_uint, write_uint);
qc_byte_order!(prop_uint_4, u64, super::U64_MAX, 4, read_uint, write_uint);
qc_byte_order!(prop_uint_5, u64, super::U64_MAX, 5, read_uint, write_uint);
qc_byte_order!(prop_uint_6, u64, super::U64_MAX, 6, read_uint, write_uint);
qc_byte_order!(prop_uint_7, u64, super::U64_MAX, 7, read_uint, write_uint);
qc_byte_order!(prop_uint_8, u64, super::U64_MAX, 8, read_uint, write_uint);
qc_byte_order!(prop_int_1, i64, super::I64_MAX, 1, read_int, write_int);
qc_byte_order!(prop_int_2, i64, super::I64_MAX, 2, read_int, write_int);
qc_byte_order!(prop_int_3, i64, super::I64_MAX, 3, read_int, write_int);
qc_byte_order!(prop_int_4, i64, super::I64_MAX, 4, read_int, write_int);
qc_byte_order!(prop_int_5, i64, super::I64_MAX, 5, read_int, write_int);
qc_byte_order!(prop_int_6, i64, super::I64_MAX, 6, read_int, write_int);
qc_byte_order!(prop_int_7, i64, super::I64_MAX, 7, read_int, write_int);
qc_byte_order!(prop_int_8, i64, super::I64_MAX, 8, read_int, write_int);
macro_rules! qc_bytes_ext {
($name:ident, $ty_int:ident, $max:expr,
$bytes:expr, $read:ident, $write:ident) => (
mod $name {
use std::io::Cursor;
use {
ReadBytesExt, WriteBytesExt,
BigEndian, NativeEndian, LittleEndian,
};
use super::qc_sized;
#[test]
fn big_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<BigEndian>(n).unwrap();
let mut rdr = Vec::new();
rdr.extend(wtr[8 - $bytes..].iter().map(|&x|x));
let mut rdr = Cursor::new(rdr);
n == rdr.$read::<BigEndian>($bytes).unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
#[test]
fn little_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<LittleEndian>(n).unwrap();
let mut rdr = Cursor::new(wtr);
n == rdr.$read::<LittleEndian>($bytes).unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
#[test]
fn native_endian() {
let max = ($max - 1) >> (8 * (8 - $bytes));
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<NativeEndian>(n).unwrap();
let mut rdr = Cursor::new(wtr);
n == rdr.$read::<NativeEndian>($bytes).unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, max);
}
}
);
($name:ident, $ty_int:ident, $max:expr, $read:ident, $write:ident) => (
mod $name {
use std::io::Cursor;
use {
ReadBytesExt, WriteBytesExt,
BigEndian, NativeEndian, LittleEndian,
};
use super::qc_sized;
#[test]
fn big_endian() {
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<BigEndian>(n).unwrap();
let mut rdr = Cursor::new(wtr);
n == rdr.$read::<BigEndian>().unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
#[test]
fn little_endian() {
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<LittleEndian>(n).unwrap();
let mut rdr = Cursor::new(wtr);
n == rdr.$read::<LittleEndian>().unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
#[test]
fn native_endian() {
fn prop(n: $ty_int) -> bool {
let mut wtr = vec![];
wtr.$write::<NativeEndian>(n).unwrap();
let mut rdr = Cursor::new(wtr);
n == rdr.$read::<NativeEndian>().unwrap()
}
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
}
}
);
}
qc_bytes_ext!(prop_ext_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16);
qc_bytes_ext!(prop_ext_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16);
qc_bytes_ext!(prop_ext_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32);
qc_bytes_ext!(prop_ext_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32);
qc_bytes_ext!(prop_ext_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64);
qc_bytes_ext!(prop_ext_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64);
qc_bytes_ext!(prop_ext_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32);
qc_bytes_ext!(prop_ext_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64);
qc_bytes_ext!(prop_ext_uint_1, u64, super::U64_MAX, 1, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_2, u64, super::U64_MAX, 2, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_3, u64, super::U64_MAX, 3, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_4, u64, super::U64_MAX, 4, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_5, u64, super::U64_MAX, 5, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_6, u64, super::U64_MAX, 6, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_7, u64, super::U64_MAX, 7, read_uint, write_u64);
qc_bytes_ext!(prop_ext_uint_8, u64, super::U64_MAX, 8, read_uint, write_u64);
qc_bytes_ext!(prop_ext_int_1, i64, super::I64_MAX, 1, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_2, i64, super::I64_MAX, 2, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_3, i64, super::I64_MAX, 3, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_4, i64, super::I64_MAX, 4, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_5, i64, super::I64_MAX, 5, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_6, i64, super::I64_MAX, 6, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_7, i64, super::I64_MAX, 7, read_int, write_i64);
qc_bytes_ext!(prop_ext_int_8, i64, super::I64_MAX, 8, read_int, write_i64);
// Test that all of the byte conversion functions panic when given a
// buffer that is too small.
//
// These tests are critical to ensure safety, otherwise we might end up
// with a buffer overflow.
macro_rules! too_small {
($name:ident, $maximally_small:expr, $zero:expr,
$read:ident, $write:ident) => (
mod $name {
use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
#[test]
#[should_panic]
fn read_big_endian() {
let buf = [0; $maximally_small];
BigEndian::$read(&buf);
}
#[test]
#[should_panic]
fn read_little_endian() {
let buf = [0; $maximally_small];
LittleEndian::$read(&buf);
}
#[test]
#[should_panic]
fn read_native_endian() {
let buf = [0; $maximally_small];
NativeEndian::$read(&buf);
}
#[test]
#[should_panic]
fn write_big_endian() {
let mut buf = [0; $maximally_small];
BigEndian::$write(&mut buf, $zero);
}
#[test]
#[should_panic]
fn write_little_endian() {
let mut buf = [0; $maximally_small];
LittleEndian::$write(&mut buf, $zero);
}
#[test]
#[should_panic]
fn write_native_endian() {
let mut buf = [0; $maximally_small];
NativeEndian::$write(&mut buf, $zero);
}
}
);
($name:ident, $maximally_small:expr, $read:ident) => (
mod $name {
use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
#[test]
#[should_panic]
fn read_big_endian() {
let buf = [0; $maximally_small];
BigEndian::$read(&buf, $maximally_small + 1);
}
#[test]
#[should_panic]
fn read_little_endian() {
let buf = [0; $maximally_small];
LittleEndian::$read(&buf, $maximally_small + 1);
}
#[test]
#[should_panic]
fn read_native_endian() {
let buf = [0; $maximally_small];
NativeEndian::$read(&buf, $maximally_small + 1);
}
}
);
}
too_small!(small_u16, 1, 0, read_u16, write_u16);
too_small!(small_i16, 1, 0, read_i16, write_i16);
too_small!(small_u32, 3, 0, read_u32, write_u32);
too_small!(small_i32, 3, 0, read_i32, write_i32);
too_small!(small_u64, 7, 0, read_u64, write_u64);
too_small!(small_i64, 7, 0, read_i64, write_i64);
too_small!(small_f32, 3, 0.0, read_f32, write_f32);
too_small!(small_f64, 7, 0.0, read_f64, write_f64);
too_small!(small_uint_1, 1, read_uint);
too_small!(small_uint_2, 2, read_uint);
too_small!(small_uint_3, 3, read_uint);
too_small!(small_uint_4, 4, read_uint);
too_small!(small_uint_5, 5, read_uint);
too_small!(small_uint_6, 6, read_uint);
too_small!(small_uint_7, 7, read_uint);
too_small!(small_int_1, 1, read_int);
too_small!(small_int_2, 2, read_int);
too_small!(small_int_3, 3, read_int);
too_small!(small_int_4, 4, read_int);
too_small!(small_int_5, 5, read_int);
too_small!(small_int_6, 6, read_int);
too_small!(small_int_7, 7, read_int);
#[test]
fn uint_bigger_buffer() {
use {ByteOrder, LittleEndian};
let n = LittleEndian::read_uint(&[1, 2, 3, 4, 5, 6, 7, 8], 5);
assert_eq!(n, 0x0504030201);
}
}

View file

@ -1,269 +0,0 @@
use std::io::{self, Result};
use ByteOrder;
/// Extends `Read` with methods for reading numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Read unsigned 16 bit big-endian integers from a `Read`:
///
/// ```rust
/// use std::io::Cursor;
/// use byteorder::{BigEndian, ReadBytesExt};
///
/// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
/// assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
/// assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
/// ```
pub trait ReadBytesExt: io::Read {
/// Reads an unsigned 8 bit integer from the underlying reader.
///
/// Note that since this reads a single byte, no byte order conversions
/// are used. It is included for completeness.
#[inline]
fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0; 1];
try!(self.read_exact(&mut buf));
Ok(buf[0])
}
/// Reads a signed 8 bit integer from the underlying reader.
///
/// Note that since this reads a single byte, no byte order conversions
/// are used. It is included for completeness.
#[inline]
fn read_i8(&mut self) -> Result<i8> {
let mut buf = [0; 1];
try!(self.read_exact(&mut buf));
Ok(buf[0] as i8)
}
/// Reads an unsigned 16 bit integer from the underlying reader.
#[inline]
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
let mut buf = [0; 2];
try!(self.read_exact(&mut buf));
Ok(T::read_u16(&buf))
}
/// Reads a signed 16 bit integer from the underlying reader.
#[inline]
fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
let mut buf = [0; 2];
try!(self.read_exact(&mut buf));
Ok(T::read_i16(&buf))
}
/// Reads an unsigned 32 bit integer from the underlying reader.
#[inline]
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_u32(&buf))
}
/// Reads a signed 32 bit integer from the underlying reader.
#[inline]
fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_i32(&buf))
}
/// Reads an unsigned 64 bit integer from the underlying reader.
#[inline]
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_u64(&buf))
}
/// Reads a signed 64 bit integer from the underlying reader.
#[inline]
fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_i64(&buf))
}
/// Reads an unsigned n-bytes integer from the underlying reader.
#[inline]
fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf[..nbytes]));
Ok(T::read_uint(&buf[..nbytes], nbytes))
}
/// Reads a signed n-bytes integer from the underlying reader.
#[inline]
fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf[..nbytes]));
Ok(T::read_int(&buf[..nbytes], nbytes))
}
/// Reads a IEEE754 single-precision (4 bytes) floating point number from
/// the underlying reader.
#[inline]
fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
let mut buf = [0; 4];
try!(self.read_exact(&mut buf));
Ok(T::read_f32(&buf))
}
/// Reads a IEEE754 double-precision (8 bytes) floating point number from
/// the underlying reader.
#[inline]
fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
let mut buf = [0; 8];
try!(self.read_exact(&mut buf));
Ok(T::read_f64(&buf))
}
}
/// All types that implement `Read` get methods defined in `ReadBytesExt`
/// for free.
impl<R: io::Read + ?Sized> ReadBytesExt for R {}
/// Extends `Write` with methods for writing numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Write unsigned 16 bit big-endian integers to a `Write`:
///
/// ```rust
/// use byteorder::{BigEndian, WriteBytesExt};
///
/// let mut wtr = vec![];
/// wtr.write_u16::<BigEndian>(517).unwrap();
/// wtr.write_u16::<BigEndian>(768).unwrap();
/// assert_eq!(wtr, vec![2, 5, 3, 0]);
/// ```
pub trait WriteBytesExt: io::Write {
/// Writes an unsigned 8 bit integer to the underlying writer.
///
/// Note that since this writes a single byte, no byte order conversions
/// are used. It is included for completeness.
#[inline]
fn write_u8(&mut self, n: u8) -> Result<()> {
self.write_all(&[n])
}
/// Writes a signed 8 bit integer to the underlying writer.
///
/// Note that since this writes a single byte, no byte order conversions
/// are used. It is included for completeness.
#[inline]
fn write_i8(&mut self, n: i8) -> Result<()> {
self.write_all(&[n as u8])
}
/// Writes an unsigned 16 bit integer to the underlying writer.
#[inline]
fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
let mut buf = [0; 2];
T::write_u16(&mut buf, n);
self.write_all(&buf)
}
/// Writes a signed 16 bit integer to the underlying writer.
#[inline]
fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> {
let mut buf = [0; 2];
T::write_i16(&mut buf, n);
self.write_all(&buf)
}
/// Writes an unsigned 32 bit integer to the underlying writer.
#[inline]
fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
let mut buf = [0; 4];
T::write_u32(&mut buf, n);
self.write_all(&buf)
}
/// Writes a signed 32 bit integer to the underlying writer.
#[inline]
fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
let mut buf = [0; 4];
T::write_i32(&mut buf, n);
self.write_all(&buf)
}
/// Writes an unsigned 64 bit integer to the underlying writer.
#[inline]
fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
let mut buf = [0; 8];
T::write_u64(&mut buf, n);
self.write_all(&buf)
}
/// Writes a signed 64 bit integer to the underlying writer.
#[inline]
fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
let mut buf = [0; 8];
T::write_i64(&mut buf, n);
self.write_all(&buf)
}
/// Writes an unsigned n-bytes integer to the underlying writer.
///
/// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 8`, this method panics.
#[inline]
fn write_uint<T: ByteOrder>(
&mut self,
n: u64,
nbytes: usize,
) -> Result<()> {
let mut buf = [0; 8];
T::write_uint(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])
}
/// Writes a signed n-bytes integer to the underlying writer.
///
/// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 8`, this method panics.
#[inline]
fn write_int<T: ByteOrder>(
&mut self,
n: i64,
nbytes: usize,
) -> Result<()> {
let mut buf = [0; 8];
T::write_int(&mut buf, n, nbytes);
self.write_all(&buf[0..nbytes])
}
/// Writes a IEEE754 single-precision (4 bytes) floating point number to
/// the underlying writer.
#[inline]
fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
let mut buf = [0; 4];
T::write_f32(&mut buf, n);
self.write_all(&buf)
}
/// Writes a IEEE754 double-precision (8 bytes) floating point number to
/// the underlying writer.
#[inline]
fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
let mut buf = [0; 8];
T::write_f64(&mut buf, n);
self.write_all(&buf)
}
}
/// All types that implement `Write` get methods defined in `WriteBytesExt`
/// for free.
impl<W: io::Write + ?Sized> WriteBytesExt for W {}

View file

@ -1 +0,0 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"5cee7774cf6d876246a0ae0f8362cceeecec5924b751049c945faac9342565ff","Cargo.toml":"2f9146c71ba5dee801cc2e4c527902408c221b10ef67cd48c5d13802447d7557","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ecb2d93f4c81edbd48d8742ff7887dc0a4530a5890967839090bbc972d49bebe","appveyor.yml":"0ae8475d1be56af48cbb6a7bf774c6167c88ddaea96f2eca4f4c190dd6dab5e4","src/bin/gcc-shim.rs":"11edfe1fc6f932bd42ffffda5145833302bc163e0b87dc0d54f4bd0997ad4708","src/lib.rs":"a62a24a2703d744f5a6308d48c20938ca08fe246395a6bd6a76dd33ee3729654","src/registry.rs":"3e2a42581ebb82e325dd5600c6571cef937b35003b2927dc618967f5238a2058","src/windows_registry.rs":"80b1556b1a94ae46b444268f8e74b9ac4ddd7e6d2b98eca8ae643a8bd099abe1","tests/cc_env.rs":"d92c5e3d3d43ac244e63b2cd2c93a521fcf124bf1ccf8d4c6bfa7f8333d88976","tests/support/mod.rs":"d11ed0db4dda5ecf5fb970c9b0c56428cd47421a2742f07032e2cc6b0a0f07e2","tests/test.rs":"4ef5c34f6d8954e64c97c2876e2697dad5efc7e1dacef4b567931ed3970425c6"},"package":"91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"}

View file

View file

@ -1,2 +0,0 @@
target
Cargo.lock

View file

@ -1,40 +0,0 @@
language: rust
rust:
- stable
- beta
- nightly
sudo: false
install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then OS=unknown-linux-gnu; else OS=apple-darwin; fi
- export TARGET=$ARCH-$OS
- curl https://static.rust-lang.org/rustup.sh |
sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build --verbose
- cargo test --verbose
- cargo test --verbose --features parallel
- cargo test --manifest-path gcc-test/Cargo.toml --target $TARGET
- cargo test --manifest-path gcc-test/Cargo.toml --target $TARGET --features parallel
- cargo test --manifest-path gcc-test/Cargo.toml --target $TARGET --release
- cargo doc
- rustdoc --test README.md -L target/debug -L target/debug/deps
after_success:
- travis-cargo --only nightly doc-upload
env:
global:
secure: ilbcq9zX+UaiBcwqkBGldeanbEQus9npLsi0/nF1PUxKbQsoWSVtVOehAD8Hy92D3hX2npIRyNL8GxBn85XEcBYc1h7DiWUhLcXfZie79v8Ly/qboHCfZLXlB1ofbypbyQfouEdOE9zHf0ZILYVpAgUkliv6KuVShsrKNlbn4QE=
matrix:
- ARCH=x86_64
- ARCH=i686
notifications:
email:
on_success: never
os:
- linux
- osx
addons:
apt:
packages:
- g++-multilib

View file

@ -1,23 +0,0 @@
[package]
name = "gcc"
version = "0.3.35"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
license = "MIT/Apache-2.0"
repository = "https://github.com/alexcrichton/gcc-rs"
documentation = "http://alexcrichton.com/gcc-rs"
description = """
A build-time dependency for Cargo build scripts to assist in invoking the native
C compiler to compile native C code into a static archive to be linked into Rust
code.
"""
keywords = ["build-dependencies"]
[dependencies]
rayon = { version = "0.4", optional = true }
[features]
parallel = ["rayon"]
[dev-dependencies]
tempdir = "0.3"

View file

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,25 +0,0 @@
Copyright (c) 2014 Alex Crichton
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View file

@ -1,161 +0,0 @@
# gcc-rs
A library to compile C/C++ code into a Rust library/application.
[![Build Status](https://travis-ci.org/alexcrichton/gcc-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/gcc-rs)
[![Build status](https://ci.appveyor.com/api/projects/status/onu270iw98h81nwv?svg=true)](https://ci.appveyor.com/project/alexcrichton/gcc-rs)
[Documentation](http://alexcrichton.com/gcc-rs)
A simple library meant to be used as a build dependency with Cargo packages in
order to build a set of C/C++ files into a static archive. Note that while this
crate is called "gcc", it actually calls out to the most relevant compile for
a platform, for example using `cl` on MSVC. That is, this crate does indeed work
on MSVC!
## Using gcc-rs
First, you'll want to both add a build script for your crate (`build.rs`) and
also add this crate to your `Cargo.toml` via:
```toml
[package]
# ...
build = "build.rs"
[build-dependencies]
gcc = "0.3"
```
Next up, you'll want to write a build script like so:
```rust,no_run
// build.rs
extern crate gcc;
fn main() {
gcc::compile_library("libfoo.a", &["foo.c", "bar.c"]);
}
```
And that's it! Running `cargo build` should take care of the rest and your Rust
application will now have the C files `foo.c` and `bar.c` compiled into it. You
can call the functions in Rust by declaring functions in your Rust code like so:
```
extern {
fn foo_function();
fn bar_function();
}
pub fn call() {
unsafe {
foo_function();
bar_function();
}
}
fn main() {
// ...
}
```
## External configuration via environment variables
To control the programs and flags used for building, the builder can set a
number of different environment variables.
* `CFLAGS` - a series of space separated flags passed to "gcc". Note that
individual flags cannot currently contain spaces, so doing
something like: "-L=foo\ bar" is not possible.
* `CC` - the actual C compiler used. Note that this is used as an exact
executable name, so (for example) no extra flags can be passed inside
this variable, and the builder must ensure that there aren't any
trailing spaces. This compiler must understand the `-c` flag. For
certain `TARGET`s, it also is assumed to know about other flags (most
common is `-fPIC`).
* `AR` - the `ar` (archiver) executable to use to build the static library.
Each of these variables can also be supplied with certain prefixes and suffixes,
in the following prioritized order:
1. `<var>_<target>` - for example, `CC_x86_64-unknown-linux-gnu`
2. `<var>_<target_with_underscores>` - for example, `CC_x86_64_unknown_linux_gnu`
3. `<build-kind>_<var>` - for example, `HOST_CC` or `TARGET_CFLAGS`
4. `<var>` - a plain `CC`, `AR` as above.
If none of these variables exist, gcc-rs uses built-in defaults
In addition to the the above optional environment variables, `gcc-rs` has some
functions with hard requirements on some variables supplied by [cargo's
build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`,
and `HOST` variables.
[cargo]: http://doc.crates.io/build-script.html#inputs-to-the-build-script
## Optional features
Currently gcc-rs supports parallel compilation (think `make -jN`) but this
feature is turned off by default. To enable gcc-rs to compile C/C++ in parallel,
you can change your dependency to:
```toml
[build-dependencies]
gcc = { version = "0.3", features = ["parallel"] }
```
By default gcc-rs will limit parallelism to `$NUM_JOBS`, or if not present it
will limit it to the number of cpus on the machine.
## Compile-time Requirements
To work properly this crate needs access to a C compiler when the build script
is being run. This crate does not ship a C compiler with it. The compiler
required varies per platform, but there are three broad categories:
* Unix platforms require `cc` to be the C compiler. This can be found by
installing gcc/clang on Linux distributions and Xcode on OSX, for example.
* Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`)
require `cl.exe` to be available and in `PATH`. This is typically found in
standard Visual Studio installations and the `PATH` can be set up by running
the appropriate developer tools shell.
* Windows platforms targeting MinGW (e.g. your target triple ends in `-gnu`)
require `gcc` to be available in `PATH`. We recommend the
[MinGW-w64](http://mingw-w64.org) distribution, which is using the
[Win-builds](http://win-builds.org) installation system.
You may also acquire it via
[MSYS2](http://msys2.github.io), as explained [here][msys2-help]. Make sure
to install the appropriate architecture corresponding to your installation of
rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible
only with 32-bit rust compiler.
[msys2-help]: http://github.com/rust-lang/rust#building-on-windows
## C++ support
`gcc-rs` supports C++ libraries compilation by using the `cpp` method on
`Config`:
```rust,no_run
extern crate gcc;
fn main() {
gcc::Config::new()
.cpp(true) // Switch to C++ library compilation.
.file("foo.cpp")
.compile("libfoo.a");
}
```
When using C++ library compilation switch, the `CXX` and `CXXFLAGS` env
variables are used instead of `CC` and `CFLAGS` and the C++ standard library is
linked to the crate target.
## License
`gcc-rs` is primarily distributed under the terms of both the MIT license and
the Apache License (Version 2.0), with portions covered by various BSD-like
licenses.
See LICENSE-APACHE, and LICENSE-MIT for details.

View file

@ -1,35 +0,0 @@
environment:
matrix:
- TARGET: x86_64-pc-windows-msvc
ARCH: amd64
VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
- TARGET: x86_64-pc-windows-msvc
ARCH: amd64
VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
- TARGET: i686-pc-windows-msvc
ARCH: x86
VS: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
- TARGET: i686-pc-windows-msvc
ARCH: x86
VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
- TARGET: x86_64-pc-windows-gnu
MSYS_BITS: 64
- TARGET: i686-pc-windows-gnu
MSYS_BITS: 32
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- if defined VS call "%VS%" %ARCH%
- set PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test
- cargo test --features parallel
- cargo test --manifest-path gcc-test/Cargo.toml
- cargo test --manifest-path gcc-test/Cargo.toml --features parallel
- cargo test --manifest-path gcc-test/Cargo.toml --release

View file

@ -1,23 +0,0 @@
#![cfg_attr(test, allow(dead_code))]
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
fn main() {
let out_dir = PathBuf::from(env::var_os("GCCTEST_OUT_DIR").unwrap());
for i in 0.. {
let candidate = out_dir.join(format!("out{}", i));
if candidate.exists() {
continue
}
let mut f = File::create(candidate).unwrap();
for arg in env::args().skip(1) {
writeln!(f, "{}", arg).unwrap();
}
File::create(out_dir.join("libfoo.a")).unwrap();
break
}
}

View file

@ -1,898 +0,0 @@
//! A library for build scripts to compile custom C code
//!
//! This library is intended to be used as a `build-dependencies` entry in
//! `Cargo.toml`:
//!
//! ```toml
//! [build-dependencies]
//! gcc = "0.3"
//! ```
//!
//! The purpose of this crate is to provide the utility functions necessary to
//! compile C code into a static archive which is then linked into a Rust crate.
//! The top-level `compile_library` function serves as a convenience and more
//! advanced configuration is available through the `Config` builder.
//!
//! This crate will automatically detect situations such as cross compilation or
//! other environment variables set by Cargo and will build code appropriately.
//!
//! # Examples
//!
//! Use the default configuration:
//!
//! ```no_run
//! extern crate gcc;
//!
//! fn main() {
//! gcc::compile_library("libfoo.a", &["src/foo.c"]);
//! }
//! ```
//!
//! Use more advanced configuration:
//!
//! ```no_run
//! extern crate gcc;
//!
//! fn main() {
//! gcc::Config::new()
//! .file("src/foo.c")
//! .define("FOO", Some("bar"))
//! .include("src")
//! .compile("libfoo.a");
//! }
//! ```
#![doc(html_root_url = "http://alexcrichton.com/gcc-rs")]
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#[cfg(feature = "parallel")]
extern crate rayon;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fs;
use std::io;
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};
use std::io::{BufReader, BufRead, Write};
#[cfg(windows)]
mod registry;
pub mod windows_registry;
/// Extra configuration to pass to gcc.
pub struct Config {
include_directories: Vec<PathBuf>,
definitions: Vec<(String, Option<String>)>,
objects: Vec<PathBuf>,
flags: Vec<String>,
files: Vec<PathBuf>,
cpp: bool,
cpp_link_stdlib: Option<Option<String>>,
cpp_set_stdlib: Option<String>,
target: Option<String>,
host: Option<String>,
out_dir: Option<PathBuf>,
opt_level: Option<u32>,
debug: Option<bool>,
env: Vec<(OsString, OsString)>,
compiler: Option<PathBuf>,
archiver: Option<PathBuf>,
cargo_metadata: bool,
pic: Option<bool>,
}
/// Configuration used to represent an invocation of a C compiler.
///
/// This can be used to figure out what compiler is in use, what the arguments
/// to it are, and what the environment variables look like for the compiler.
/// This can be used to further configure other build systems (e.g. forward
/// along CC and/or CFLAGS) or the `to_command` method can be used to run the
/// compiler itself.
pub struct Tool {
path: PathBuf,
args: Vec<OsString>,
env: Vec<(OsString, OsString)>,
}
/// Compile a library from the given set of input C files.
///
/// This will simply compile all files into object files and then assemble them
/// into the output. This will read the standard environment variables to detect
/// cross compilations and such.
///
/// This function will also print all metadata on standard output for Cargo.
///
/// # Example
///
/// ```no_run
/// gcc::compile_library("libfoo.a", &["foo.c", "bar.c"]);
/// ```
pub fn compile_library(output: &str, files: &[&str]) {
let mut c = Config::new();
for f in files.iter() {
c.file(*f);
}
c.compile(output)
}
impl Config {
/// Construct a new instance of a blank set of configuration.
///
/// This builder is finished with the `compile` function.
pub fn new() -> Config {
Config {
include_directories: Vec::new(),
definitions: Vec::new(),
objects: Vec::new(),
flags: Vec::new(),
files: Vec::new(),
cpp: false,
cpp_link_stdlib: None,
cpp_set_stdlib: None,
target: None,
host: None,
out_dir: None,
opt_level: None,
debug: None,
env: Vec::new(),
compiler: None,
archiver: None,
cargo_metadata: true,
pic: None,
}
}
/// Add a directory to the `-I` or include path for headers
pub fn include<P: AsRef<Path>>(&mut self, dir: P) -> &mut Config {
self.include_directories.push(dir.as_ref().to_path_buf());
self
}
/// Specify a `-D` variable with an optional value.
pub fn define(&mut self, var: &str, val: Option<&str>) -> &mut Config {
self.definitions.push((var.to_string(), val.map(|s| s.to_string())));
self
}
/// Add an arbitrary object file to link in
pub fn object<P: AsRef<Path>>(&mut self, obj: P) -> &mut Config {
self.objects.push(obj.as_ref().to_path_buf());
self
}
/// Add an arbitrary flag to the invocation of the compiler
pub fn flag(&mut self, flag: &str) -> &mut Config {
self.flags.push(flag.to_string());
self
}
/// Add a file which will be compiled
pub fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut Config {
self.files.push(p.as_ref().to_path_buf());
self
}
/// Set C++ support.
///
/// The other `cpp_*` options will only become active if this is set to
/// `true`.
pub fn cpp(&mut self, cpp: bool) -> &mut Config {
self.cpp = cpp;
self
}
/// Set the standard library to link against when compiling with C++
/// support.
///
/// The default value of this property depends on the current target: On
/// OS X `Some("c++")` is used, when compiling for a Visual Studio based
/// target `None` is used and for other targets `Some("stdc++")` is used.
///
/// A value of `None` indicates that no automatic linking should happen,
/// otherwise cargo will link against the specified library.
///
/// The given library name must not contain the `lib` prefix.
pub fn cpp_link_stdlib(&mut self, cpp_link_stdlib: Option<&str>)
-> &mut Config {
self.cpp_link_stdlib = Some(cpp_link_stdlib.map(|s| s.into()));
self
}
/// Force the C++ compiler to use the specified standard library.
///
/// Setting this option will automatically set `cpp_link_stdlib` to the same
/// value.
///
/// The default value of this option is always `None`.
///
/// This option has no effect when compiling for a Visual Studio based
/// target.
///
/// This option sets the `-stdlib` flag, which is only supported by some
/// compilers (clang, icc) but not by others (gcc). The library will not
/// detect which compiler is used, as such it is the responsibility of the
/// caller to ensure that this option is only used in conjuction with a
/// compiler which supports the `-stdlib` flag.
///
/// A value of `None` indicates that no specific C++ standard library should
/// be used, otherwise `-stdlib` is added to the compile invocation.
///
/// The given library name must not contain the `lib` prefix.
pub fn cpp_set_stdlib(&mut self, cpp_set_stdlib: Option<&str>)
-> &mut Config {
self.cpp_set_stdlib = cpp_set_stdlib.map(|s| s.into());
self.cpp_link_stdlib(cpp_set_stdlib);
self
}
/// Configures the target this configuration will be compiling for.
///
/// This option is automatically scraped from the `TARGET` environment
/// variable by build scripts, so it's not required to call this function.
pub fn target(&mut self, target: &str) -> &mut Config {
self.target = Some(target.to_string());
self
}
/// Configures the host assumed by this configuration.
///
/// This option is automatically scraped from the `HOST` environment
/// variable by build scripts, so it's not required to call this function.
pub fn host(&mut self, host: &str) -> &mut Config {
self.host = Some(host.to_string());
self
}
/// Configures the optimization level of the generated object files.
///
/// This option is automatically scraped from the `OPT_LEVEL` environment
/// variable by build scripts, so it's not required to call this function.
pub fn opt_level(&mut self, opt_level: u32) -> &mut Config {
self.opt_level = Some(opt_level);
self
}
/// Configures whether the compiler will emit debug information when
/// generating object files.
///
/// This option is automatically scraped from the `PROFILE` environment
/// variable by build scripts (only enabled when the profile is "debug"), so
/// it's not required to call this function.
pub fn debug(&mut self, debug: bool) -> &mut Config {
self.debug = Some(debug);
self
}
/// Configures the output directory where all object files and static
/// libraries will be located.
///
/// This option is automatically scraped from the `OUT_DIR` environment
/// variable by build scripts, so it's not required to call this function.
pub fn out_dir<P: AsRef<Path>>(&mut self, out_dir: P) -> &mut Config {
self.out_dir = Some(out_dir.as_ref().to_owned());
self
}
/// Configures the compiler to be used to produce output.
///
/// This option is automatically determined from the target platform or a
/// number of environment variables, so it's not required to call this
/// function.
pub fn compiler<P: AsRef<Path>>(&mut self, compiler: P) -> &mut Config {
self.compiler = Some(compiler.as_ref().to_owned());
self
}
/// Configures the tool used to assemble archives.
///
/// This option is automatically determined from the target platform or a
/// number of environment variables, so it's not required to call this
/// function.
pub fn archiver<P: AsRef<Path>>(&mut self, archiver: P) -> &mut Config {
self.archiver = Some(archiver.as_ref().to_owned());
self
}
/// Define whether metadata should be emitted for cargo allowing it to
/// automatically link the binary. Defaults to `true`.
pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Config {
self.cargo_metadata = cargo_metadata;
self
}
/// Configures whether the compiler will emit position independent code.
///
/// This option defaults to `false` for `i686` and `windows-gnu` targets and to `true` for all
/// other targets.
pub fn pic(&mut self, pic: bool) -> &mut Config {
self.pic = Some(pic);
self
}
#[doc(hidden)]
pub fn __set_env<A, B>(&mut self, a: A, b: B) -> &mut Config
where A: AsRef<OsStr>, B: AsRef<OsStr>
{
self.env.push((a.as_ref().to_owned(), b.as_ref().to_owned()));
self
}
/// Run the compiler, generating the file `output`
///
/// The name `output` must begin with `lib` and end with `.a`
pub fn compile(&self, output: &str) {
assert!(output.starts_with("lib"));
assert!(output.ends_with(".a"));
let lib_name = &output[3..output.len() - 2];
let dst = self.get_out_dir();
let mut objects = Vec::new();
let mut src_dst = Vec::new();
for file in self.files.iter() {
let obj = dst.join(file).with_extension("o");
let obj = if !obj.starts_with(&dst) {
dst.join(obj.file_name().unwrap())
} else {
obj
};
fs::create_dir_all(&obj.parent().unwrap()).unwrap();
src_dst.push((file.to_path_buf(), obj.clone()));
objects.push(obj);
}
self.compile_objects(&src_dst);
self.assemble(lib_name, &dst.join(output), &objects);
self.print(&format!("cargo:rustc-link-lib=static={}",
&output[3..output.len() - 2]));
self.print(&format!("cargo:rustc-link-search=native={}", dst.display()));
// Add specific C++ libraries, if enabled.
if self.cpp {
if let Some(stdlib) = self.get_cpp_link_stdlib() {
self.print(&format!("cargo:rustc-link-lib={}", stdlib));
}
}
}
#[cfg(feature = "parallel")]
fn compile_objects(&self, objs: &[(PathBuf, PathBuf)]) {
use self::rayon::prelude::*;
let mut cfg = rayon::Configuration::new();
if let Ok(amt) = env::var("NUM_JOBS") {
if let Ok(amt) = amt.parse() {
cfg = cfg.set_num_threads(amt);
}
}
drop(rayon::initialize(cfg));
objs.par_iter().weight_max().for_each(|&(ref src, ref dst)| {
self.compile_object(src, dst)
})
}
#[cfg(not(feature = "parallel"))]
fn compile_objects(&self, objs: &[(PathBuf, PathBuf)]) {
for &(ref src, ref dst) in objs {
self.compile_object(src, dst);
}
}
fn compile_object(&self, file: &Path, dst: &Path) {
let is_asm = file.extension().and_then(|s| s.to_str()) == Some("asm");
let msvc = self.get_target().contains("msvc");
let (mut cmd, name) = if msvc && is_asm {
self.msvc_macro_assembler()
} else {
let compiler = self.get_compiler();
let mut cmd = compiler.to_command();
for &(ref a, ref b) in self.env.iter() {
cmd.env(a, b);
}
(cmd, compiler.path.file_name().unwrap()
.to_string_lossy().into_owned())
};
if msvc && is_asm {
cmd.arg("/Fo").arg(dst);
} else if msvc {
let mut s = OsString::from("/Fo");
s.push(&dst);
cmd.arg(s);
} else {
cmd.arg("-o").arg(&dst);
}
cmd.arg(if msvc {"/c"} else {"-c"});
cmd.arg(file);
run(&mut cmd, &name);
}
/// Get the compiler that's in use for this configuration.
///
/// This function will return a `Tool` which represents the culmination
/// of this configuration at a snapshot in time. The returned compiler can
/// be inspected (e.g. the path, arguments, environment) to forward along to
/// other tools, or the `to_command` method can be used to invoke the
/// compiler itself.
///
/// This method will take into account all configuration such as debug
/// information, optimization level, include directories, defines, etc.
/// Additionally, the compiler binary in use follows the standard
/// conventions for this path, e.g. looking at the explicitly set compiler,
/// environment variables (a number of which are inspected here), and then
/// falling back to the default configuration.
pub fn get_compiler(&self) -> Tool {
let opt_level = self.get_opt_level();
let debug = self.get_debug();
let target = self.get_target();
let msvc = target.contains("msvc");
self.print(&format!("debug={} opt-level={}", debug, opt_level));
let mut cmd = self.get_base_compiler();
let nvcc = cmd.path.to_str()
.map(|path| path.contains("nvcc"))
.unwrap_or(false);
if msvc {
cmd.args.push("/nologo".into());
cmd.args.push("/MD".into()); // link against msvcrt.dll for now
if opt_level != 0 {
cmd.args.push("/O2".into());
}
if target.contains("i686") {
cmd.args.push("/SAFESEH".into());
} else if target.contains("i586") {
cmd.args.push("/SAFESEH".into());
cmd.args.push("/ARCH:IA32".into());
}
} else if nvcc {
cmd.args.push(format!("-O{}", opt_level).into());
} else {
cmd.args.push(format!("-O{}", opt_level).into());
cmd.args.push("-ffunction-sections".into());
cmd.args.push("-fdata-sections".into());
}
for arg in self.envflags(if self.cpp {"CXXFLAGS"} else {"CFLAGS"}) {
cmd.args.push(arg.into());
}
if debug {
cmd.args.push(if msvc {"/Z7"} else {"-g"}.into());
}
if target.contains("-ios") {
self.ios_flags(&mut cmd);
} else if !msvc {
if target.contains("i686") || target.contains("i586") {
cmd.args.push("-m32".into());
} else if target.contains("x86_64") || target.contains("powerpc64") {
cmd.args.push("-m64".into());
}
if !nvcc && self.pic.unwrap_or(!target.contains("i686") && !target.contains("windows-gnu")) {
cmd.args.push("-fPIC".into());
} else if nvcc && self.pic.unwrap_or(false) {
cmd.args.push("-Xcompiler".into());
cmd.args.push("\'-fPIC\'".into());
}
if target.contains("musl") {
cmd.args.push("-static".into());
}
if target.starts_with("armv7-unknown-linux-") {
cmd.args.push("-march=armv7-a".into());
}
if target.starts_with("arm-unknown-linux-") {
cmd.args.push("-march=armv6".into());
cmd.args.push("-marm".into());
}
if target.starts_with("i586-unknown-linux-") {
cmd.args.push("-march=pentium".into());
}
if target.starts_with("i686-unknown-linux-") {
cmd.args.push("-march=i686".into());
}
}
if self.cpp && !msvc {
if let Some(ref stdlib) = self.cpp_set_stdlib {
cmd.args.push(format!("-stdlib=lib{}", stdlib).into());
}
}
for directory in self.include_directories.iter() {
cmd.args.push(if msvc {"/I"} else {"-I"}.into());
cmd.args.push(directory.into());
}
for flag in self.flags.iter() {
cmd.args.push(flag.into());
}
for &(ref key, ref value) in self.definitions.iter() {
let lead = if msvc {"/"} else {"-"};
if let &Some(ref value) = value {
cmd.args.push(format!("{}D{}={}", lead, key, value).into());
} else {
cmd.args.push(format!("{}D{}", lead, key).into());
}
}
cmd
}
fn msvc_macro_assembler(&self) -> (Command, String) {
let target = self.get_target();
let tool = if target.contains("x86_64") {"ml64.exe"} else {"ml.exe"};
let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| {
self.cmd(tool)
});
for directory in self.include_directories.iter() {
cmd.arg("/I").arg(directory);
}
for &(ref key, ref value) in self.definitions.iter() {
if let &Some(ref value) = value {
cmd.arg(&format!("/D{}={}", key, value));
} else {
cmd.arg(&format!("/D{}", key));
}
}
if target.contains("i686") || target.contains("i586") {
cmd.arg("/safeseh");
}
for flag in self.flags.iter() {
cmd.arg(flag);
}
(cmd, tool.to_string())
}
fn assemble(&self, lib_name: &str, dst: &Path, objects: &[PathBuf]) {
// Delete the destination if it exists as the `ar` tool at least on Unix
// appends to it, which we don't want.
let _ = fs::remove_file(&dst);
let target = self.get_target();
if target.contains("msvc") {
let mut cmd = match self.archiver {
Some(ref s) => self.cmd(s),
None => windows_registry::find(&target, "lib.exe")
.unwrap_or(self.cmd("lib.exe")),
};
let mut out = OsString::from("/OUT:");
out.push(dst);
run(cmd.arg(out).arg("/nologo")
.args(objects)
.args(&self.objects), "lib.exe");
// The Rust compiler will look for libfoo.a and foo.lib, but the
// MSVC linker will also be passed foo.lib, so be sure that both
// exist for now.
let lib_dst = dst.with_file_name(format!("{}.lib", lib_name));
let _ = fs::remove_file(&lib_dst);
fs::hard_link(&dst, &lib_dst).or_else(|_| {
//if hard-link fails, just copy (ignoring the number of bytes written)
fs::copy(&dst, &lib_dst).map(|_| ())
}).ok().expect("Copying from {:?} to {:?} failed.");;
} else {
let ar = self.get_ar();
let cmd = ar.file_name().unwrap().to_string_lossy();
run(self.cmd(&ar).arg("crus")
.arg(dst)
.args(objects)
.args(&self.objects), &cmd);
}
}
fn ios_flags(&self, cmd: &mut Tool) {
enum ArchSpec {
Device(&'static str),
Simulator(&'static str),
}
let target = self.get_target();
let arch = target.split('-').nth(0).unwrap();
let arch = match arch {
"arm" | "armv7" | "thumbv7" => ArchSpec::Device("armv7"),
"armv7s" | "thumbv7s" => ArchSpec::Device("armv7s"),
"arm64" | "aarch64" => ArchSpec::Device("arm64"),
"i386" | "i686" => ArchSpec::Simulator("-m32"),
"x86_64" => ArchSpec::Simulator("-m64"),
_ => fail("Unknown arch for iOS target")
};
let sdk = match arch {
ArchSpec::Device(arch) => {
cmd.args.push("-arch".into());
cmd.args.push(arch.into());
cmd.args.push("-miphoneos-version-min=7.0".into());
"iphoneos"
},
ArchSpec::Simulator(arch) => {
cmd.args.push(arch.into());
cmd.args.push("-mios-simulator-version-min=7.0".into());
"iphonesimulator"
}
};
self.print(&format!("Detecting iOS SDK path for {}", sdk));
let sdk_path = self.cmd("xcrun")
.arg("--show-sdk-path")
.arg("--sdk")
.arg(sdk)
.stderr(Stdio::inherit())
.output()
.unwrap()
.stdout;
let sdk_path = String::from_utf8(sdk_path).unwrap();
cmd.args.push("-isysroot".into());
cmd.args.push(sdk_path.trim().into());
}
fn cmd<P: AsRef<OsStr>>(&self, prog: P) -> Command {
let mut cmd = Command::new(prog);
for &(ref a, ref b) in self.env.iter() {
cmd.env(a, b);
}
return cmd
}
fn get_base_compiler(&self) -> Tool {
if let Some(ref c) = self.compiler {
return Tool::new(c.clone())
}
let host = self.get_host();
let target = self.get_target();
let (env, msvc, gnu, default) = if self.cpp {
("CXX", "cl.exe", "g++", "c++")
} else {
("CC", "cl.exe", "gcc", "cc")
};
self.env_tool(env).map(|(tool, args)| {
let mut t = Tool::new(PathBuf::from(tool));
for arg in args {
t.args.push(arg.into());
}
return t
}).or_else(|| {
windows_registry::find_tool(&target, "cl.exe")
}).unwrap_or_else(|| {
let compiler = if host.contains("windows") &&
target.contains("windows") {
if target.contains("msvc") {
msvc.to_string()
} else {
format!("{}.exe", gnu)
}
} else if target.contains("android") {
format!("{}-{}", target, gnu)
} else if self.get_host() != target {
let prefix = match &target[..] {
"aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"),
"arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"),
"arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
"armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"),
"arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"),
"arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
"armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"),
"powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
"powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
"powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
"mips-unknown-linux-gnu" => Some("mips-linux-gnu"),
"mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"),
"i686-pc-windows-gnu" => Some("i686-w64-mingw32"),
"x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"),
"x86_64-unknown-linux-musl" => Some("musl"),
"x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"),
_ => None,
};
match prefix {
Some(prefix) => format!("{}-{}", prefix, gnu),
None => default.to_string(),
}
} else {
default.to_string()
};
Tool::new(PathBuf::from(compiler))
})
}
fn get_var(&self, var_base: &str) -> Result<String, String> {
let target = self.get_target();
let host = self.get_host();
let kind = if host == target {"HOST"} else {"TARGET"};
let target_u = target.replace("-", "_");
let res = self.getenv(&format!("{}_{}", var_base, target))
.or_else(|| self.getenv(&format!("{}_{}", var_base, target_u)))
.or_else(|| self.getenv(&format!("{}_{}", kind, var_base)))
.or_else(|| self.getenv(var_base));
match res {
Some(res) => Ok(res),
None => Err("could not get environment variable".to_string()),
}
}
fn envflags(&self, name: &str) -> Vec<String> {
self.get_var(name).unwrap_or(String::new())
.split(|c: char| c.is_whitespace()).filter(|s| !s.is_empty())
.map(|s| s.to_string())
.collect()
}
fn env_tool(&self, name: &str) -> Option<(String, Vec<String>)> {
self.get_var(name).ok().map(|tool| {
let whitelist = ["ccache", "distcc"];
for t in whitelist.iter() {
if tool.starts_with(t) && tool[t.len()..].starts_with(" ") {
return (t.to_string(),
vec![tool[t.len()..].trim_left().to_string()])
}
}
(tool, Vec::new())
})
}
/// Returns the default C++ standard library for the current target: `libc++`
/// for OS X and `libstdc++` for anything else.
fn get_cpp_link_stdlib(&self) -> Option<String> {
self.cpp_link_stdlib.clone().unwrap_or_else(|| {
let target = self.get_target();
if target.contains("msvc") {
None
} else if target.contains("darwin") {
Some("c++".to_string())
} else {
Some("stdc++".to_string())
}
})
}
fn get_ar(&self) -> PathBuf {
self.archiver.clone().or_else(|| {
self.get_var("AR").map(PathBuf::from).ok()
}).unwrap_or_else(|| {
if self.get_target().contains("android") {
PathBuf::from(format!("{}-ar", self.get_target()))
} else {
PathBuf::from("ar")
}
})
}
fn get_target(&self) -> String {
self.target.clone().unwrap_or_else(|| self.getenv_unwrap("TARGET"))
}
fn get_host(&self) -> String {
self.host.clone().unwrap_or_else(|| self.getenv_unwrap("HOST"))
}
fn get_opt_level(&self) -> u32 {
self.opt_level.unwrap_or_else(|| {
self.getenv_unwrap("OPT_LEVEL").parse().unwrap()
})
}
fn get_debug(&self) -> bool {
self.debug.unwrap_or_else(|| self.getenv_unwrap("PROFILE") == "debug")
}
fn get_out_dir(&self) -> PathBuf {
self.out_dir.clone().unwrap_or_else(|| {
env::var_os("OUT_DIR").map(PathBuf::from).unwrap()
})
}
fn getenv(&self, v: &str) -> Option<String> {
let r = env::var(v).ok();
self.print(&format!("{} = {:?}", v, r));
r
}
fn getenv_unwrap(&self, v: &str) -> String {
match self.getenv(v) {
Some(s) => s,
None => fail(&format!("environment variable `{}` not defined", v)),
}
}
fn print(&self, s: &str) {
if self.cargo_metadata {
println!("{}", s);
}
}
}
impl Tool {
fn new(path: PathBuf) -> Tool {
Tool {
path: path,
args: Vec::new(),
env: Vec::new(),
}
}
/// Converts this compiler into a `Command` that's ready to be run.
///
/// This is useful for when the compiler needs to be executed and the
/// command returned will already have the initial arguments and environment
/// variables configured.
pub fn to_command(&self) -> Command {
let mut cmd = Command::new(&self.path);
cmd.args(&self.args);
for &(ref k, ref v) in self.env.iter() {
cmd.env(k, v);
}
return cmd
}
/// Returns the path for this compiler.
///
/// Note that this may not be a path to a file on the filesystem, e.g. "cc",
/// but rather something which will be resolved when a process is spawned.
pub fn path(&self) -> &Path {
&self.path
}
/// Returns the default set of arguments to the compiler needed to produce
/// executables for the target this compiler generates.
pub fn args(&self) -> &[OsString] {
&self.args
}
/// Returns the set of environment variables needed for this compiler to
/// operate.
///
/// This is typically only used for MSVC compilers currently.
pub fn env(&self) -> &[(OsString, OsString)] {
&self.env
}
}
fn run(cmd: &mut Command, program: &str) {
println!("running: {:?}", cmd);
// Capture the standard error coming from these programs, and write it out
// with cargo:warning= prefixes. Note that this is a bit wonky to avoid
// requiring the output to be UTF-8, we instead just ship bytes from one
// location to another.
let spawn_result = match cmd.stderr(Stdio::piped()).spawn() {
Ok(mut child) => {
let stderr = BufReader::new(child.stderr.take().unwrap());
for line in stderr.split(b'\n').filter_map(|l| l.ok()) {
print!("cargo:warning=");
std::io::stdout().write_all(&line).unwrap();
println!("");
}
child.wait()
}
Err(e) => Err(e),
};
let status = match spawn_result {
Ok(status) => status,
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
let extra = if cfg!(windows) {
" (see https://github.com/alexcrichton/gcc-rs#compile-time-requirements \
for help)"
} else {
""
};
fail(&format!("failed to execute command: {}\nIs `{}` \
not installed?{}", e, program, extra));
}
Err(e) => fail(&format!("failed to execute command: {}", e)),
};
println!("{:?}", status);
if !status.success() {
fail(&format!("command did not execute successfully, got: {}", status));
}
}
fn fail(s: &str) -> ! {
println!("\n\n{}\n\n", s);
panic!()
}

View file

@ -1,169 +0,0 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ffi::{OsString, OsStr};
use std::io;
use std::ops::RangeFrom;
use std::os::raw;
use std::os::windows::prelude::*;
pub struct RegistryKey(Repr);
type HKEY = *mut u8;
type DWORD = u32;
type LPDWORD = *mut DWORD;
type LPCWSTR = *const u16;
type LPWSTR = *mut u16;
type LONG = raw::c_long;
type PHKEY = *mut HKEY;
type PFILETIME = *mut u8;
type LPBYTE = *mut u8;
type REGSAM = u32;
const ERROR_SUCCESS: DWORD = 0;
const ERROR_NO_MORE_ITEMS: DWORD = 259;
const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
const REG_SZ: DWORD = 1;
const KEY_READ: DWORD = 0x20019;
const KEY_WOW64_32KEY: DWORD = 0x200;
#[link(name = "advapi32")]
extern "system" {
fn RegOpenKeyExW(key: HKEY,
lpSubKey: LPCWSTR,
ulOptions: DWORD,
samDesired: REGSAM,
phkResult: PHKEY) -> LONG;
fn RegEnumKeyExW(key: HKEY,
dwIndex: DWORD,
lpName: LPWSTR,
lpcName: LPDWORD,
lpReserved: LPDWORD,
lpClass: LPWSTR,
lpcClass: LPDWORD,
lpftLastWriteTime: PFILETIME) -> LONG;
fn RegQueryValueExW(hKey: HKEY,
lpValueName: LPCWSTR,
lpReserved: LPDWORD,
lpType: LPDWORD,
lpData: LPBYTE,
lpcbData: LPDWORD) -> LONG;
fn RegCloseKey(hKey: HKEY) -> LONG;
}
struct OwnedKey(HKEY);
enum Repr {
Const(HKEY),
Owned(OwnedKey),
}
pub struct Iter<'a> {
idx: RangeFrom<DWORD>,
key: &'a RegistryKey,
}
unsafe impl Sync for Repr {}
unsafe impl Send for Repr {}
pub static LOCAL_MACHINE: RegistryKey =
RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
impl RegistryKey {
fn raw(&self) -> HKEY {
match self.0 {
Repr::Const(val) => val,
Repr::Owned(ref val) => val.0,
}
}
pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut ret = 0 as *mut _;
let err = unsafe {
RegOpenKeyExW(self.raw(), key.as_ptr(), 0,
KEY_READ | KEY_WOW64_32KEY, &mut ret)
};
if err == ERROR_SUCCESS as LONG {
Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
} else {
Err(io::Error::from_raw_os_error(err as i32))
}
}
pub fn iter(&self) -> Iter {
Iter { idx: 0.., key: self }
}
pub fn query_str(&self, name: &str) -> io::Result<OsString> {
let name: &OsStr = name.as_ref();
let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
let mut len = 0;
let mut kind = 0;
unsafe {
let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
&mut kind, 0 as *mut _, &mut len);
if err != ERROR_SUCCESS as LONG {
return Err(io::Error::from_raw_os_error(err as i32))
}
if kind != REG_SZ {
return Err(io::Error::new(io::ErrorKind::Other,
"registry key wasn't a string"))
}
// The length here is the length in bytes, but we're using wide
// characters so we need to be sure to halve it for the capacity
// passed in.
let mut v = Vec::with_capacity(len as usize / 2);
let err = RegQueryValueExW(self.raw(), name.as_ptr(), 0 as *mut _,
0 as *mut _, v.as_mut_ptr() as *mut _,
&mut len);
if err != ERROR_SUCCESS as LONG {
return Err(io::Error::from_raw_os_error(err as i32))
}
v.set_len(len as usize / 2);
// Some registry keys may have a terminating nul character, but
// we're not interested in that, so chop it off if it's there.
if v[v.len() - 1] == 0 {
v.pop();
}
Ok(OsString::from_wide(&v))
}
}
}
impl Drop for OwnedKey {
fn drop(&mut self) {
unsafe { RegCloseKey(self.0); }
}
}
impl<'a> Iterator for Iter<'a> {
type Item = io::Result<OsString>;
fn next(&mut self) -> Option<io::Result<OsString>> {
self.idx.next().and_then(|i| unsafe {
let mut v = Vec::with_capacity(256);
let mut len = v.capacity() as DWORD;
let ret = RegEnumKeyExW(self.key.raw(), i, v.as_mut_ptr(), &mut len,
0 as *mut _, 0 as *mut _, 0 as *mut _,
0 as *mut _);
if ret == ERROR_NO_MORE_ITEMS as LONG {
None
} else if ret != ERROR_SUCCESS as LONG {
Some(Err(io::Error::from_raw_os_error(ret as i32)))
} else {
v.set_len(len as usize);
Some(Ok(OsString::from_wide(&v)))
}
})
}
}

View file

@ -1,423 +0,0 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A helper module to probe the Windows Registry when looking for
//! windows-specific tools.
use std::process::Command;
use Tool;
macro_rules! otry {
($expr:expr) => (match $expr {
Some(val) => val,
None => return None,
})
}
/// Attempts to find a tool within an MSVC installation using the Windows
/// registry as a point to search from.
///
/// The `target` argument is the target that the tool should work for (e.g.
/// compile or link for) and the `tool` argument is the tool to find (e.g.
/// `cl.exe` or `link.exe`).
///
/// This function will return `None` if the tool could not be found, or it will
/// return `Some(cmd)` which represents a command that's ready to execute the
/// tool with the appropriate environment variables set.
///
/// Note that this function always returns `None` for non-MSVC targets.
pub fn find(target: &str, tool: &str) -> Option<Command> {
find_tool(target, tool).map(|c| c.to_command())
}
/// Similar to the `find` function above, this function will attempt the same
/// operation (finding a MSVC tool in a local install) but instead returns a
/// `Tool` which may be introspected.
#[cfg(not(windows))]
pub fn find_tool(_target: &str, _tool: &str) -> Option<Tool> {
None
}
/// Documented above.
#[cfg(windows)]
pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
use std::env;
use std::ffi::OsString;
use std::mem;
use std::path::{Path, PathBuf};
use registry::{RegistryKey, LOCAL_MACHINE};
struct MsvcTool {
tool: PathBuf,
libs: Vec<PathBuf>,
path: Vec<PathBuf>,
include: Vec<PathBuf>,
}
impl MsvcTool {
fn new(tool: PathBuf) -> MsvcTool {
MsvcTool {
tool: tool,
libs: Vec::new(),
path: Vec::new(),
include: Vec::new(),
}
}
fn into_tool(self) -> Tool {
let MsvcTool { tool, libs, path, include } = self;
let mut tool = Tool::new(tool.into());
add_env(&mut tool, "LIB", libs);
add_env(&mut tool, "PATH", path);
add_env(&mut tool, "INCLUDE", include);
return tool
}
}
// This logic is all tailored for MSVC, if we're not that then bail out
// early.
if !target.contains("msvc") {
return None
}
// Looks like msbuild isn't located in the same location as other tools like
// cl.exe and lib.exe. To handle this we probe for it manually with
// dedicated registry keys.
if tool.contains("msbuild") {
return find_msbuild(target)
}
// If VCINSTALLDIR is set, then someone's probably already run vcvars and we
// should just find whatever that indicates.
if env::var_os("VCINSTALLDIR").is_some() {
return env::var_os("PATH").and_then(|path| {
env::split_paths(&path).map(|p| p.join(tool)).find(|p| p.exists())
}).map(|path| {
Tool::new(path.into())
})
}
// Ok, if we're here, now comes the fun part of the probing. Default shells
// or shells like MSYS aren't really configured to execute `cl.exe` and the
// various compiler tools shipped as part of Visual Studio. Here we try to
// first find the relevant tool, then we also have to be sure to fill in
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
// the tool is actually usable.
return find_msvc_latest(tool, target, "15.0").or_else(|| {
find_msvc_latest(tool, target, "14.0")
}).or_else(|| {
find_msvc_12(tool, target)
}).or_else(|| {
find_msvc_11(tool, target)
});
// For MSVC 14 or newer we need to find the Universal CRT as well as either
// the Windows 10 SDK or Windows 8.1 SDK.
fn find_msvc_latest(tool: &str, target: &str, ver: &str) -> Option<Tool> {
let vcdir = otry!(get_vc_dir(ver));
let mut tool = otry!(get_tool(tool, &vcdir, target));
let sub = otry!(lib_subdir(target));
let (ucrt, ucrt_version) = otry!(get_ucrt_dir());
let ucrt_include = ucrt.join("include").join(&ucrt_version);
tool.include.push(ucrt_include.join("ucrt"));
let ucrt_lib = ucrt.join("lib").join(&ucrt_version);
tool.libs.push(ucrt_lib.join("ucrt").join(sub));
if let Some((sdk, version)) = get_sdk10_dir() {
tool.path.push(sdk.join("bin").join(sub));
let sdk_lib = sdk.join("lib").join(&version);
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk.join("include").join(&version);
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
tool.include.push(sdk_include.join("shared"));
} else if let Some(sdk) = get_sdk81_dir() {
tool.path.push(sdk.join("bin").join(sub));
let sdk_lib = sdk.join("lib").join("winv6.3");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk.join("include");
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
tool.include.push(sdk_include.join("shared"));
} else {
return None
}
Some(tool.into_tool())
}
// For MSVC 12 we need to find the Windows 8.1 SDK.
fn find_msvc_12(tool: &str, target: &str) -> Option<Tool> {
let vcdir = otry!(get_vc_dir("12.0"));
let mut tool = otry!(get_tool(tool, &vcdir, target));
let sub = otry!(lib_subdir(target));
let sdk81 = otry!(get_sdk81_dir());
tool.path.push(sdk81.join("bin").join(sub));
let sdk_lib = sdk81.join("lib").join("winv6.3");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk81.join("include");
tool.include.push(sdk_include.join("shared"));
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
Some(tool.into_tool())
}
// For MSVC 11 we need to find the Windows 8 SDK.
fn find_msvc_11(tool: &str, target: &str) -> Option<Tool> {
let vcdir = otry!(get_vc_dir("11.0"));
let mut tool = otry!(get_tool(tool, &vcdir, target));
let sub = otry!(lib_subdir(target));
let sdk8 = otry!(get_sdk8_dir());
tool.path.push(sdk8.join("bin").join(sub));
let sdk_lib = sdk8.join("lib").join("win8");
tool.libs.push(sdk_lib.join("um").join(sub));
let sdk_include = sdk8.join("include");
tool.include.push(sdk_include.join("shared"));
tool.include.push(sdk_include.join("um"));
tool.include.push(sdk_include.join("winrt"));
Some(tool.into_tool())
}
fn add_env(tool: &mut Tool, env: &str, paths: Vec<PathBuf>) {
let prev = env::var_os(env).unwrap_or(OsString::new());
let prev = env::split_paths(&prev);
let new = paths.into_iter().chain(prev);
tool.env.push((env.to_string().into(), env::join_paths(new).unwrap()));
}
// Given a possible MSVC installation directory, we look for the linker and
// then add the MSVC library path.
fn get_tool(tool: &str, path: &Path, target: &str) -> Option<MsvcTool> {
bin_subdir(target).into_iter().map(|(sub, host)| {
(path.join("bin").join(sub).join(tool),
path.join("bin").join(host))
}).filter(|&(ref path, _)| {
path.is_file()
}).map(|(path, host)| {
let mut tool = MsvcTool::new(path);
tool.path.push(host);
tool
}).filter_map(|mut tool| {
let sub = otry!(vc_lib_subdir(target));
tool.libs.push(path.join("lib").join(sub));
tool.include.push(path.join("include"));
Some(tool)
}).next()
}
// To find MSVC we look in a specific registry key for the version we are
// trying to find.
fn get_vc_dir(ver: &str) -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let path = otry!(key.query_str(ver).ok());
Some(path.into())
}
// To find the Universal CRT we look in a specific registry key for where
// all the Universal CRTs are located and then sort them asciibetically to
// find the newest version. While this sort of sorting isn't ideal, it is
// what vcvars does so that's good enough for us.
//
// Returns a pair of (root, version) for the ucrt dir if found
fn get_ucrt_dir() -> Option<(PathBuf, String)> {
let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("KitsRoot10").ok());
let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
let max_libdir = otry!(readdir.filter_map(|dir| {
dir.ok()
}).map(|dir| {
dir.path()
}).filter(|dir| {
dir.components().last().and_then(|c| {
c.as_os_str().to_str()
}).map(|c| {
c.starts_with("10.") && dir.join("ucrt").is_dir()
}).unwrap_or(false)
}).max());
let version = max_libdir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Vcvars finds the correct version of the Windows 10 SDK by looking
// for the include `um\Windows.h` because sometimes a given version will
// only have UCRT bits without the rest of the SDK. Since we only care about
// libraries and not includes, we instead look for `um\x64\kernel32.lib`.
// Since the 32-bit and 64-bit libraries are always installed together we
// only need to bother checking x64, making this code a tiny bit simpler.
// Like we do for the Universal CRT, we sort the possibilities
// asciibetically to find the newest one as that is what vcvars does.
fn get_sdk10_dir() -> Option<(PathBuf, String)> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("InstallationFolder").ok());
let readdir = otry!(Path::new(&root).join("lib").read_dir().ok());
let mut dirs = readdir.filter_map(|dir| dir.ok())
.map(|dir| dir.path())
.collect::<Vec<_>>();
dirs.sort();
let dir = otry!(dirs.into_iter().rev().filter(|dir| {
dir.join("um").join("x64").join("kernel32.lib").is_file()
}).next());
let version = dir.components().last().unwrap();
let version = version.as_os_str().to_str().unwrap().to_string();
Some((root.into(), version))
}
// Interestingly there are several subdirectories, `win7` `win8` and
// `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same
// applies to us. Note that if we were targetting kernel mode drivers
// instead of user mode applications, we would care.
fn get_sdk81_dir() -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("InstallationFolder").ok());
Some(root.into())
}
fn get_sdk8_dir() -> Option<PathBuf> {
let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0";
let key = otry!(LOCAL_MACHINE.open(key.as_ref()).ok());
let root = otry!(key.query_str("InstallationFolder").ok());
Some(root.into())
}
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
const X86: u16 = PROCESSOR_ARCHITECTURE_INTEL;
const X86_64: u16 = PROCESSOR_ARCHITECTURE_AMD64;
// When choosing the tool to use, we have to choose the one which matches
// the target architecture. Otherwise we end up in situations where someone
// on 32-bit Windows is trying to cross compile to 64-bit and it tries to
// invoke the native 64-bit compiler which won't work.
//
// For the return value of this function, the first member of the tuple is
// the folder of the tool we will be invoking, while the second member is
// the folder of the host toolchain for that tool which is essential when
// using a cross linker. We return a Vec since on x64 there are often two
// linkers that can target the architecture we desire. The 64-bit host
// linker is preferred, and hence first, due to 64-bit allowing it more
// address space to work with and potentially being faster.
fn bin_subdir(target: &str) -> Vec<(&'static str, &'static str)> {
let arch = target.split('-').next().unwrap();
match (arch, host_arch()) {
("i686", X86) => vec![("", "")],
("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")],
("x86_64", X86) => vec![("x86_amd64", "")],
("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")],
("arm", X86) => vec![("x86_arm", "")],
("arm", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
_ => vec![],
}
}
fn lib_subdir(target: &str) -> Option<&'static str> {
let arch = target.split('-').next().unwrap();
match arch {
"i686" => Some("x86"),
"x86_64" => Some("x64"),
"arm" => Some("arm"),
_ => None,
}
}
// MSVC's x86 libraries are not in a subfolder
fn vc_lib_subdir(target: &str) -> Option<&'static str> {
let arch = target.split('-').next().unwrap();
match arch {
"i686" => Some(""),
"x86_64" => Some("amd64"),
"arm" => Some("arm"),
_ => None,
}
}
#[allow(bad_style)]
fn host_arch() -> u16 {
type DWORD = u32;
type WORD = u16;
type LPVOID = *mut u8;
type DWORD_PTR = usize;
#[repr(C)]
struct SYSTEM_INFO {
wProcessorArchitecture: WORD,
_wReserved: WORD,
_dwPageSize: DWORD,
_lpMinimumApplicationAddress: LPVOID,
_lpMaximumApplicationAddress: LPVOID,
_dwActiveProcessorMask: DWORD_PTR,
_dwNumberOfProcessors: DWORD,
_dwProcessorType: DWORD,
_dwAllocationGranularity: DWORD,
_wProcessorLevel: WORD,
_wProcessorRevision: WORD,
}
extern "system" {
fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
}
unsafe {
let mut info = mem::zeroed();
GetNativeSystemInfo(&mut info);
info.wProcessorArchitecture
}
}
// Given a registry key, look at all the sub keys and find the one which has
// the maximal numeric value.
//
// Returns the name of the maximal key as well as the opened maximal key.
fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
let mut max_vers = 0;
let mut max_key = None;
for subkey in key.iter().filter_map(|k| k.ok()) {
let val = subkey.to_str().and_then(|s| {
s.trim_left_matches("v").replace(".", "").parse().ok()
});
let val = match val {
Some(s) => s,
None => continue,
};
if val > max_vers {
if let Ok(k) = key.open(&subkey) {
max_vers = val;
max_key = Some((subkey, k));
}
}
}
return max_key
}
// see http://stackoverflow.com/questions/328017/path-to-msbuild
fn find_msbuild(target: &str) -> Option<Tool> {
let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions";
LOCAL_MACHINE.open(key.as_ref()).ok().and_then(|key| {
max_version(&key).and_then(|(_vers, key)| {
key.query_str("MSBuildToolsPath").ok()
})
}).map(|path| {
let mut path = PathBuf::from(path);
path.push("MSBuild.exe");
let mut tool = Tool::new(path);
if target.contains("x86_64") {
tool.env.push(("Platform".into(), "X64".into()));
}
tool
})
}
}

View file

@ -1,49 +0,0 @@
extern crate tempdir;
extern crate gcc;
use std::env;
mod support;
use support::Test;
#[test]
fn main() {
ccache();
distcc();
ccache_spaces();
}
fn ccache() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "ccache lol-this-is-not-a-compiler foo");
test.gcc().file("foo.c").compile("libfoo.a");
test.cmd(0)
.must_have("lol-this-is-not-a-compiler foo")
.must_have("foo.c")
.must_not_have("ccache");
}
fn ccache_spaces() {
let test = Test::gnu();
test.shim("ccache");
env::set_var("CC", "ccache lol-this-is-not-a-compiler foo");
test.gcc().file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("lol-this-is-not-a-compiler foo");
}
fn distcc() {
let test = Test::gnu();
test.shim("distcc");
env::set_var("CC", "distcc lol-this-is-not-a-compiler foo");
test.gcc().file("foo.c").compile("libfoo.a");
test.cmd(0)
.must_have("lol-this-is-not-a-compiler foo")
.must_have("foo.c")
.must_not_have("distcc");
}

View file

@ -1,111 +0,0 @@
#![allow(dead_code)]
use std::env;
use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::PathBuf;
use gcc;
use tempdir::TempDir;
pub struct Test {
pub td: TempDir,
pub gcc: PathBuf,
pub msvc: bool,
}
pub struct Execution {
args: Vec<String>,
}
impl Test {
pub fn new() -> Test {
let mut gcc = PathBuf::from(env::current_exe().unwrap());
gcc.pop();
gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
Test {
td: TempDir::new("gcc-test").unwrap(),
gcc: gcc,
msvc: false,
}
}
pub fn gnu() -> Test {
let t = Test::new();
t.shim("cc").shim("ar");
return t
}
pub fn msvc() -> Test {
let mut t = Test::new();
t.shim("cl").shim("lib.exe");
t.msvc = true;
return t
}
pub fn shim(&self, name: &str) -> &Test {
let fname = format!("{}{}", name, env::consts::EXE_SUFFIX);
fs::hard_link(&self.gcc, self.td.path().join(&fname)).or_else(|_| {
fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ())
}).unwrap();
self
}
pub fn gcc(&self) -> gcc::Config {
let mut cfg = gcc::Config::new();
let mut path = env::split_paths(&env::var_os("PATH").unwrap())
.collect::<Vec<_>>();
path.insert(0, self.td.path().to_owned());
let target = if self.msvc {
"x86_64-pc-windows-msvc"
} else {
"x86_64-unknown-linux-gnu"
};
cfg.target(target).host(target)
.opt_level(2)
.debug(false)
.out_dir(self.td.path())
.__set_env("PATH", env::join_paths(path).unwrap())
.__set_env("GCCTEST_OUT_DIR", self.td.path());
if self.msvc {
cfg.compiler(self.td.path().join("cl"));
cfg.archiver(self.td.path().join("lib.exe"));
}
return cfg
}
pub fn cmd(&self, i: u32) -> Execution {
let mut s = String::new();
File::open(self.td.path().join(format!("out{}", i))).unwrap()
.read_to_string(&mut s).unwrap();
Execution {
args: s.lines().map(|s| s.to_string()).collect(),
}
}
}
impl Execution {
pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
if !self.has(p.as_ref()) {
panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
} else {
self
}
}
pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
if self.has(p.as_ref()) {
panic!("found {:?}", p.as_ref());
} else {
self
}
}
pub fn has(&self, p: &OsStr) -> bool {
self.args.iter().any(|arg| {
OsStr::new(arg) == p
})
}
}

View file

@ -1,193 +0,0 @@
extern crate gcc;
extern crate tempdir;
use support::Test;
mod support;
#[test]
fn gnu_smoke() {
let test = Test::gnu();
test.gcc()
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-O2")
.must_have("foo.c")
.must_not_have("-g")
.must_have("-c")
.must_have("-ffunction-sections")
.must_have("-fdata-sections");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn gnu_opt_level_1() {
let test = Test::gnu();
test.gcc()
.opt_level(1)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-O1")
.must_not_have("-O2");
}
#[test]
fn gnu_debug() {
let test = Test::gnu();
test.gcc()
.debug(true)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-g");
}
#[test]
fn gnu_x86_64() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-fPIC")
.must_have("-m64");
}
}
#[test]
fn gnu_x86_64_no_pic() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("x86_64-{}", vendor);
let test = Test::gnu();
test.gcc()
.pic(false)
.target(&target)
.host(&target)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_not_have("-fPIC");
}
}
#[test]
fn gnu_i686() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
test.gcc()
.target(&target)
.host(&target)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_not_have("-fPIC")
.must_have("-m32");
}
}
#[test]
fn gnu_i686_pic() {
for vendor in &["unknown-linux-gnu", "apple-darwin"] {
let target = format!("i686-{}", vendor);
let test = Test::gnu();
test.gcc()
.pic(true)
.target(&target)
.host(&target)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-fPIC");
}
}
#[test]
fn gnu_set_stdlib() {
let test = Test::gnu();
test.gcc()
.cpp_set_stdlib(Some("foo"))
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_not_have("-stdlib=foo");
}
#[test]
fn gnu_include() {
let test = Test::gnu();
test.gcc()
.include("foo/bar")
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-I").must_have("foo/bar");
}
#[test]
fn gnu_define() {
let test = Test::gnu();
test.gcc()
.define("FOO", Some("bar"))
.define("BAR", None)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
}
#[test]
fn gnu_compile_assembly() {
let test = Test::gnu();
test.gcc()
.file("foo.S").compile("libfoo.a");
test.cmd(0).must_have("foo.S");
}
#[test]
fn msvc_smoke() {
let test = Test::msvc();
test.gcc()
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("/O2")
.must_have("foo.c")
.must_not_have("/Z7")
.must_have("/c");
test.cmd(1).must_have(test.td.path().join("foo.o"));
}
#[test]
fn msvc_opt_level_0() {
let test = Test::msvc();
test.gcc()
.opt_level(0)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_not_have("/O2");
}
#[test]
fn msvc_debug() {
let test = Test::msvc();
test.gcc()
.debug(true)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("/Z7");
}
#[test]
fn msvc_include() {
let test = Test::msvc();
test.gcc()
.include("foo/bar")
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("/I").must_have("foo/bar");
}
#[test]
fn msvc_define() {
let test = Test::msvc();
test.gcc()
.define("FOO", Some("bar"))
.define("BAR", None)
.file("foo.c").compile("libfoo.a");
test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR");
}

View file

@ -1 +0,0 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"d0aad6852ec947597bab20cd85ad15e014044cb7717c9a91f4b8da0081b7134d","src/IdnaMappingTable.txt":"5e9f5929130b713e698162ac5b60a99ccfb831606686b1c50777cd920b55dee2","src/lib.rs":"b8e85707a40e8472d2e90849a1e0e24a7442f3c4614a57a60125f87d11e985a4","src/make_uts46_mapping_table.py":"36fa77c443672f15872d60438f96b7302eae28ec506b60a892579debc79b8e39","src/punycode.rs":"df883ec00b35cab38f96992667eef0767d8587746bfdab0613a03e4c49a26c16","src/uts46.rs":"c879570c511f210565ac0dbce8a212be6503e62cd7ed698830804bb7729e98de","src/uts46_mapping_table.rs":"daa59e4b6399a738f73967b222b7dce6c9706a471d306330d77380c89089fa24","tests/IdnaTest.txt":"12e7e150b04a7a2cb1f9b72222174844342218807126e9dbc53069505a5f6000","tests/punycode.rs":"2f4086411c00b0641377afe81071e51a695110a0cce474287557738c07f74322","tests/punycode_tests.json":"3d4ac0cf25984c37b9ce197f5df680a0136f728fb8ec82bc76624e42139eb3a8","tests/tests.rs":"bb92e129dc5e17e9a86ec6062dd7b3f4c905c4af69e773d7c70efea177654c7b","tests/uts46.rs":"be9f928c60b88a8e277ddfb1769f09a8cd273e2e120e8450fb9b34f4dc852b37"},"package":"1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"}

View file

View file

@ -1,24 +0,0 @@
[package]
name = "idna"
version = "0.1.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
description = "IDNA (Internationalizing Domain Names in Applications) and Punycode."
repository = "https://github.com/servo/rust-url/"
license = "MIT/Apache-2.0"
[lib]
doctest = false
test = false
[[test]]
name = "tests"
harness = false
[dev-dependencies]
rustc-test = "0.1"
rustc-serialize = "0.3"
[dependencies]
unicode-bidi = "0.2.3"
unicode-normalization = "0.1.2"
matches = "0.1"

File diff suppressed because it is too large Load diff

View file

@ -1,73 +0,0 @@
// Copyright 2016 Simon Sapin.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This Rust crate implements IDNA
//! [per the WHATWG URL Standard](https://url.spec.whatwg.org/#idna).
//!
//! It also exposes the underlying algorithms from [*Unicode IDNA Compatibility Processing*
//! (Unicode Technical Standard #46)](http://www.unicode.org/reports/tr46/)
//! and [Punycode (RFC 3492)](https://tools.ietf.org/html/rfc3492).
//!
//! Quoting from [UTS #46s introduction](http://www.unicode.org/reports/tr46/#Introduction):
//!
//! > Initially, domain names were restricted to ASCII characters.
//! > A system was introduced in 2003 for internationalized domain names (IDN).
//! > This system is called Internationalizing Domain Names for Applications,
//! > or IDNA2003 for short.
//! > This mechanism supports IDNs by means of a client software transformation
//! > into a format known as Punycode.
//! > A revision of IDNA was approved in 2010 (IDNA2008).
//! > This revision has a number of incompatibilities with IDNA2003.
//! >
//! > The incompatibilities force implementers of client software,
//! > such as browsers and emailers,
//! > to face difficult choices during the transition period
//! > as registries shift from IDNA2003 to IDNA2008.
//! > This document specifies a mechanism
//! > that minimizes the impact of this transition for client software,
//! > allowing client software to access domains that are valid under either system.
#[macro_use] extern crate matches;
extern crate unicode_bidi;
extern crate unicode_normalization;
pub mod punycode;
pub mod uts46;
/// The [domain to ASCII](https://url.spec.whatwg.org/#concept-domain-to-ascii) algorithm.
///
/// Return the ASCII representation a domain name,
/// normalizing characters (upper-case to lower-case and other kinds of equivalence)
/// and using Punycode as necessary.
///
/// This process may fail.
pub fn domain_to_ascii(domain: &str) -> Result<String, uts46::Errors> {
uts46::to_ascii(domain, uts46::Flags {
use_std3_ascii_rules: false,
transitional_processing: true, // XXX: switch when Firefox does
verify_dns_length: false,
})
}
/// The [domain to Unicode](https://url.spec.whatwg.org/#concept-domain-to-unicode) algorithm.
///
/// Return the Unicode representation of a domain name,
/// normalizing characters (upper-case to lower-case and other kinds of equivalence)
/// and decoding Punycode as necessary.
///
/// This may indicate [syntax violations](https://url.spec.whatwg.org/#syntax-violation)
/// but always returns a string for the mapped domain.
pub fn domain_to_unicode(domain: &str) -> (String, Result<(), uts46::Errors>) {
uts46::to_unicode(domain, uts46::Flags {
use_std3_ascii_rules: false,
// Unused:
transitional_processing: true,
verify_dns_length: false,
})
}

View file

@ -1,56 +0,0 @@
# Copyright 2013-2014 Valentin Gosu.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# Run as: python make_uts46_mapping_table.py IdnaMappingTable.txt > uts46_mapping_table.rs
# You can get the latest idna table from
# http://www.unicode.org/Public/idna/latest/IdnaMappingTable.txt
print('''\
// Copyright 2013-2014 Valentin Gosu.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Generated by make_idna_table.py
static TABLE: &'static [Range] = &[
''')
txt = open("IdnaMappingTable.txt")
def char(s):
return (unichr(int(s, 16))
.encode('utf8')
.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('\0', '\\0'))
for line in txt:
# remove comments
line, _, _ = line.partition('#')
# skip empty lines
if len(line.strip()) == 0:
continue
fields = line.split(';')
if fields[0].strip() == 'D800..DFFF':
continue # Surrogates don't occur in Rust strings.
first, _, last = fields[0].strip().partition('..')
if not last:
last = first
mapping = fields[1].strip().replace('_', ' ').title().replace(' ', '')
if len(fields) > 2:
if fields[2].strip():
mapping += '("%s")' % ''.join(char(c) for c in fields[2].strip().split(' '))
elif mapping == "Deviation":
mapping += '("")'
print(" Range { from: '%s', to: '%s', mapping: %s }," % (char(first), char(last), mapping))
print("];")

View file

@ -1,213 +0,0 @@
// Copyright 2013 Simon Sapin.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Punycode ([RFC 3492](http://tools.ietf.org/html/rfc3492)) implementation.
//!
//! Since Punycode fundamentally works on unicode code points,
//! `encode` and `decode` take and return slices and vectors of `char`.
//! `encode_str` and `decode_to_string` provide convenience wrappers
//! that convert from and to Rusts UTF-8 based `str` and `String` types.
use std::u32;
use std::char;
use std::ascii::AsciiExt;
// Bootstring parameters for Punycode
static BASE: u32 = 36;
static T_MIN: u32 = 1;
static T_MAX: u32 = 26;
static SKEW: u32 = 38;
static DAMP: u32 = 700;
static INITIAL_BIAS: u32 = 72;
static INITIAL_N: u32 = 0x80;
static DELIMITER: char = '-';
#[inline]
fn adapt(mut delta: u32, num_points: u32, first_time: bool) -> u32 {
delta /= if first_time { DAMP } else { 2 };
delta += delta / num_points;
let mut k = 0;
while delta > ((BASE - T_MIN) * T_MAX) / 2 {
delta /= BASE - T_MIN;
k += BASE;
}
k + (((BASE - T_MIN + 1) * delta) / (delta + SKEW))
}
/// Convert Punycode to an Unicode `String`.
///
/// This is a convenience wrapper around `decode`.
#[inline]
pub fn decode_to_string(input: &str) -> Option<String> {
decode(input).map(|chars| chars.into_iter().collect())
}
/// Convert Punycode to Unicode.
///
/// Return None on malformed input or overflow.
/// Overflow can only happen on inputs that take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn decode(input: &str) -> Option<Vec<char>> {
// Handle "basic" (ASCII) code points.
// They are encoded as-is before the last delimiter, if any.
let (mut output, input) = match input.rfind(DELIMITER) {
None => (Vec::new(), input),
Some(position) => (
input[..position].chars().collect(),
if position > 0 { &input[position + 1..] } else { input }
)
};
let mut code_point = INITIAL_N;
let mut bias = INITIAL_BIAS;
let mut i = 0;
let mut iter = input.bytes();
loop {
let previous_i = i;
let mut weight = 1;
let mut k = BASE;
let mut byte = match iter.next() {
None => break,
Some(byte) => byte,
};
// Decode a generalized variable-length integer into delta,
// which gets added to i.
loop {
let digit = match byte {
byte @ b'0' ... b'9' => byte - b'0' + 26,
byte @ b'A' ... b'Z' => byte - b'A',
byte @ b'a' ... b'z' => byte - b'a',
_ => return None
} as u32;
if digit > (u32::MAX - i) / weight {
return None // Overflow
}
i += digit * weight;
let t = if k <= bias { T_MIN }
else if k >= bias + T_MAX { T_MAX }
else { k - bias };
if digit < t {
break
}
if weight > u32::MAX / (BASE - t) {
return None // Overflow
}
weight *= BASE - t;
k += BASE;
byte = match iter.next() {
None => return None, // End of input before the end of this delta
Some(byte) => byte,
};
}
let length = output.len() as u32;
bias = adapt(i - previous_i, length + 1, previous_i == 0);
if i / (length + 1) > u32::MAX - code_point {
return None // Overflow
}
// i was supposed to wrap around from length+1 to 0,
// incrementing code_point each time.
code_point += i / (length + 1);
i %= length + 1;
let c = match char::from_u32(code_point) {
Some(c) => c,
None => return None
};
output.insert(i as usize, c);
i += 1;
}
Some(output)
}
/// Convert an Unicode `str` to Punycode.
///
/// This is a convenience wrapper around `encode`.
#[inline]
pub fn encode_str(input: &str) -> Option<String> {
encode(&input.chars().collect::<Vec<char>>())
}
/// Convert Unicode to Punycode.
///
/// Return None on overflow, which can only happen on inputs that would take more than
/// 63 encoded bytes, the DNS limit on domain name labels.
pub fn encode(input: &[char]) -> Option<String> {
// Handle "basic" (ASCII) code points. They are encoded as-is.
let output_bytes = input.iter().filter_map(|&c|
if c.is_ascii() { Some(c as u8) } else { None }
).collect();
let mut output = unsafe { String::from_utf8_unchecked(output_bytes) };
let basic_length = output.len() as u32;
if basic_length > 0 {
output.push_str("-")
}
let mut code_point = INITIAL_N;
let mut delta = 0;
let mut bias = INITIAL_BIAS;
let mut processed = basic_length;
let input_length = input.len() as u32;
while processed < input_length {
// All code points < code_point have been handled already.
// Find the next larger one.
let min_code_point = input.iter().map(|&c| c as u32)
.filter(|&c| c >= code_point).min().unwrap();
if min_code_point - code_point > (u32::MAX - delta) / (processed + 1) {
return None // Overflow
}
// Increase delta to advance the decoders <code_point,i> state to <min_code_point,0>
delta += (min_code_point - code_point) * (processed + 1);
code_point = min_code_point;
for &c in input {
let c = c as u32;
if c < code_point {
delta += 1;
if delta == 0 {
return None // Overflow
}
}
if c == code_point {
// Represent delta as a generalized variable-length integer:
let mut q = delta;
let mut k = BASE;
loop {
let t = if k <= bias { T_MIN }
else if k >= bias + T_MAX { T_MAX }
else { k - bias };
if q < t {
break
}
let value = t + ((q - t) % (BASE - t));
value_to_digit(value, &mut output);
q = (q - t) / (BASE - t);
k += BASE;
}
value_to_digit(q, &mut output);
bias = adapt(delta, processed + 1, processed == basic_length);
delta = 0;
processed += 1;
}
}
delta += 1;
code_point += 1;
}
Some(output)
}
#[inline]
fn value_to_digit(value: u32, output: &mut String) {
let code_point = match value {
0 ... 25 => value + 0x61, // a..z
26 ... 35 => value - 26 + 0x30, // 0..9
_ => panic!()
};
unsafe { output.as_mut_vec().push(code_point as u8) }
}

View file

@ -1,322 +0,0 @@
// Copyright 2013-2014 Valentin Gosu.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! [*Unicode IDNA Compatibility Processing*
//! (Unicode Technical Standard #46)](http://www.unicode.org/reports/tr46/)
use self::Mapping::*;
use punycode;
use std::ascii::AsciiExt;
use unicode_normalization::UnicodeNormalization;
use unicode_normalization::char::is_combining_mark;
use unicode_bidi::{BidiClass, bidi_class};
include!("uts46_mapping_table.rs");
#[derive(Debug)]
enum Mapping {
Valid,
Ignored,
Mapped(&'static str),
Deviation(&'static str),
Disallowed,
DisallowedStd3Valid,
DisallowedStd3Mapped(&'static str),
}
struct Range {
from: char,
to: char,
mapping: Mapping,
}
fn find_char(codepoint: char) -> &'static Mapping {
let mut min = 0;
let mut max = TABLE.len() - 1;
while max > min {
let mid = (min + max) >> 1;
if codepoint > TABLE[mid].to {
min = mid;
} else if codepoint < TABLE[mid].from {
max = mid;
} else {
min = mid;
max = mid;
}
}
&TABLE[min].mapping
}
fn map_char(codepoint: char, flags: Flags, output: &mut String, errors: &mut Vec<Error>) {
match *find_char(codepoint) {
Mapping::Valid => output.push(codepoint),
Mapping::Ignored => {},
Mapping::Mapped(mapping) => output.push_str(mapping),
Mapping::Deviation(mapping) => {
if flags.transitional_processing {
output.push_str(mapping)
} else {
output.push(codepoint)
}
}
Mapping::Disallowed => {
errors.push(Error::DissallowedCharacter);
output.push(codepoint);
}
Mapping::DisallowedStd3Valid => {
if flags.use_std3_ascii_rules {
errors.push(Error::DissallowedByStd3AsciiRules);
}
output.push(codepoint)
}
Mapping::DisallowedStd3Mapped(mapping) => {
if flags.use_std3_ascii_rules {
errors.push(Error::DissallowedMappedInStd3);
}
output.push_str(mapping)
}
}
}
// http://tools.ietf.org/html/rfc5893#section-2
fn passes_bidi(label: &str, transitional_processing: bool) -> bool {
let mut chars = label.chars();
let class = match chars.next() {
Some(c) => bidi_class(c),
None => return true, // empty string
};
if class == BidiClass::L
|| (class == BidiClass::ON && transitional_processing) // starts with \u200D
|| (class == BidiClass::ES && transitional_processing) // hack: 1.35.+33.49
|| class == BidiClass::EN // hack: starts with number 0à.\u05D0
{ // LTR
// Rule 5
loop {
match chars.next() {
Some(c) => {
let c = bidi_class(c);
if !matches!(c, BidiClass::L | BidiClass::EN |
BidiClass::ES | BidiClass::CS |
BidiClass::ET | BidiClass::ON |
BidiClass::BN | BidiClass::NSM) {
return false;
}
},
None => { break; },
}
}
// Rule 6
let mut rev_chars = label.chars().rev();
let mut last = rev_chars.next();
loop { // must end in L or EN followed by 0 or more NSM
match last {
Some(c) if bidi_class(c) == BidiClass::NSM => {
last = rev_chars.next();
continue;
}
_ => { break; },
}
}
// TODO: does not pass for àˇ.\u05D0
// match last {
// Some(c) if bidi_class(c) == BidiClass::L
// || bidi_class(c) == BidiClass::EN => {},
// Some(c) => { return false; },
// _ => {}
// }
} else if class == BidiClass::R || class == BidiClass::AL { // RTL
let mut found_en = false;
let mut found_an = false;
// Rule 2
loop {
match chars.next() {
Some(c) => {
let char_class = bidi_class(c);
if char_class == BidiClass::EN {
found_en = true;
}
if char_class == BidiClass::AN {
found_an = true;
}
if !matches!(char_class, BidiClass::R | BidiClass::AL |
BidiClass::AN | BidiClass::EN |
BidiClass::ES | BidiClass::CS |
BidiClass::ET | BidiClass::ON |
BidiClass::BN | BidiClass::NSM) {
return false;
}
},
None => { break; },
}
}
// Rule 3
let mut rev_chars = label.chars().rev();
let mut last = rev_chars.next();
loop { // must end in L or EN followed by 0 or more NSM
match last {
Some(c) if bidi_class(c) == BidiClass::NSM => {
last = rev_chars.next();
continue;
}
_ => { break; },
}
}
match last {
Some(c) if matches!(bidi_class(c), BidiClass::R | BidiClass::AL |
BidiClass::EN | BidiClass::AN) => {},
_ => { return false; }
}
// Rule 4
if found_an && found_en {
return false;
}
} else {
// Rule 2: Should start with L or R/AL
return false;
}
return true;
}
/// http://www.unicode.org/reports/tr46/#Validity_Criteria
fn validate(label: &str, flags: Flags, errors: &mut Vec<Error>) {
if label.nfc().ne(label.chars()) {
errors.push(Error::ValidityCriteria);
}
// Can not contain '.' since the input is from .split('.')
if {
let mut chars = label.chars().skip(2);
let third = chars.next();
let fourth = chars.next();
(third, fourth) == (Some('-'), Some('-'))
} || label.starts_with("-")
|| label.ends_with("-")
|| label.chars().next().map_or(false, is_combining_mark)
|| label.chars().any(|c| match *find_char(c) {
Mapping::Valid => false,
Mapping::Deviation(_) => flags.transitional_processing,
Mapping::DisallowedStd3Valid => flags.use_std3_ascii_rules,
_ => true,
})
|| !passes_bidi(label, flags.transitional_processing)
{
errors.push(Error::ValidityCriteria)
}
}
/// http://www.unicode.org/reports/tr46/#Processing
fn processing(domain: &str, flags: Flags, errors: &mut Vec<Error>) -> String {
let mut mapped = String::new();
for c in domain.chars() {
map_char(c, flags, &mut mapped, errors)
}
let normalized: String = mapped.nfc().collect();
let mut validated = String::new();
for label in normalized.split('.') {
if validated.len() > 0 {
validated.push('.');
}
if label.starts_with("xn--") {
match punycode::decode_to_string(&label["xn--".len()..]) {
Some(decoded_label) => {
let flags = Flags { transitional_processing: false, ..flags };
validate(&decoded_label, flags, errors);
validated.push_str(&decoded_label)
}
None => errors.push(Error::PunycodeError)
}
} else {
validate(label, flags, errors);
validated.push_str(label)
}
}
validated
}
#[derive(Copy, Clone)]
pub struct Flags {
pub use_std3_ascii_rules: bool,
pub transitional_processing: bool,
pub verify_dns_length: bool,
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
enum Error {
PunycodeError,
ValidityCriteria,
DissallowedByStd3AsciiRules,
DissallowedMappedInStd3,
DissallowedCharacter,
TooLongForDns,
}
/// Errors recorded during UTS #46 processing.
///
/// This is opaque for now, only indicating the precense of at least one error.
/// More details may be exposed in the future.
#[derive(Debug)]
pub struct Errors(Vec<Error>);
/// http://www.unicode.org/reports/tr46/#ToASCII
pub fn to_ascii(domain: &str, flags: Flags) -> Result<String, Errors> {
let mut errors = Vec::new();
let mut result = String::new();
for label in processing(domain, flags, &mut errors).split('.') {
if result.len() > 0 {
result.push('.');
}
if label.is_ascii() {
result.push_str(label);
} else {
match punycode::encode_str(label) {
Some(x) => {
result.push_str("xn--");
result.push_str(&x);
},
None => errors.push(Error::PunycodeError)
}
}
}
if flags.verify_dns_length {
let domain = if result.ends_with(".") { &result[..result.len()-1] } else { &*result };
if domain.len() < 1 || domain.len() > 253 ||
domain.split('.').any(|label| label.len() < 1 || label.len() > 63) {
errors.push(Error::TooLongForDns)
}
}
if errors.is_empty() {
Ok(result)
} else {
Err(Errors(errors))
}
}
/// http://www.unicode.org/reports/tr46/#ToUnicode
///
/// Only `use_std3_ascii_rules` is used in `flags`.
pub fn to_unicode(domain: &str, mut flags: Flags) -> (String, Result<(), Errors>) {
flags.transitional_processing = false;
let mut errors = Vec::new();
let domain = processing(domain, flags, &mut errors);
let errors = if errors.is_empty() {
Ok(())
} else {
Err(Errors(errors))
};
(domain, errors)
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,65 +0,0 @@
// Copyright 2013 Simon Sapin.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use idna::punycode::{decode, encode_str};
use rustc_serialize::json::{Json, Object};
use test::TestFn;
fn one_test(decoded: &str, encoded: &str) {
match decode(encoded) {
None => panic!("Decoding {} failed.", encoded),
Some(result) => {
let result = result.into_iter().collect::<String>();
assert!(result == decoded,
format!("Incorrect decoding of \"{}\":\n \"{}\"\n!= \"{}\"\n",
encoded, result, decoded))
}
}
match encode_str(decoded) {
None => panic!("Encoding {} failed.", decoded),
Some(result) => {
assert!(result == encoded,
format!("Incorrect encoding of \"{}\":\n \"{}\"\n!= \"{}\"\n",
decoded, result, encoded))
}
}
}
fn get_string<'a>(map: &'a Object, key: &str) -> &'a str {
match map.get(&key.to_string()) {
Some(&Json::String(ref s)) => s,
None => "",
_ => panic!(),
}
}
pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
match Json::from_str(include_str!("punycode_tests.json")) {
Ok(Json::Array(tests)) => for (i, test) in tests.into_iter().enumerate() {
match test {
Json::Object(o) => {
let test_name = {
let desc = get_string(&o, "description");
if desc.is_empty() {
format!("Punycode {}", i + 1)
} else {
format!("Punycode {}: {}", i + 1, desc)
}
};
add_test(test_name, TestFn::dyn_test_fn(move || one_test(
get_string(&o, "decoded"),
get_string(&o, "encoded"),
)))
}
_ => panic!(),
}
},
other => panic!("{:?}", other)
}
}

View file

@ -1,120 +0,0 @@
[
{
"description": "These tests are copied from https://github.com/bestiejs/punycode.js/blob/master/tests/tests.js , used under the MIT license.",
"decoded": "",
"encoded": ""
},
{
"description": "a single basic code point",
"decoded": "Bach",
"encoded": "Bach-"
},
{
"description": "a single non-ASCII character",
"decoded": "\u00FC",
"encoded": "tda"
},
{
"description": "multiple non-ASCII characters",
"decoded": "\u00FC\u00EB\u00E4\u00F6\u2665",
"encoded": "4can8av2009b"
},
{
"description": "mix of ASCII and non-ASCII characters",
"decoded": "b\u00FCcher",
"encoded": "bcher-kva"
},
{
"description": "long string with both ASCII and non-ASCII characters",
"decoded": "Willst du die Bl\u00FCthe des fr\u00FChen, die Fr\u00FCchte des sp\u00E4teren Jahres",
"encoded": "Willst du die Blthe des frhen, die Frchte des spteren Jahres-x9e96lkal"
},
{
"description": "Arabic (Egyptian)",
"decoded": "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
"encoded": "egbpdaj6bu4bxfgehfvwxn"
},
{
"description": "Chinese (simplified)",
"decoded": "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2d\u6587",
"encoded": "ihqwcrb4cv8a8dqg056pqjye"
},
{
"description": "Chinese (traditional)",
"decoded": "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
"encoded": "ihqwctvzc91f659drss3x8bo0yb"
},
{
"description": "Czech",
"decoded": "Pro\u010Dprost\u011Bnemluv\u00ED\u010Desky",
"encoded": "Proprostnemluvesky-uyb24dma41a"
},
{
"description": "Hebrew",
"decoded": "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2\u05D1\u05E8\u05D9\u05EA",
"encoded": "4dbcagdahymbxekheh6e0a7fei0b"
},
{
"description": "Hindi (Devanagari)",
"decoded": "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947\u0939\u0948\u0902",
"encoded": "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd"
},
{
"description": "Japanese (kanji and hiragana)",
"decoded": "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
"encoded": "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa"
},
{
"description": "Korean (Hangul syllables)",
"decoded": "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
"encoded": "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c"
},
{
"description": "Russian (Cyrillic)",
"decoded": "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A\u0438",
"encoded": "b1abfaaepdrnnbgefbadotcwatmq2g4l"
},
{
"description": "Spanish",
"decoded": "Porqu\u00E9nopuedensimplementehablarenEspa\u00F1ol",
"encoded": "PorqunopuedensimplementehablarenEspaol-fmd56a"
},
{
"description": "Vietnamese",
"decoded": "T\u1EA1isaoh\u1ECDkh\u00F4ngth\u1EC3ch\u1EC9n\u00F3iti\u1EBFngVi\u1EC7t",
"encoded": "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g"
},
{
"decoded": "3\u5E74B\u7D44\u91D1\u516B\u5148\u751F",
"encoded": "3B-ww4c5e180e575a65lsy2b"
},
{
"decoded": "\u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS",
"encoded": "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n"
},
{
"decoded": "Hello-Another-Way-\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
"encoded": "Hello-Another-Way--fc4qua05auwb3674vfr0b"
},
{
"decoded": "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B2",
"encoded": "2-u9tlzr9756bt3uc0v"
},
{
"decoded": "Maji\u3067Koi\u3059\u308B5\u79D2\u524D",
"encoded": "MajiKoi5-783gue6qz075azm5e"
},
{
"decoded": "\u30D1\u30D5\u30A3\u30FCde\u30EB\u30F3\u30D0",
"encoded": "de-jg4avhby1noc0d"
},
{
"decoded": "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
"encoded": "d9juau41awczczp"
},
{
"description": "ASCII string that breaks the existing rules for host-name labels (It's not a realistic example for IDNA, because IDNA never encodes pure ASCII labels.)",
"decoded": "-> $1.00 <-",
"encoded": "-> $1.00 <--"
}
]

View file

@ -1,25 +0,0 @@
extern crate idna;
extern crate rustc_serialize;
extern crate test;
mod punycode;
mod uts46;
fn main() {
let mut tests = Vec::new();
{
let mut add_test = |name, run| {
tests.push(test::TestDescAndFn {
desc: test::TestDesc {
name: test::DynTestName(name),
ignore: false,
should_panic: test::ShouldPanic::No,
},
testfn: run,
})
};
punycode::collect_tests(&mut add_test);
uts46::collect_tests(&mut add_test);
}
test::test_main(&std::env::args().collect::<Vec<_>>(), tests)
}

View file

@ -1,117 +0,0 @@
// Copyright 2013-2014 Valentin Gosu.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::char;
use idna::uts46;
use test::TestFn;
pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
// http://www.unicode.org/Public/idna/latest/IdnaTest.txt
for (i, line) in include_str!("IdnaTest.txt").lines().enumerate() {
if line == "" || line.starts_with("#") {
continue
}
// Remove comments
let mut line = match line.find("#") {
Some(index) => &line[0..index],
None => line
};
let mut expected_failure = false;
if line.starts_with("XFAIL") {
expected_failure = true;
line = &line[5..line.len()];
};
let mut pieces = line.split(';').map(|x| x.trim()).collect::<Vec<&str>>();
let test_type = pieces.remove(0);
let original = pieces.remove(0);
let source = unescape(original);
let to_unicode = pieces.remove(0);
let to_ascii = pieces.remove(0);
let nv8 = if pieces.len() > 0 { pieces.remove(0) } else { "" };
if expected_failure {
continue;
}
let test_name = format!("UTS #46 line {}", i + 1);
add_test(test_name, TestFn::dyn_test_fn(move || {
let result = uts46::to_ascii(&source, uts46::Flags {
use_std3_ascii_rules: true,
transitional_processing: test_type == "T",
verify_dns_length: true,
});
if to_ascii.starts_with("[") {
if to_ascii.starts_with("[C") {
// http://unicode.org/reports/tr46/#Deviations
// applications that perform IDNA2008 lookup are not required to check
// for these contexts
return;
}
let res = result.ok();
assert!(res == None, "Expected error. result: {} | original: {} | source: {}",
res.unwrap(), original, source);
return;
}
let to_ascii = if to_ascii.len() > 0 {
to_ascii.to_string()
} else {
if to_unicode.len() > 0 {
to_unicode.to_string()
} else {
source.clone()
}
};
if nv8 == "NV8" {
// This result isn't valid under IDNA2008. Skip it
return;
}
assert!(result.is_ok(), "Couldn't parse {} | original: {} | error: {:?}",
source, original, result.err());
let output = result.ok().unwrap();
assert!(output == to_ascii, "result: {} | expected: {} | original: {} | source: {}",
output, to_ascii, original, source);
}))
}
}
fn unescape(input: &str) -> String {
let mut output = String::new();
let mut chars = input.chars();
loop {
match chars.next() {
None => return output,
Some(c) =>
if c == '\\' {
match chars.next().unwrap() {
'\\' => output.push('\\'),
'u' => {
let c1 = chars.next().unwrap().to_digit(16).unwrap();
let c2 = chars.next().unwrap().to_digit(16).unwrap();
let c3 = chars.next().unwrap().to_digit(16).unwrap();
let c4 = chars.next().unwrap().to_digit(16).unwrap();
match char::from_u32((((c1 * 16 + c2) * 16 + c3) * 16 + c4))
{
Some(c) => output.push(c),
None => { output.push_str(&format!("\\u{:X}{:X}{:X}{:X}",c1,c2,c3,c4)); }
};
}
_ => panic!("Invalid test data input"),
}
} else {
output.push(c);
}
}
}
}

File diff suppressed because one or more lines are too long

View file

View file

@ -1,3 +0,0 @@
target
Cargo.lock
*~

View file

@ -1,119 +0,0 @@
language: rust
sudo: required
dist: trusty
services:
- docker
install:
- curl https://static.rust-lang.org/rustup.sh |
sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
script:
- cargo build
- cargo build --no-default-features
- cargo generate-lockfile --manifest-path libc-test/Cargo.toml
- if [[ $TRAVIS_OS_NAME = "linux" ]]; then
sh ci/run-docker.sh $TARGET;
else
export CARGO_TARGET_DIR=`pwd`/target;
sh ci/run.sh $TARGET;
fi
- rustc ci/style.rs && ./style src
osx_image: xcode7.3
env:
global:
secure: eIDEoQdTyglcsTD13zSGotAX2HDhRSXIaaTnVZTThqLSrySOc3/6KY3qmOc2Msf7XaBqfFy9QA+alk7OwfePp253eiy1Kced67ffjjFOytEcRT7FlQiYpcYQD6WNHZEj62/bJBO4LTM9sGtWNCTJVEDKW0WM8mUK7qNuC+honPM=
matrix:
include:
# 1.0.0 compat
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
rust: 1.0.0
script: cargo build
install:
# build documentation
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
rust: stable
script: sh ci/dox.sh
# stable compat
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
rust: stable
- os: linux
env: TARGET=i686-unknown-linux-gnu
rust: stable
- os: osx
env: TARGET=x86_64-apple-darwin
rust: stable
- os: osx
env: TARGET=i686-apple-darwin
rust: stable
- os: linux
env: TARGET=arm-linux-androideabi
rust: stable
- os: linux
env: TARGET=x86_64-unknown-linux-musl
rust: stable
- os: linux
env: TARGET=i686-unknown-linux-musl
rust: stable
- os: linux
env: TARGET=arm-unknown-linux-gnueabihf
rust: stable
- os: linux
env: TARGET=aarch64-unknown-linux-gnu
rust: stable
- os: osx
env: TARGET=i386-apple-ios
rust: stable
- os: osx
env: TARGET=x86_64-apple-ios
rust: stable
- os: linux
env: TARGET=x86_64-rumprun-netbsd
rust: stable
- os: linux
env: TARGET=powerpc-unknown-linux-gnu
rust: stable
- os: linux
env: TARGET=powerpc64-unknown-linux-gnu
rust: stable
- os: linux
env: TARGET=mipsel-unknown-linux-musl
rust: stable
# beta
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
rust: beta
- os: osx
env: TARGET=x86_64-apple-darwin
rust: beta
# nightly
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
rust: nightly
- os: osx
env: TARGET=x86_64-apple-darwin
rust: nightly
- os: linux
env: TARGET=mips-unknown-linux-gnu
# not sure why this has to be nightly...
rust: nightly
# QEMU based targets that compile in an emulator
- os: linux
env: TARGET=x86_64-unknown-freebsd
rust: stable
- os: linux
env: TARGET=x86_64-unknown-openbsd QEMU=openbsd.qcow2
rust: stable
script: sh ci/run-docker.sh $TARGET
install:
notifications:
email:
on_success: never
webhooks: https://buildbot.rust-lang.org/homu/travis

View file

@ -1,18 +0,0 @@
[package]
name = "libc"
version = "0.2.16"
authors = ["The Rust Project Developers"]
license = "MIT/Apache-2.0"
readme = "README.md"
repository = "https://github.com/rust-lang/libc"
homepage = "https://github.com/rust-lang/libc"
documentation = "http://doc.rust-lang.org/libc"
description = """
A library for types and bindings to native C functions often found in libc or
other common platform libraries.
"""
[features]
default = ["use_std"]
use_std = []

View file

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,25 +0,0 @@
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View file

@ -1,135 +0,0 @@
libc
====
A Rust library with native bindings to the types and functions commonly found on
various systems, including libc.
[![Build Status](https://travis-ci.org/rust-lang/libc.svg?branch=master)](https://travis-ci.org/rust-lang/libc)
[![Build status](https://ci.appveyor.com/api/projects/status/34csq3uurnw7c0rl?svg=true)](https://ci.appveyor.com/project/alexcrichton/libc)
[Documentation](#platforms-and-documentation)
## Usage
First, add the following to your `Cargo.toml`:
```toml
[dependencies]
libc = "0.2"
```
Next, add this to your crate root:
```rust
extern crate libc;
```
Currently libc by default links to the standard library, but if you would
instead like to use libc in a `#![no_std]` situation or crate you can request
this via:
```toml
[dependencies]
libc = { version = "0.2", default-features = false }
```
## What is libc?
The primary purpose of this crate is to provide all of the definitions necessary
to easily interoperate with C code (or "C-like" code) on each of the platforms
that Rust supports. This includes type definitions (e.g. `c_int`), constants
(e.g. `EINVAL`) as well as function headers (e.g. `malloc`).
This crate does not strive to have any form of compatibility across platforms,
but rather it is simply a straight binding to the system libraries on the
platform in question.
## Public API
This crate exports all underlying platform types, functions, and constants under
the crate root, so all items are accessible as `libc::foo`. The types and values
of all the exported APIs match the platform that libc is compiled for.
More detailed information about the design of this library can be found in its
[associated RFC][rfc].
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1291-promote-libc.md
## Adding an API
Want to use an API which currently isn't bound in `libc`? It's quite easy to add
one!
The internal structure of this crate is designed to minimize the number of
`#[cfg]` attributes in order to easily be able to add new items which apply
to all platforms in the future. As a result, the crate is organized
hierarchically based on platform. Each module has a number of `#[cfg]`'d
children, but only one is ever actually compiled. Each module then reexports all
the contents of its children.
This means that for each platform that libc supports, the path from a
leaf module to the root will contain all bindings for the platform in question.
Consequently, this indicates where an API should be added! Adding an API at a
particular level in the hierarchy means that it is supported on all the child
platforms of that level. For example, when adding a Unix API it should be added
to `src/unix/mod.rs`, but when adding a Linux-only API it should be added to
`src/unix/notbsd/linux/mod.rs`.
If you're not 100% sure at what level of the hierarchy an API should be added
at, fear not! This crate has CI support which tests any binding against all
platforms supported, so you'll see failures if an API is added at the wrong
level or has different signatures across platforms.
With that in mind, the steps for adding a new API are:
1. Determine where in the module hierarchy your API should be added.
2. Add the API.
3. Send a PR to this repo.
4. Wait for CI to pass, fixing errors.
5. Wait for a merge!
### Test before you commit
We have two automated tests running on [Travis](https://travis-ci.org/rust-lang/libc):
1. [`libc-test`](https://github.com/alexcrichton/ctest)
- `cd libc-test && cargo run`
- Use the `skip_*()` functions in `build.rs` if you really need a workaround.
2. Style checker
- `rustc ci/style.rs && ./style src`
## Platforms and Documentation
The following platforms are currently tested and have documentation available:
Tested:
* [`i686-pc-windows-msvc`](https://doc.rust-lang.org/libc/i686-pc-windows-msvc/libc/)
* [`x86_64-pc-windows-msvc`](https://doc.rust-lang.org/libc/x86_64-pc-windows-msvc/libc/)
(Windows)
* [`i686-pc-windows-gnu`](https://doc.rust-lang.org/libc/i686-pc-windows-gnu/libc/)
* [`x86_64-pc-windows-gnu`](https://doc.rust-lang.org/libc/x86_64-pc-windows-gnu/libc/)
* [`i686-apple-darwin`](https://doc.rust-lang.org/libc/i686-apple-darwin/libc/)
* [`x86_64-apple-darwin`](https://doc.rust-lang.org/libc/x86_64-apple-darwin/libc/)
(OSX)
* `i686-apple-ios`
* `x86_64-apple-ios`
* [`i686-unknown-linux-gnu`](https://doc.rust-lang.org/libc/i686-unknown-linux-gnu/libc/)
* [`x86_64-unknown-linux-gnu`](https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu/libc/)
(Linux)
* [`x86_64-unknown-linux-musl`](https://doc.rust-lang.org/libc/x86_64-unknown-linux-musl/libc/)
(Linux MUSL)
* [`aarch64-unknown-linux-gnu`](https://doc.rust-lang.org/libc/aarch64-unknown-linux-gnu/libc/)
* [`mips-unknown-linux-gnu`](https://doc.rust-lang.org/libc/mips-unknown-linux-gnu/libc/)
* [`arm-unknown-linux-gnueabihf`](https://doc.rust-lang.org/libc/arm-unknown-linux-gnueabihf/libc/)
* [`arm-linux-androideabi`](https://doc.rust-lang.org/libc/arm-linux-androideabi/libc/)
(Android)
* [`x86_64-unknown-freebsd`](https://doc.rust-lang.org/libc/x86_64-unknown-freebsd/libc/)
* [`x86_64-unknown-openbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-openbsd/libc/)
* [`x86_64-rumprun-netbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-netbsd/libc/)
The following may be supported, but are not guaranteed to always work:
* `i686-unknown-freebsd`
* [`x86_64-unknown-bitrig`](https://doc.rust-lang.org/libc/x86_64-unknown-bitrig/libc/)
* [`x86_64-unknown-dragonfly`](https://doc.rust-lang.org/libc/x86_64-unknown-dragonfly/libc/)
* [`x86_64-unknown-netbsd`](https://doc.rust-lang.org/libc/x86_64-unknown-netbsd/libc/)

View file

@ -1,21 +0,0 @@
environment:
matrix:
- TARGET: x86_64-pc-windows-gnu
MSYS2_BITS: 64
- TARGET: i686-pc-windows-gnu
MSYS2_BITS: 32
- TARGET: x86_64-pc-windows-msvc
- TARGET: i686-pc-windows-msvc
install:
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET%
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test
- cargo run --manifest-path libc-test/Cargo.toml

View file

@ -1,203 +0,0 @@
The goal of the libc crate is to have CI running everywhere to have the
strongest guarantees about the definitions that this library contains, and as a
result the CI is pretty complicated and also pretty large! Hopefully this can
serve as a guide through the sea of scripts in this directory and elsewhere in
this project.
# Files
First up, let's talk about the files in this directory:
* `run-travis.sh` - a shell script run by all Travis builders, this is
responsible for setting up the rest of the environment such as installing new
packages, downloading Rust target libraries, etc.
* `run.sh` - the actual script which runs tests for a particular architecture.
Called from the `run-travis.sh` script this will run all tests for the target
specified.
* `cargo-config` - Cargo configuration of linkers to use copied into place by
the `run-travis.sh` script before builds are run.
* `dox.sh` - script called from `run-travis.sh` on only the linux 64-bit nightly
Travis bots to build documentation for this crate.
* `landing-page-*.html` - used by `dox.sh` to generate a landing page for all
architectures' documentation.
* `run-qemu.sh` - see discussion about QEMU below
* `mips`, `rumprun` - instructions to build the docker image for each respective
CI target
# CI Systems
Currently this repository leverages a combination of Travis CI and AppVeyor for
running tests. The triples tested are:
* AppVeyor
* `{i686,x86_64}-pc-windows-{msvc,gnu}`
* Travis
* `{i686,x86_64,mips,aarch64}-unknown-linux-gnu`
* `x86_64-unknown-linux-musl`
* `arm-unknown-linux-gnueabihf`
* `arm-linux-androideabi`
* `{i686,x86_64}-apple-{darwin,ios}`
* `x86_64-rumprun-netbsd`
* `x86_64-unknown-freebsd`
* `x86_64-unknown-openbsd`
The Windows triples are all pretty standard, they just set up their environment
then run tests, no need for downloading any extra target libs (we just download
the right installer). The Intel Linux/OSX builds are similar in that we just
download the right target libs and run tests. Note that the Intel Linux/OSX
builds are run on stable/beta/nightly, but are the only ones that do so.
The remaining architectures look like:
* Android runs in a [docker image][android-docker] with an emulator, the NDK,
and the SDK already set up. The entire build happens within the docker image.
* The MIPS, ARM, and AArch64 builds all use the QEMU userspace emulator to run
the generated binary to actually verify the tests pass.
* The MUSL build just has to download a MUSL compiler and target libraries and
then otherwise runs tests normally.
* iOS builds need an extra linker flag currently, but beyond that they're built
as standard as everything else.
* The rumprun target builds an entire kernel from the test suite and then runs
it inside QEMU using the serial console to test whether it succeeded or
failed.
* The BSD builds, currently OpenBSD and FreeBSD, use QEMU to boot up a system
and compile/run tests. More information on that below.
[android-docker]: https://github.com/rust-lang/rust-buildbot/blob/master/slaves/android/Dockerfile
## QEMU
Lots of the architectures tested here use QEMU in the tests, so it's worth going
over all the crazy capabilities QEMU has and the various flavors in which we use
it!
First up, QEMU has userspace emulation where it doesn't boot a full kernel, it
just runs a binary from another architecture (using the `qemu-<arch>` wrappers).
We provide it the runtime path for the dynamically loaded system libraries,
however. This strategy is used for all Linux architectures that aren't intel.
Note that one downside of this QEMU system is that threads are barely
implemented, so we're careful to not spawn many threads.
For the rumprun target the only output is a kernel image, so we just use that
plus the `rumpbake` command to create a full kernel image which is then run from
within QEMU.
Finally, the fun part, the BSDs. Quite a few hoops are jumped through to get CI
working for these platforms, but the gist of it looks like:
* Cross compiling from Linux to any of the BSDs seems to be quite non-standard.
We may be able to get it working but it might be difficult at that point to
ensure that the libc definitions align with what you'd get on the BSD itself.
As a result, we try to do compiles within the BSD distro.
* On Travis we can't run a VM-in-a-VM, so we resort to userspace emulation
(QEMU).
* Unfortunately on Travis we also can't use KVM, so the emulation is super slow.
With all that in mind, the way BSD is tested looks like:
1. Download a pre-prepared image for the OS being tested.
2. Generate the tests for the OS being tested. This involves running the `ctest`
library over libc to generate a Rust file and a C file which will then be
compiled into the final test.
3. Generate a disk image which will later be mounted by the OS being tested.
This image is mostly just the libc directory, but some modifications are made
to compile the generated files from step 2.
4. The kernel is booted in QEMU, and it is configured to detect the libc-test
image being available, run the test script, and then shut down afterwards.
5. Look for whether the tests passed in the serial console output of the kernel.
There's some pretty specific instructions for setting up each image (detailed
below), but the main gist of this is that we must avoid a vanilla `cargo run`
inside of the `libc-test` directory (which is what it's intended for) because
that would compile `syntex_syntax`, a large library, with userspace emulation.
This invariably times out on Travis, so we can't do that.
Once all those hoops are jumped through, however, we can be happy that we're
testing almost everything!
Below are some details of how to set up the initial OS images which are
downloaded. Each image must be enabled have input/output over the serial
console, log in automatically at the serial console, detect if a second drive in
QEMU is available, and if so mount it, run a script (it'll specifically be
`run-qemu.sh` in this folder which is copied into the generated image talked
about above), and then shut down.
### QEMU setup - FreeBSD
1. Download CD installer (most minimal is fine)
2. `qemu-img create -f qcow2 foo.qcow2 2G`
3. `qemu -cdrom foo.iso -drive if=virtio,file=foo.qcow2 -net nic,model=virtio -net user`
4. run installer
5. `echo 'console="comconsole"' >> /boot/loader.conf`
6. `echo 'autoboot_delay="0"' >> /boot/loader.conf`
7. look at /etc/ttys, see what getty argument is for ttyu0
8. edit /etc/gettytab, look for ttyu0 argument, prepend `:al=root` to line
beneath
(note that the current image has a `freebsd` user, but this isn't really
necessary)
Once that's done, arrange for this script to run at login:
```
#!/bin/sh
sudo kldload ext2fs
[ -e /dev/vtbd1 ] || exit 0
sudo mount -t ext2fs /dev/vtbd1 /mnt
sh /mnt/run.sh /mnt
sudo poweroff
```
Helpful links
* https://en.wikibooks.org/wiki/QEMU/Images
* https://blog.nekoconeko.nl/blog/2015/06/04/creating-an-openstack-freebsd-image.html
* https://www.freebsd.org/doc/handbook/serialconsole-setup.html
### QEMU setup - OpenBSD
1. Download CD installer
2. `qemu-img create -f qcow2 foo.qcow2 2G`
3. `qemu -cdrom foo.iso -drive if=virtio,file=foo.qcow2 -net nic,model=virtio -net user`
4. run installer
5. `echo 'set tty com0' >> /etc/boot.conf`
6. `echo 'boot' >> /etc/boot.conf`
7. Modify /etc/ttys, change the `tty00` at the end from 'unknown off' to
'vt220 on secure'
8. Modify same line in /etc/ttys to have `"/root/foo.sh"` as the shell
9. Add this script to `/root/foo.sh`
```
#!/bin/sh
exec 1>/dev/tty00
exec 2>&1
if mount -t ext2fs /dev/sd1c /mnt; then
sh /mnt/run.sh /mnt
shutdown -ph now
fi
# limited shell...
exec /bin/sh < /dev/tty00
```
10. `chmod +x /root/foo.sh`
Helpful links:
* https://en.wikibooks.org/wiki/QEMU/Images
* http://www.openbsd.org/faq/faq7.html#SerCon
# Questions?
Hopefully that's at least somewhat of an introduction to everything going on
here, and feel free to ping @alexcrichton with questions!

View file

@ -1,7 +0,0 @@
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev ca-certificates \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross qemu-user
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
PATH=$PATH:/rust/bin

View file

@ -1,4 +0,0 @@
FROM alexcrichton/rust-slave-android:2015-11-22
ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
PATH=$PATH:/rust/bin
ENTRYPOINT ["sh"]

View file

@ -1,7 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev ca-certificates \
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user
ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
PATH=$PATH:/rust/bin

View file

@ -1,5 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc-multilib libc6-dev ca-certificates
ENV PATH=$PATH:/rust/bin

View file

@ -1,13 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc make libc6-dev git curl ca-certificates
RUN curl https://www.musl-libc.org/releases/musl-1.1.14.tar.gz | \
tar xzf - && \
cd musl-1.1.14 && \
CFLAGS=-m32 ./configure --prefix=/musl-i686 --disable-shared --target=i686 && \
make install -j4 && \
cd .. && \
rm -rf musl-1.1.14
ENV PATH=$PATH:/musl-i686/bin:/rust/bin

View file

@ -1,10 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev qemu-user ca-certificates \
gcc-mips-linux-gnu libc6-dev-mips-cross \
qemu-system-mips
ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc \
PATH=$PATH:/rust/bin

View file

@ -1,14 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev qemu-user ca-certificates qemu-system-mips curl \
bzip2
RUN mkdir /toolchain
RUN curl -L https://downloads.openwrt.org/snapshots/trunk/malta/generic/OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 | \
tar xjf - -C /toolchain --strip-components=2
ENV PATH=$PATH:/rust/bin:/toolchain/bin \
CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER=mipsel-openwrt-linux-gcc

View file

@ -1,10 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev qemu-user ca-certificates \
gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \
qemu-system-ppc
ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER=powerpc-linux-gnu-gcc \
PATH=$PATH:/rust/bin

View file

@ -1,11 +0,0 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
gcc libc6-dev qemu-user ca-certificates \
gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \
qemu-system-ppc
ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER=powerpc64-linux-gnu-gcc \
CC=powerpc64-linux-gnu-gcc \
PATH=$PATH:/rust/bin

View file

@ -1,6 +0,0 @@
FROM mato/rumprun-toolchain-hw-x86_64
USER root
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
qemu
ENV PATH=$PATH:/rust/bin

View file

@ -1,13 +0,0 @@
FROM alexcrichton/rust-slave-linux-cross:2016-04-15
USER root
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
qemu qemu-kvm kmod cpu-checker
ENTRYPOINT ["sh"]
ENV PATH=$PATH:/rust/bin \
QEMU=freebsd.qcow2 \
CAN_CROSS=1 \
CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_LINKER=x86_64-unknown-freebsd10-gcc

Some files were not shown because too many files have changed in this diff Show more