From e2005fda57ea4da12754d67ba127b09508125395 Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 10 Oct 2018 21:54:10 +0200 Subject: cross compiling struggles --- README.md | 33 +- interface/Makefile | 2 + interface/crt0.s | 20 +- kernel/kernel.h | 20 +- packages/ncurses-6.1/README | 1 + packages/ncurses-6.1/termios.h | 275 ++++++++++++ ref/Cross-Porting_Software.html | 446 +++++++++++++++++++ ref/GCC_Cross-Compiler.html | 860 +++++++++++++++++++++++++++++++++++++ ref/Hosted_GCC_Cross-Compiler.html | 408 ++++++++++++++++++ ref/Porting_Newlib.html | 694 ++++++++++++++++++++++++++++++ ref/README | 1 + userspace/Makefile | 10 +- userspace/clear.c | 9 - userspace/myclear.c | 9 + userspace/ncurses/Makefile | 10 + userspace/ncurses/ncurs.c | 13 + xxx/packages/ncurses-5.9/termios.h | 14 +- 17 files changed, 2787 insertions(+), 38 deletions(-) create mode 100644 packages/ncurses-6.1/README create mode 100644 packages/ncurses-6.1/termios.h create mode 100644 ref/Cross-Porting_Software.html create mode 100644 ref/GCC_Cross-Compiler.html create mode 100644 ref/Hosted_GCC_Cross-Compiler.html create mode 100644 ref/Porting_Newlib.html create mode 100644 ref/README delete mode 100644 userspace/clear.c create mode 100644 userspace/myclear.c create mode 100644 userspace/ncurses/Makefile create mode 100644 userspace/ncurses/ncurs.c diff --git a/README.md b/README.md index 07f47b9..7b3e289 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,39 @@ Todos * EXTRA: port to arm and berryboot / minicom? * EXTRA: port doom/quake/mesa 3d + +1.GCC & Binutils +================ + + * ref: GCC Cross Compiler + * ref: OS Specific Toolchain + * ref: Hosted GCC Cross Compiler + +2.Porting Newlib +================ + + * ref: Porting_Newlib + * Add fool-os specifics under ../newlib-foolos/newlib/libc/sys/foolos + * TODO: os specifics diff + * cd newlib-build + * ../newlib-foolos/configure --prefix=/usr --target=i686-foolos + * make all + * make DESTDIR=${SYSROOT} install (e.g. make DESTDIR=/home/miguel/temp/foolos/ install) + +3.Porting Software +=================== + + * ref: Cross Porting Software + + * ncurses: ../ncurses-6.1/configure --host=i686-foolos --without-tests + --with-fallbacks="fool-term" --with-debug --prefix=/usr --with-termlib --without-progs + + * ncurses-examples: ../ncurses-examples-20180127/configure --host=i686-foolos --prefix=/usr --with-ncurses + make DESTDIR=/home/miguel/temp/foolos/ install + + Disclaimer ----------- +========== THIS IS A WORK IN PROGRESS. diff --git a/interface/Makefile b/interface/Makefile index 1cefd39..d70fc30 100644 --- a/interface/Makefile +++ b/interface/Makefile @@ -1,4 +1,6 @@ AS=i686-foolos-as +crt0.o: + clean: rm -f *.o diff --git a/interface/crt0.s b/interface/crt0.s index 0b833c0..c24d2d9 100644 --- a/interface/crt0.s +++ b/interface/crt0.s @@ -5,19 +5,19 @@ _start: push %ebx push %ecx -cmp $0,_impure_ptr -jne skipzero +//cmp $0,_impure_ptr +//jne skipzero -movl $0xf5000000, _impure_ptr -mov $0xf5000000,%ebx +//movl $0xf5000000, _impure_ptr +//mov $0xf5000000,%ebx -allzero: -movl $0, (%ebx) -add $4, %ebx -cmp $0xf5001000,%ebx -jne allzero +//allzero: +//movl $0, (%ebx) +//add $4, %ebx +//cmp $0xf5001000,%ebx +//jne allzero -skipzero: +//skipzero: mov _impure_ptr,%eax mov $0xf5000000,%ebx diff --git a/kernel/kernel.h b/kernel/kernel.h index acd3451..46302ba 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -62,18 +62,18 @@ REFERENCES // 8192 pages = 0x2000000 bytes // minimal space between user and kernel pages 1024 pages! -#define VMEM_KERNEL 0x00000000 // 8192 pages (32megs) / identity mapped -#define VMEM_KERNEL_PAGES (1024*16) +#define VMEM_KERNEL 0x00000000 /// identity mapped +#define VMEM_KERNEL_PAGES (1024*16) // 64mb // VMEM_KERNEL END 0x02000000 #define VMEM_USER_ENV 0x07000000 // 1 page / per user process //#define VMEM_USER_PROG_PAGES (256*16) -#define VMEM_USER_PROG_PAGES (1024*16) -#define VMEM_USER_PROG 0x08048000 // ? pages / per user process (usual entry: 0x8048080) +#define VMEM_USER_PROG_PAGES (1024*16) // 64 megs +#define VMEM_USER_PROG 0x08048000 // / per user process (usual entry: 0x8048080) -#define VMEM_USER_STACK_PAGES (1024*16) // 4 pages / per thread -#define VMEM_USER_STACK_TOP 0xF0000000 // 4 pages / per thread +#define VMEM_USER_STACK_PAGES (1024*16) // 64 megs / per thread +#define VMEM_USER_STACK_TOP 0xF0000000 // s / per thread #define VMEM_LAPIC 0xF0005000 // 1 pages / identity mapped #define VMEM_IOAPIC 0xF0006000 // 1 pages / identity mapped @@ -87,11 +87,11 @@ REFERENCES //TODO: do not hardcode in crt0.s!!!! #define VMEM_USER_NEWLIB 0xF5000000 // 1 page / newlib reentrancy struct. 1 per thread -#define VMEM_FRAMEBUFFER 0xF6000000 // 8192 pages (32megs) / identity mapped -#define VMEM_FRAMEBUFFER_PAGES (1024*8) +#define VMEM_FRAMEBUFFER 0xF6000000 // identity mapped +#define VMEM_FRAMEBUFFER_PAGES (1024*8) // 32mb -#define VMEM_EXT2_RAMIMAGE 0xF8000000 // 8192 pages (32megs) / identity mapped -#define VMEM_EXT2_PAGES (1024*16) +#define VMEM_EXT2_RAMIMAGE 0xF8000000 // identity mapped +#define VMEM_EXT2_PAGES (1024*16) // 64mb #define VMEM_USER_FRAMEBUFFER 0xFC000000 #define VMEM_USER_FRAMEBUFFER_PAGES 300// 4*320*480 bytes per app (one extra?) diff --git a/packages/ncurses-6.1/README b/packages/ncurses-6.1/README new file mode 100644 index 0000000..31432fa --- /dev/null +++ b/packages/ncurses-6.1/README @@ -0,0 +1 @@ +../ncurses-6.1/configure --host=i686-foolos --without-tests --with-fallbacks="fool-term" --with-debug --prefix=/usr --with-termlib --without-progs diff --git a/packages/ncurses-6.1/termios.h b/packages/ncurses-6.1/termios.h new file mode 100644 index 0000000..57011cd --- /dev/null +++ b/packages/ncurses-6.1/termios.h @@ -0,0 +1,275 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993-1999, 2003, 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ +#include + +struct __dirstream +{ + int fd; + //.. + //https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/dirstream.h;h=8303f07fab6f6efaa39e51411ef924e712d995e0;hb=fa39685d5c7df2502213418bead44e9543a9b9ec +}; + +//typedef uint32_t __ino_t; + +struct dirent +{ + __ino_t d_ino; + __off_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + int d_namlen; +}; +#define direct dirent + + +typedef struct __dirstream DIR; + +#include + + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 +#ifdef __USE_BSD +# define EXTPROC 0200000 +#endif + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) + + static inline int tcgetattr(int fd, struct termios *termios_p) + { + } + + int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); +/** + + int tcsendbreak(int fd, int duration); + + int tcdrain(int fd); + + int tcflush(int fd, int queue_selector); + + int tcflow(int fd, int action); +*/ + void cfmakeraw(struct termios *termios_p); + + /* + speed_t cfgetispeed(const struct termios *termios_p); + + */ + speed_t cfgetospeed(const struct termios *termios_p); + + /* + int cfsetispeed(struct termios *termios_p, speed_t speed); + + int cfsetospeed(struct termios *termios_p, speed_t speed); + + int cfsetspeed(struct termios *termios_p, speed_t speed); + */ + diff --git a/ref/Cross-Porting_Software.html b/ref/Cross-Porting_Software.html new file mode 100644 index 0000000..7aa63e5 --- /dev/null +++ b/ref/Cross-Porting_Software.html @@ -0,0 +1,446 @@ + + + +Cross-Porting Software - OSDev Wiki + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Cross-Porting Software

+ + +
+ +
From OSDev Wiki
+ + +
+ + +
+ Jump to: navigation, + search +
+ + +
Difficulty level
Difficulty 3.png
Advanced
+

This page is notes on how to port software to your operating system by cross-compiling it. Many core packages use autoconf-generated ./configure script that provide a convenient interface for our purposes. This assumes your operating is somewhat Unix-like. There is a lot of subtle semantics that first-time porters often get wrong and particular packages occasionally misbehave. This tutorial assumes you are porting a package using a conventional configure script (generated with autoconf), but the principles can be adapted to other build systems. +

+

Contents

+ +
+

Prerequisites

+

This is an advanced matter and your operating system needs to have an established user-space and a dedicated toolchain: +

+ +

System Root

+
Please read this article's section on sysroots. +
+

Your build process needs to involve a system root, a fake root directory for your operating system. Your cross-compiler must be set up to search this directory tree for libraries and headers. I recommend for your build system to look through each of your subprojects and make install them into this system root, then do the same for ports, and finally your build system extracts the desired files from the system root and makes a boot-able image. We will be installing ports into this directory tree. Futher ports may depend on previous ones and it's crucial the system root is searched. +

+

Prefixes

+

The build systems of the software installs the software somewhere. This is normally in ${PREFIX}/bin, ${PREFIX}/lib and so on. The packages often defaults to /usr/local, but this is generally used for site-specific files rather than vendor-provided files (you are a vendor now). Note how if you want to install packages into /bin and /lib, you set the prefix to the empty string, not a single slash. A prefix is not a directory path in its own right, but something that is added in front of a real directory path. +

+

Dependencies

+

Before porting a package, you need to port its dependencies first (and transitively their dependencies as well). You can often find a list of dependencies in the documentation (perhaps look for README or INSTALL files). Try also to run ./configure --help, this will often list --with-foo options if the package depends on libfoo, it will also list which dependencies are optional. See also guides like Beyond Linux from Scratch as it contains useful dependency information. +

You should be able to construct a nice directed acylic graph of packages and their dependencies (some edges being optional) and use it to decide the order packages are built. If you are not interested in optional dependencies, you can skip them, but beware: Later package may hard-depend on the package you skipped, and may assume a library was built with support for the packager you skipped. +

+

Patches

+

It is very likely that you will need to patch the packages you port. You need to set yourself up such that you can easily patch the packages with no to low cost in effort. You can help other people by hosting your patch collection somewhere public. It is often nicer to actually fix misbehaving packages than working around the problem in your build system in complex manners. +

+

Source Code

+

You need to find the source code for the package you wish to port. This is rather obvious. Generally, it's best to find the latest stable tarball of the package use that. This is preferable to using a git checkout of the package. It's a good idea to save a copy of the original tarball. +

It's advisable to check whether this is a real release or whether it has been maliciously modified. Many projects provide hash values of their releases or otherwise sign their releases. Configure scripts are highly convenient places to hide malware (if you have the autoconf skills, you can regenerate the configure script and other files and see if they match). Man-in-the-middle attacking in insecure http/ftp download of a tarball is trivial, you can mitigate this danger by downloading from multiple networks and verifying what other people have. +

You also definitely wish to to read the license for the software and whether it even permits the efforts we are taking here. +

You extract the source code somewhere appropriate: +

+
# Use --extract --file if you have a hard time surviving xkcd 1168.
+tar -xf libfoo-4.2.tar.xz
+

pkg-config

+

Libraries increasingly provide pkg-config files that describe where the headers are installed and how to link against the library (and private library dependencies if statically linked). Working with pkg-config is preferable to fighting it (see below on packages rolling their own foo-config program) and it nicely supports system roots and is cross-compile aware. It's possible to compile a custom cross-pkg-config, or you can simply wrap your system one. Make a x86_64-myos-pkg-config executable shell script and put it somewhere in your path for the duration of the cross-compilation: +

+
#!/bin/sh
+# Fill these in appropriately:
+export PKG_CONFIG_SYSROOT_DIR=$MYOS_SYSROOT
+export PKG_CONFIG_LIBDIR=$MYOS_SYSROOT/usr/lib/pkgconfig
+# TODO: If it works this should probably just be set to the empty string.
+export PKG_CONFIG_PATH=$PKG_CONFIG_LIBDIR
+# Use --static here if your OS only has static linking.
+# TODO: Perhaps it's a bug in the libraries if their pkg-config files doesn't
+#       record that only static libraries were built.
+exec pkg-config --static "$@"
+

You then set PKG_CONFIG=x86_64-myos-pkg-config to packages use your custom pkg-config instead, and PKG_CONFIG_FOR_BUILD=pkg-config so packages that wish to compile local programs use the system pkg-config. +

+

Build

+

This section lists the steps that are sufficient for an ideal port, but see below. +

First you wish to find the config.sub file. The GNU coding conventions usually place it at build-aux/config.sub to avoid clutter in the main directory. You wish to add your operating system's target name to it, as you did in the OS Specific Toolchain article. This change is required, or otherwise the --host value will be rejected. This simple fact means that you likely have to have a small patch for every single port. +

Secondly, you cross-build the package in this manner: +

+
# Potentially unset CC and such here (see configure --help) to prevent local
+# tools from being mistakenly used as cross-tools. Alternatively, set them to
+# your cross-tools unconditionally. Note also the existence of CC_FOR_BUILD in
+# the case of packages that needs to build local tools to build themselves.
+ 
+./configure --host=x86_64-myos --prefix=/usr
+make
+make DESTDIR=$SYSROOT install
+

This will cross-compile the software and install it under /usr on your system, inside your system root as the temporary installation location. Note how many packages remember --prefix and use it at runtime to locate their data files. You must not do --prefix=$SYSROOT/usr as that means libfoo would look files in /home/myuser/myos/sysroot/usr/share/libfoo while running on your operating system instead of /usr/share/libfoo. The DESTDIR acts as a second prefix for the purpose of installation, it's not revealed to the package before the install step, so it won't mistakenly remember it. +

Alternatively, instead of setting DESTDIR to the system root, you can set it to a temporary location and create an installable binary package from it, and then install the binary package into the system root. +

+

Porting

+

The make command likely didn't succeed. You'll need to investigate the build errors and improve your standard library, or improve the package if it is unreasonable. +

+

Runtime

+

After you cross-compiled the package and installed it onto your operating system, it's time to try it out. If you implemented your operating system and standard library well, it should now work. Likely, especially if you made your own custom standard library, your first real ports won't. You now need to learn to debug programs you know nothing about on your new operating system. Have fun! Suddenly it'll work and you have something to talk about in the 'Aww, Yeah!' forum thread. +

+

Problems

+

Unfortunately, this is the real world and some packages misbehave in manners that breaks our naive cross-compilation. This is a bug in such packages; the practice described so far should be sufficient for well-made packages. Fortunately, community members likely know of such issues and generally work to upstream fixes, see the patch collections below. This section lists common problems and solutions. +

In case it's a bug in these packages, it's advisable to patch the packages to fix the bug and upstream the bugfix (or report the issue), rather than poorly working around the issues in your build system (in ways that tend to get more and more complex). Generally, the best approach is to make the packages implement the interface we rely on above. +

+

libtool .la files

+

Many libraries use libtool and install .la files into the system library directory. These work somewhat like pkg-config files, except often semantically wrong as they are not sysroot aware (but research the --with-sysroot option that libtool-aware configure scripts provide, it might save the system root path in the .la files which is wrong). The files can cause the build system to add library directories to the link command that weren't prefixed with the system root, causing the command link with the /usr/lib files from your local operating system. +

It's entirely safe to delete these files, so set up your post-install build steps to delete any .la files on sight. The libraries generally install pkg-config files as well and the programs generally use pkg-config to locate libraries anyways (if not, it's perhaps a bug). +

+

Dumb pkg-config use

+

Some packages simply invoke pkg-config with the raw pkg-config command, rather than using the PKG_CONFIG and PKG_CONFIG_FOR_BUILD variables. That is a bug. The correct logic is to use the variables if they exist and fall back on the raw command otherwise. The shell expression ${PKG_CONFIG:=pkg-config} is useful as if it is set and non-empty, then it is used, otherwise pkg-config us used. +

+

foo-config

+

Some packages (like libfreetype, libpng, libsdl, libxml2, and more) install a custom program like freetype-config into the bin directory. The idea is packages depending on libfreetype can run freetype-config --cflags --libs and it gets the compiler options needed to use the library. This scheme fails horribly in practice, as the bin directory of your operating system is not in your PATH (neither should it be!) and instead the freetype-config program of your distribution is used instead. The programs are not even sysroot-aware so it's not added in front of the compiler options. Suddenly your otherwise-nicely cross-compiled programs got linked with a Linux libfreetype with the Linux version of the headers. +

The solution is to nuke these programs on sight. They're broken and should never be used or installed on your operating system. Tell the upstream developers to stop providing them and provide pkg-config files, and projects using them to use pkg-config instead. This is supposedly why pkg-config was created, to do this once and for all in a proper way. If you see programs using the foo-config programs, patch the configure script so they use pkg-config instead. +

+

Running Cross-Compiled Programs

+

Some packages are not cross-compile aware and use the standard compiler (your cross-compiler) to build a local program that generates parts of the program and then runs the program. This doesn't work, it runs a cross-compiled executable and it won't run on your local operating system. The results vary from execve returning an error, infinite loops, or mysterious crashes. The bug is that the package should have used a variable like CC_FOR_BUILD to compile programs for the local system. +

This occasionally also takes the form of configure tests that are mistakenly run (not just compiled and linked) when cross-compiling. A while ago, a lot of packages checked for Japanese locales by unconditionally running such tests when cross-compiling leading to fun results. The correct behavior is to attempt running this test, and if we are cross-compiling, then assume something reasonable (or delaying the test until the program is actually run). +

+

Assuming the Worst

+

Some packages take portability to the levels where they want to support broken operating systems and do compatibility magic in these cases. This is often to work around a bug in a particular release of a particular operating system. This compatibility occasionally takes the form of a configure test that needs to be executed. In the event of cross-compilation, these tests needs to assume something. The developers made the error of assuming unknown systems are terribly broken, instead of just using a heuristic that FooBSD (before release 5) is broken and assuming the best about all other systems. +

The correct solution is for packages to assume the best about unknown operating systems. This shifts the punishment from the good systems to the bad systems (so they break and they have the opportunity to fix bugs). This is not a problem for existing systems, because if the developers care about FooBSD, that's not an unknown system. +

+

Gnulib

+

The GNU portability layer takes the form of a collection of files that everyone copies into their packages and then neglect to update often. These files are often deeply integrated into the package (i.e. hard to disable properly). The principle of replacing standard library functions if broken or missing is not too terribly bad - but Gnulib mixes it with a huge paranoia that the host system is terribly broken and assumes the very worst when cross-compiling. The result is that when you cross-compile these ports, huge amounts of compatibility code gets compiled in, and much of this compatibility code does not even work on unknown platforms. Of particular fun is code that needs to integrate deeply into stdio internals or when it replaces your printf. The result is that as you port packages, you often find yourself fixing the same gnulib code over and over (each time subtly different depending on when it was forked). When you improve your stdio implementation to be more standards-compliant, you find yourself needing to fix all those gnulib stdio-internals-aware files all over again, because some silly internal changed. +

The solution is to scream in horror at how troublesome and unnecessary this scheme is as obviously you are capable of implementing a correct operating system. This racketeering scheme has #error statements that tell you to upstream preprocessor conditionals for your operating system, so they can relish in even more complexity that didn't need to exist in the first place. +

Sortie has developed a gnulib policy for his OS that describes how to handle gnulib and it has a long list of secret autoconf variables that makes gnulib assume everything is perfect. +

+

Custom Configure Script

+

Some packages considers autoconf to be hellish and refuses to use it. They occasionally replace an autoconf-generated configure script with a hand-written one. This is well, but they unfortunately often fail to completely implement the same interface and don't support cross-compilation. You can attempt to patch the configure script to it implements the same interface, or do whatever else gets the job done. You probably want to yell at the developers. +

+

No DESTDIR

+

The package might not support the DESTDIR variable. You should patch the Makefile (perhaps Makefile.in) to support it and tell the upstream developers. Perhaps it's called something else like INSTALLROOT, you can rename it in the Makefile or add INSTALLROOT ?= $(DESTDIR). +

+

Packages Containing Dependencies

+

Sometimes packages contain copies of their dependencies as subdirectories. If you are really unlucky, they get used instead of the real deal. That means you have to port a two year old version all over again. If you are more unlucky, you get something that actually compiles on your operating system, but contains unfixed bugs and has security issues and this gets silently used. Extra fun is if they fixed bugs or enhanced the library and this is not in the upstream version. Tell upstream projects to get their act together if you see it, it's your responsibility to provide dependencies for a good reason. +

+

Exotic problems

+

As you start porting packages that rarely get ported or cross-compiled, you'll likely start finding some seriously messed up packages. For instance, I once found a library that stores the path to the compiler and the compiler options in a header, so other libraries/programs depending on it could locate the compiler that way (and they did) - despite the fact they also had a full and generated configure script. At some point, you should reconsider whether this is actually software you want to port. +

+

Upstreaming Local Patches

+

As you port more packages, you gradually get a patch collection. Many of these patches likely works around issues in your system, but other patches solves general issues in the packages. Ideally, you should not need to patch packages at all. Though, your operating system is not terribly important to support in the upstream version and any patches will likely go stale soon as your operating system improves. However, the patches not related to your operating system is likely of value upstream (or to the other osdever's that also port stuff). You should send such patches upstream or file bug reports. In the long run, it decreases the size of your patch collection and makes it more maintainable. +

+

Patch Collections

+

It is probable that other community members have already ported a particular package. Their patches likely contain insight into how troublesome it is to do a port and what needs to be done. You can often find a collection of all their local patches in a central location. +

+ + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ + +
+
Personal tools
+ +
+ + +
+ + +
+
Namespaces
+ +
+ + + + +
+
Variants
+ +
+ + +
+
+ + +
+
Views
+ +
+ + + + +
+
Actions
+ +
+ + + + + + + +
+
+ + +
+ + + + + +
+
Navigation
+ +
+ + + + +
+
About
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + diff --git a/ref/GCC_Cross-Compiler.html b/ref/GCC_Cross-Compiler.html new file mode 100644 index 0000000..6752ffc --- /dev/null +++ b/ref/GCC_Cross-Compiler.html @@ -0,0 +1,860 @@ + + + +GCC Cross-Compiler - OSDev Wiki + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

GCC Cross-Compiler

+ + +
+ +
From OSDev Wiki
+ + +
+ + +
+ Jump to: navigation, + search +
+ + +
+ + +
+

This page or section refers to its readers or editors using I, my, we or us. It should be edited to be in an encyclopedic tone. +

+
+
Difficulty level
Difficulty 1.png
Beginner
+

In this tutorial we will create a GCC cross-compiler for your own operating system. This compiler is specially made to target exactly your operating system and is what allows you to leave the current operating system behind. You need a cross-compiler for operating systems development, unless you are developing on your own operating system. +

+

Contents

+ +
+

Introduction

+

Generally speaking, a cross-compiler is a compiler that runs on platform A (the host), but generates executables for platform B (the target). These two platforms may (but do not need to) differ in CPU, operating system, and/or executable format. In our case, the host platform is your current operating system, and the target platform is the operating system you are about to make. It is important to realize that these two platforms are not the same; your operating system is always going to be different from your current operating system. This is why we need to build a cross-compiler first, you will most certainly run into trouble otherwise. +

+

Why do I need a Cross Compiler?

+
Main article: Why do I need a Cross Compiler? +
+

You need to use a cross-compiler unless you are developing on your own operating system. The compiler must know the correct target platform (CPU, operating system), otherwise you will run into trouble. If you use the compiler that comes with your system, then the compiler won't know it is compiling something else entirely. Some tutorials suggest using your system compiler and passing a lot of problematic options to the compiler. This will certainly give you a lot of problems in the future and the solution is build a cross-compiler. If you have already attempted to make an operating system without using a cross-compiler, please read the article Why do I need a Cross Compiler?. +

+

Which compiler version do I want?

+
Main article: Building GCC +
+

The newest GCC is recommended as it is the latest and greatest release. For instance, you may run into trouble if you use GCC 4.6.3 to build a GCC 4.8.0 cross-compiler. If you are not using the latest major GCC release for your system compiler, we recommend that you build the newest GCC as your system compiler. +

You can also use older releases as they are usually reasonably good. If your local system compiler isn't too terribly old (at least GCC 4.6.0), you may wish to save yourself the trouble and just pick the latest minor release (such as 4.6.3 if your system compiler is 4.6.1) for your cross-compiler. +

You can view your current compiler version by invoking: +

+
gcc --version
+

You may be able to use an older major GCC release to build a cross-compiler of a newer major GCC release. For instance, GCC 4.7.3 may be able to build a GCC 4.8.0 cross-compiler. However, if you want to use the latest and greatest GCC version for your cross-compiler, we recommend that you bootstrap the newest GCC as your system compiler first. Individuals using OS X 10.7 or earlier might want to invest in either building a system GCC (that outputs native Mach-O), or upgrading the local LLVM/Clang installation. Users with 10.8 and above should install the Command Line Tools from Apple's developer website and use Clang to cross-compile GCC. +

+

Which Binutils version do I want?

+
Main article: Cross-Compiler Successful Builds +
+

We recommend that you use the latest and greatest Binutils release. Note, however, that not all combinations of GCC and Binutils work. If you run into trouble, use a Binutils that was released at roughly the same time as your desired compiler version. You probably need at least Binutils 2.22, or preferably the latest 2.23.2 release. It doesn't matter what Binutils version you have installed on your current operating system. +

+

Deciding on the target platform

+
Main article: Target Triplet +
+

You should already know this. If you are following the Bare Bones tutorial, you wish to build a cross-compiler for i686-elf. +

+

Preparing for the build

Difficulty level
Difficulty 1.png
Beginner
+


+

The GNU Compiler Collection is an advanced piece of software with dependencies. You need the following the following in order to build GCC: +

+
  • A Unix-like environment (Windows users can use the Windows Subsystem for Linux or Cygwin) +
  • Enough memory and hard disk space (it depends, 256 MiB will not be enough). +
  • GCC (existing release you wish to replace), or another system C compiler +
  • G++ (if building a version of GCC >= 4.8.0), or another system C++ compiler +
  • Make +
  • Bison +
  • Flex +
  • GMP +
  • MPFR +
  • MPC +
  • Texinfo +
  • ISL (optional) +
  • CLooG (optional) +
+

Installing Dependencies

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
↓ Dependency / OS → + Source Code + Debian (Ubuntu, Mint, WSL, ...) + Gentoo + Fedora + Cygwin + OpenBSD +
How to install +Normally +sudo apt install foo +? +sudo dnf install foo +Cygwin GUI setup +doas pkg_add foo +
Compiler +N/A +build-essential +? +gcc gcc-c++ +mingw64-x86_64-gcc-g++ / mingw64-i686-gcc-g++ +Preinstalled +
Make +N/A +build-essential +? +make +make +Preinstalled +
Bison +[1] +bison +? +bison +bison +? +
Flex +[2] +flex +? +flex +flex +? +
GMP +[3] +libgmp3-dev +dev-libs/gmp +gmp-devel +libgmp-devel +gmp +
MPC +[4] +libmpc-dev +dev-libs/mpc +libmpc-devel +libmpc-devel +libmpc +
MPFR +[5] +libmpfr-dev +dev-libs/mpfr +mpfr-devel +libmpfr-devel +mpfr +
Texinfo +[6] +texinfo +? +texinfo +texinfo +texinfo +
CLooG (Optional) +CLooG +libcloog-isl-dev +? +? +libcloog-isl-devel +N/A +
ISL (Optional) +[7] +libisl-dev +? +? +libisl-devel +N/A +
+

You need to have Texinfo installed to build Binutils. You need to have GMP, MPC, and MPFR installed to build GCC. GCC optionally can make use of the CLooG and ISL libraries. +

For instance, you can install libgmp3-dev on Debian by running the shell command: sudo apt install libgmp3-dev +

Note: Version 5.x (or later) of Texinfo is known to be incompatible with the current Binutils 2.23.2 release (and older). You can check your current version using makeinfo --version. If your version is too new and you encounter problems during the build, you will need to either use Binutils 2.24 release (or newer) or install an older version of Texinfo - perhaps through building from source - and add it to your PATH prior and during the Binutils build. +

Note: Version 0.13 (or later) of ISL is incompatible with the current CLooG 0.18.1 release (and older). Use version 0.12.2 of ISL or the build will fail. +

+

Downloading the Source Code

+

Download the needed source code into a suitable directory such as $HOME/src: +

+ + +

Note: The versioning scheme used is that each fullstop separates a full number, i.e. Binutils 2.20.0 is newer than 2.9.0. This may be confusing, if you have not encountered this (quite common) versioning scheme yet, when looking at an alphanumerically sorted list of tarballs: The file at the bottom of the list is not the latest version! An easy way of getting the latest version is to sort by the last modified date and scrolling to the bottom. +

+

Linux Users building a System Compiler

+

Your distribution may ship its own patched GCC and Binutils that is customized to work on your particular Linux distribution. You should be able to build a working cross-compiler using the above source code, but you might not be able to build a new system compiler for your current Linux distribution. In that case, try a newer GCC release or get the patched source code. +

+

Gentoo Users

+

Gentoo lets you set up a cross-development toolchain: +

+
   emerge -av crossdev
+   crossdev --help
+   PORTDIR_OVERLAY="/usr/local/crossdev" crossdev --stage1 --binutils <binutils-version> --gcc <gcc-version> --target <target>
+
+

This will install a GCC cross-compiler into a "slot", i.e. alongside already-existing compiler versions. You can install several cross-compilers that way, simply by changing target designations. An unfortunate downside is that it will also pull in gentoo patches and pass additional configure options that differ from the official GCC Cross-Compiler setup, and they might behave differently. +

After the compilation ran, you can now use your cross-compiler by calling <target>-gcc. You can also use gcc-config to toggle between compiler versions should you need to do so. Don't replace your system compiler with a cross-compiler. The package manager will also suggest updates as soon as they become available. +

You can uninstall the cross-compiler by calling crossdev --clean <target>. Read the cross-development document for additional information. +

Note that the version numbers to binutils and gcc are Gentoo package versions, i.e. there might be a suffix to the "official" (GNU) version that addresses additional patchsets supplied by the Gentoo maintainers. (For example, --binutils 2.24-r3 --gcc 4.8.3 is the latest stable package pair at the time of this writing.) You can omit the version numbers to use the latest package available. +

Portage uses overlays to store packages that are not part of the original package management. Crossdev needs one overlay where it can store its binutils and gcc packages before building them. You can configure one properly, or you can use PORTDIR_OVERLAY to point at where it should keep its package manager files. Using PORTDIR_OVERLAY is not a good idea with existing overlays, but by then you should know how you have personally set them up earlier anyway and how to do it properly. +

+

macOS Users

+

macOS users need a replacement libiconv because the system libiconv is seriously out of date. macOS users can download the latest libiconv release by visiting the libiconv website or directly accessing the GNU main FTP mirror. Otherwise you may get unresolved symbol errors related to libiconv when compiling GCC 4.3 or higher on OS X 10.4 and 10.5. +

Install a new version (compile it yourself or use MacPorts) and add --with-libiconv-prefix=/opt/local (or /usr/local if you compiled it yourself) to GCC's ./configure line. Alternatively you may place the libiconv source as gcc-x.y.z/libiconv and it will be compiled as part of the GCC compilation process. (This trick also works for MPFR, GMP, and MPC). +

The makefiles of Binutils and GCC use the $(CC) variable to invoke the compiler. On OS X, this resolves to gcc by default, which is actually clang. Prior to OS X 10.8, the Clang that came with Xcode's Command Line Tools package was not able to build a working GCC. Users running OS X 10.7 or below may need to find and install GCC, either from Homebrew, or from somewhere on Apple's website. You can try with the old GCC that comes preinstalled on some macOS versions. +

+
# This is only necessary for OS X users running 10.7 or below.
+export CC=/usr/bin/gcc-4.2
+export CXX=/usr/bin/g++-4.2
+export CPP=/usr/bin/cpp-4.2
+export LD=/usr/bin/gcc-4.2
+

You will want to unset these exports once you compiled and installed the cross compiler. +

Note for Lion users: If you're on Lion (or above) chances are that you don't have the "real" GCC since Apple removed it from the Xcode package, but you can still install it. You can do it via Homebrew or by compiling from source, both are perfectly described on a StackExchange answer. +

Note for Maverick users: You can build binutils-2.24 and gcc-4.8.3 (possible other version) with Xcode 5.1.1. Note that building GCC with LLVM is not officially supported and may cause interesting bugs, if you are willing to take this risk and save time building host-gcc just to compile a cross-gcc, follow this. +Install GMP, MPFR, Mpc with MacPorts. +

+
sudo port install gmp mpfr libmpc
+
+
../binutils-2.24/configure --prefix=$PREFIX \
+--target=$TARGET \
+--enable-interwork --enable-multilib \
+--disable-nls --disable-werror
+
+
../gcc-4.8.3/configure --prefix=$PREFIX \
+--target=$TARGET \
+--disable-nls \
+--enable-languages=c,c++ --without-headers \
+--enable-interwork --enable-multilib \
+--with-gmp=/usr --with-mpc=/opt/local --with-mpfr=/opt/local
+
+

Note: There is an issue with port's GMP, so the version from OS X from /usr is used instead. +

+

Windows Users

+

Windows users need to set up a Unix-like enviroment such as MinGW or Cygwin. It may well be worth looking into systems such as Linux and see if they fit your needs, as you commonly use a lot of Unix-like tools in operating systems development and this is much easier from a Unix-like operating system. If you have just installed the basic Cygwin package, you have to run the setup.exe again and install the following packages: GCC, G++, Make, Flex, Bison, Diffutils, libintl-devel, libgmp-devel, libmpfr-devel, libmpc-devel, Texinfo +

MinGW + MSYS is an option, and as it addresses the native Windows API instead of a POSIX emulation layer, results in a slightly faster toolchain. Some software packages will not build properly under MSYS as they were not designed for use with Windows. As far as this tutorial is concerned, everything that applies to Cygwin also applies to MSYS unless otherwise specified. Make sure you install the C and C++ compilers, and the MSYS Basic System. +

The "Windows Subsystem for Linux (Beta)", released with the Windows 10 Anniversary update is also an option for using a cross compiler. (Tested 08/08/2016 with GCC 6.1.0 and Binutils 2.27) This cross-compiler works reasonably fast, although being in beta state, it may not be ideal permanent development platform. +

Cygwin note: Cygwin includes your Windows %PATH% in its bash $PATH. If you were using DJGPP before, this could result in confusion as e.g. calling GCC on the Cygwin bash command line would still call the DJGPP compiler. After uninstalling DJGPP, you should delete the DJGPP environment variable and clear the C:\djgpp entry (or wherever you installed it) from your %PATH%. Likewise, it might be a bad idea to mix build environments in your system PATH variable. +

MinGW note: Some MinGW-specific information on building a cross-toolchain can be found on the hosted cross-compiler how-to page on the MinGW homepage. +

Windows Subsystem for Linux (Beta) Note: You cannot have your cross compiler in the /mnt/c/ (or /mnt/"x") areas, as trying to compile your cross-compiler there will generate errors, whereas building to $HOME/opt/cross works perfectly. This is fixed with Windows Update KB3176929 +

+

The Build

+

We build a toolset running on your host that can turn source code into object files for your target system. +

You need to decide where to install your new compiler. It is dangerous and a very bad idea to install it into system directories. You also need to decide whether the new compiler should be installed globally or just for you. If you want to install it just for you (recommended), installing into $HOME/opt/cross is normally a good idea. If you want to install it globally, installing it into /usr/local/cross is normally a good idea. +

Please note that we build everything out of the source directory tree, as is considered good practice. Some packages only support building outside, some only inside and some both (but may not offer extensive checking with make). Building GCC inside the source directory tree fails miserably, at least for older versions. +

+

Preparation

+
export PREFIX="$HOME/opt/cross"
+export TARGET=i686-elf
+export PATH="$PREFIX/bin:$PATH"
+

We add the installation prefix to the PATH of the current shell session. This ensures that the compiler build is able to detect our new binutils once we have built them. +

The prefix will configure the build process so that all the files of your cross-compiler environment end up in $HOME/opt/cross. You can change that prefix to whatever you like (e.g., /opt/cross or $HOME/cross would be options). If you have administrator access and wish to make the cross-compiler toolchain available to all users, you can install it into the /usr/local prefix - or perhaps a /usr/local/cross prefix if you are willing to change the system configuration such that this directory is in the search paths for all users. Technically, you could even install directly to /usr, so that your cross-compiler would reside alongside your system compiler, but that is not recommended for several reasons (like risking to overwrite your system compiler if you get TARGET wrong, or getting into conflict with your system's package management). +

+

Binutils

+
cd $HOME/src
+ 
+mkdir build-binutils
+cd build-binutils
+../binutils-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
+make
+make install
+

This compiles the binutils (assembler, disassembler, and various other useful stuff), runnable on your system but handling code in the format specified by $TARGET. +

--disable-nls tells binutils not to include native language support. This is basically optional, but reduces dependencies and compile time. It will also result in English-language diagnostics, which the people on the Forum understand when you ask your questions. ;-) +

--with-sysroot tells binutils to enable sysroot support in the cross-compiler by pointing it to a default empty directory. By default, the linker refuses to use sysroots for no good technical reason, while gcc is able to handle both cases at runtime. This will be useful later on. +

+

GCC

+
See also the offical instructions for configuring gcc. +
+

Now, you can build GCC. +

+
cd $HOME/src
+ 
+# The $PREFIX/bin dir _must_ be in the PATH. We did that above.
+which -- $TARGET-as || echo $TARGET-as is not in the PATH
+ 
+mkdir build-gcc
+cd build-gcc
+../gcc-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
+make all-gcc
+make all-target-libgcc
+make install-gcc
+make install-target-libgcc
+

We build libgcc, a low-level support library that the compiler expects available at compile time. Linking against libgcc provides integer, floating point, decimal, stack unwinding (useful for exception handling) and other support functions. Note how we are not simply running make && make install as that would build way too much, not all components of gcc are ready to target your unfinished operating system. +

--disable-nls is the same as for binutils above. +

--without-headers tells GCC not to rely on any C library (standard or runtime) being present for the target. +

--enable-languages tells GCC not to compile all the other language frontends it supports, but only C (and optionally C++). +

It will take a while to build your cross-compiler. +

If you are building a cross compiler for x86-64, you may want to consider building Libgcc without the "red zone": Libgcc_without_red_zone +

+

Using the new Compiler

+

Now you have a "naked" cross-compiler. It does not have access to a C library or C runtime yet, so you cannot use any of the standard includes or create runnable binaries. But it is quite sufficient to compile the kernel you will be making shortly. Your toolset resides in $HOME/opt/cross (or what you set $PREFIX to). For example, you have a GCC executable installed as $HOME/opt/cross/bin/$TARGET-gcc, which creates programs for your TARGET. +

You can now run your new compiler by invoking something like: +

+
$HOME/opt/cross/bin/$TARGET-gcc --version
+

Note how this compiler is not able to compile normal C programs. The cross-compiler will spit errors whenever you want to #include any of the standard headers (except for a select few that actually are platform-independent, and generated by the compiler itself). This is quite correct - you don't have a standard library for the target system yet! +

The C standard defines two different kinds of executing environments - "freestanding" and "hosted". While the definition might be rather fuzzy for the average application programmer, it is pretty clear-cut when you're doing OS development: A kernel is "freestanding", everything you do in user space is "hosted". A "freestanding" environment needs to provide only a subset of the C library: float.h, iso646.h, limits.h, stdalign.h, stdarg.h, stdbool.h, stddef.h, stdint.h and stdnoreturn.h (as of C11). All of these consist of typedef s and #define s "only", so you can implement them without a single .c file in sight. +

To use your new compiler simply by invoking $TARGET-gcc, add $HOME/opt/cross/bin to your $PATH by typing: +

+
export PATH="$HOME/opt/cross/bin:$PATH"
+

This command will add your new compiler to your PATH for this shell session. If you wish to use it permanently, add the PATH command to your ~/.profile configuration shell script or similar. Consult your shell documentation for more information. +

You can now move on to complete the Bare Bones tutorial variant that lead you here and complete it using your new cross-compiler. If you built a new GCC version as your system compiler and used it to build the cross-compiler, you can now safely uninstall it unless you wish to continue using it. +

+

Troubleshooting

+

In general, verify that you read the instructions carefully and typed the commands precisely. Don't skip instructions. You will have to set your PATH variable again if you use a new shell instance, if you don't make it permanent by adding it to your shell profile. If a compilation seems to have gotten really messed up, type make distclean, and then start the make process over again. Ensure your un-archiever doesn't change newline characters. +

+

ld: cannot find -lgcc

+

You specified that you want to link the GCC low-level runtime library into your executable through the -lgcc' switch, but forgot to build and properly install the library. +

+

Binutils 2.9

+

What's alphabetically on the top or bottom is not necessarily the latest version. After 2.9 comes 2.10, 2.11, 2.12 and then there are fifteen more releases that are all newer and progressively more likely to build or support your choice of GCC version. +

+

See Also

+

Articles

+ +

External Links

+ +

Prebuilt Toolchains

+

These were built by people in the OSdev community for their own building needs and shared at will, without guaranteeing any support or that it will even work on your setup. YMMV. +

Latests versions for Linux (many arch) +

+ +

For Linux x86_64 host +

+ + +

The packages from phillid.tk below have been shrunk to about 10 MiB for each pair of packages (GCC & Binutils). +Please note that this has been achieved by enabling only the C front-end for GCC. +If you're going to write your OS in any language but C or Assembly, these packages aren't for you. +These are actually Pacman packages, but untarring them to / and rm-ing /.MTREE and other clutter dotfiles contained in the package will work the same. +

For Windows host +

+ +

For Windows Subsystem for Linux (Beta) host +

+
  • i686-elf 6.1.0 target (extracts to a directory called "cross", don't forget to install 'make' - I would recommend "apt-get install build-essential" to also add additional useful tools) +
+

For OSX host +

+ +

ARM prebuilt toolchains for multiple host platforms +

ARM provides it's own prebuilt toolchain based upon GNU utilities for development targeting ARM systems. +

+ +

Docker image +

+ + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ + +
+
Personal tools
+ +
+ + +
+ + +
+
Namespaces
+ +
+ + + + +
+
Variants
+ +
+ + +
+
+ + +
+
Views
+ +
+ + + + +
+
Actions
+ +
+ + + + + + + +
+
+ + +
+ + + + + +
+
Navigation
+ +
+ + + + +
+
About
+ +
+ + + + + + + + + + + + + +
+
In other languages
+
+ +
+
+ + +
+ + + + + + + + + + + + + diff --git a/ref/Hosted_GCC_Cross-Compiler.html b/ref/Hosted_GCC_Cross-Compiler.html new file mode 100644 index 0000000..c3a0555 --- /dev/null +++ b/ref/Hosted_GCC_Cross-Compiler.html @@ -0,0 +1,408 @@ + + + +Hosted GCC Cross-Compiler - OSDev Wiki + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Hosted GCC Cross-Compiler

+ + +
+ +
From OSDev Wiki
+ + +
+ + +
+ Jump to: navigation, + search +
+ + +
Difficulty level
Difficulty 3.png
Advanced
+

In this tutorial we create a cross-compiler that provides a hosted environment (user-space, libc, all that good stuff) as opposed to the initial GCC Cross-Compiler that only provides a freestanding environment. This is an advanced topic meant for established developers, newcomers should start with a freestanding cross-compiler. The -elf targets are incapable of having a user-space, so you need to make a OS Specific Toolchain before following this tutorial. You also need a C Library, perhaps a homemade one. +

+

Contents

+ +
+

Introduction

+

This tutorial acts as a patch to the original GCC Cross-Compiler article by subtly changing the instructions. The caveats and instructions from it generally apply here, too. You are assumed to be an experienced reader that automatically remembers trivial matters such as adding the cross-compiler prefix bindir to the PATH before building the cross-compiler, or installing the dependencies of Binutils and GCC. +

This article completes the work begun in OS Specific Toolchain by compiling it, thus implementing the next step in Porting GCC to your OS: Teaching GCC what your operating system is and making a cross-compiler for it. +

You will be using a new target triplet, rather than i686-elf, we'll be using your custom i686-myos target. You will be supplying the Binutils and GCC source code yourself rather than using pure upstream releases. +

+

Prerequisites

+

To correctly complete this tutorial, your libc must need particular minimum requirements. The libgcc will be built with libc support, meaning that your libc needs a few standard headers that define particular types, constants and functions. In particular, you need to supply: +

+
  • sys/types.h: This header is just required to exist and can be empty. +
  • errno.h: This header is just required to exist and can be empty. +
  • stdlib.h: abort(), free(), malloc(). +
  • stdio.h: FILE, stderr, fflush(), fprintf(). +
  • string.h: size_t, memcpy, memset(), strlen(). +
  • time.h: This header is just required to exist and can be empty. +
  • unistd.h: This header is just required to exist and can be empty. +
+

Additionally, the all-target-libgcc target also unconditionally builds the libgcov support library, which has these additional requirements: +

+
  • sys/types.h: pid_t. +
  • stdlib.h: atexit(), atoi(), getenv(). +
  • stdio.h: size_t, SEEK_SET, fclose(), fopen(), fread(), fseek(), ftell(), fwrite(), setbuf(), vfprintf(). +
  • string.h: strcpy(). +
  • unistd.h: pid_t, fork(), execv(), execve(), execvp(). +
+

Note how these are statically linked libraries and are not linked. It will do to simply add function prototypes with no implementation (or better yet, a stub implementation, or a real one) and no linker errors will happen unless the relevant parts of libgcc or libgcov are needed. Note how these are just the minimum requirements to get by without any implicit-function-declaration issues; the code is able to use more standard library features if available. +

For the record and convenience, here are minimal headers that satisfies the requirements. +

+

Sysroot Headers

+

Your previous i686-elf toolchain was built using the --without-headers configure option. This tells the compiler that there is no standard library and no headers. The libgcc is built with libc support as described above. This requires the standard library headers to be installed into your system root prior to the cross-compiler build. +

+
cd $HOME/myos
+mkdir -p sysroot
+mkdir -p sysroot/usr/include
+cp -RT libc/include sysroot/usr/include
+cp -RT kernel/include sysroot/usr/include
+

Note: Not all cp(1) implementations support the -RT combination that conveniently merges the contents of one directory into another. +

+

Binutils

+
cd $HOME/src
+mkdir build-binutils
+cd build-binutils
+../myos-binutils/configure --target=i686-myos --prefix="$PREFIX" --with-sysroot=$HOME/myos/sysroot --disable-werror
+make
+make install
+

--with-sysroot= This option tells the compiler where your sysroot is. It is not used during the compilation process, but it is remembered and used when the linker searches for libraries. +

+

GCC

+
cd $HOME/src
+mkdir build-gcc
+cd build-gcc
+../myos-gcc/configure --target=i686-myos --prefix="$PREFIX" --with-sysroot=$HOME/myos/sysroot --enable-languages=c,c++
+make all-gcc all-target-libgcc
+make install-gcc install-target-libgcc
+

--with-sysroot= This option tells the compiler where your sysroot is. It is used during the libgcc build and is remembered and used when the compiler searches for headers and libraries. +

+

libc

+

You can now compile your C Library normally using your fresh, custom cross-compiler. +

+

libstdc++

+

The libstdc++ library was still not built above as it depends on libc as it needs to perform link tests to know about it. The GCC developers have poorly designed the libstdc++ package and it is tied to GCC and must be built as part of GCC, it can't be built on its own without tricks. If you saved your build-gcc directory from earlier, you can continue the process now (otherwise, it will build a full new cross-compiler for no good reason): +

+
cd $HOME/src/build-gcc
+make all-target-libstdc++-v3
+make install-target-libstdc++-v3
+

Troubleshooting

+

In case you get an this error (occurs when using newlib): +

+
./../../../gcc-7.2.0/libstdc++-v3/libsupc++/new_opa.cc:62:1: error: ‘void* aligned_alloc(std::size_t, std::size_t)’ was declared ‘extern’ and later ‘static’ [-fpermissive]
+ aligned_alloc (std::size_t al, std::size_t sz)
+

Open the file libstdc++-v3/libsupc++/new_opa.cc with an editor and remove the "static inline" before in the function prototype. +

+

Conclusion

+

You now have a full i686-myos toolchain that provides a hosted environment producing executables for your user-space. Your program loader will load programs into the current process, set up an initial thread at the program entry point, and the process will perform system calls to cooperate with the kernel. +

You can continue to polish your custom toolchain by teaching it more about your operating system and customizing its behavior to your needs. As your standard library and kernel support improves, you will become able to easily port third party software to your operating system by making third party software use your cross-compiler. +

+

See Also

+

Articles

+ + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ + +
+
Personal tools
+ +
+ + +
+ + +
+
Namespaces
+ +
+ + + + +
+
Variants
+ +
+ + +
+
+ + +
+
Views
+ +
+ + + + +
+
Actions
+ +
+ + + + + + + +
+
+ + +
+ + + + + +
+
Navigation
+ +
+ + + + +
+
About
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + diff --git a/ref/Porting_Newlib.html b/ref/Porting_Newlib.html new file mode 100644 index 0000000..0f4fe17 --- /dev/null +++ b/ref/Porting_Newlib.html @@ -0,0 +1,694 @@ + + + +Porting Newlib - OSDev Wiki + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +

Porting Newlib

+ + +
+ +
From OSDev Wiki
+ + +
+ + +
+ Jump to: navigation, + search +
+ + +
Difficulty level
Difficulty 3.png
Advanced
+

Newlib is a C library intended for use on embedded systems available under a free software license. It is known for being simple to port to new operating systems. Allegedly, it's coding practices are sometimes questionable. This tutorial follows OS Specific Toolchain and completes it using newlib rather than using another C Library such as your own. +

Porting newlib is one of the easiest ways to get a simple C library into your operating system without an excessive amount of effort. As an added bonus, once complete you can port the toolchain (GCC/binutils) to your OS - and who wouldn't want to do that? +

+

Contents

+ +
+

Introduction

+

I decided that after an incredibly difficult week of trying to get newlib ported to my own OS that I would write a tutorial that outlines the requirements for porting newlib and how to actually do it. I'm assuming you can already load binaries from somewhere and that these binaries are compiled C code. I also assume you have a syscall interface setup already. Why wait? Let's get cracking! +

+

Preparation

+

Download newlib source (I'm using 2.5.0) from this ftp server. +


+

+

Download source code of Automake and Autoconf

+

Acquire Automake (v1.12) and Autoconf (v2.65) from here: +[1] +[2] +


+Untar both of the archives: +

+
tar xvf automake-1.12.tar.gz
+tar xvf autoconf-2.65.tar.gz
+

Create a destination folder: +

+
mkdir ~/bin
+

Create a build folder: +

+
mkdir build
+cd build
+

Configure automake first: +

+
../automake-1.12/configure --prefix="~/bin"
+

Make and install +

+
make && make install
+

Now lets configure autoconf +

+
../autoconf-2.65/configure --prefix=~/bin
+

Then make and install: +

+
make && make install
+

You should now have the proper binaries in ~/bin! +

To add these binaries to your path temporarily +

+
export PATH=~/bin:$PATH
+

System Calls

+

First of all you need to support a set of 17 system calls that act as 'glue' between newlib and your OS. These calls are the typical "_exit", "open", "read/write", "execve" (et al). See the Red Hat newlib C library documentation. +

My kernel exposes all the system calls on interrupt 0x80 (128d) so I just had to put a bit of inline assembly into each stub to do what I needed it to do. It's up to you how to implement them in relation to your kernel. +

+

Porting Newlib

+

config.sub

+

Same as for binutils in OS Specific Toolchain. +

+

newlib/configure.host

+

Tell newlib which system-specific directory to use for our particular target. In the section starting 'Get the source directories to use for the host ... case "${host}" in', add a section: +

+
i[3-7]86-*-myos*)
+    sys_dir=myos
+    ;;
+

newlib/libc/sys/configure.in

+

Tell the newlib build system that it also needs to configure our myos-specific host directory. In the case ${sys_dir} in list, simply add +

+
  myos) AC_CONFIG_SUBDIRS(myos) ;;
+

Note: After this, you need to run autoconf (precisely version 2.64) in the libc/sys directory. +

+

newlib/libc/sys/myos

+

This is a directory that we need to create where we put our OS-specific extensions to newlib. We need to create a minimum of 4 files. You can easily add more files to this directory to define your own os-specific library functions, if you want them to be included in libc.a (and so linked in to every application by default). +

+

newlib/libc/sys/myos/crt0.c

+

This file creates crt0.o, which is included in every application. It should define the symbol _start, and then call the main() function, possibly after setting up process-space segment selectors and pushing argc and argv onto the stack. A simple implementation is: +

+
#include <fcntl.h>
+ 
+extern void exit(int code);
+extern int main ();
+ 
+void _start() {
+    int ex = main();
+    exit(ex);
+}
+

Note: add in argc and argv support based on how you handle them in your OS +

+

newlib/libc/sys/myos/syscalls.c

+

This file should contain the implementations for each glue function newlib requires. +

+
/* note these headers are all provided by newlib - you don't need to provide them */
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/times.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <stdio.h>
+ 
+void _exit();
+int close(int file);
+char **environ; /* pointer to array of char * strings that define the current environment variables */
+int execve(char *name, char **argv, char **env);
+int fork();
+int fstat(int file, struct stat *st);
+int getpid();
+int isatty(int file);
+int kill(int pid, int sig);
+int link(char *old, char *new);
+int lseek(int file, int ptr, int dir);
+int open(const char *name, int flags, ...);
+int read(int file, char *ptr, int len);
+caddr_t sbrk(int incr);
+int stat(const char *file, struct stat *st);
+clock_t times(struct tms *buf);
+int unlink(char *name);
+int wait(int *status);
+int write(int file, char *ptr, int len);
+int gettimeofday(struct timeval *p, struct timezone *z);
+

Note: You may split this up into multiple files, just don't forget to link against all of them in Makefile.am. +

+

newlib/libc/sys/myos/configure.in

+

Configure script for our system directory. +

+
AC_PREREQ(2.59)
+AC_INIT([newlib], [NEWLIB_VERSION])
+AC_CONFIG_SRCDIR([crt0.c])
+AC_CONFIG_AUX_DIR(../../../..)
+NEWLIB_CONFIGURE(../../..)
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+

newlib/libc/sys/myos/Makefile.am

+

A Makefile template for this directory: +

+
AUTOMAKE_OPTIONS = cygnus
+INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
+AM_CCASFLAGS = $(INCLUDES)
+ 
+noinst_LIBRARIES = lib.a
+ 
+if MAY_SUPPLY_SYSCALLS
+extra_objs = syscalls.o # add more object files here if you split up
+else                    # syscalls.c into multiple files in the previous step
+extra_objs =
+endif
+ 
+lib_a_SOURCES =
+lib_a_LIBADD = $(extra_objs)
+EXTRA_lib_a_SOURCES = syscalls.c crt0.c # add more source files here if you split up
+lib_a_DEPENDENCIES = $(extra_objs)      # syscalls.c into multiple files
+lib_a_CCASFLAGS = $(AM_CCASFLAGS)
+lib_a_CFLAGS = $(AM_CFLAGS)
+ 
+if MAY_SUPPLY_SYSCALLS
+all: crt0.o
+endif
+ 
+ACLOCAL_AMFLAGS = -I ../../..
+CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
+

Note: After this, you need to run autoconf in the newlib/libc/sys/ directory, and autoreconf in the newlib/libc/sys/myos directory. +

+

Signal handling

+

Newlib has two different mechanisms for dealing with UNIX signals (see the man pages for signal()/raise()). In the first, it provides its own emulation, where it maintains a table of signal handlers in a per-process manner. If you use this method, then you will only be able to respond to signals sent from within the current process. In order to support it, all you need to do is make sure your crt0 calls '_init_signal' before it calls main, which sets up the signal handler table. +

Alternatively, you can provide your own implementation. To do this, you need to define your own version of signal() in syscalls.c. A typical implementation would register the handler somewhere in kernel space, so that issuing a signal from another process causes the corresponding function to be called in the receiving process (this will also require some nifty stack-playing in the receiving process, as you are basically interrupting the program flow in the middle). You then need to provide a kill() function in syscalls.c which actually sends signals to another process. Newlib will still define a raise() function for you, but it is just a stub which calls kill() with the current process id. To switch newlib to this mode, you need to #define the SIGNAL_PROVIDED macro when compiling. A simple way to do this is to add the line: +

+
newlib_cflags="${newlib_cflags} -DSIGNAL_PROVIDED"
+

to your host's entry in configure.host. It would probably also make sense to provide sigaction(), and provide signal() as a wrapper for it. Note that the Open Group's definition of sigaction states that 1) sigaction supersedes signal, and 2) an application designed shouldn't use both to manipulate the same signal. +

+

Compiling

+

You can build newlib in this manner: +Newlib is very pesky about the compiler, and you probably haven't built your own i686-myos-gcc toolchain yet, meaning that configure will not be happy when you set target to i686-myos. So use this hack to get it to work (it worked fine for me). +

Note: there must be a better way then this. +

+
# newlib setup
+CURRDIR=$(pwd)
+ 
+# make symlinks (a bad hack) to make newlib work
+cd ~/cross/bin/ # this is where the bootstrapped generic cross compiler toolchain (i686-elf-xxx) is installed in,
+                # change this based on your development environment.
+ln i686-elf-ar i686-myos-ar
+ln i686-elf-as i686-myos-as
+ln i686-elf-gcc i686-myos-gcc
+ln i686-elf-gcc i686-myos-cc
+ln i686-elf-ranlib i686-myos-ranlib
+ 
+# return
+cd $CURRDIR
+

Then run the following commands to build newlib +

+
mkdir build-newlib
+cd build-newlib
+../newlib-x.y.z/configure --prefix=/usr --target=i686-myos
+make all
+make DESTDIR=${SYSROOT} install
+

Note: SYSROOT is where all your OS-specific toolchains will be installed in. It will look like a miniature version of the Linux filesystem, but have your OS-specific toolchains in; I am using ~/myos as my SYSROOT directory. +

For some reason, the newer versions of newlib (at least for me) didn't put the libraries in a location where other utilities like binutils could find. +So here's another hack to fix this: +

+
cp -ar $SYSROOT/usr/i386-myos/* $SYSROOT/usr/
+

After building all of this, your freshly built libc will be installed in your SYSROOT directory! Now you can progress to building your own OS Specific Toolchain. +

Important Note: I found that for newlib to properly work, you have to link against libc, libg, libm, and libnosys - hence when porting gcc, in +

+
#define LIB_SPEC ...
+

in gcc/config/myos.h, +

make sure you put +

+
#define LIB_SPEC "-lc -lg -lm -lnosys"
+

at the bare minimum. +

I highly recommend rebuilding the library with your OS Specific Toolchain after you are done porting one. (don't forget to remove the symlinks, too.) +

+

Conclusion

+

Well, you've done it. You've ported newlib to your OS! With this you can start creating user mode programs with ease! You may now also add in new functions to newlib, such as dlopen(), dlclose(), dlsym(), and dlerror() for dynamic linking support. Your operating system has a bright road ahead! You can now port the toolchain and run binutils and GCC on your own OS. Almost self-hosting, how do you feel? +

Good luck! +

Last Updated by 0fb1d8 for compatibility with newer versions of newlib and the OS Specific Toolchain tutorial. +

Note: I used a lot of hacks in this article, if you find a better way to do something, please contribute to the page. Thank you. +

+

See Also

+

Articles

+ + + + + +
+ + + + + +
+ + +
+ +
+ + +
+ + +
+
Personal tools
+ +
+ + +
+ + +
+
Namespaces
+ +
+ + + + +
+
Variants
+ +
+ + +
+
+ + +
+
Views
+ +
+ + + + +
+
Actions
+ +
+ + + + + + + +
+
+ + +
+ + + + + +
+
Navigation
+ +
+ + + + +
+
About
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + diff --git a/ref/README b/ref/README new file mode 100644 index 0000000..70d9e39 --- /dev/null +++ b/ref/README @@ -0,0 +1 @@ +https://wiki.osdev.org/ diff --git a/userspace/Makefile b/userspace/Makefile index f7d0ae5..dc5509c 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -1,4 +1,4 @@ -IMAGESIZE=40000 #ext2.img size in Kb +IMAGESIZE=60000 #ext2.img size in Kb ####################### @@ -36,6 +36,7 @@ ext2.img: $(PROGS) make -C fonts make -C xterm make -C cpp + make -C ncurses @echo "----------------------" @echo "Creating ext2.img ...." @dd if=/dev/zero of=ext2.img bs=1024 count=$(IMAGESIZE) @@ -54,6 +55,8 @@ ext2.img: $(PROGS) @cp fonts/binfont.bin mnt/doc/fonts @cp xterm/xterm mnt/bin @cp cpp/testcpp mnt/bin + @cp ncurses/ncurs mnt/bin + @cp /home/miguel/temp/foolos/usr/bin/* mnt/bin # cp ~/temp/fool-os-stuff/binutils-build-host-foolos/binutils/readelf mnt/bin # cp ../font/binfont.bin mnt/ @@ -77,6 +80,11 @@ clean: make -C fonts clean make -C xterm clean make -C cpp clean + make -C ncurses clean @echo "Cleaning userspace ..."; rm -f *.o $(PROGS) ext2.img *.d +umount: + sudo umount mnt + rm mnt -r + new: clean all diff --git a/userspace/clear.c b/userspace/clear.c deleted file mode 100644 index 1c794b8..0000000 --- a/userspace/clear.c +++ /dev/null @@ -1,9 +0,0 @@ -/** clear our console */ - -#include -int main() -{ - printf("\033c"); - fflush(stdout); // force printing to console - return 0; -} diff --git a/userspace/myclear.c b/userspace/myclear.c new file mode 100644 index 0000000..1c794b8 --- /dev/null +++ b/userspace/myclear.c @@ -0,0 +1,9 @@ +/** clear our console */ + +#include +int main() +{ + printf("\033c"); + fflush(stdout); // force printing to console + return 0; +} diff --git a/userspace/ncurses/Makefile b/userspace/ncurses/Makefile new file mode 100644 index 0000000..4a8fc56 --- /dev/null +++ b/userspace/ncurses/Makefile @@ -0,0 +1,10 @@ +CC=i686-foolos-gcc +AS=i686-foolos-as + +LDLIBS=-lncurses -lcurses +CFLAGS=-static + +ncurs: + +clean: + rm -f *.o ncurs diff --git a/userspace/ncurses/ncurs.c b/userspace/ncurses/ncurs.c new file mode 100644 index 0000000..6edf8e6 --- /dev/null +++ b/userspace/ncurses/ncurs.c @@ -0,0 +1,13 @@ +#include + +int main() +{ + +// initscr(); /* Start curses mode */ +// printw("Hello World !!!"); /* Print Hello World */ +// refresh(); /* Print it on to the real screen */ +// getch(); /* Wait for user input */ +// endwin(); /* End curses mode */ + + return 0; +} diff --git a/xxx/packages/ncurses-5.9/termios.h b/xxx/packages/ncurses-5.9/termios.h index 98ae1b7..e38434d 100644 --- a/xxx/packages/ncurses-5.9/termios.h +++ b/xxx/packages/ncurses-5.9/termios.h @@ -25,7 +25,7 @@ struct __dirstream //https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/dirstream.h;h=8303f07fab6f6efaa39e51411ef924e712d995e0;hb=fa39685d5c7df2502213418bead44e9543a9b9ec }; -typedef uint32_t __ino_t; +//typedef uint32_t __ino_t; struct dirent { @@ -36,19 +36,19 @@ struct dirent char d_name[256]; /* We must not include limits.h! */ int d_namlen; }; -#define direct dirent +#define direct dirent typedef struct __dirstream DIR; #include - typedef unsigned char cc_t; typedef unsigned int speed_t; typedef unsigned int tcflag_t; #define NCCS 32 + struct termios { tcflag_t c_iflag; /* input mode flags */ @@ -242,8 +242,8 @@ struct termios #define _IOT_termios /* Hurd ioctl type field. */ \ _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) - int tcgetattr(int fd, struct termios *termios_p); - int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); + // int tcgetattr(int fd, struct termios *termios_p); + // int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); /** int tcsendbreak(int fd, int duration); @@ -254,13 +254,13 @@ struct termios int tcflow(int fd, int action); */ - void cfmakeraw(struct termios *termios_p); + // void cfmakeraw(struct termios *termios_p); /* speed_t cfgetispeed(const struct termios *termios_p); */ - speed_t cfgetospeed(const struct termios *termios_p); +// speed_t cfgetospeed(const struct termios *termios_p); /* int cfsetispeed(struct termios *termios_p, speed_t speed); -- cgit v1.2.3