提交 2cf7ab9a 编写于 作者: D dhy308

Fix review issues.

    Issue: I6DO52
    Test: Build & Boot Devices
Signed-off-by: Ndhy308 <tony.gan@huawei.com>
上级 581a2073
*.o
*.lo
*.a
*.so
*.so.1
config.mak
lib/musl-gcc.specs
/obj/
Ada Worcester <oss@ada.pikhq.com> <josiahw@gmail.com>
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2020 Rich Felker, et al.
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.
----------------------------------------------------------------------
Authors/contributors include:
A. Wilcox
Ada Worcester
Alex Dowad
Alex Suykov
Alexander Monakov
Andre McCurdy
Andrew Kelley
Anthony G. Basile
Aric Belsito
Arvid Picciani
Bartosz Brachaczek
Benjamin Peterson
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Daniel Sabogal
Daurnimator
David Carlier
David Edelsohn
Denys Vlasenko
Dmitry Ivanov
Dmitry V. Levin
Drew DeVault
Emil Renner Berthing
Fangrui Song
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
He X
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Julien Ramseier
Justin Cormack
Kaarle Ritvanen
Khem Raj
Kylie McClain
Leah Neukirchen
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Markus Wichmann
Masanori Ogino
Michael Clark
Michael Forney
Mikhail Kremnyov
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Patrick Oppenlander
Petr Hosek
Petr Skocik
Pierre Carrier
Reini Urban
Rich Felker
Richard Pennington
Ryan Fairfax
Samuel Holland
Segev Finer
Shiz
sin
Solar Designer
Stefan Kristiansson
Stefan O'Rear
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
Will Dietz
William Haddon
William Pitcock
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier or
Copyright © 2017-2018 Arm Limited
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The AArch64 memcpy and memset code (src/string/aarch64/*) are
Copyright © 1999-2019, Arm Limited.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.
Quick Installation Guide for musl libc
======================================
There are many different ways to install musl depending on your usage
case. This document covers only the build and installation of musl by
itself, which is useful for upgrading an existing musl-based system or
compiler toolchain, or for using the provided musl-gcc wrapper with an
existing non-musl-based compiler.
Building complete native or cross-compiler toolchains is outside the
scope of this INSTALL file. More information can be found on the musl
website and community wiki.
Build Prerequisites
-------------------
The only build-time prerequisites for musl are GNU Make and a
freestanding C99 compiler toolchain targeting the desired instruction
set architecture and ABI, with support for a minimal subset of "GNU C"
extensions consisting mainly of gcc-style inline assembly, weak
aliases, hidden visibility, and stand-alone assembly source files.
GCC, LLVM/clang, Firm/cparser, and PCC have all successfully built
musl, but GCC is the most widely used/tested. Recent compiler (and
binutils) versions should be used if possible since some older
versions have bugs which affect musl.
The system used to build musl does not need to be Linux-based, nor do
the Linux kernel headers need to be available.
Supported Targets
-----------------
musl can be built for the following CPU instruction set architecture
and ABI combinations:
* i386
* Minimum CPU model is actually 80486 unless kernel emulation of
the `cmpxchg` instruction is added
* x86_64
* ILP32 ABI (x32) is available as a separate arch but is still
experimental
* ARM
* EABI, standard or hard-float VFP variant
* Little-endian default; big-endian variants also supported
* Compiler toolchains only support armv4t and later
* AArch64
* Little-endian default; big-endian variants also supported
* MIPS
* ABI is o32, fp32/fpxx (except on r6 which is fp64)
* Big-endian default; little-endian variants also supported
* Default ABI variant uses FPU registers; alternate soft-float ABI
that does not use FPU registers or instructions is available
* MIPS2 or later, or kernel emulation of ll/sc (standard in Linux)
is required
* MIPS32r6, an incompatible ISA, is supported as a variant "mipsr6"
* MIPS64
* ABI is n64 (LP64) or n32 (ILP32)
* Big-endian default; little-endian variants also supported
* Default ABI variant uses FPU registers; alternate soft-float ABI
that does not use FPU registers or instructions is available
* PowerPC
* Compiler toolchain must provide 64-bit long double, not IBM
double-double or IEEE quad
* For dynamic linking, compiler toolchain must be configured for
"secure PLT" variant
* PowerPC64
* Both little and big endian variants are supported
* Compiler toolchain must provide 64-bit long double, not IBM
double-double or IEEE quad
* Compiler toolchain must use the new (ELFv2) ABI regardless of
whether it is for little or big endian
* S390X (64-bit S390)
* SuperH (SH)
* Standard ELF ABI or FDPIC ABI (shared-text without MMU)
* Little-endian by default; big-endian variant also supported
* Full FPU ABI or soft-float ABI is supported, but the
single-precision-only FPU ABI is not
* Microblaze
* Big-endian default; little-endian variants also supported
* Soft-float
* Requires support for lwx/swx instructions
* OpenRISC 1000 (or1k)
* RISC-V 64
* Little endian
* Hard, soft, and hard-single/soft-double floating point ABIs
* Standard ELF; no shared-text NOMMU support
Build and Installation Procedure
--------------------------------
To build and install musl:
1. Run the provided configure script from the top-level source
directory, passing on its command line any desired options.
2. Run "make" to compile.
3. Run "make install" with appropriate privileges to write to the
target locations.
The configure script attempts to determine automatically the correct
target architecture based on the compiler being used. For some
compilers, this may not be possible. If detection fails or selects the
wrong architecture, you can provide an explicit selection on the
configure command line.
By default, configure installs to a prefix of "/usr/local/musl". This
differs from the behavior of most configure scripts, and is chosen
specifically to avoid clashing with libraries already present on the
system. DO NOT set the prefix to "/usr", "/usr/local", or "/" unless
you're upgrading libc on an existing musl-based system. Doing so will
break your existing system when you run "make install" and it may be
difficult to recover.
Notes on Dynamic Linking
------------------------
If dynamic linking is enabled, one file needs to be installed outside
of the installation prefix: /lib/ld-musl-$ARCH.so.1. This is the
dynamic linker. Its pathname is hard-coded into all dynamic-linked
programs, so for the sake of being able to share binaries between
systems, a consistent location should be used everywhere. Note that
the same applies to glibc and its dynamic linker, which is named
/lib/ld-linux.so.2 on i386 systems.
If for some reason it is impossible to install the dynamic linker in
its standard location (for example, if you are installing without root
privileges), the --syslibdir option to configure can be used to
provide a different location
At runtime, the dynamic linker needs to know the paths to search for
shared libraries. You should create a text file named
/etc/ld-musl-$ARCH.path (where $ARCH matches the architecture name
used in the dynamic linker) containing a list of directories where you
want the dynamic linker to search for shared libraries, separated by
colons or newlines. If the dynamic linker has been installed in a
non-default location, the path file also needs to reside at that
location (../etc relative to the chosen syslibdir).
If you do not intend to use dynamic linking, you may disable it by
passing --disable-shared to configure; this also cuts the build time
in half.
Checking for Successful Installation
------------------------------------
After installing, you should be able to use musl via the musl-gcc
wrapper. For example:
cat > hello.c <<EOF
#include <stdio.h>
int main()
{
printf("hello, world!\n");
return 0;
}
EOF
/usr/local/musl/bin/musl-gcc hello.c
./a.out
To configure autoconf-based program to compile and link against musl,
set the CC variable to musl-gcc when running configure, as in:
CC=musl-gcc ./configure ...
You will probably also want to use --prefix when building libraries to
ensure that they are installed under the musl prefix and not in the
main host system library directories.
#
# Makefile for musl (requires GNU make)
#
# This is how simple every makefile should be...
# No, I take that back - actually most should be less than half this size.
#
# Use config.mak to override any of the following variables.
# Do not make changes here.
#
srcdir = .
exec_prefix = /usr/local
bindir = $(exec_prefix)/bin
prefix = /usr/local/musl
includedir = $(prefix)/include
libdir = $(prefix)/lib
syslibdir = /lib
MALLOC_DIR = mallocng
SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS))
BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS)))
ARCH_SRCS = $(sort $(wildcard $(ARCH_GLOBS)))
BASE_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(BASE_SRCS)))
ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS)))
REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS)))
ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS))
LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo))
CRT_OBJS = $(filter obj/crt/%,$(ALL_OBJS))
AOBJS = $(LIBC_OBJS)
LOBJS = $(LIBC_OBJS:.o=.lo)
GENH = obj/include/bits/alltypes.h obj/include/bits/syscall.h
GENH_INT = obj/src/internal/version.h
IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/locale_impl.h src/internal/libc.h)
LDFLAGS =
LDFLAGS_AUTO =
LIBCC = -lgcc
CPPFLAGS =
CFLAGS =
CFLAGS_AUTO = -Os -pipe
CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
CFLAGS_ALL = $(CFLAGS_C99FSE)
CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
AR = $(CROSS_COMPILE)ar
RANLIB = $(CROSS_COMPILE)ranlib
INSTALL = $(srcdir)/tools/install.sh
ARCH_INCLUDES = $(wildcard $(srcdir)/arch/$(ARCH)/bits/*.h)
GENERIC_INCLUDES = $(wildcard $(srcdir)/arch/generic/bits/*.h)
INCLUDES = $(wildcard $(srcdir)/include/*.h $(srcdir)/include/*/*.h)
ALL_INCLUDES = $(sort $(INCLUDES:$(srcdir)/%=%) $(GENH:obj/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%) $(GENERIC_INCLUDES:$(srcdir)/arch/generic/%=include/%))
EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
CRT_LIBS = $(addprefix lib/,$(notdir $(CRT_OBJS)))
STATIC_LIBS = lib/libc.a
SHARED_LIBS = lib/libc.so
TOOL_LIBS = lib/musl-gcc.specs
ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
ALL_TOOLS = obj/musl-gcc
WRAPCC_GCC = gcc
WRAPCC_CLANG = clang
LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
-include config.mak
-include $(srcdir)/arch/$(ARCH)/arch.mak
ifeq ($(ARCH),)
all:
@echo "Please set ARCH in config.mak before running make."
@exit 1
else
all: $(ALL_LIBS) $(ALL_TOOLS)
OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include)
$(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS)
$(OBJ_DIRS):
mkdir -p $@
obj/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed
sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
obj/include/bits/syscall.h: $(srcdir)/arch/$(ARCH)/bits/syscall.h.in
cp $< $@
sed -n -e s/__NR_/SYS_/p < $< >> $@
obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h
obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS))
$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \
%/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \
%/__set_thread_area.o %/memset.o %/memcpy.o \
, $(LIBC_OBJS))
$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
$(CRT_OBJS): CFLAGS_ALL += -DCRT
$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC
CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
# Choose invocation of assembler to be used
ifeq ($(ADD_CFI),yes)
AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
else
AS_CMD = $(CC_CMD)
endif
obj/%.o: $(srcdir)/%.s
$(AS_CMD)
obj/%.o: $(srcdir)/%.S
$(CC_CMD)
obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
obj/%.lo: $(srcdir)/%.s
$(AS_CMD)
obj/%.lo: $(srcdir)/%.S
$(CC_CMD)
obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
lib/libc.so: $(LOBJS) $(LDSO_OBJS)
$(CC) $(CFLAGS_ALL) $(LDFLAGS_ALL) -nostdlib -shared \
-Wl,-e,_dlstart -o $@ $(LOBJS) $(LDSO_OBJS) $(LIBCC)
lib/libc.a: $(AOBJS)
rm -f $@
$(AR) rc $@ $(AOBJS)
$(RANLIB) $@
$(EMPTY_LIBS):
rm -f $@
$(AR) rc $@
lib/%.o: obj/crt/$(ARCH)/%.o
cp $< $@
lib/%.o: obj/crt/%.o
cp $< $@
lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
obj/musl-gcc: config.mak
printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
chmod +x $@
obj/%-clang: $(srcdir)/tools/%-clang.in config.mak
sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@
chmod +x $@
$(DESTDIR)$(bindir)/%: obj/%
$(INSTALL) -D $< $@
$(DESTDIR)$(libdir)/%.so: lib/%.so
$(INSTALL) -D -m 755 $< $@
$(DESTDIR)$(libdir)/%: lib/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/generic/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: obj/include/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
$(INSTALL) -D -l $(libdir)/libc.so $@ || true
install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%)
install: install-libs install-headers install-tools
musl-git-%.tar.gz: .git
git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)
musl-%.tar.gz: .git
git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@)
endif
clean:
rm -rf obj lib
distclean: clean
rm -f config.mak
.PHONY: all clean install install-libs install-headers install-tools
musl libc
musl, pronounced like the word "mussel", is an MIT-licensed
implementation of the standard C library targetting the Linux syscall
API, suitable for use in a wide range of deployment environments. musl
offers efficient static and dynamic linking support, lightweight code
and low runtime overhead, strong fail-safe guarantees under correct
usage, and correctness in the sense of standards conformance and
safety. musl is built on the principle that these goals are best
achieved through simple code that is easy to understand and maintain.
The 1.1 release series for musl features coverage for all interfaces
defined in ISO C99 and POSIX 2008 base, along with a number of
non-standardized interfaces for compatibility with Linux, BSD, and
glibc functionality.
For basic installation instructions, see the included INSTALL file.
Information on full musl-targeted compiler toolchains, system
bootstrapping, and Linux distributions built on musl can be found on
the project website:
http://www.musl-libc.org/
此差异已折叠。
#define O_CREAT 0100
#define O_EXCL 0200
#define O_NOCTTY 0400
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NONBLOCK 04000
#define O_DSYNC 010000
#define O_SYNC 04010000
#define O_RSYNC 04010000
#define O_DIRECTORY 0200000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define O_ASYNC 020000
#define O_DIRECT 040000
#define O_LARGEFILE 0
#define O_NOATIME 01000000
#define O_PATH 010000000
#define O_TMPFILE 020200000
#define O_NDELAY O_NONBLOCK
#define F_DUPFD 0
#define F_GETFD 1
#define F_SETFD 2
#define F_GETFL 3
#define F_SETFL 4
#define F_SETOWN 8
#define F_GETOWN 9
#define F_SETSIG 10
#define F_GETSIG 11
#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
#define F_SETOWN_EX 15
#define F_GETOWN_EX 16
#define F_GETOWNER_UIDS 17
......@@ -30,11 +30,14 @@ System types:
Optional features:
--enable-optimize=... optimize listed components for speed over size [auto]
--enable-debug build with debugging information [disabled]
--enable-warnings build with recommended warnings flags [disabled]
--disable-warnings build with recommended warnings flags [enabled]
--enable-wrapper=... build given musl toolchain wrapper [auto]
--disable-shared inhibit building shared library [enabled]
--disable-static inhibit building static library [enabled]
Optional packages:
--with-malloc=... choose malloc implementation [mallocng]
Some influential environment variables:
CC C compiler command [detected]
CFLAGS C compiler flags [-Os -pipe ...]
......@@ -133,12 +136,13 @@ build=
target=
optimize=auto
debug=no
warnings=no
warnings=yes
shared=auto
static=yes
wrapper=auto
gcc_wrapper=no
clang_wrapper=no
malloc_dir=mallocng
for arg ; do
case "$arg" in
......@@ -168,6 +172,7 @@ case "$arg" in
--disable-wrapper|--enable-wrapper=no) wrapper=no ;;
--enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ; gcc_wrapper=yes ;;
--disable-gcc-wrapper|--enable-gcc-wrapper=no) wrapper=no ;;
--with-malloc=*) malloc_dir=${arg#*=} ;;
--enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
--host=*|--target=*) target=${arg#*=} ;;
--build=*) build=${arg#*=} ;;
......@@ -199,7 +204,7 @@ fi
abs_builddir="$(pwd)" || fail "$0: cannot determine working directory"
abs_srcdir="$(cd $srcdir && pwd)" || fail "$0: invalid source directory $srcdir"
test "$abs_srcdir" = "$abs_builddir" && srcdir=.
test "$srcdir" != "." -a -f Makefile -a ! -h Makefile && fail "$0: Makefile already exists in the working directory"
test "$srcdir" != "." && test -f Makefile && test ! -h Makefile && fail "$0: Makefile already exists in the working directory"
#
# Get a temp filename we can use
......@@ -214,6 +219,12 @@ done
set +C
trap 'rm "$tmpc"' EXIT INT QUIT TERM HUP
#
# Check that the requested malloc implementation exists
#
test -d "$srcdir/src/malloc/$malloc_dir" \
|| fail "$0: error: chosen malloc implementation '$malloc_dir' does not exist"
#
# Check whether we are cross-compiling, and set a default
# CROSS_COMPILE prefix if none was provided.
......@@ -268,7 +279,7 @@ echo "$cc_family"
#
# Figure out toolchain wrapper to build
#
if test "$wrapper" = auto -o "$wrapper" = detect ; then
if test "$wrapper" = auto || test "$wrapper" = detect ; then
echo "#include <stdlib.h>" > "$tmpc"
echo "#if ! __GLIBC__" >> "$tmpc"
echo "#error no" >> "$tmpc"
......@@ -398,7 +409,7 @@ test "$debug" = yes && CFLAGS_AUTO=-g
#
printf "checking whether we should preprocess assembly to add debugging information... "
if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" &&
test -f "tools/add-cfi.$ARCH.awk" &&
test -f "$srcdir/tools/add-cfi.$ARCH.awk" &&
printf ".file 1 \"srcfile.s\"\n.line 1\n.cfi_startproc\n.cfi_endproc" | $CC -g -x assembler -c -o /dev/null 2>/dev/null -
then
ADD_CFI=yes
......@@ -457,7 +468,7 @@ tryflag CFLAGS_AUTO -pipe
# pointer is no longer needed for debugging.
#
if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then :
else
else
tryflag CFLAGS_AUTO -fomit-frame-pointer
fi
......@@ -494,6 +505,16 @@ fnmatch '-march=*|*\ -march=*' "$CC $CFLAGS" || tryldflag CFLAGS_AUTO -march=i48
fnmatch '-mtune=*|*\ -mtune=*' "$CC $CFLAGS" || tryldflag CFLAGS_AUTO -mtune=generic
fi
#
# GCC defines -w as overriding any -W options, regardless of order, but
# clang has a bunch of annoying warnings enabled by default and needs -w
# to start from a clean slate. So use -w if building with clang. Also
# turn off a common on-by-default cast warning regardless of compiler.
#
test "$cc_family" = clang && tryflag CFLAGS_AUTO -w
tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast
#
# Even with -std=c99, gcc accepts some constructs which are constraint
# violations. We want to treat these as errors regardless of whether
......@@ -504,6 +525,10 @@ tryflag CFLAGS_AUTO -Werror=implicit-function-declaration
tryflag CFLAGS_AUTO -Werror=implicit-int
tryflag CFLAGS_AUTO -Werror=pointer-sign
tryflag CFLAGS_AUTO -Werror=pointer-arith
tryflag CFLAGS_AUTO -Werror=int-conversion
tryflag CFLAGS_AUTO -Werror=incompatible-pointer-types
tryflag CFLAGS_AUTO -Werror=discarded-qualifiers
tryflag CFLAGS_AUTO -Werror=discarded-array-qualifiers
#
# GCC ignores unused arguements by default, but Clang needs this extra
......@@ -513,14 +538,17 @@ tryflag CFLAGS_AUTO -Werror=pointer-arith
test "$cc_family" = clang && tryflag CFLAGS_AUTO -Qunused-arguments
if test "x$warnings" = xyes ; then
tryflag CFLAGS_AUTO -Wall
tryflag CFLAGS_AUTO -Wno-parentheses
tryflag CFLAGS_AUTO -Wno-uninitialized
tryflag CFLAGS_AUTO -Wno-missing-braces
tryflag CFLAGS_AUTO -Wno-unused-value
tryflag CFLAGS_AUTO -Wno-unused-but-set-variable
tryflag CFLAGS_AUTO -Wno-unknown-pragmas
tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast
tryflag CFLAGS_AUTO -Waddress
tryflag CFLAGS_AUTO -Warray-bounds
tryflag CFLAGS_AUTO -Wchar-subscripts
tryflag CFLAGS_AUTO -Wduplicate-decl-specifier
tryflag CFLAGS_AUTO -Winit-self
tryflag CFLAGS_AUTO -Wreturn-type
tryflag CFLAGS_AUTO -Wsequence-point
tryflag CFLAGS_AUTO -Wstrict-aliasing
tryflag CFLAGS_AUTO -Wunused-function
tryflag CFLAGS_AUTO -Wunused-label
tryflag CFLAGS_AUTO -Wunused-variable
fi
# Determine if the compiler produces position-independent code (PIC)
......@@ -643,9 +671,7 @@ trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
fi
if test "$ARCH" = "powerpc" ; then
trycppif "__NO_FPRS__ && !_SOFT_FLOAT" "$t" && fail \
"$0: error: compiler's floating point configuration is unsupported"
trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf
trycppif "_SOFT_FLOAT || __NO_FPRS__" "$t" && SUBARCH=${SUBARCH}-sf
printf "checking whether compiler can use 'd' constraint in asm... "
echo 'double f(double x) { __asm__ ("fabs %0, %1" : "=d"(x) : "d"(x)); return x; }' > "$tmpc"
if $CC $CFLAGS_C99FSE $CPPFLAGS $CFLAGS -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
......@@ -772,6 +798,7 @@ OPTIMIZE_GLOBS = $OPTIMIZE_GLOBS
ALL_TOOLS = $tools
TOOL_LIBS = $tool_libs
ADD_CFI = $ADD_CFI
MALLOC_DIR = $malloc_dir
EOF
test "x$static" = xno && echo "STATIC_LIBS ="
test "x$shared" = xno && echo "SHARED_LIBS ="
......
......@@ -310,6 +310,7 @@
acoshl;
acosl;
addmntent;
add_special_signal_handler;
adjtime;
adjtimex;
aio_cancel;
......@@ -1486,6 +1487,7 @@
remainderl;
remap_file_pages;
remove;
remove_special_signal_handler;
removexattr;
remque;
remquo;
......
if (is_lite_system && current_os == "ohos") {
group("sysroot_lite") {
print("ohos_build_compiler:", ohos_build_compiler)
print("ohos_kernel_type:", ohos_kernel_type)
# Mini system of liteos_a needs not prepare for build, so set "kernel_is_prebuilt is true" in
# config.json to avoid it.
if (!is_mini_system && !ohos_kernel_is_prebuilt) {
deps = [ "scripts/build_lite:build" ]
} else if (!ohos_kernel_is_prebuilt) {
if (ohos_kernel_type == "liteos_m") {
all_dependent_configs = [
"//kernel/liteos_m:public",
"//kernel/liteos_m:kconfig_config",
]
} else if (ohos_kernel_type == "uniproton") {
all_dependent_configs = [
"//kernel/uniproton:os_config",
"//kernel/uniproton:kconfig_config",
]
}
}
}
} else {
import("musl_template.gni")
group("musl_all") {
deps = [
":musl_headers",
":soft_libs",
]
}
ohos_prebuilt_etc("ld-musl-namespace-${musl_arch}-test.ini") {
source =
"${musl_porting_dir}/config/ld-musl-namespace-${musl_arch}-test.ini"
}
ohos_prebuilt_etc("ld-musl-namespace-${musl_arch}.ini") {
source = "${musl_porting_dir}/config/ld-musl-namespace-${musl_arch}.ini"
install_images = [
"system",
"updater",
]
}
group("musl_ns_config") {
deps = [
":ld-musl-namespace-${musl_arch}-test.ini",
":ld-musl-namespace-${musl_arch}.ini",
]
}
group("musl_libs") {
deps = [
":musl_headers",
":musl_sysparam",
":soft_libs",
]
}
ohos_prebuilt_etc("musl_sysparam") {
source = "${musl_porting_dir}/etc/musl.para"
relative_install_dir = "param"
}
musl_libs("soft_libs") {
}
group("musl_headers") {
deps = [
":copy_uapi",
":create_alltypes_h",
":create_syscall_h",
":create_version_h",
":musl_copy_inc_arpa",
":musl_copy_inc_bits",
":musl_copy_inc_fortify",
":musl_copy_inc_hook",
":musl_copy_inc_info",
":musl_copy_inc_net",
":musl_copy_inc_netinet",
":musl_copy_inc_netpacket",
":musl_copy_inc_root",
":musl_copy_inc_scsi",
":musl_copy_inc_sys",
":musl_copy_inc_trace",
":musl_ns_config",
]
}
action("create_porting_src") {
script = "scripts/porting.sh"
sources_dir = [ "//third_party/musl" ]
outdir = [ "${target_out_dir}/${musl_ported_dir}" ]
src_files = musl_src_arch_file
src_files += musl_src_file
src_files += musl_src_ldso
src_files += musl_inc_bits_files
src_files += musl_inc_arpa_files
src_files += musl_inc_net_files
src_files += musl_inc_netinet_files
src_files += musl_inc_netpacket_files
src_files += musl_inc_scsi_files
src_files += musl_inc_sys_files
src_files += musl_inc_fortify_files
src_files += musl_inc_root_files
src_files += [
"crt/${musl_arch}/crti.s",
"crt/${musl_arch}/crtn.s",
"crt/Scrt1.c",
"crt/crt1.c",
"crt/rcrt1.c",
"tools/mkalltypes.sed",
"arch/${musl_arch}/bits/alltypes.h.in",
"arch/${musl_arch}/bits/syscall.h.in",
"include/alltypes.h.in",
"VERSION",
"tools/version.sh",
"tools/install.sh",
"scripts/install.py",
"scripts/create_alltypes.sh",
"scripts/create_vesion.sh",
"scripts/create_syscall.sh",
]
args = [ "-i" ] + rebase_path(sources_dir)
args += [ "-o" ] + rebase_path(outdir)
args += [ "-p" ] + [ "${musl_target_os}" ]
foreach(i, src_files) {
foreach(s, musl_src_porting_file) {
if (i == s) {
src_files -= [ "${s}" ]
}
}
}
outputs = []
foreach(s, src_files) {
outputs += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
foreach(s, musl_src_porting_file) {
outputs += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
inputs = []
foreach(s, src_files) {
inputs += [ "${musl_dir}/${s}" ]
}
foreach(s, musl_src_porting_file) {
inputs += [ "${musl_porting_dir}/${s}" ]
}
}
action("create_alltypes_h") {
script = "${target_out_dir}/${musl_ported_dir}/scripts/create_alltypes.sh"
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/bits/alltypes.h" ]
sources = [ "${target_out_dir}/${musl_ported_dir}/tools/mkalltypes.sed" ]
sources += [
"${target_out_dir}/${musl_ported_dir}/arch/${musl_arch}/bits/alltypes.h.in",
"${target_out_dir}/${musl_ported_dir}/include/alltypes.h.in",
]
args = [ "-o" ] + rebase_path(outputs, root_build_dir)
args += rebase_path(sources, root_build_dir)
deps = [ ":create_porting_src" ]
}
action("create_version_h") {
script = "${target_out_dir}/${musl_ported_dir}/scripts/create_vesion.sh"
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/version.h" ]
sources = [
"${target_out_dir}/${musl_ported_dir}/VERSION",
"${target_out_dir}/${musl_ported_dir}/tools/version.sh",
]
args = rebase_path(sources, root_build_dir)
args +=
[ rebase_path("${target_out_dir}/${musl_inc_out_dir}", root_build_dir) ]
deps = [ ":create_porting_src" ]
}
action("create_syscall_h") {
script = "${target_out_dir}/${musl_ported_dir}/scripts/create_syscall.sh"
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/bits/syscall.h" ]
sources = [ "${target_out_dir}/${musl_ported_dir}/arch/${musl_arch}/bits/syscall.h.in" ]
args = rebase_path(sources, root_build_dir)
args += rebase_path(outputs, root_build_dir)
deps = [ ":create_porting_src" ]
}
# if uapi_dir does not exist, then make uapi from linux_kernel_dir
if (exec_script("/bin/sh",
[
"-c",
"if [ ! -d " + rebase_path(uapi_dir) +
" ]; then echo true; else echo false; fi",
],
"value")) {
kernel_dir = rebase_path(linux_kernel_dir)
kernel_out_dir = "${kernel_dir}/make_output"
uapi_dir = "${kernel_out_dir}/usr/include"
make_uapi_cmd = "rm -rf ${uapi_dir}"
make_uapi_cmd += " && make -C ${kernel_dir} -sj headers O=${kernel_out_dir} ARCH=${target_cpu}"
make_uapi_cmd += " && cp -f ${kernel_dir}/drivers/staging/android/uapi/ashmem.h ${uapi_dir}/linux/ashmem.h"
make_uapi_cmd += " && sed -i '/#define _INPUT_H/i#define _UAPI_INPUT_H' ${uapi_dir}/linux/input.h"
make_uapi_cmd += " && sed -i '/struct __kernel_sockaddr_storage/i#define sockaddr_storage __kernel_sockaddr_storage' ${uapi_dir}/linux/socket.h"
args_make_uapi = [ "-c" ]
args_make_uapi += [ make_uapi_cmd ]
exec_script("/bin/sh", args_make_uapi, "value")
uapi_from = "make"
} else {
uapi_from = "local"
}
uapi_full_path = rebase_path(uapi_dir)
arguments_uapi = [ "-c" ]
# exclude these files because they need special treatment
if (uapi_from == "make") {
exclude_files = "^asm\$|^scsi\$"
} else {
exclude_files = "^asm-arm\$|^asm-arm64\$|^scsi\$"
}
arguments_uapi +=
[ "ls ${uapi_full_path} | grep -Ev " + "\"" + "${exclude_files}" + "\"" ]
uspi_files = exec_script("/bin/sh", arguments_uapi, "list lines")
# Generate a copy target for each file
foreach(file, uspi_files) {
copy("copy_uapi_${file}") {
sources = [ "${uapi_dir}/${file}" ]
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/${file}" ]
}
}
group("copy_uapi_scsi") {
deps = []
sources = []
outputs = []
uapi_scsi_dir = rebase_path("${uapi_dir}/scsi")
arguments_scsi = [ "-c" ]
arguments_scsi += [ "ls ${uapi_scsi_dir}" ]
uapi_scsi_files = exec_script("/bin/sh", arguments_scsi, "list lines")
# Generate a copy target for each file in scsi dir to avoid being influenced by musl_copy_inc_scsi output
foreach(file, uapi_scsi_files) {
copy("copy_uapi_scsi_${file}") {
sources += [ "${uapi_dir}/scsi/${file}" ]
outputs += [ "${target_out_dir}/${musl_inc_out_dir}/scsi/${file}" ]
}
deps += [ ":copy_uapi_scsi_${file}" ]
}
}
copy("copy_uapi_asm") {
if (uapi_from == "local") {
if ("${musl_arch}" == "arm") {
file_name = "asm-arm"
} else { # aarch64 and x86_64 use same file
file_name = "asm-arm64"
}
sources = [ "${uapi_dir}/${file_name}/asm" ]
} else {
sources = [ "${uapi_dir}/asm" ]
}
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/asm" ]
}
group("copy_uapi") {
deps = [ ":copy_uapi_scsi" ]
# We need do different processing for asm according to the source of uapi
deps += [ ":copy_uapi_asm" ]
foreach(file, uspi_files) {
deps += [ ":copy_uapi_${file}" ]
}
}
copy("musl_copy_inc_bits") {
sources = []
sources_orig = musl_inc_bits_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/bits/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_arpa") {
sources = []
sources_orig = musl_inc_arpa_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/arpa/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_net") {
sources = []
sources_orig = musl_inc_net_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/net/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_netinet") {
sources = []
sources_orig = musl_inc_netinet_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/netinet/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_netpacket") {
sources = []
sources_orig = musl_inc_netpacket_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs = [
"${target_out_dir}/${musl_inc_out_dir}/netpacket/{{source_file_part}}",
]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_scsi") {
sources = []
sources_orig = musl_inc_scsi_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/scsi/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_sys") {
sources = []
sources_orig = musl_inc_sys_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/sys/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_trace") {
sources = []
sources_orig = musl_inc_trace_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/trace/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_info") {
sources = []
sources_orig = musl_inc_info_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/info/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_fortify") {
sources = []
sources_orig = musl_inc_fortify_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs =
[ "${target_out_dir}/${musl_inc_out_dir}/fortify/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_root") {
sources = []
sources_orig = musl_inc_root_files
foreach(s, sources_orig) {
sources += [ "${target_out_dir}/${musl_ported_dir}/${s}" ]
}
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/{{source_file_part}}" ]
deps = [ ":create_porting_src" ]
}
copy("musl_copy_inc_hook") {
sources = musl_inc_hook_files
outputs = [ "${target_out_dir}/${musl_inc_out_dir}/{{source_file_part}}" ]
}
group("libctest") {
testonly = true
deps = [ "libc-test:musl_libc_test" ]
}
}
......@@ -216,7 +216,7 @@ static void do_tzset()
|| !strcmp(dummy_name, "UTC")
|| !strcmp(dummy_name, "GMT")))
posix_form = 1;
}
}
/* Non-suid can use an absolute tzfile pathname or a relative
* pathame beginning with "."; in secure mode, only the
* standard path will be searched. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册