feat(coreutils): implement coreutils and compile it using cmake

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-10 02:29:14 +00:00
parent 88a3b0912b
commit 87540ab0b9
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
9 changed files with 322 additions and 2 deletions

View File

@ -20,7 +20,8 @@
"userspace/libs",
"userspace/apps/test",
"userspace/apps/usr",
"userspace"
"userspace",
"coreutils"
]
}
}

View File

@ -11,3 +11,7 @@ indent_size = 4
[Makefile]
indent_style = tab
[{CMakeLists.txt,*.cmake}]
indent_size = 2
indent_style = space

View File

@ -160,5 +160,30 @@
"*/"
],
"description": "Create libc license."
},
"Core Utilities License": {
"isFileTemplate": true,
"prefix": [
"license_coreutils",
],
"body": [
"/*",
"\tThis file is part of Fennix Core Utilities.",
"",
"\tFennix Core Utilities is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix Core Utilities is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create coreutils license."
}
}

View File

@ -4,6 +4,7 @@
"name": "Fennix x64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@ -45,6 +46,7 @@
"name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@ -86,6 +88,7 @@
"name": "Fennix Arm (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@ -107,6 +110,7 @@
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/libc/include/**",
"${workspaceFolder}/coreutils/include/**",
"${workspaceFolder}/libs/include/**"
],
"defines": [
@ -126,4 +130,4 @@
}
],
"version": 4
}
}

View File

@ -37,9 +37,22 @@ create_out:
mkdir -p out/usr/include
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
build_coreutils:
mkdir -p cache/coreutils
cd cache/coreutils && \
cmake $(WORKSPACE_DIR)/coreutils \
-DCMAKE_INSTALL_PREFIX:PATH=$(WORKSPACE_DIR)/out \
-DCMAKE_SYSROOT=$(WORKSPACE_DIR)/out \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
&& \
make -j$(shell nproc) && \
make install
build: create_out
make -C libc build
make -C libs build
$(MAKE) build_coreutils
make -C apps build
prepare:

1
Userspace/coreutils/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.10)
project(FennixCoreUtilities VERSION 1.0.0)
if(NOT DEFINED ENV{WORKSPACE_DIR})
set(STANDALONE_BUILD ON)
message(STATUS "Compiling standalone")
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
endif()
set(CMAKE_C_COMPILER "$ENV{CC}")
set(CMAKE_CXX_COMPILER "$ENV{CXX}")
set(CMAKE_ASM_COMPILER "$ENV{AS}")
set(CMAKE_AR "$ENV{AR}")
set(CMAKE_LINKER "$ENV{LD}")
if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
else()
set(CMAKE_C_FLAGS "-O2")
endif()
include_directories(${CMAKE_SOURCE_DIR}/include)
file(GLOB SINGLE_SOURCE "src/*.c")
foreach(file ${SINGLE_SOURCE})
get_filename_component(name ${file} NAME_WE)
add_executable(${name} ${file})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()
file(GLOB_RECURSE GROUP_SOURCES "src/*/*.c")
foreach(file ${GROUP_SOURCES})
get_filename_component(name ${file} DIRECTORY)
get_filename_component(name ${name} NAME)
list(APPEND GROUP_MAP_${name} ${file})
endforeach()
foreach(name IN LISTS GROUP_MAP_)
add_executable(${name} ${GROUP_MAP_${name}})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COREUTILS_H
#define _COREUTILS_H
#ifndef PROGRAM_NAME
#define PROGRAM_NAME "<unknown>"
#endif
#ifndef PROGRAM_VERSION
#define PROGRAM_VERSION "<unknown>"
#endif
#define BUILD_YEAR (__DATE__ + 7)
#define PRINTF_VERSION \
printf("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); \
printf("Fennix Core Utilities Copyright (C) %s EnderIce2\n", BUILD_YEAR); \
printf("This program comes with ABSOLUTELY NO WARRANTY\n"); \
printf("This is free software, and you are welcome to redistribute it\n"); \
printf("under certain conditions\n")
#endif // _COREUTILS_H

View File

@ -0,0 +1,183 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <coreutils.h>
void PrintHelp()
{
printf("Usage: echo [OPTION]... [STRING]...\n");
printf("Echo the STRING(s) to standard output.\n\n");
printf(" -n do not output the trailing newline\n");
printf(" -e enable interpretation of backslash escapes\n");
printf(" -E disable interpretation of backslash escapes (default)\n");
printf(" --help display this help and exit\n");
printf(" --version output version information and exit\n\n");
printf("If -e is specified, the following sequences are recognized:\n");
printf(" \\\\ backslash\n");
printf(" \\a alert (BEL)\n");
printf(" \\b backspace\n");
printf(" \\c produce no further output\n");
printf(" \\e escape\n");
printf(" \\f form feed\n");
printf(" \\n new line\n");
printf(" \\r carriage return\n");
printf(" \\t horizontal tab\n");
printf(" \\v vertical tab\n");
}
static void PrintEscaped(const char *str)
{
while (*str)
{
if (*str == '\\')
{
str++;
switch (*str)
{
case 'n':
putchar('\n');
break;
case 't':
putchar('\t');
break;
case '\\':
putchar('\\');
break;
case 'a':
putchar('\a');
break;
case 'b':
putchar('\b');
break;
case 'r':
putchar('\r');
break;
case 'v':
putchar('\v');
break;
case 'f':
putchar('\f');
break;
case '0' ... '7':
{
int octal = 0;
for (int i = 0; i < 3 && *str >= '0' && *str <= '7'; i++, str++)
{
octal = octal * 8 + (*str - '0');
}
putchar(octal);
str--;
break;
}
case 'x':
{
int hex = 0;
str++;
for (int i = 0; i < 2 && ((*str >= '0' && *str <= '9') ||
(*str >= 'a' && *str <= 'f') ||
(*str >= 'A' && *str <= 'F'));
i++, str++)
{
if (*str >= '0' && *str <= '9')
hex = hex * 16 + (*str - '0');
else if (*str >= 'a' && *str <= 'f')
hex = hex * 16 + (*str - 'a' + 10);
else if (*str >= 'A' && *str <= 'F')
hex = hex * 16 + (*str - 'A' + 10);
}
putchar(hex);
str--;
break;
}
default:
putchar(*str);
break;
}
}
else
{
putchar(*str);
}
str++;
}
}
int main(int argc, char *argv[])
{
bool newline = true;
bool interpret_escapes = false;
int arg_start = 1;
if (argc == 2)
{
if (strcmp(argv[1], "--help") == 0)
{
PrintHelp();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[1], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
}
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-' && argv[i][1] != '\0')
{
for (size_t j = 1; argv[i][j] != '\0'; j++)
{
if (argv[i][j] == 'n')
newline = false;
else if (argv[i][j] == 'e')
interpret_escapes = true;
else if (argv[i][j] == 'E')
interpret_escapes = false;
else
goto print_args;
}
arg_start++;
}
else
{
break;
}
}
}
print_args:
for (int i = arg_start; i < argc; i++)
{
if (interpret_escapes)
PrintEscaped(argv[i]);
else
fputs(argv[i], stdout);
if (i < argc - 1)
putchar(' ');
}
if (newline)
putchar('\n');
return 0;
}