[libc][picolibc] improve gcc picolibc support
This commit is contained in:
parent
063c8f7bec
commit
da55491608
|
@ -1,10 +1,16 @@
|
|||
import os
|
||||
from building import *
|
||||
from llvm_arm import *
|
||||
Import('rtconfig')
|
||||
|
||||
group = []
|
||||
|
||||
if rtconfig.PLATFORM == 'gcc':
|
||||
from gcc import *
|
||||
elif rtconfig.PLATFORM == 'llvm-arm':
|
||||
from llvm_arm import *
|
||||
else:
|
||||
Return('group')
|
||||
|
||||
picolibc_version = GetPicoLibcVersion(rtconfig)
|
||||
|
||||
if picolibc_version and not GetDepend('RT_USING_EXTERNAL_LIBC'):
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* for exit() and abort() */
|
||||
rt_noreturn void _exit (int status)
|
||||
{
|
||||
extern void __rt_libc_exit(int status);
|
||||
__rt_libc_exit(status);
|
||||
while(1);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-02 Meco Man First version
|
||||
*/
|
||||
|
||||
#ifndef __FCNTL_H__
|
||||
#define __FCNTL_H__
|
||||
|
||||
#include <sys/_default_fcntl.h>
|
||||
|
||||
#ifndef O_EXEC
|
||||
#define O_EXEC 0x400000
|
||||
#endif
|
||||
|
||||
#ifndef O_TMPFILE
|
||||
#define O_TMPFILE 0x800000
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0x10000
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0x100000
|
||||
#endif
|
||||
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 0x200000
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifdef RT_USING_POSIX_STDIO
|
||||
#include <posix/stdio.h>
|
||||
#endif /* RT_USING_POSIX_STDIO */
|
||||
#define DBG_TAG "picolibc.iob"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#ifdef TINY_STDIO
|
||||
|
||||
static int __fputc(char c, FILE *file);
|
||||
static int __fgetc(FILE *file);
|
||||
|
||||
static FILE __stdio_in = FDEV_SETUP_STREAM(NULL, __fgetc, NULL, _FDEV_SETUP_READ);
|
||||
static FILE __stdio_out = FDEV_SETUP_STREAM(__fputc, NULL, NULL, _FDEV_SETUP_WRITE);
|
||||
|
||||
#ifdef __strong_reference
|
||||
#define STDIO_ALIAS(x) __strong_reference(stdout, x);
|
||||
#else
|
||||
#define STDIO_ALIAS(x) FILE *const x = &__stdio_out;
|
||||
#endif
|
||||
|
||||
FILE *const stdin = &__stdio_in;
|
||||
FILE *const stdout = &__stdio_out;
|
||||
STDIO_ALIAS(stderr);
|
||||
|
||||
static int __fputc(char c, FILE *file)
|
||||
{
|
||||
if (file == &__stdio_out)
|
||||
{
|
||||
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
|
||||
rt_device_t console = rt_console_get_device();
|
||||
if (console)
|
||||
{
|
||||
rt_ssize_t rc = rt_device_write(console, -1, &c, 1);
|
||||
return rc > 0 ? rc : -1;
|
||||
}
|
||||
#endif /* defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __fgetc(FILE *file)
|
||||
{
|
||||
if (file == &__stdio_in)
|
||||
{
|
||||
#ifdef RT_USING_POSIX_STDIO
|
||||
if (rt_posix_stdio_get_console() >= 0)
|
||||
{
|
||||
char c;
|
||||
int rc = read(STDIN_FILENO, &c, 1);
|
||||
return rc == 1 ? c : EOF;
|
||||
}
|
||||
#endif /* RT_USING_POSIX_STDIO */
|
||||
}
|
||||
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#endif
|
116
tools/gcc.py
116
tools/gcc.py
|
@ -20,10 +20,12 @@
|
|||
# Change Logs:
|
||||
# Date Author Notes
|
||||
# 2018-05-22 Bernard The first version
|
||||
# 2023-11-03 idings return file path in GetHeader
|
||||
|
||||
import os
|
||||
import re
|
||||
import platform
|
||||
import subprocess
|
||||
|
||||
def GetGCCRoot(rtconfig):
|
||||
exec_path = rtconfig.EXEC_PATH
|
||||
|
@ -39,12 +41,68 @@ def GetGCCRoot(rtconfig):
|
|||
|
||||
return root_path
|
||||
|
||||
def CheckHeader(rtconfig, filename):
|
||||
root = GetGCCRoot(rtconfig)
|
||||
# https://stackoverflow.com/questions/4980819/what-are-the-gcc-default-include-directories
|
||||
# https://stackoverflow.com/questions/53937211/how-can-i-parse-gcc-output-by-regex-to-get-default-include-paths
|
||||
def match_pattern(pattern, input, start = 0, stop = -1, flags = 0):
|
||||
length = len(input)
|
||||
|
||||
if length == 0:
|
||||
return None
|
||||
|
||||
end_it = max(0, length - 1)
|
||||
|
||||
if start >= end_it:
|
||||
return None
|
||||
|
||||
if stop<0:
|
||||
stop = length
|
||||
|
||||
if stop <= start:
|
||||
return None
|
||||
|
||||
for it in range(max(0, start), min(stop, length)):
|
||||
elem = input[it]
|
||||
match = re.match(pattern, elem, flags)
|
||||
if match:
|
||||
return it
|
||||
|
||||
def GetGccDefaultSearchDirs(rtconfig):
|
||||
start_pattern = r' *#include <\.\.\.> search starts here: *'
|
||||
end_pattern = r' *End of search list\. *'
|
||||
|
||||
gcc_cmd = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC)
|
||||
device_flags = rtconfig.DEVICE.split()
|
||||
args = [gcc_cmd] + device_flags + ['-xc', '-E', '-v', os.devnull]
|
||||
|
||||
proc = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||
lines = proc.stdout.splitlines()
|
||||
|
||||
start_it = match_pattern(start_pattern, lines)
|
||||
if start_it == None:
|
||||
return []
|
||||
|
||||
end_it = match_pattern(end_pattern, lines, start_it)
|
||||
if end_it == None:
|
||||
return []
|
||||
|
||||
# theres no paths between them
|
||||
if (end_it - start_it) == 1:
|
||||
return []
|
||||
|
||||
return lines[start_it + 1 : end_it]
|
||||
|
||||
def GetHeader(rtconfig, filename):
|
||||
include_dirs = GetGccDefaultSearchDirs(rtconfig)
|
||||
for directory in include_dirs:
|
||||
fn = os.path.join(directory, filename).strip()
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
|
||||
# fallback to use fixed method if can't autodetect
|
||||
root = GetGCCRoot(rtconfig)
|
||||
fn = os.path.join(root, 'include', filename)
|
||||
if os.path.isfile(fn):
|
||||
return True
|
||||
return fn
|
||||
|
||||
# Usually the cross compiling gcc toolchain has directory as:
|
||||
#
|
||||
|
@ -62,14 +120,34 @@ def CheckHeader(rtconfig, filename):
|
|||
|
||||
fn = os.path.join(root, prefix, 'include', filename)
|
||||
if os.path.isfile(fn):
|
||||
return True
|
||||
return fn
|
||||
|
||||
return False
|
||||
return None
|
||||
|
||||
# GCC like means the toolchains which are compatible with GCC
|
||||
def GetGCCLikePLATFORM():
|
||||
return ['gcc', 'armclang', 'llvm-arm']
|
||||
|
||||
def GetPicoLibcVersion(rtconfig):
|
||||
version = None
|
||||
try:
|
||||
rtconfig.PREFIX
|
||||
except:
|
||||
return version
|
||||
|
||||
# get version from picolibc.h
|
||||
fn = GetHeader(rtconfig, 'picolibc.h')
|
||||
|
||||
if fn:
|
||||
f = open(fn, 'r')
|
||||
if f:
|
||||
for line in f:
|
||||
if line.find('__PICOLIBC_VERSION__') != -1 and line.find('"') != -1:
|
||||
version = re.search(r'\"([^"]+)\"', line).groups()[0]
|
||||
f.close()
|
||||
|
||||
return version
|
||||
|
||||
def GetNewLibVersion(rtconfig):
|
||||
version = None
|
||||
|
||||
|
@ -78,21 +156,25 @@ def GetNewLibVersion(rtconfig):
|
|||
except:
|
||||
return version
|
||||
|
||||
root = GetGCCRoot(rtconfig)
|
||||
if CheckHeader(rtconfig, '_newlib_version.h'): # get version from _newlib_version.h file
|
||||
f = open(os.path.join(root, 'include', '_newlib_version.h'), 'r')
|
||||
if f:
|
||||
for line in f:
|
||||
if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
|
||||
version = re.search(r'\"([^"]+)\"', line).groups()[0]
|
||||
f.close()
|
||||
elif CheckHeader(rtconfig, 'newlib.h'): # get version from newlib.h
|
||||
f = open(os.path.join(root, 'include', 'newlib.h'), 'r')
|
||||
if f:
|
||||
# if find picolibc.h, use picolibc
|
||||
fn = GetHeader(rtconfig, 'picolibc.h')
|
||||
if fn:
|
||||
return version
|
||||
|
||||
# get version from _newlib_version.h file
|
||||
fn = GetHeader(rtconfig, '_newlib_version.h')
|
||||
|
||||
# get version from newlib.h
|
||||
if not fn:
|
||||
fn = GetHeader(rtconfig, 'newlib.h')
|
||||
|
||||
if fn:
|
||||
f = open(fn, 'r')
|
||||
for line in f:
|
||||
if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
|
||||
version = re.search(r'\"([^"]+)\"', line).groups()[0]
|
||||
f.close()
|
||||
|
||||
return version
|
||||
|
||||
# FIXME: there is no musl version or musl macros can be found officially
|
||||
|
@ -109,8 +191,6 @@ def GetMuslVersion(rtconfig):
|
|||
return version
|
||||
|
||||
def GCCResult(rtconfig, str):
|
||||
import subprocess
|
||||
|
||||
result = ''
|
||||
|
||||
def checkAndGetResult(pattern, string):
|
||||
|
|
Loading…
Reference in New Issue