meta: replace cmake mono-build system with a custom build co-ordinator
every system component now has its own self-contained build system, and a seed file describing the component and its build system and dependencies. a new tool, meadow, collects and uses these seed files to build the components into a full system. meadow also manages the target system root and a host prefix where toolchain tools are installed to. the build system has also been updated to use a new $ARCH-rosetta-gcc compiler, and the patches files necessary to build it have been added to toolchain/cross-compiler.
This commit is contained in:
+2
-2
@@ -243,7 +243,6 @@ docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
@@ -341,5 +340,6 @@ pyrightconfig.json
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/c,vim,linux,macos,windows,cmake,python
|
||||
|
||||
build*
|
||||
build
|
||||
build-native
|
||||
.cache
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
set(CMAKE_SYSTEM_NAME Rosetta)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
#set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
|
||||
set(CMAKE_C_COMPILER_WORKS TRUE)
|
||||
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||
|
||||
find_program(C_COMPILER x86_64-elf-gcc REQUIRED)
|
||||
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
||||
find_program(C_COMPILER x86_64-rosetta-gcc REQUIRED)
|
||||
find_program(CXX_COMPILER x86_64-rosetta-g++ REQUIRED)
|
||||
#find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
||||
|
||||
add_compile_definitions(__magenta__=1 __rosetta__=1)
|
||||
@@ -13,17 +15,45 @@ set(CMAKE_C_COMPILER ${C_COMPILER})
|
||||
set(CMAKE_CXX_COMPILER ${CXX_COMPILER})
|
||||
#set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
|
||||
|
||||
SET(CMAKE_C_FLAGS "-ffreestanding -nostdlib -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234" CACHE STRING "" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-shared" CACHE STRING "" FORCE)
|
||||
SET(CMAKE_C_FLAGS "-z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234" CACHE STRING "" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-shared" CACHE STRING "" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--unresolved-symbols=report-all,--dynamic-linker=/lib/ld64.so" CACHE STRING "" FORCE)
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "-pie")
|
||||
set(CMAKE_C_LINK_PIE_SUPPORTED TRUE)
|
||||
set(CMAKE_C_LINK_NO_PIE_SUPPORTED TRUE)
|
||||
SET(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
|
||||
|
||||
if ("$ENV{ROSETTA_SYSROOT}" STREQUAL "")
|
||||
message(FATAL_ERROR "No system root has been specified. Please define the $ROSETTA_SYSROOT environment variable")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_SYSROOT $ENV{ROSETTA_SYSROOT})
|
||||
set(CMAKE_SYSTEM_LIBRARY_PATH
|
||||
$ENV{ROSETTA_SYSROOT}/lib
|
||||
$ENV{ROSETTA_SYSROOT}/usr/lib)
|
||||
|
||||
set(CMAKE_C_OUTPUT_EXTENSION .o)
|
||||
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
|
||||
set(CMAKE_DL_LIBS "dl")
|
||||
set(CMAKE_INSTALL_RPATH \$ORIGIN/../lib)
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
#set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
|
||||
#set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
|
||||
set(CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "\$ORIGIN")
|
||||
set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link,")
|
||||
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
|
||||
set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic")
|
||||
|
||||
set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
|
||||
set(CMAKE_C_LINK_GROUP_USING_cross_refs
|
||||
"LINKER:--start-group"
|
||||
"LINKER:--end-group"
|
||||
)
|
||||
|
||||
set(CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME 1)
|
||||
|
||||
link_libraries(-lgcc)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[seed]
|
||||
name = 'cdrom'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,5 @@
|
||||
[command]
|
||||
name = 'debug'
|
||||
description = 'Run the system under a debugger'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,12 @@
|
||||
[command]
|
||||
name = 'run-kernel'
|
||||
description = 'Run the kernel image directly under QEMU'
|
||||
|
||||
[dependency]
|
||||
commands = [ 'qemu-system-x86_64' ]
|
||||
seeds = [ 'magenta', 'bsp' ]
|
||||
|
||||
[exec]
|
||||
args = [ 'src:run-kernel.py']
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,30 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
sysroot = os.environ['MEADOW_SYSROOT']
|
||||
native_root = os.environ['MEADOW_NATIVE_ROOT']
|
||||
tmp = os.environ['MEADOW_TEMP']
|
||||
|
||||
bsp = os.path.join(sysroot, 'boot', 'rosetta-system.bsp')
|
||||
kernel_exe = os.path.join(sysroot, 'boot', 'magenta_kernel')
|
||||
kernel_exe_elf32 = os.path.join(tmp, 'magenta_kernel.elf32')
|
||||
e64patch = os.path.join(native_root, 'bin', 'e64patch')
|
||||
|
||||
shutil.copyfile(kernel_exe, kernel_exe_elf32)
|
||||
subprocess.run([ e64patch, kernel_exe_elf32 ])
|
||||
|
||||
qemu_args = [
|
||||
'qemu-system-x86_64',
|
||||
'-m', '128M',
|
||||
'-cpu', 'qemu64,+rdrand',
|
||||
'-kernel', kernel_exe_elf32,
|
||||
'-initrd', bsp,
|
||||
'-serial', 'stdio',
|
||||
'--append', 'kernel.early-console=ttyS0'
|
||||
]
|
||||
|
||||
try:
|
||||
subprocess.run(qemu_args)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
@@ -0,0 +1,19 @@
|
||||
[platform]
|
||||
name = 'x86_64-pc'
|
||||
arch = 'x86_64'
|
||||
|
||||
[cmake]
|
||||
module_paths = [ '.' ]
|
||||
system_name = 'Rosetta'
|
||||
toolchain_file = 'Platform/Rosetta.cmake'
|
||||
|
||||
[extension]
|
||||
commands = [
|
||||
'command/run-kernel.command',
|
||||
]
|
||||
|
||||
seeds = [
|
||||
'cdrom.seed'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'base'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'source-only'
|
||||
build_for = 'target'
|
||||
watch_files = [ 'src:**' ]
|
||||
|
||||
[install]
|
||||
"/" = [ 'src:boot' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -37,6 +37,7 @@ function(add_interface)
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_dependencies(iflib-${arg_NAME} ifgen-${arg_NAME})
|
||||
add_library(interface::${arg_NAME} ALIAS iflib-${arg_NAME})
|
||||
install(FILES ${header_path} DESTINATION include/${arg_PARENT_DIR})
|
||||
endfunction(add_interface)
|
||||
|
||||
function(iface_get_header_path)
|
||||
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
[seed]
|
||||
name = 'libmagenta'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
source_dir = 'kernel/libmagenta'
|
||||
watch_files = [ 'src:**/*.c', 'src:**/*.h' ]
|
||||
|
||||
# vim: ft=toml
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
[seed]
|
||||
name = 'magenta-headers'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'source-only'
|
||||
build_for = 'target'
|
||||
source_dir = 'kernel/libmagenta'
|
||||
watch_files = [
|
||||
'src:include/magenta/*.h',
|
||||
'src:include-user/magenta/*.h',
|
||||
]
|
||||
|
||||
[install]
|
||||
"/usr/include/magenta" = [
|
||||
'src:include/magenta/*.h',
|
||||
'src:include-user/magenta/*.h',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'magenta-tools'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_for = 'host'
|
||||
build_system = 'cmake'
|
||||
source_dir = 'kernel/tools'
|
||||
|
||||
[publish]
|
||||
path = [ 'install:bin/' ]
|
||||
|
||||
# vim: ft=toml
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
[seed]
|
||||
name = 'magenta'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'magenta-tools'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
source_dir = 'kernel'
|
||||
watch_files = [ 'src:**/*.c', 'src:**/*.h' ]
|
||||
|
||||
[install]
|
||||
prefix = "/"
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,7 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(rosetta-interface)
|
||||
|
||||
include(Msg-Interface)
|
||||
|
||||
file(GLOB if_files *.xpc)
|
||||
|
||||
foreach (file ${if_files})
|
||||
get_filename_component(name ${file} NAME_WLE)
|
||||
add_interface(NAME ${name} PATH ${file} PARENT_DIR rosetta)
|
||||
sysroot_add_interface(NAME ${name} DEST_DIR /usr/include)
|
||||
endforeach (file)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[seed]
|
||||
name = 'librosetta-interface'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [ 'xpcg' ]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
watch_files = [ 'src:*.xpc' ]
|
||||
module_paths = [ 'root-src:cmake/' ]
|
||||
|
||||
# vim: ft=toml
|
||||
+1
-1
Submodule kernel updated: bd6872d672...a14d0173c8
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'libfx-host'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_for = 'host'
|
||||
build_system = 'cmake'
|
||||
source_dir = 'lib/libfx'
|
||||
|
||||
[publish.cmake]
|
||||
module_paths = [ 'src:cmake/' ]
|
||||
|
||||
# vim: ft=toml
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
[seed]
|
||||
name = 'libfx'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
source_dir = 'lib/libfx'
|
||||
configure_args = [
|
||||
'-Dfx_assemblies=fx.runtime;fx.collections;fx.serial;fx.io;fx.term;fx.cmdline',
|
||||
'-Dfx_enable_floating_point=0',
|
||||
'-Dfx_enable_tests=0',
|
||||
]
|
||||
|
||||
[publish.cmake]
|
||||
module_paths = [ 'src:cmake/' ]
|
||||
|
||||
# vim: ft=toml
|
||||
+12
-21
@@ -1,10 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc C ASM)
|
||||
|
||||
set(source_dirs core malloc io exec)
|
||||
|
||||
set(LIBC_STANDALONE FALSE)
|
||||
set(public_include_dirs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
add_subdirectory(runtime)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
add_subdirectory(${dir})
|
||||
set(sources ${sources} ${component_sources})
|
||||
@@ -12,22 +14,11 @@ foreach (dir ${source_dirs})
|
||||
set(public_include_dirs ${public_include_dirs} ${component_public_include_dirs})
|
||||
endforeach (dir)
|
||||
|
||||
rosetta_add_library(SHARED
|
||||
NAME libc
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
bsp_add_library(
|
||||
NAME libc
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc PRIVATE librosetta libxpc-static liblaunch-static interface::fs)
|
||||
target_link_libraries(libc PUBLIC libmagenta)
|
||||
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1)
|
||||
|
||||
add_subdirectory(pthread)
|
||||
add_library(libc SHARED ${sources} ${headers})
|
||||
target_include_directories(libc PUBLIC ${public_include_dirs})
|
||||
target_link_libraries(libc PRIVATE rosetta libxpc.a liblaunch.a libmagenta.a)
|
||||
target_compile_options(libc PRIVATE -ffreestanding -nostdlib)
|
||||
target_link_options(libc PRIVATE -ffreestanding -nostdlib)
|
||||
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_SHARED=1)
|
||||
set_target_properties(libc PROPERTIES PREFIX "")
|
||||
install(TARGETS libc)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
if (LIBC_STANDALONE)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-core C ASM)
|
||||
endif ()
|
||||
|
||||
set(source_dirs assert stdio stdlib string errno ctype wctype unistd)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
@@ -12,18 +17,16 @@ file(GLOB sys_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
|
||||
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-core
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources} ${sys_sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-core
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
if (NOT LIBC_STANDALONE)
|
||||
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
add_library(libc-core STATIC ${sources} ${sys_sources} ${headers})
|
||||
target_include_directories(libc-core PUBLIC ${public_include_dirs})
|
||||
target_link_libraries(libc-core PRIVATE libmagenta librosetta)
|
||||
target_compile_definitions(libc-core PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||
set_target_properties(libc-core PROPERTIES
|
||||
PREFIX "")
|
||||
install(TARGETS libc-core)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
[seed]
|
||||
name = 'libc-core'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libc-headers',
|
||||
'libmagenta',
|
||||
'librosetta'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DLIBC_STANDALONE=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,5 +1,10 @@
|
||||
set(source_dirs unistd spawn)
|
||||
|
||||
if (LIBC_STANDALONE)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-exec C ASM)
|
||||
endif ()
|
||||
|
||||
file(GLOB sources *.c *.h)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
@@ -13,21 +18,17 @@ endforeach (dir)
|
||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||
set(headers ${headers} ${sub_headers})
|
||||
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
if (NOT LIBC_STANDALONE)
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
endif ()
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-exec
|
||||
PUBLIC_INCLUDE_DIRS
|
||||
add_library(libc-exec STATIC ${sources} ${headers})
|
||||
target_include_directories(libc-exec PUBLIC
|
||||
${public_include_dirs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-exec
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_link_libraries(libc-exec libc-core libc-io libmagenta liblaunch-static)
|
||||
target_compile_definitions(libc-exec PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||
set_target_properties(libc-exec PROPERTIES PREFIX "")
|
||||
install(TARGETS libc-exec)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
[seed]
|
||||
name = 'libc-exec'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libc-core',
|
||||
'libc-io',
|
||||
'libmagenta',
|
||||
'liblaunch-static',
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DLIBC_STANDALONE=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-headers C)
|
||||
|
||||
file(GLOB headers *.h)
|
||||
file(GLOB sys_headers sys/*.h)
|
||||
|
||||
install(FILES ${headers} DESTINATION include)
|
||||
install(FILES ${sys_headers} DESTINATION include/sys)
|
||||
@@ -0,0 +1,16 @@
|
||||
[seed]
|
||||
name = 'libc-headers'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'source-only'
|
||||
build_for = 'target'
|
||||
watch_files = [ 'src:**' ]
|
||||
|
||||
[install]
|
||||
"/usr/include" = [ 'src:*.h' ]
|
||||
"/usr/include/sys" = [ 'src:sys/*.h' ]
|
||||
|
||||
# vim: ft=toml
|
||||
+18
-16
@@ -1,5 +1,10 @@
|
||||
set(source_dirs unistd stdio)
|
||||
|
||||
if (LIBC_STANDALONE)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-io C ASM)
|
||||
endif ()
|
||||
|
||||
file(GLOB sources *.c *.h)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
@@ -13,21 +18,18 @@ endforeach (dir)
|
||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||
set(headers ${headers} ${sub_headers})
|
||||
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
if (NOT LIBC_STANDALONE)
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
return ()
|
||||
endif ()
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-io
|
||||
PUBLIC_INCLUDE_DIRS
|
||||
add_library(libc-io STATIC ${sources} ${headers})
|
||||
target_include_directories(libc-io PUBLIC
|
||||
${public_include_dirs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-io
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc-io libc-core interface::fs libxpc-static libmagenta)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_link_libraries(libc-io libc-core libxpc.a libmagenta)
|
||||
target_compile_definitions(libc-io PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||
set_target_properties(libc-io PROPERTIES PREFIX "")
|
||||
install(TARGETS libc-io)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
[seed]
|
||||
name = 'libc-io'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
'libc-core',
|
||||
'librosetta-interface',
|
||||
'libxpc-static'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DLIBC_STANDALONE=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,17 @@
|
||||
[seed]
|
||||
name = 'libc'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libc-headers',
|
||||
'libmagenta',
|
||||
'librosetta',
|
||||
'libxpc-static',
|
||||
'liblaunch-static',
|
||||
'librosetta-interface'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,5 +1,10 @@
|
||||
set(source_dirs stdlib string)
|
||||
|
||||
if (LIBC_STANDALONE)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-malloc C ASM)
|
||||
endif ()
|
||||
|
||||
file(GLOB sources *.c *.h)
|
||||
|
||||
foreach (dir ${source_dirs})
|
||||
@@ -13,22 +18,17 @@ endforeach (dir)
|
||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||
set(headers ${headers} ${sub_headers})
|
||||
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-malloc
|
||||
PUBLIC_INCLUDE_DIRS
|
||||
${public_include_dirs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-malloc
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
if (NOT LIBC_STANDALONE)
|
||||
set(component_sources ${sources} PARENT_SCOPE)
|
||||
set(component_headers ${headers} PARENT_SCOPE)
|
||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||
endif ()
|
||||
|
||||
add_library(libc-malloc STATIC ${sources} ${headers})
|
||||
target_compile_definitions(libc-malloc PRIVATE LIBC_STATIC=1 ENABLE_GLOBAL_HEAP=1)
|
||||
target_include_directories(libc-malloc PUBLIC ${public_include_dirs} include)
|
||||
target_compile_definitions(libc-malloc PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||
target_link_libraries(libc-malloc libc-core libmagenta)
|
||||
set_target_properties(libc-malloc PROPERTIES PREFIX "")
|
||||
install(TARGETS libc-malloc)
|
||||
install(FILES ${sub_headers} DESTINATION include/heap)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[seed]
|
||||
name = 'libc-malloc'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
'libc-core'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DLIBC_STANDALONE=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,4 +1,7 @@
|
||||
set(pthread_source_dirs thread)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-pthread C ASM)
|
||||
|
||||
set(pthread_source_dirs thread mutex)
|
||||
|
||||
foreach (dir ${pthread_source_dirs})
|
||||
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
||||
@@ -17,30 +20,27 @@ set(pthread_sources ${pthread_sources} ${pthread_sys_sources})
|
||||
set(pthread_headers ${pthread_headers} ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread.h)
|
||||
set(pthread_public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
rosetta_add_library(STATIC
|
||||
NAME libc-pthread
|
||||
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||
SOURCES ${pthread_sources}
|
||||
HEADERS ${pthread_headers})
|
||||
rosetta_add_library(SHARED
|
||||
NAME libpthread
|
||||
PUBLIC_INCLUDE_DIRS ${pthread_public_include_dir}
|
||||
SOURCES ${pthread_sources}
|
||||
HEADERS ${pthread_headers})
|
||||
if (PTHREAD_STATIC)
|
||||
add_library(libc-pthread STATIC ${pthread_sources} ${pthread_headers})
|
||||
target_link_libraries(libc-pthread PRIVATE libc-io libmagenta)
|
||||
target_include_directories(libc-pthread PUBLIC
|
||||
${public_include_dirs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
set_target_properties(libc-pthread PROPERTIES PREFIX "")
|
||||
target_compile_definitions(libc-pthread PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||
install(TARGETS libc-pthread)
|
||||
else ()
|
||||
add_library(libpthread SHARED ${pthread_sources} ${pthread_headers})
|
||||
target_link_libraries(libpthread PRIVATE magenta)
|
||||
target_link_libraries(libpthread PUBLIC c)
|
||||
target_include_directories(libpthread PUBLIC
|
||||
${public_include_dirs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
set_target_properties(libpthread PROPERTIES PREFIX "")
|
||||
target_compile_options(libpthread PRIVATE -ffreestanding -nostdlib)
|
||||
target_link_options(libpthread PRIVATE -ffreestanding -nostdlib)
|
||||
target_compile_definitions(libpthread PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_SHARED=1)
|
||||
install(TARGETS libpthread)
|
||||
endif ()
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libc-pthread
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
sysroot_add_library(
|
||||
NAME libpthread
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
bsp_add_library(
|
||||
NAME libpthread
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libc-pthread PRIVATE libc-io libmagenta)
|
||||
target_link_libraries(libpthread PRIVATE libmagenta)
|
||||
target_link_libraries(libpthread PUBLIC libc)
|
||||
install(FILES include/pthread.h DESTINATION include)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[seed]
|
||||
name = 'libc-pthread'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
'libc-io'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DPTHREAD_STATIC=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,7 @@
|
||||
[seed]
|
||||
name = 'libpthread'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,10 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(libc-runtime C ASM)
|
||||
|
||||
file(GLOB runtime_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
||||
|
||||
rosetta_add_object_library(
|
||||
NAME libc-runtime STATIC
|
||||
SOURCES ${runtime_sources})
|
||||
foreach (s ${runtime_sources})
|
||||
get_filename_component(object_name ${s} NAME)
|
||||
get_filename_component(object_basename ${s} NAME_WE)
|
||||
# TODO find a better way of finding the compiled object files
|
||||
set(object_path
|
||||
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/libc-runtime.dir/${CMAKE_SYSTEM_PROCESSOR}/${object_name}.obj)
|
||||
install(FILES ${object_path} DESTINATION lib RENAME "${object_basename}.o")
|
||||
endforeach (s)
|
||||
|
||||
sysroot_add_object_library(
|
||||
NAME libc-runtime
|
||||
LIB_DIR /usr/lib)
|
||||
add_library(libc-runtime OBJECT ${runtime_sources})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[seed]
|
||||
name = 'libc-runtime'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [
|
||||
'-DLIBC_STANDALONE=TRUE'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
+16
-22
@@ -1,33 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(fs C ASM)
|
||||
|
||||
file(GLOB sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/interface/*.c)
|
||||
file(GLOB headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/fs/*.h)
|
||||
file(GLOB public_headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/fs/*.h)
|
||||
|
||||
set(public_include_dirs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
rosetta_add_library(
|
||||
NAME libfs SHARED STATIC
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
if (FS_STATIC)
|
||||
add_library(fs STATIC ${sources} ${headers})
|
||||
target_link_libraries(fs magenta libc-core libxpc.a)
|
||||
set_target_properties(fs PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||
else ()
|
||||
add_library(fs SHARED ${sources} ${headers})
|
||||
target_link_libraries(fs magenta c xpc)
|
||||
endif ()
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libfs
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
sysroot_add_library(
|
||||
NAME libfs-static
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
bsp_add_library(
|
||||
NAME libfs
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libfs libmagenta interface::fs libc libxpc)
|
||||
target_link_libraries(libfs-static libmagenta interface::fs libc-core libxpc-static)
|
||||
|
||||
set_target_properties(libfs-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||
target_include_directories(fs PUBLIC include)
|
||||
install(TARGETS fs)
|
||||
install(FILES ${public_headers} DESTINATION include/fs)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[seed]
|
||||
name = 'libfs-static'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libxpc-static',
|
||||
'liblaunch-static',
|
||||
'librosetta-interface'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [ '-DFS_STATIC=TRUE' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,13 @@
|
||||
[seed]
|
||||
name = 'libfs'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libxpc',
|
||||
'librosetta-interface'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
+1
-1
Submodule lib/libfx updated: 20dc844c9d...9da33eec71
@@ -1,25 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(launch C ASM)
|
||||
|
||||
file(GLOB sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||
file(GLOB headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||
file(GLOB public_headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h)
|
||||
|
||||
set(public_include_dirs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
rosetta_add_library(
|
||||
NAME liblaunch SHARED STATIC
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
if (LAUNCH_STATIC)
|
||||
add_library(launch STATIC ${sources} ${headers})
|
||||
target_link_libraries(launch PRIVATE librosetta libmagenta libc-core)
|
||||
else ()
|
||||
add_library(launch SHARED ${sources} ${headers})
|
||||
target_link_libraries(launch PRIVATE rosetta magenta c)
|
||||
endif ()
|
||||
|
||||
sysroot_add_library(
|
||||
NAME liblaunch
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
bsp_add_library(
|
||||
NAME liblaunch
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(liblaunch-static PRIVATE librosetta libmagenta libc-core)
|
||||
target_link_libraries(liblaunch PRIVATE librosetta libmagenta libc)
|
||||
target_include_directories(launch PUBLIC include)
|
||||
install(TARGETS launch)
|
||||
install(FILES ${public_headers} DESTINATION include)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[seed]
|
||||
name = 'liblaunch-static'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'librosetta',
|
||||
'libmagenta',
|
||||
'libc-core'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [ '-DLAUNCH_STATIC=TRUE' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,7 @@
|
||||
[seed]
|
||||
name = 'liblaunch'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,15 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(librosetta C ASM)
|
||||
|
||||
file(GLOB sources *.c)
|
||||
file(GLOB headers include/rosetta/*.h)
|
||||
|
||||
rosetta_add_library(
|
||||
NAME librosetta STATIC
|
||||
PUBLIC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
add_library(rosetta STATIC ${sources} ${headers})
|
||||
target_include_directories(rosetta PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
sysroot_add_library(
|
||||
NAME librosetta
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
target_link_libraries(rosetta PRIVATE libmagenta)
|
||||
|
||||
target_link_libraries(librosetta PRIVATE libmagenta)
|
||||
install(TARGETS rosetta)
|
||||
install(FILES ${headers} DESTINATION include/rosetta)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[seed]
|
||||
name = 'librosetta'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
+16
-16
@@ -1,28 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(xpc C ASM)
|
||||
|
||||
file(GLOB sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||
file(GLOB headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||
|
||||
file(GLOB public_headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||
|
||||
set(public_include_dirs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
rosetta_add_library(
|
||||
NAME libxpc SHARED STATIC
|
||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
||||
SOURCES ${sources}
|
||||
HEADERS ${headers})
|
||||
if (XPC_STATIC)
|
||||
add_library(xpc STATIC ${sources} ${headesr})
|
||||
target_link_libraries(xpc magenta libc-core)
|
||||
else ()
|
||||
add_library(xpc SHARED ${sources} ${headesr})
|
||||
target_link_libraries(xpc magenta c)
|
||||
endif ()
|
||||
|
||||
sysroot_add_library(
|
||||
NAME libxpc
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
sysroot_add_library(
|
||||
NAME libxpc-static
|
||||
HEADER_DIR /usr/include
|
||||
LIB_DIR /usr/lib)
|
||||
|
||||
target_link_libraries(libxpc libmagenta libc)
|
||||
target_link_libraries(libxpc-static libmagenta libc-core)
|
||||
target_include_directories(xpc PUBLIC ${public_include_dirs})
|
||||
|
||||
install(TARGETS xpc)
|
||||
install(FILES ${public_headers} DESTINATION include/xpc)
|
||||
#set_target_properties(libxpc-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'libxpc-static'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
'libc-core'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
configure_args = [ '-DXPC_STATIC=TRUE' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,7 @@
|
||||
[seed]
|
||||
name = 'libxpc'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
if [ ! -d "$SCRIPT_DIR/build" ]; then
|
||||
mkdir build
|
||||
fi
|
||||
|
||||
if [ ! -d "$SCRIPT_DIR/build/meadow_venv" ]; then
|
||||
echo 'Initialising meadow...'
|
||||
python3 -m venv $SCRIPT_DIR/build/meadow_venv
|
||||
source $SCRIPT_DIR/build/meadow_venv/bin/activate
|
||||
pip install -r $SCRIPT_DIR/toolchain/meadow/requirements.txt
|
||||
else
|
||||
source $SCRIPT_DIR/build/meadow_venv/bin/activate
|
||||
fi
|
||||
|
||||
python3 $SCRIPT_DIR/toolchain/meadow/main.py "$@"
|
||||
@@ -3,6 +3,7 @@ file(GLOB items *)
|
||||
set(bshell_interactive 0)
|
||||
set(bshell_verbose 0)
|
||||
set(bshell_enable_floating_point 0)
|
||||
set(bshell_enable_native_commands 0)
|
||||
|
||||
foreach(item ${items})
|
||||
if (NOT IS_DIRECTORY ${item})
|
||||
|
||||
+1
-1
Submodule programs/bshell updated: 8843f2d2a9...f189643cf4
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
[seed]
|
||||
name = 'bshell'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libfx',
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
source_dir = 'programs/bshell'
|
||||
configure_args = [
|
||||
'-Dbshell_interactive=FALSE',
|
||||
'-Dbshell_enable_native_commands=FALSE',
|
||||
'-Dbshell_enable_floating_point=FALSE',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,17 +1,9 @@
|
||||
rosetta_add_misc_service(
|
||||
NAME bshell-test
|
||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bshell-test.service)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(bshell-test)
|
||||
|
||||
rosetta_service_add_file(
|
||||
NAME bshell-test
|
||||
SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/test.bshell
|
||||
DEST_DIR /sbin)
|
||||
|
||||
sysroot_add_service(
|
||||
NAME bshell-test
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
bsp_add_service(
|
||||
NAME bshell-test
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/bshell-test.service
|
||||
DESTINATION etc/herdd/services)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/test.bshell
|
||||
DESTINATION sbin)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[seed]
|
||||
name = 'bshell-test'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
[install]
|
||||
prefix = "/"
|
||||
'/etc/herdd/services' = [ 'bshell-test.service' ]
|
||||
'/sbin' = [ 'test.bshell' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,15 +1,7 @@
|
||||
file(GLOB sources *.c)
|
||||
rosetta_add_service(
|
||||
NAME devmd
|
||||
SOURCES ${sources}
|
||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/devmd.service)
|
||||
target_link_libraries(devmd libc libc-runtime)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(devmd C)
|
||||
|
||||
sysroot_add_service(
|
||||
NAME devmd
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
bsp_add_service(
|
||||
NAME devmd
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
file(GLOB sources *.c)
|
||||
add_executable(devmd ${sources})
|
||||
target_link_libraries(devmd c -l:crt0.o)
|
||||
install(TARGETS devmd)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[seed]
|
||||
name = 'devmd'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
[install]
|
||||
"/etc/herdd/services" = [ 'src:devmd.service' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,13 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(herdd C)
|
||||
|
||||
file(GLOB sources *.c)
|
||||
add_executable(herdd ${sources})
|
||||
target_link_libraries(herdd
|
||||
libc libc-runtime
|
||||
libmagenta libpthread liblaunch librosetta
|
||||
c -l:crt0.o
|
||||
magenta pthread launch rosetta
|
||||
fx.runtime fx.collections fx.serial)
|
||||
|
||||
sysroot_add_program(
|
||||
NAME herdd
|
||||
BIN_DIR /usr/bin)
|
||||
bsp_add_program(
|
||||
NAME herdd
|
||||
BIN_DIR /usr/bin)
|
||||
install(TARGETS herdd)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'herdd'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'liblaunch',
|
||||
'librosetta',
|
||||
'libfx'
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
watch_files = [ 'src:*.c', 'src:*.h' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,15 +1,7 @@
|
||||
file(GLOB sources *.c)
|
||||
rosetta_add_service(
|
||||
NAME nsd
|
||||
SOURCES ${sources}
|
||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/nsd.service)
|
||||
target_link_libraries(nsd libc libc-runtime)
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(nsd C)
|
||||
|
||||
sysroot_add_service(
|
||||
NAME nsd
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
bsp_add_service(
|
||||
NAME nsd
|
||||
BIN_DIR /usr/bin
|
||||
SVC_DIR /etc/herdd/services)
|
||||
file(GLOB sources *.c)
|
||||
add_executable(nsd ${sources})
|
||||
target_link_libraries(nsd c -l:crt0.o)
|
||||
install(TARGETS nsd)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[seed]
|
||||
name = 'nsd'
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
[install]
|
||||
"/etc/herdd/services" = [ 'src:nsd.service' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,15 @@
|
||||
[seed]
|
||||
name = 'herdd-targets'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
|
||||
[build]
|
||||
build_system = 'source-only'
|
||||
build_for = 'target'
|
||||
watch_files = [ 'src:*.target' ]
|
||||
|
||||
[install]
|
||||
"/etc/herdd/targets" = [ 'src:*.target' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,15 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(bootstrap C ASM)
|
||||
|
||||
file(GLOB c_sources *.c *.h)
|
||||
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
|
||||
add_executable(bootstrap ${c_sources} ${arch_sources})
|
||||
|
||||
set(static_deps
|
||||
magenta rosetta
|
||||
libc-core.a libc-malloc.a libc-io.a
|
||||
libfs.a
|
||||
liblaunch.a
|
||||
libxpc.a)
|
||||
target_link_libraries(bootstrap
|
||||
libmagenta librosetta
|
||||
libc-core libc-malloc libc-pthread
|
||||
libfs-static
|
||||
liblaunch-static
|
||||
libxpc-static
|
||||
interface::fs)
|
||||
"$<LINK_GROUP:cross_refs,${static_deps}>")
|
||||
|
||||
target_compile_options(bootstrap PRIVATE
|
||||
-fno-stack-protector -nostdlib -ffreestanding -fno-PIC)
|
||||
@@ -17,3 +21,4 @@ target_link_options(bootstrap PRIVATE
|
||||
-static -nostdlib -ffreestanding)
|
||||
|
||||
set_target_properties(bootstrap PROPERTIES POSITIION_INDEPENDENT_CODE FALSE)
|
||||
install(TARGETS bootstrap DESTINATION boot)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
[seed]
|
||||
name = 'bootstrap'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libmagenta',
|
||||
'librosetta',
|
||||
'libc-core',
|
||||
'libc-malloc',
|
||||
'libc-pthread',
|
||||
'libfs-static',
|
||||
'liblaunch-static',
|
||||
'libxpc-static',
|
||||
'librosetta-interface',
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
[install]
|
||||
prefix = "/"
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,38 @@
|
||||
[seed]
|
||||
name = 'bsp'
|
||||
|
||||
[build]
|
||||
build_system = 'generic'
|
||||
build_command = {
|
||||
args = [
|
||||
'root-src:toolchain/mkbsp/mkbsp',
|
||||
'--preset',
|
||||
'src:rosetta.preset',
|
||||
'--sysroot',
|
||||
'install:.',
|
||||
'--out',
|
||||
'bin:rosetta-system.bsp',
|
||||
],
|
||||
}
|
||||
watch_files = [ 'install:**' ]
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'ld',
|
||||
'bshell',
|
||||
'libc',
|
||||
'libpthread',
|
||||
'libfx',
|
||||
'liblaunch',
|
||||
'libfs',
|
||||
'libxpc',
|
||||
'herdd',
|
||||
'herdd-targets',
|
||||
'nsd',
|
||||
'devmd',
|
||||
]
|
||||
|
||||
[install]
|
||||
"/boot" = [ 'bin:rosetta-system.bsp' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,8 @@
|
||||
[bootstrap]
|
||||
bootstrap_exec = '/boot/bootstrap'
|
||||
|
||||
[contents]
|
||||
"/lib" = [ '/lib/ld64.so' ]
|
||||
"/usr/bin" = [ '/usr/bin/herdd' ]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,16 @@
|
||||
[contents]
|
||||
"/usr/lib" = [
|
||||
'/usr/lib/libc.so',
|
||||
'/usr/lib/libpthread.so',
|
||||
'/usr/lib/libfs.so',
|
||||
'/usr/lib/libfx.runtime.so',
|
||||
'/usr/lib/libfx.collections.so',
|
||||
'/usr/lib/libfx.io.so',
|
||||
'/usr/lib/libfx.serial.so',
|
||||
'/usr/lib/libfx.term.so',
|
||||
'/usr/lib/libfx.cmdline.so',
|
||||
'/usr/lib/liblaunch.so',
|
||||
'/usr/lib/libxpc.so',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,12 @@
|
||||
[contents]
|
||||
"/usr/bin" = [
|
||||
'/usr/bin/devmd',
|
||||
'/usr/bin/nsd',
|
||||
]
|
||||
|
||||
"/etc/herdd/services" = [
|
||||
'/etc/herdd/services/devmd.service',
|
||||
'/etc/herdd/services/nsd.service',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,7 @@
|
||||
[contents]
|
||||
"/etc/herdd/targets" = [
|
||||
'/etc/herdd/targets/minimal.target',
|
||||
'/etc/herdd/targets/single-user.target',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,8 @@
|
||||
[contents]
|
||||
"/usr/bin" = [ '/usr/bin/bshell' ]
|
||||
"/usr/lib" = [
|
||||
'/usr/lib/libbshell.runtime.so',
|
||||
'/usr/lib/libbshell.core.so',
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -1,3 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(ld C ASM)
|
||||
|
||||
file(GLOB c_sources *.c *.h)
|
||||
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||
|
||||
@@ -7,9 +10,11 @@ set_target_properties(ld PROPERTIES
|
||||
OUTPUT_NAME "ld64"
|
||||
SUFFIX ".so")
|
||||
|
||||
set(libc_deps
|
||||
libc-core.a libc-malloc.a libc-io.a)
|
||||
target_link_libraries(ld
|
||||
libc-core libc-malloc libc-io libmagenta librosetta libxpc-static
|
||||
interface::fs)
|
||||
"$<LINK_GROUP:cross_refs,${libc_deps}>"
|
||||
libmagenta.a librosetta.a -l:libxpc.a)
|
||||
|
||||
target_compile_options(ld PRIVATE
|
||||
-fvisibility=hidden
|
||||
@@ -19,10 +24,4 @@ target_link_options(ld PRIVATE
|
||||
# -Wl,--entry="_ld_start"
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR}/layout.ld
|
||||
-fPIC -nostdlib -ffreestanding -Wl,-shared)
|
||||
|
||||
sysroot_add_program(
|
||||
NAME ld
|
||||
BIN_DIR /lib)
|
||||
bsp_add_program(
|
||||
NAME ld
|
||||
BIN_DIR /lib)
|
||||
install(TARGETS ld DESTINATION lib)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[seed]
|
||||
name = 'ld'
|
||||
|
||||
[dependency]
|
||||
no_standard_dependencies = true
|
||||
seeds = [
|
||||
'libc-core',
|
||||
'libc-malloc',
|
||||
'libc-io',
|
||||
'libc-headers',
|
||||
'libxpc-static',
|
||||
'libmagenta',
|
||||
'librosetta',
|
||||
'librosetta-interface',
|
||||
]
|
||||
|
||||
[build]
|
||||
build_system = 'cmake'
|
||||
|
||||
[install]
|
||||
prefix = "/"
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,42 @@
|
||||
[target]
|
||||
name = 'rosetta'
|
||||
base_components = [
|
||||
'libmagenta',
|
||||
'libc',
|
||||
'libpthread',
|
||||
'libc-headers',
|
||||
]
|
||||
default_prefix = '/usr'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libfx-host',
|
||||
'xpcg',
|
||||
'magenta',
|
||||
'libmagenta',
|
||||
'librosetta',
|
||||
'libc',
|
||||
'libpthread',
|
||||
'libc-core',
|
||||
'libc-io',
|
||||
'libc-runtime',
|
||||
'libc-pthread',
|
||||
'libc-exec',
|
||||
'libc-malloc',
|
||||
|
||||
'librosetta-interface',
|
||||
'ld',
|
||||
'bootstrap',
|
||||
'bshell',
|
||||
'libfs',
|
||||
'libxpc',
|
||||
'libfx',
|
||||
'base',
|
||||
'herdd',
|
||||
'herdd-targets',
|
||||
'nsd',
|
||||
'devmd',
|
||||
'bsp'
|
||||
]
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,139 @@
|
||||
diff --git a/bfd/config.bfd b/bfd/config.bfd
|
||||
index 4dde5321f23..94c1a871ec2 100644
|
||||
--- a/bfd/config.bfd
|
||||
+++ b/bfd/config.bfd
|
||||
@@ -242,7 +242,17 @@ esac
|
||||
|
||||
case "${targ}" in
|
||||
# START OF targmatch.h
|
||||
+ i[3-7]86-*-rosetta*)
|
||||
+ targ_defvec=i386_elf32_vec
|
||||
+ targ_selvecs=
|
||||
+ targ64_selvecs=x86_64_elf64_vec
|
||||
+ ;;
|
||||
#ifdef BFD64
|
||||
+ x86_64-*-rosetta*)
|
||||
+ targ_defvec=x86_64_elf64_vec
|
||||
+ targ_selvecs=i386_elf32_vec
|
||||
+ want64=true
|
||||
+ ;;
|
||||
aarch64-*-darwin*)
|
||||
targ_defvec=aarch64_mach_o_vec
|
||||
targ_selvecs="arm_mach_o_vec mach_o_le_vec mach_o_be_vec mach_o_fat_vec"
|
||||
diff --git a/config.sub b/config.sub
|
||||
index 3d35cde174d..19cd8f07cd7 100755
|
||||
--- a/config.sub
|
||||
+++ b/config.sub
|
||||
@@ -2102,6 +2102,7 @@ case $os in
|
||||
| rhapsody* \
|
||||
| riscix* \
|
||||
| riscos* \
|
||||
+ | rosetta* \
|
||||
| rtems* \
|
||||
| rtmk* \
|
||||
| rtu* \
|
||||
diff --git a/gas/configure.tgt b/gas/configure.tgt
|
||||
index f0ea55d9def..4f194e70501 100644
|
||||
--- a/gas/configure.tgt
|
||||
+++ b/gas/configure.tgt
|
||||
@@ -126,6 +126,7 @@ esac
|
||||
generic_target=${cpu_type}-$vendor-$os
|
||||
# Note: This table is alpha-sorted, please try to keep it that way.
|
||||
case ${generic_target} in
|
||||
+ i386-*-rosetta*) fmt=elf em=gnu;;
|
||||
aarch64*-*-elf*) fmt=elf;;
|
||||
aarch64*-*-fuchsia*) fmt=elf;;
|
||||
aarch64*-*-haiku*) fmt=elf em=haiku ;;
|
||||
diff --git a/ld/Makefile.am b/ld/Makefile.am
|
||||
index c219662d2e3..8d17fed7581 100644
|
||||
--- a/ld/Makefile.am
|
||||
+++ b/ld/Makefile.am
|
||||
@@ -153,6 +153,7 @@ endif
|
||||
|
||||
# These all start with e so 'make clean' can find them.
|
||||
ALL_EMULATION_SOURCES = \
|
||||
+ eelf_i386_rosetta.c \
|
||||
eaix5ppc.c \
|
||||
eaix5rs6.c \
|
||||
eaixppc.c \
|
||||
@@ -373,6 +374,7 @@ ALL_EMULATION_SOURCES = \
|
||||
ALL_EMULATIONS = $(ALL_EMULATION_SOURCES:.c=.@OBJEXT@)
|
||||
|
||||
ALL_64_EMULATION_SOURCES = \
|
||||
+ eelf_x86_64_rosetta.c \
|
||||
eaarch64elf.c \
|
||||
eaarch64elf32.c \
|
||||
eaarch64elf32b.c \
|
||||
diff --git a/ld/Makefile.in b/ld/Makefile.in
|
||||
index f1ba6af5269..a4d76c4cc0b 100644
|
||||
--- a/ld/Makefile.in
|
||||
+++ b/ld/Makefile.in
|
||||
@@ -668,6 +668,7 @@ LIBIBERTY = ../libiberty/libiberty.a
|
||||
|
||||
# These all start with e so 'make clean' can find them.
|
||||
ALL_EMULATION_SOURCES = \
|
||||
+ eelf_i386_rosetta.c \
|
||||
eaix5ppc.c \
|
||||
eaix5rs6.c \
|
||||
eaixppc.c \
|
||||
@@ -887,6 +888,7 @@ ALL_EMULATION_SOURCES = \
|
||||
|
||||
ALL_EMULATIONS = $(ALL_EMULATION_SOURCES:.c=.@OBJEXT@)
|
||||
ALL_64_EMULATION_SOURCES = \
|
||||
+ eelf_x86_64_rosetta.c \
|
||||
eaarch64elf.c \
|
||||
eaarch64elf32.c \
|
||||
eaarch64elf32b.c \
|
||||
@@ -1474,6 +1476,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Po@am__quote@
|
||||
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_rosetta.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_sol2.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_vxworks.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_iamcu.Po@am__quote@
|
||||
@@ -1482,6 +1485,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Po@am__quote@
|
||||
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_rosetta.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_sol2.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh8300elf_linux.Po@am__quote@
|
||||
diff --git a/ld/configure.tgt b/ld/configure.tgt
|
||||
index 3e158913b89..53c091fb78f 100644
|
||||
--- a/ld/configure.tgt
|
||||
+++ b/ld/configure.tgt
|
||||
@@ -82,6 +82,13 @@ fi
|
||||
# Please try to keep this table more or less in alphabetic order - it
|
||||
# makes it much easier to lookup a specific archictecture.
|
||||
case "${targ}" in
|
||||
+i[3-7]86-*-rosetta*) targ_emul=elf_i386_rosetta
|
||||
+ targ_extra_emuls=elf_i386
|
||||
+ targ64_extra_emuls="elf_x86_64_rosetta elf_x86_64"
|
||||
+ ;;
|
||||
+x86_64-*-rosetta*) targ_emul=elf_x86_64_rosetta
|
||||
+ targ_extra_emuls="elf_i386_rosetta elf_x86_64 elf_i386"
|
||||
+ ;;
|
||||
aarch64_be-*-elf) targ_emul=aarch64elfb
|
||||
targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b armelfb armelf"
|
||||
;;
|
||||
diff --git a/ld/emulparams/elf_i386_rosetta.sh b/ld/emulparams/elf_i386_rosetta.sh
|
||||
new file mode 100644
|
||||
index 00000000000..002e918bc53
|
||||
--- /dev/null
|
||||
+++ b/ld/emulparams/elf_i386_rosetta.sh
|
||||
@@ -0,0 +1,4 @@
|
||||
+source_sh ${srcdir}/emulparams/elf_i386.sh
|
||||
+TEXT_START_ADDR=0x08000000
|
||||
+GENERATE_SHLIB_SCRIPT=yes
|
||||
+GENERATE_PIE_SCRIPT=yes
|
||||
diff --git a/ld/emulparams/elf_x86_64_rosetta.sh b/ld/emulparams/elf_x86_64_rosetta.sh
|
||||
new file mode 100644
|
||||
index 00000000000..4ddde5ab2a5
|
||||
--- /dev/null
|
||||
+++ b/ld/emulparams/elf_x86_64_rosetta.sh
|
||||
@@ -0,0 +1,3 @@
|
||||
+source_sh ${srcdir}/emulparams/elf_x86_64.sh
|
||||
+GENERATE_SHLIB_SCRIPT=yes
|
||||
+GENERATE_PIE_SCRIPT=yes
|
||||
@@ -0,0 +1,14 @@
|
||||
[command]
|
||||
name = 'build-compiler'
|
||||
description = 'Build a GCC cross-compiler that targets the Rosetta operating system'
|
||||
|
||||
[dependency]
|
||||
seeds = [
|
||||
'libc-headers',
|
||||
'magenta-headers',
|
||||
]
|
||||
|
||||
[exec]
|
||||
args = [ 'src:build.py']
|
||||
|
||||
# vim: ft=toml
|
||||
@@ -0,0 +1,31 @@
|
||||
import os
|
||||
|
||||
class Builder:
|
||||
def get_prefix(self):
|
||||
return os.environ.get('MEADOW_NATIVE_ROOT', None)
|
||||
|
||||
|
||||
def get_target(self):
|
||||
env = os.environ
|
||||
target = os.environ.get('MEADOW_TARGET_PLATFORM', None)
|
||||
parts = target.split('-')
|
||||
return f'{parts[0]}-rosetta'
|
||||
|
||||
|
||||
def download(self):
|
||||
pass
|
||||
|
||||
|
||||
def configure(self):
|
||||
pass
|
||||
|
||||
|
||||
def build(self):
|
||||
pass
|
||||
|
||||
|
||||
def install(self):
|
||||
pass
|
||||
|
||||
|
||||
print(f'building cross compiler for {get_gcc_target()}, installed to {get_prefix()}')
|
||||
@@ -0,0 +1 @@
|
||||
../binutils-gdb/configure --target=x86_64-rosetta --prefix=/opt/cross-rosetta --with-sysroot=/opt/cross-rosetta --disable-nls --disable-werror --enable-default-execstack=no --with-gmp=/opt/homebrew --enable-shared
|
||||
@@ -0,0 +1 @@
|
||||
../gcc/configure --target=x86_64-rosetta --prefix=/opt/cross-rosetta --with-sysroot=/Users/wash/projects/rosetta/build/target-root --disable-nls --enable-languages=c,c++ --enable-shared --enable-initfini-array --with-gmp=/opt/homebrew
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
class Args:
|
||||
def __init__(self, argv):
|
||||
self.__argv = argv
|
||||
|
||||
|
||||
def get_positional(self, index):
|
||||
if len(self.__argv) > index:
|
||||
return self.__argv[index]
|
||||
return None
|
||||
|
||||
|
||||
def get_named(self, name, index, nr_args):
|
||||
found_name = False
|
||||
values = []
|
||||
|
||||
for s in self.__argv:
|
||||
if found_name:
|
||||
if nr_args > 0:
|
||||
nr_args -= 1
|
||||
values.append(s)
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
if s == '--{}'.format(name):
|
||||
if index > 0:
|
||||
index -= 1
|
||||
continue
|
||||
|
||||
found_name = True
|
||||
continue
|
||||
|
||||
if nr_args == 0:
|
||||
return found_name
|
||||
|
||||
if nr_args > 0 or not found_name:
|
||||
return None
|
||||
|
||||
if len(values) == 1:
|
||||
return values[0]
|
||||
|
||||
return values
|
||||
@@ -0,0 +1,146 @@
|
||||
import os
|
||||
import shutil
|
||||
from env import Environment
|
||||
from path import Path
|
||||
from pathlib import Path as SysPath
|
||||
|
||||
|
||||
class UnknownBuildSystemError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BuildConfigurationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BuildError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BuildSystem:
|
||||
def __init__(self, **kwargs):
|
||||
self.__name = None
|
||||
self.__source_dir = None
|
||||
self.__bin_dir = None
|
||||
self.__parent = None
|
||||
self.__install = None
|
||||
|
||||
if 'name' in kwargs:
|
||||
self.__name = kwargs['name']
|
||||
if 'source_dir' in kwargs:
|
||||
self.__source_dir = kwargs['source_dir']
|
||||
if 'bin_dir' in kwargs:
|
||||
self.__bin_dir = kwargs['bin_dir']
|
||||
if 'parent' in kwargs:
|
||||
self.__parent = kwargs['parent']
|
||||
if 'install' in kwargs:
|
||||
self.__install = kwargs['install']
|
||||
|
||||
|
||||
def name(self):
|
||||
return self.__name
|
||||
|
||||
|
||||
def source_dir(self):
|
||||
return self.__source_dir
|
||||
|
||||
|
||||
def binary_dir(self):
|
||||
return self.__bin_dir
|
||||
|
||||
|
||||
def parent(self):
|
||||
return self.__parent
|
||||
|
||||
|
||||
def install_manifest(self):
|
||||
return self.__install
|
||||
|
||||
|
||||
def build_for(self):
|
||||
return 'target'
|
||||
|
||||
|
||||
def get_path_namespaces(self):
|
||||
ns = {
|
||||
'src': os.path.abspath(self.source_dir()),
|
||||
'root-src': Environment.source_root(),
|
||||
'bin': os.path.abspath(self.binary_dir()),
|
||||
}
|
||||
|
||||
if self.build_for() == 'host':
|
||||
ns['install'] = Environment.native_root()
|
||||
else:
|
||||
ns['install'] = Environment.system_root()
|
||||
|
||||
return ns
|
||||
|
||||
|
||||
def check_out_of_date(self):
|
||||
self.__config_out_of_date = self._is_configuration_out_of_date()
|
||||
self.__build_out_of_date = self._is_build_out_of_date()
|
||||
|
||||
|
||||
def is_configuration_out_of_date(self):
|
||||
return self.__config_out_of_date
|
||||
|
||||
|
||||
def is_build_out_of_date(self):
|
||||
return self.__build_out_of_date
|
||||
|
||||
|
||||
def configure(self):
|
||||
return
|
||||
|
||||
|
||||
def build(self):
|
||||
return
|
||||
|
||||
|
||||
def __copy_dir(self, src, dst):
|
||||
dst_dir = os.path.dirname(dst)
|
||||
SysPath(dst_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copytree(src, dst, dirs_exist_ok=True)
|
||||
|
||||
|
||||
def __copy_file(self, src, dst):
|
||||
dst_dir = os.path.dirname(dst)
|
||||
SysPath(dst_dir).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(src, dst)
|
||||
|
||||
|
||||
def install_from_seed(self):
|
||||
manifest = self.install_manifest()
|
||||
if manifest is None:
|
||||
return
|
||||
|
||||
ns = self.get_path_namespaces()
|
||||
source_dir = self.source_dir()
|
||||
|
||||
dest_dir = Environment.system_root()
|
||||
if self.build_for() == 'host':
|
||||
dest_dir = Environment.native_root()
|
||||
|
||||
for dest, src in manifest.items():
|
||||
if dest[0] != '/':
|
||||
continue
|
||||
|
||||
dest = Path(dest).remove_root().get_path()
|
||||
|
||||
for p in src:
|
||||
path = Path(p)
|
||||
files = path.expand_path(relative_to=ns)
|
||||
|
||||
for p2 in files:
|
||||
file_name = os.path.basename(p2)
|
||||
rel_path = os.path.relpath(p2, start=source_dir)
|
||||
src_path = p2
|
||||
dst_path = os.path.join(dest_dir, dest, file_name)
|
||||
if os.path.isdir(src_path):
|
||||
self.__copy_dir(src_path, dst_path)
|
||||
else:
|
||||
self.__copy_file(src_path, dst_path)
|
||||
|
||||
|
||||
def install(self):
|
||||
return
|
||||
@@ -0,0 +1,237 @@
|
||||
import os
|
||||
import shutil
|
||||
from command import Command
|
||||
from config import Config
|
||||
from cache import Cache
|
||||
from seed import Seed
|
||||
from target import Target
|
||||
from env import Environment
|
||||
from platform import Platform
|
||||
from colorama import Fore, Style
|
||||
|
||||
|
||||
class SetCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='set',
|
||||
description='Set a configuration key value.')
|
||||
|
||||
|
||||
def run(self, args):
|
||||
key = args.get_positional(0)
|
||||
value = args.get_positional(1)
|
||||
|
||||
if key is None or value is None:
|
||||
print('usage: meadow set <key> <value>')
|
||||
return -1
|
||||
|
||||
try:
|
||||
value_i = int(value)
|
||||
Config.set(key, value_i)
|
||||
except:
|
||||
Config.set(key, value)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
class SeedsCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='seeds',
|
||||
description='List all available seeds.')
|
||||
|
||||
|
||||
def write_dot(self, path):
|
||||
f = open(path, mode='w')
|
||||
f.write('digraph seeds {\n')
|
||||
f.write(' node [shape=Mrecord];\n')
|
||||
nodes = {}
|
||||
|
||||
seeds = Seed.all_seeds()
|
||||
targets = Target.all_targets()
|
||||
for s in seeds.values():
|
||||
if s.name() in nodes:
|
||||
continue
|
||||
|
||||
sname = s.name().replace('-', '_')
|
||||
nodes[s.name()] = s
|
||||
f.write(' {} [label="{}"];\n'.format(sname, s.name()))
|
||||
|
||||
for d in s.dependencies().values():
|
||||
continue
|
||||
|
||||
|
||||
for t in targets.values():
|
||||
if t.name() in nodes:
|
||||
continue
|
||||
|
||||
t.resolve()
|
||||
tname = t.name().replace('-', '_')
|
||||
nodes[t.name()] = t
|
||||
f.write(' {} [label="{}",shape=hexagon];\n'.format(tname, t.name()))
|
||||
|
||||
for s in seeds.values():
|
||||
for k, d in s.dependencies().items():
|
||||
if d.name() not in nodes:
|
||||
nodes[d.name()] = d
|
||||
dname = d.name().replace('-', '_')
|
||||
f.write(' {} [label="{}",shape=diamond];\n'.format(dname, d.name()))
|
||||
|
||||
sname = s.name().replace('-', '_')
|
||||
dname = d.name().replace('-', '_')
|
||||
|
||||
if d.is_resolved():
|
||||
f.write(' {} -> {};\n'.format(dname, sname))
|
||||
else:
|
||||
f.write(' {} -> {}[style=dotted];\n'.format(dname, sname))
|
||||
|
||||
for t in targets.values():
|
||||
for k, d in t.dependencies().items():
|
||||
tname = t.name().replace('-', '_')
|
||||
dname = d.name().replace('-', '_')
|
||||
|
||||
if d.is_resolved():
|
||||
f.write(' {} -> {};\n'.format(dname, tname))
|
||||
else:
|
||||
f.write(' {} -> {}[style=dotted];\n'.format(dname, tname))
|
||||
|
||||
f.write('}\n')
|
||||
f.close()
|
||||
|
||||
|
||||
def run(self, args):
|
||||
seeds = Seed.all_seeds()
|
||||
|
||||
dot_path = args.get_named('to-dot-file', 0, 1)
|
||||
if dot_path is not None:
|
||||
self.write_dot(dot_path)
|
||||
return 0
|
||||
|
||||
for s in seeds.values():
|
||||
print('{}'.format(s.name()))
|
||||
|
||||
|
||||
class PlatformsCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='platforms',
|
||||
description='List all available platforms')
|
||||
|
||||
|
||||
def run(self, args):
|
||||
print('Supported platforms:')
|
||||
|
||||
platforms = Platform.all_platforms()
|
||||
current_platform = Platform.current_platform()
|
||||
|
||||
for p in platforms.values():
|
||||
if current_platform is not None and p.name() == current_platform.name():
|
||||
print(f'* {Fore.GREEN}{p.name()}{Style.RESET_ALL}')
|
||||
else:
|
||||
print(f' {p.name()}')
|
||||
|
||||
|
||||
class HelpCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='help',
|
||||
description='List all available commands.')
|
||||
|
||||
|
||||
def run(self, args):
|
||||
print('Available commands:')
|
||||
|
||||
commands = Command.all_commands()
|
||||
max_len = 0
|
||||
|
||||
for c in commands.values():
|
||||
if len(c.name()) > max_len:
|
||||
max_len = len(c.name())
|
||||
|
||||
max_len += 5
|
||||
for c in commands.values():
|
||||
print(' ', end='')
|
||||
print(c.name(), end='')
|
||||
|
||||
for i in range(len(c.name()), max_len):
|
||||
print(' ', end='')
|
||||
|
||||
print(c.description())
|
||||
|
||||
|
||||
class BuildCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='build',
|
||||
description='Build the currently selected target.')
|
||||
|
||||
|
||||
def run(self, args):
|
||||
verbose = args.get_named('verbose', 0, 0)
|
||||
|
||||
current_target = Target.current_target()
|
||||
if current_target is None:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} no build target has been set. Use `meadow set target.name <...>` to specify which target to build')
|
||||
return -1
|
||||
|
||||
current_platform = Platform.current_platform()
|
||||
if current_platform is None:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} no target platform has been set. Use `meadow set target.platform <...>` to specify which platform to target')
|
||||
return -1
|
||||
|
||||
components = current_target.resolve()
|
||||
|
||||
for c in components:
|
||||
build_system = None
|
||||
if isinstance(c, Seed):
|
||||
build_system = c.build_system()
|
||||
build_system.check_out_of_date()
|
||||
|
||||
for c in components:
|
||||
build_system = None
|
||||
if isinstance(c, Seed):
|
||||
build_system = c.build_system()
|
||||
|
||||
if build_system is not None:
|
||||
out_of_date = \
|
||||
build_system.is_configuration_out_of_date() \
|
||||
or build_system.is_build_out_of_date()
|
||||
|
||||
if out_of_date:
|
||||
print(f'{Fore.GREEN}>>>{Style.RESET_ALL} Building {c.name()}')
|
||||
|
||||
if build_system.is_configuration_out_of_date():
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Configuring build...')
|
||||
build_system.configure(verbose=verbose)
|
||||
|
||||
if out_of_date:
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Building...')
|
||||
build_system.build(verbose=verbose)
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Installing...')
|
||||
build_system.install(verbose=verbose)
|
||||
|
||||
print(f'{Style.BRIGHT}{Fore.GREEN}>>> Build Complete!{Style.RESET_ALL}')
|
||||
|
||||
|
||||
class CleanCommand(Command):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
name='clean',
|
||||
description='Delete all build-related files.')
|
||||
|
||||
|
||||
def run(self, args):
|
||||
build_dir = Environment.build_root()
|
||||
|
||||
for i in os.listdir(build_dir):
|
||||
if i.startswith('meadow') and ('cache' not in i):
|
||||
continue
|
||||
|
||||
ipath = os.path.join(build_dir, i)
|
||||
if os.path.isdir(ipath):
|
||||
shutil.rmtree(ipath)
|
||||
else:
|
||||
os.remove(ipath)
|
||||
|
||||
Cache.reset()
|
||||
return 0
|
||||
@@ -0,0 +1,69 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
cache_path = 'build/meadow-cache.json'
|
||||
cache_data = None
|
||||
|
||||
|
||||
class Cache:
|
||||
def load():
|
||||
global cache_data
|
||||
|
||||
if not os.path.exists(cache_path):
|
||||
cache_data = {}
|
||||
return
|
||||
|
||||
with open(cache_path, mode='r') as f:
|
||||
cache_data = json.load(f)
|
||||
|
||||
|
||||
def reset():
|
||||
global cache_data
|
||||
cache_data = {}
|
||||
|
||||
|
||||
def save():
|
||||
global cache_data
|
||||
|
||||
with open(cache_path, mode='w') as f:
|
||||
json.dump(cache_data, f, indent=4)
|
||||
|
||||
|
||||
def get(path):
|
||||
parts = path.split('.')
|
||||
container = cache_data
|
||||
|
||||
for p in parts[:-1]:
|
||||
if p not in container:
|
||||
return None
|
||||
|
||||
if not isinstance(container[p], dict):
|
||||
print('Err: element "{}" in cache key "{}" is not a dictionary'.format(p, path))
|
||||
return
|
||||
|
||||
container = container[p]
|
||||
|
||||
|
||||
if parts[-1] in container:
|
||||
return container[parts[-1]]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def set(path, value):
|
||||
parts = path.split('.')
|
||||
container = cache_data
|
||||
|
||||
for p in parts[:-1]:
|
||||
if p not in container:
|
||||
container[p] = {}
|
||||
|
||||
if not isinstance(container[p], dict):
|
||||
print('Err: element "{}" in cache key "{}" is not a dictionary'.format(p, path))
|
||||
return
|
||||
|
||||
container = container[p]
|
||||
|
||||
|
||||
container[parts[-1]] = value
|
||||
@@ -0,0 +1,316 @@
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
from build import *
|
||||
from pathlib import Path as SysPath
|
||||
from cache import Cache
|
||||
from env import Environment
|
||||
from platform import Platform
|
||||
from target import Target
|
||||
from path import Path
|
||||
|
||||
class CMakeBuildSystem(BuildSystem):
|
||||
def __init__(self, **kwargs):
|
||||
name = kwargs.get('name', None)
|
||||
source_dir = kwargs.get('source_dir', None)
|
||||
bin_dir = kwargs.get('bin_dir', None)
|
||||
parent = kwargs.get('parent', None)
|
||||
self.__data = kwargs.get('data', None)
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def build_for(self):
|
||||
if self.__data is None or 'build_for' not in self.__data:
|
||||
return 'target'
|
||||
return self.__data['build_for']
|
||||
|
||||
|
||||
def __get_watched_files(self):
|
||||
result = []
|
||||
ns = self.get_path_namespaces()
|
||||
|
||||
if 'watch_files' in self.__data:
|
||||
watch_list = self.__data['watch_files']
|
||||
for p in watch_list:
|
||||
path = Path(p)
|
||||
|
||||
real_paths = path.expand_path(relative_to=ns)
|
||||
for p2 in real_paths:
|
||||
result.append(p2)
|
||||
|
||||
manifest_path = os.path.join(self.binary_dir(), 'compile_commands.json')
|
||||
manifest_file = None
|
||||
manifest = None
|
||||
try:
|
||||
manifest_file = open(manifest_path, mode='r')
|
||||
except:
|
||||
return result
|
||||
|
||||
try:
|
||||
manifest = json.load(manifest_file)
|
||||
except:
|
||||
return result
|
||||
|
||||
for v in manifest:
|
||||
if 'file' not in v:
|
||||
continue
|
||||
|
||||
path = v['file']
|
||||
result.append(path)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def __get_build_mtime(self):
|
||||
files = self.__get_watched_files()
|
||||
result = 0
|
||||
|
||||
for path in files:
|
||||
mtime = os.path.getmtime(path)
|
||||
|
||||
if mtime > result:
|
||||
result = mtime
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def __get_configure_mtime(self):
|
||||
source_dir = os.path.abspath(self.source_dir())
|
||||
result = 0
|
||||
for root, dirs, files in os.walk(source_dir):
|
||||
for f in files:
|
||||
if f != 'CMakeLists.txt' and not f.endswith('.cmake'):
|
||||
continue
|
||||
|
||||
target_path = os.path.join(root, f)
|
||||
mtime = os.path.getmtime(target_path)
|
||||
if mtime > result:
|
||||
result = mtime
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _is_configuration_out_of_date(self):
|
||||
cache_file = os.path.join(self.binary_dir(), 'CMakeCache.txt')
|
||||
if not os.path.isfile(cache_file):
|
||||
return True
|
||||
|
||||
current_mtime = self.__get_configure_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.configure-mtime')
|
||||
if target_mtime is None:
|
||||
target_mtime = 0
|
||||
|
||||
if current_mtime > target_mtime:
|
||||
return True
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_system = d.build_system()
|
||||
if build_system is None:
|
||||
continue
|
||||
|
||||
if build_system.is_build_out_of_date() or build_system.is_configuration_out_of_date():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _is_build_out_of_date(self):
|
||||
current_mtime = self.__get_build_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if target_mtime is None:
|
||||
target_mtime = 0
|
||||
|
||||
if current_mtime > target_mtime:
|
||||
return True
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_system = d.build_system()
|
||||
if build_system is None:
|
||||
continue
|
||||
|
||||
if build_system.is_build_out_of_date() or build_system.is_configuration_out_of_date():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __get_published_items(self):
|
||||
published = {}
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_sys = d.build_system()
|
||||
ns = {}
|
||||
if build_sys is not None:
|
||||
ns = build_sys.get_path_namespaces()
|
||||
|
||||
p = d.publish()
|
||||
if p is None:
|
||||
continue
|
||||
|
||||
path = p.path()
|
||||
if path is not None:
|
||||
if 'path' not in published:
|
||||
published['path'] = []
|
||||
|
||||
path = Path.expand_all(path, relative_to=ns)
|
||||
published['path'].extend(path)
|
||||
|
||||
cmake = p.cmake()
|
||||
if cmake is not None:
|
||||
if 'cmake' not in published:
|
||||
published['cmake'] = {}
|
||||
|
||||
if 'module_paths' in cmake:
|
||||
if 'module_paths' not in published['cmake']:
|
||||
published['cmake']['module_paths'] = []
|
||||
|
||||
module_paths = cmake['module_paths']
|
||||
module_paths = Path.expand_all(module_paths, relative_to=ns)
|
||||
published['cmake']['module_paths'].extend(module_paths)
|
||||
|
||||
return published
|
||||
|
||||
|
||||
def configure(self, **kwargs):
|
||||
verbose = kwargs.get('verbose', False)
|
||||
ns = self.get_path_namespaces()
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
target = Target.current_target()
|
||||
platform = Platform.current_platform()
|
||||
cmake_platform = platform.get_component('cmake')
|
||||
cmake_args = [
|
||||
'cmake',
|
||||
'-DCMAKE_EXPORT_COMPILE_COMMANDS=ON',
|
||||
'--no-warn-unused-cli'
|
||||
]
|
||||
|
||||
if 'configure_args' in self.__data:
|
||||
cmake_args.extend(self.__data['configure_args'])
|
||||
|
||||
published = self.__get_published_items()
|
||||
env = os.environ.copy()
|
||||
if 'path' in published:
|
||||
path = ''
|
||||
if 'PATH' in env:
|
||||
path = env['PATH']
|
||||
|
||||
if len(path):
|
||||
path += ':'
|
||||
|
||||
path += ':'.join(published['path'])
|
||||
env['PATH'] = path
|
||||
|
||||
module_paths = []
|
||||
if 'cmake' in published:
|
||||
cmake_publish = published['cmake']
|
||||
for p in cmake_publish.get('module_paths', []):
|
||||
path = Path(p)
|
||||
for p2 in path.expand_path(relative_to=ns):
|
||||
module_paths.append(p2)
|
||||
|
||||
install_details = self.parent().install()
|
||||
install_prefix = ''
|
||||
if self.build_for() == 'host':
|
||||
install_prefix = Environment.native_root()
|
||||
cmake_platform = None
|
||||
seed_install_prefix = '/'
|
||||
if install_details is not None:
|
||||
seed_install_prefix = install_details.get('prefix', seed_install_prefix)
|
||||
seed_install_prefix = Path(seed_install_prefix).remove_root().get_path()
|
||||
install_prefix = os.path.join(install_prefix, seed_install_prefix)
|
||||
else:
|
||||
install_prefix = Environment.system_root()
|
||||
env['ROSETTA_SYSROOT'] = Environment.system_root()
|
||||
|
||||
seed_install_prefix = target.install_prefix()
|
||||
if install_details is not None:
|
||||
seed_install_prefix = install_details.get('prefix', seed_install_prefix)
|
||||
seed_install_prefix = Path(seed_install_prefix).remove_root().get_path()
|
||||
install_prefix = os.path.join(install_prefix, seed_install_prefix)
|
||||
|
||||
cmake_args.append(f'-DCMAKE_INSTALL_PREFIX={install_prefix}')
|
||||
|
||||
if cmake_platform is not None:
|
||||
if 'module_paths' in cmake_platform:
|
||||
for p in cmake_platform['module_paths']:
|
||||
module_paths.append(os.path.join(platform.base_directory(), p))
|
||||
if 'toolchain_file' in cmake_platform:
|
||||
toolchain_file = os.path.join(platform.base_directory(), cmake_platform['toolchain_file'])
|
||||
cmake_args.append(f'-DCMAKE_TOOLCHAIN_FILE={toolchain_file}')
|
||||
if 'system_name' in cmake_platform:
|
||||
cmake_args.append(f'-DCMAKE_SYSTEM_NAME={cmake_platform['system_name']}')
|
||||
|
||||
if 'module_paths' in self.__data:
|
||||
for p in self.__data['module_paths']:
|
||||
path = Path(p)
|
||||
for p2 in path.expand_path(relative_to=ns):
|
||||
module_paths.append(p2)
|
||||
|
||||
if len(module_paths) > 0:
|
||||
cmake_args.append(f'-DCMAKE_MODULE_PATH={';'.join(module_paths)}')
|
||||
|
||||
source_dir = os.path.abspath(self.source_dir())
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
cmake_args.append(source_dir)
|
||||
|
||||
SysPath(bin_dir).mkdir(parents=True, exist_ok=True)
|
||||
result = subprocess.run(cmake_args, cwd=bin_dir, env=env, stdout=stdout)
|
||||
|
||||
if result.returncode == 0:
|
||||
Cache.set(f'component.{self.name()}.configure-mtime', self.__get_configure_mtime())
|
||||
else:
|
||||
raise BuildConfigurationError(f'CMake configuration for {self.name()} failed. See log for details')
|
||||
|
||||
|
||||
def __find_build_command(self):
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
if os.path.isfile(os.path.join(bin_dir, 'build.ninja')):
|
||||
return 'ninja'
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def build(self, **kwargs):
|
||||
verbose = kwargs.get('verbose', False)
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
build_cmd = self.__find_build_command()
|
||||
if build_cmd is None:
|
||||
raise BuildError(f'Cannot determine which command to use to build {self.name()}')
|
||||
|
||||
env = os.environ.copy()
|
||||
if self.build_for() != 'host':
|
||||
env['ROSETTA_SYSROOT'] = Environment.system_root()
|
||||
|
||||
args = [ build_cmd ]
|
||||
result = subprocess.run(args, cwd=bin_dir, stdout=stdout, env=env)
|
||||
|
||||
if result.returncode != 0:
|
||||
raise BuildConfigurationError(f'{build_cmd} build for {self.name()} failed. See log for details')
|
||||
|
||||
|
||||
def install(self, **kwargs):
|
||||
self.install_from_seed()
|
||||
|
||||
verbose = kwargs.get('verbose', False)
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
bin_dir = os.path.abspath(self.binary_dir())
|
||||
build_cmd = self.__find_build_command()
|
||||
if build_cmd is None:
|
||||
raise BuildError(f'Cannot determine which command to use to build {self.name()}')
|
||||
|
||||
args = [ build_cmd, 'install' ]
|
||||
result = subprocess.run(args, cwd=bin_dir, stdout=stdout)
|
||||
|
||||
if result.returncode == 0:
|
||||
Cache.set(f'component.{self.name()}.build-mtime', self.__get_build_mtime())
|
||||
@@ -0,0 +1,205 @@
|
||||
import os
|
||||
import sys
|
||||
import tomli
|
||||
import tempfile
|
||||
import subprocess
|
||||
from dependency import *
|
||||
from colorama import Fore, Style
|
||||
from env import Environment
|
||||
from path import Path
|
||||
from config import Config
|
||||
|
||||
|
||||
commands = {}
|
||||
|
||||
|
||||
class CommandConfigurationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CommandExecutionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Command(DependencyItem):
|
||||
def all_commands():
|
||||
return commands
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__()
|
||||
|
||||
if 'name' in kwargs:
|
||||
self.__name = kwargs['name']
|
||||
if 'description' in kwargs:
|
||||
self.__description = kwargs['description']
|
||||
|
||||
|
||||
def name(self):
|
||||
return self.__name
|
||||
|
||||
|
||||
def description(self):
|
||||
return self.__description
|
||||
|
||||
|
||||
def dependencies(self):
|
||||
return None
|
||||
|
||||
|
||||
def register(cmd):
|
||||
commands[cmd.name()] = cmd
|
||||
|
||||
|
||||
def get(name):
|
||||
if name in commands:
|
||||
return commands[name]
|
||||
return None
|
||||
|
||||
|
||||
def run(self, args):
|
||||
return
|
||||
|
||||
|
||||
class UserCommand(Command):
|
||||
def load_file(self, path):
|
||||
with open(path, mode='rb') as f:
|
||||
self.__data = tomli.load(f)
|
||||
|
||||
|
||||
def __init_dependencies(self):
|
||||
if 'dependency' not in self.__data:
|
||||
return
|
||||
|
||||
dependency = self.__data['dependency']
|
||||
self.__dependencies = {}
|
||||
if 'seeds' in dependency:
|
||||
seeds = dependency['seeds']
|
||||
for s in seeds:
|
||||
self.__dependencies[s] = SeedDependency(parent=self.name(), name=s)
|
||||
|
||||
if 'commands' in dependency:
|
||||
commands = dependency['commands']
|
||||
for c in commands:
|
||||
self.__dependencies[c] = ProgramDependency(parent=self.name(), name=c)
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
if 'path' not in kwargs:
|
||||
return
|
||||
|
||||
self.__tmpdir = tempfile.TemporaryDirectory()
|
||||
self.__path = kwargs['path']
|
||||
self.load_file(self.__path)
|
||||
cmd = self.__data['command']
|
||||
super().__init__(name=cmd['name'], description=cmd['description'])
|
||||
|
||||
self.__init_dependencies()
|
||||
|
||||
|
||||
def dependencies(self):
|
||||
return self.__dependencies
|
||||
|
||||
|
||||
def scan_directory(paths):
|
||||
for p in paths:
|
||||
for root, dirs, files in os.walk(p):
|
||||
for f in files:
|
||||
if not f.endswith('.command'):
|
||||
continue
|
||||
cmd_path = os.path.join(root, f)
|
||||
cmd = None
|
||||
try:
|
||||
cmd = UserCommand(path=cmd_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
print('Err: Failed to parse command file {}\n {}'.format(seed_path, e))
|
||||
return -1
|
||||
|
||||
Command.register(cmd)
|
||||
|
||||
|
||||
def get_path_namespaces(self):
|
||||
ns = {
|
||||
'src': os.path.dirname(self.__path),
|
||||
'root-src': Environment.source_root(),
|
||||
'install': Environment.system_root(),
|
||||
}
|
||||
|
||||
return ns
|
||||
|
||||
|
||||
def get_environment(self):
|
||||
return {
|
||||
'MEADOW_SYSROOT': Environment.system_root(),
|
||||
'MEADOW_NATIVE_ROOT': Environment.native_root(),
|
||||
'MEADOW_SOURCE_ROOT': Environment.source_root(),
|
||||
'MEADOW_TEMP': self.__tmpdir.name,
|
||||
'MEADOW_TARGET_PLATFORM': Config.get('target.platform'),
|
||||
}
|
||||
|
||||
|
||||
def run(self, args):
|
||||
from seed import Seed
|
||||
deps = self.resolve()
|
||||
|
||||
for c in deps:
|
||||
build_system = None
|
||||
if isinstance(c, Seed):
|
||||
build_system = c.build_system()
|
||||
build_system.check_out_of_date()
|
||||
|
||||
for c in deps:
|
||||
build_system = None
|
||||
if isinstance(c, Seed):
|
||||
build_system = c.build_system()
|
||||
|
||||
if build_system is not None:
|
||||
out_of_date = \
|
||||
build_system.is_configuration_out_of_date() \
|
||||
or build_system.is_build_out_of_date()
|
||||
|
||||
if out_of_date:
|
||||
print(f'{Fore.GREEN}>>>{Style.RESET_ALL} Building {c.name()}')
|
||||
|
||||
if build_system.is_configuration_out_of_date():
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Configuring build...')
|
||||
build_system.configure(verbose=False)
|
||||
|
||||
if out_of_date:
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Building...')
|
||||
build_system.build(verbose=False)
|
||||
print(f'{Fore.CYAN} >>{Style.RESET_ALL} Installing...')
|
||||
build_system.install(verbose=False)
|
||||
|
||||
exec_info = self.__data.get('exec', None)
|
||||
if exec_info is None:
|
||||
raise CommandConfigurationError(f'Command {self.name()} has no executable configured')
|
||||
|
||||
args = exec_info.get('args', None)
|
||||
if args is None or len(args) == 0:
|
||||
raise CommandConfigurationError(f'Command {self.name()} has no executable configured')
|
||||
|
||||
ns = self.get_path_namespaces()
|
||||
expanded_args = []
|
||||
for p in args:
|
||||
parts = p.split(':')
|
||||
if len(parts) < 2 or parts[0] not in ns:
|
||||
expanded_args.append(p)
|
||||
continue
|
||||
|
||||
paths = Path(p).expand_path(relative_to=ns)
|
||||
expanded_args.extend(paths)
|
||||
|
||||
if expanded_args[0].endswith('.py'):
|
||||
expanded_args.insert(0, sys.executable)
|
||||
|
||||
env = os.environ | self.get_environment()
|
||||
result = None
|
||||
|
||||
try:
|
||||
result = subprocess.run(expanded_args, env=env)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
if result is not None and result.returncode != 0:
|
||||
raise CommandExecutionError(f'Execution of {self.name()} failed. See log for details')
|
||||
@@ -0,0 +1,64 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
config_path = 'build/meadow-config.json'
|
||||
config_data = None
|
||||
|
||||
|
||||
class Config:
|
||||
def load():
|
||||
global config_data
|
||||
|
||||
if not os.path.exists(config_path):
|
||||
config_data = {}
|
||||
return
|
||||
|
||||
with open(config_path, mode='r') as f:
|
||||
config_data = json.load(f)
|
||||
|
||||
|
||||
def save():
|
||||
global config_data
|
||||
|
||||
with open(config_path, mode='w') as f:
|
||||
json.dump(config_data, f, indent=4)
|
||||
|
||||
|
||||
def get(path):
|
||||
parts = path.split('.')
|
||||
container = config_data
|
||||
|
||||
for p in parts[:-1]:
|
||||
if p not in container:
|
||||
return None
|
||||
|
||||
if not isinstance(container[p], dict):
|
||||
print('Err: element "{}" in config key "{}" is not a dictionary'.format(p, path))
|
||||
return
|
||||
|
||||
container = container[p]
|
||||
|
||||
|
||||
if parts[-1] in container:
|
||||
return container[parts[-1]]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def set(path, value):
|
||||
parts = path.split('.')
|
||||
container = config_data
|
||||
|
||||
for p in parts[:-1]:
|
||||
if p not in container:
|
||||
container[p] = {}
|
||||
|
||||
if not isinstance(container[p], dict):
|
||||
print('Err: element "{}" in config key "{}" is not a dictionary'.format(p, path))
|
||||
return
|
||||
|
||||
container = container[p]
|
||||
|
||||
|
||||
container[parts[-1]] = value
|
||||
@@ -0,0 +1,156 @@
|
||||
import os
|
||||
|
||||
|
||||
class DependencyResolutionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DependencyItem:
|
||||
def __init__(self):
|
||||
self.__target = None
|
||||
self.__dep_list = None
|
||||
|
||||
|
||||
def name(self):
|
||||
return None
|
||||
|
||||
|
||||
def target(self):
|
||||
return self.__target
|
||||
|
||||
|
||||
def dependencies(self):
|
||||
return None
|
||||
|
||||
|
||||
def dependency_list(self):
|
||||
return self.__dep_list
|
||||
|
||||
|
||||
def publish(self):
|
||||
return None
|
||||
|
||||
|
||||
def reset_resolution(self):
|
||||
self.__dep_list = None
|
||||
|
||||
|
||||
def resolve(self, **kwargs):
|
||||
if self.__dep_list is not None:
|
||||
return self.__dep_list
|
||||
|
||||
ctx = None
|
||||
dep_list = None
|
||||
if 'ctx' in kwargs:
|
||||
ctx = kwargs['ctx']
|
||||
else:
|
||||
ctx = {}
|
||||
|
||||
if 'dep_list' in kwargs:
|
||||
dep_list = kwargs['dep_list']
|
||||
else:
|
||||
dep_list = []
|
||||
|
||||
if self.name() in ctx:
|
||||
return
|
||||
|
||||
ctx[self.name()] = self
|
||||
|
||||
deps = self.dependencies()
|
||||
if deps is None:
|
||||
return
|
||||
|
||||
for d in deps.values():
|
||||
d_value = d.resolve_self()
|
||||
if d_value is not None:
|
||||
d_value.resolve(ctx=ctx, dep_list=dep_list)
|
||||
|
||||
dep_list.append(self)
|
||||
return dep_list
|
||||
|
||||
|
||||
class Dependency:
|
||||
def __init__(self, parent):
|
||||
self.__parent = parent
|
||||
|
||||
|
||||
def name(self, parent):
|
||||
return None
|
||||
|
||||
|
||||
def parent_name(self):
|
||||
return self.__parent
|
||||
|
||||
|
||||
def resolve_self(self):
|
||||
return None
|
||||
|
||||
|
||||
def is_resolved(self):
|
||||
return False
|
||||
|
||||
|
||||
class SeedDependency(Dependency):
|
||||
def __init__(self, **kwargs):
|
||||
self.__target_seed = None
|
||||
if 'name' in kwargs:
|
||||
self.__name = kwargs['name']
|
||||
if 'parent' in kwargs:
|
||||
super().__init__(kwargs['parent'])
|
||||
|
||||
|
||||
def name(self):
|
||||
return self.__name
|
||||
|
||||
|
||||
def target(self):
|
||||
return self.__target_seed
|
||||
|
||||
|
||||
def resolve_self(self):
|
||||
from seed import Seed
|
||||
if self.__target_seed is not None:
|
||||
return self.__target_seed
|
||||
|
||||
target = Seed.get(self.__name)
|
||||
if target is None:
|
||||
raise DependencyResolutionError(
|
||||
'{} depends on seed "{}", but the required seed cannot be found'.format(self.parent_name(), self.__name))
|
||||
|
||||
self.__target_seed = target
|
||||
return self.__target_seed
|
||||
|
||||
|
||||
def is_resolved(self):
|
||||
return self.__target_seed is not None
|
||||
|
||||
|
||||
class ProgramDependency(Dependency):
|
||||
def __init__(self, **kwargs):
|
||||
if 'name' in kwargs:
|
||||
self.__name = kwargs['name']
|
||||
if 'parent' in kwargs:
|
||||
super().__init__(kwargs['parent'])
|
||||
|
||||
|
||||
def __is_exe(self, fpath):
|
||||
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||
|
||||
|
||||
def name(self):
|
||||
return self.__name
|
||||
|
||||
|
||||
def resolve_self(self):
|
||||
if self.__is_exe(self.__name):
|
||||
return None
|
||||
|
||||
path_string = os.environ['PATH']
|
||||
path_list = path_string.split(':')
|
||||
for d in path_list:
|
||||
exe_path = os.path.join(d, self.__name)
|
||||
if self.__is_exe(exe_path):
|
||||
return None
|
||||
|
||||
raise DependencyResolutionError(f'{self.parent_name()} depends on command `{self.__name}`, but the command cannot be found. Make sure that the named command exists, the containing directory is in $PATH if necessary, and the executable file has the correct permissions.')
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
|
||||
|
||||
source_root = None
|
||||
|
||||
|
||||
class Environment:
|
||||
def set_source_root(path):
|
||||
global source_root
|
||||
source_root = path
|
||||
|
||||
|
||||
def source_root():
|
||||
global source_root
|
||||
return source_root
|
||||
|
||||
|
||||
def build_root():
|
||||
global source_root
|
||||
return os.path.join(source_root, 'build')
|
||||
|
||||
|
||||
def system_root():
|
||||
return os.path.join(Environment.build_root(), 'target-root')
|
||||
|
||||
|
||||
def native_root():
|
||||
return os.path.join(Environment.build_root(), 'host-root')
|
||||
@@ -0,0 +1,140 @@
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from build import *
|
||||
from pathlib import Path as SysPath
|
||||
from cache import Cache
|
||||
from env import Environment
|
||||
from platform import Platform
|
||||
from target import Target
|
||||
from path import Path
|
||||
|
||||
class GenericBuildSystem(BuildSystem):
|
||||
def __init__(self, **kwargs):
|
||||
self.__data = kwargs.get('data', None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def __get_watched_files(self):
|
||||
result = []
|
||||
ns = self.get_path_namespaces()
|
||||
|
||||
if 'watch_files' in self.__data:
|
||||
watch_list = self.__data['watch_files']
|
||||
for p in watch_list:
|
||||
path = Path(p)
|
||||
|
||||
real_paths = path.expand_path(relative_to=ns)
|
||||
for p2 in real_paths:
|
||||
result.append(p2)
|
||||
|
||||
manifest_path = os.path.join(self.binary_dir(), 'compile_commands.json')
|
||||
manifest_file = None
|
||||
manifest = None
|
||||
try:
|
||||
manifest_file = open(manifest_path, mode='r')
|
||||
except:
|
||||
return result
|
||||
|
||||
try:
|
||||
manifest = json.load(manifest_file)
|
||||
except:
|
||||
return result
|
||||
|
||||
for v in manifest:
|
||||
if 'file' not in v:
|
||||
continue
|
||||
|
||||
path = v['file']
|
||||
result.append(path)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def __get_mtime(self):
|
||||
files = self.__get_watched_files()
|
||||
result = 0
|
||||
|
||||
for path in files:
|
||||
mtime = os.path.getmtime(path)
|
||||
|
||||
if mtime > result:
|
||||
result = mtime
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _is_configuration_out_of_date(self):
|
||||
return False
|
||||
|
||||
|
||||
def _is_build_out_of_date(self):
|
||||
current_mtime = self.__get_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if target_mtime is None:
|
||||
return True
|
||||
|
||||
if current_mtime > target_mtime:
|
||||
return True
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_system = d.build_system()
|
||||
if build_system is None:
|
||||
continue
|
||||
|
||||
if build_system.is_build_out_of_date() or build_system.is_configuration_out_of_date():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def __run_command(self, name, **kwargs):
|
||||
verbose = kwargs.get('verbose', False)
|
||||
ns = self.get_path_namespaces()
|
||||
stdout = None
|
||||
if not verbose:
|
||||
stdout = subprocess.DEVNULL
|
||||
|
||||
cmd = self.__data.get(name, None)
|
||||
if cmd is None:
|
||||
return
|
||||
|
||||
args = cmd.get('args', None)
|
||||
if args is None:
|
||||
raise BuildConfigurationError(f'{self.name()} is incorrectly configured. build_command has no args defined')
|
||||
|
||||
|
||||
expanded_args = []
|
||||
for p in args:
|
||||
parts = p.split(':')
|
||||
if len(parts) < 2 or parts[0] not in ns:
|
||||
expanded_args.append(p)
|
||||
continue
|
||||
|
||||
paths = Path(p).expand_path(relative_to=ns)
|
||||
expanded_args.extend(paths)
|
||||
|
||||
result = subprocess.run(expanded_args, stdout=stdout)
|
||||
if result.returncode != 0:
|
||||
raise BuildConfigurationError(f'Execution of {name} for {self.name()} failed. See log for details')
|
||||
|
||||
|
||||
def configure(self, **kwargs):
|
||||
self.__run_command('configure_command', **kwargs)
|
||||
|
||||
|
||||
def build(self, **kwargs):
|
||||
self.__run_command('build_command', **kwargs)
|
||||
|
||||
|
||||
def install(self, **kwargs):
|
||||
self.install_from_seed()
|
||||
|
||||
previous_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if previous_mtime is None:
|
||||
previous_mtime = 0
|
||||
|
||||
new_mtime = self.__get_mtime()
|
||||
if new_mtime > previous_mtime:
|
||||
Cache.set(f'component.{self.name()}.build-mtime', new_mtime)
|
||||
@@ -0,0 +1,95 @@
|
||||
import sys
|
||||
import os
|
||||
import tomli
|
||||
from seed import Seed
|
||||
from target import Target
|
||||
from platform import Platform
|
||||
from config import Config
|
||||
from cache import Cache
|
||||
from command import Command, UserCommand
|
||||
from args import Args
|
||||
from env import Environment
|
||||
from dependency import SeedDependency, DependencyResolutionError
|
||||
from builtin import *
|
||||
from colorama import init as colorama_init
|
||||
from colorama import Fore, Style
|
||||
|
||||
|
||||
def main():
|
||||
colorama_init()
|
||||
Command.register(SetCommand())
|
||||
Command.register(SeedsCommand())
|
||||
Command.register(PlatformsCommand())
|
||||
Command.register(HelpCommand())
|
||||
Command.register(BuildCommand())
|
||||
Command.register(CleanCommand())
|
||||
Config.load()
|
||||
Cache.load()
|
||||
Environment.set_source_root(os.getcwd())
|
||||
|
||||
Seed.scan_directory([
|
||||
'base',
|
||||
'external',
|
||||
'interface',
|
||||
'toolchain',
|
||||
'lib',
|
||||
'programs',
|
||||
'services',
|
||||
'sys'
|
||||
])
|
||||
|
||||
UserCommand.scan_directory([
|
||||
'toolchain'
|
||||
])
|
||||
|
||||
Target.scan_directory('./target')
|
||||
platforms = Platform.scan_directory('./arch')
|
||||
|
||||
current_platform = Platform.current_platform()
|
||||
if current_platform:
|
||||
current_platform.load_extensions()
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(f'{Fore.CYAN}Usage:{Style.RESET_ALL} {sys.argv[0]} <command> [args...]')
|
||||
return -1
|
||||
|
||||
command_name = sys.argv[1]
|
||||
command = Command.get(command_name)
|
||||
if command is None:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} unknown command "{command_name}"')
|
||||
return -1
|
||||
|
||||
current_target = Target.current_target()
|
||||
seeds = Seed.all_seeds()
|
||||
|
||||
if current_target is not None:
|
||||
system_dep_names = current_target.base_components()
|
||||
|
||||
for s in seeds.values():
|
||||
if s.name() in system_dep_names or not s.should_include_standard_dependencies():
|
||||
continue
|
||||
|
||||
for n in system_dep_names:
|
||||
s.add_dependency(n, SeedDependency(parent=s.name(), name=n))
|
||||
|
||||
try:
|
||||
current_target.resolve()
|
||||
except DependencyResolutionError as e:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} {e}')
|
||||
return -1
|
||||
|
||||
args = Args(sys.argv[2:])
|
||||
result = None
|
||||
try:
|
||||
result = command.run(args)
|
||||
except Exception as e:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} {e}')
|
||||
finally:
|
||||
Cache.save()
|
||||
Config.save()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
||||
@@ -0,0 +1,88 @@
|
||||
import glob
|
||||
import os
|
||||
|
||||
|
||||
class Path:
|
||||
def __init__(self, value):
|
||||
self.__path = value
|
||||
self.__namespace = None
|
||||
|
||||
parts = value.split(':')
|
||||
|
||||
if len(parts) != 2:
|
||||
return
|
||||
|
||||
if len(parts[0]) < 3:
|
||||
return
|
||||
|
||||
self.__namespace = parts[0]
|
||||
self.__path = parts[1]
|
||||
|
||||
|
||||
def get_path(self):
|
||||
return self.__path
|
||||
|
||||
|
||||
def remove_root(self):
|
||||
while len(self.__path) > 0 and self.__path[0] == '/':
|
||||
self.__path = self.__path [1:]
|
||||
|
||||
if len(self.__path) == 0:
|
||||
self.__path= '.'
|
||||
|
||||
return self
|
||||
|
||||
|
||||
def expand_path(self, **kwargs):
|
||||
relative_to = None
|
||||
|
||||
if 'relative_to' in kwargs:
|
||||
relative_to = kwargs['relative_to']
|
||||
|
||||
if isinstance(relative_to, dict):
|
||||
if self.__namespace is not None:
|
||||
relative_to = relative_to[self.__namespace]
|
||||
else:
|
||||
relative_to = None
|
||||
|
||||
paths = glob.glob(self.__path, root_dir=relative_to, recursive=True)
|
||||
if len(paths) == 0 and '*' not in self.__path:
|
||||
if relative_to is not None:
|
||||
return [os.path.join(relative_to, self.__path)]
|
||||
return [self.__path]
|
||||
|
||||
if relative_to is not None:
|
||||
abs_paths = []
|
||||
|
||||
for p in paths:
|
||||
abs_paths.append(os.path.join(relative_to, p))
|
||||
|
||||
return abs_paths
|
||||
|
||||
return paths
|
||||
|
||||
|
||||
def expand_all(paths, **kwargs):
|
||||
relative_to = None
|
||||
|
||||
if 'relative_to' in kwargs:
|
||||
relative_to = kwargs['relative_to']
|
||||
|
||||
result = []
|
||||
for p in paths:
|
||||
if not isinstance(p, Path):
|
||||
p = Path(p)
|
||||
r = p.expand_path(relative_to=relative_to)
|
||||
result.extend(r)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_namespace(self, **kwargs):
|
||||
if self.__namespace is not None:
|
||||
return self.__namespace
|
||||
|
||||
if 'default' in kwargs:
|
||||
return kwargs['default']
|
||||
|
||||
return None
|
||||
@@ -0,0 +1,119 @@
|
||||
import os
|
||||
import sys
|
||||
import tomli
|
||||
from config import Config
|
||||
from command import Command, UserCommand
|
||||
|
||||
|
||||
all_platforms = {}
|
||||
|
||||
|
||||
class Platform:
|
||||
def all_platforms():
|
||||
return all_platforms
|
||||
|
||||
|
||||
def current_platform():
|
||||
name = Config.get('target.platform')
|
||||
if not name or name not in all_platforms:
|
||||
return None
|
||||
|
||||
return all_platforms[name]
|
||||
|
||||
|
||||
def load_file(self, path):
|
||||
self.__path = path
|
||||
with open(path, mode='rb') as f:
|
||||
self.__data = tomli.load(f)
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
if 'path' in kwargs:
|
||||
self.__platform_file = os.path.abspath(kwargs['path'])
|
||||
self.load_file(kwargs['path'])
|
||||
|
||||
|
||||
def base_directory(self):
|
||||
return os.path.dirname(self.__platform_file)
|
||||
|
||||
|
||||
def name(self):
|
||||
if 'platform' not in self.__data:
|
||||
return None
|
||||
|
||||
platform = self.__data['platform']
|
||||
if 'name' in platform:
|
||||
return platform['name']
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def arch(self):
|
||||
if 'platform' not in self.__data:
|
||||
return None
|
||||
|
||||
platform = self.__data['platform']
|
||||
if 'arch' in platform:
|
||||
return platform['arch']
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def load_extensions(self):
|
||||
from seed import Seed
|
||||
if 'extension' not in self.__data:
|
||||
return
|
||||
|
||||
|
||||
all_seeds = Seed.all_seeds()
|
||||
|
||||
extension_dir = os.path.dirname(self.__path)
|
||||
extension = self.__data['extension']
|
||||
|
||||
if 'seeds' in extension:
|
||||
seeds = extension['seeds']
|
||||
for seed_filename in seeds:
|
||||
seed_path = os.path.join(extension_dir, seed_filename)
|
||||
seed = None
|
||||
try:
|
||||
seed = Seed(path=seed_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
print('Err: Failed to parse seed file {}\n {}'.format(seed_path, e))
|
||||
return -1
|
||||
|
||||
all_seeds[seed.name()] = seed
|
||||
|
||||
if 'commands' in extension:
|
||||
commands = extension['commands']
|
||||
for cmd_filename in commands:
|
||||
cmd_path = os.path.join(extension_dir, cmd_filename)
|
||||
cmd = None
|
||||
try:
|
||||
cmd = UserCommand(path=cmd_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
print('Err: Failed to parse command file {}\n {}'.format(seed_path, e))
|
||||
return -1
|
||||
|
||||
Command.register(cmd)
|
||||
|
||||
|
||||
def get_component(self, name):
|
||||
if name in self.__data:
|
||||
return self.__data[name]
|
||||
return None
|
||||
|
||||
|
||||
def scan_directory(root_path):
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for f in files:
|
||||
if not f.endswith('.platform'):
|
||||
continue
|
||||
platform_path = os.path.join(root, f)
|
||||
platform = None
|
||||
try:
|
||||
platform = Platform(path=platform_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
print('Err: Failed to parse platform file {}\n {}'.format(platform_path, e))
|
||||
continue
|
||||
|
||||
all_platforms[platform.name()] = platform
|
||||
@@ -0,0 +1,21 @@
|
||||
import os
|
||||
|
||||
|
||||
class Publish:
|
||||
def __init__(self, **kwargs):
|
||||
self.__data = None
|
||||
self.__install_root = None
|
||||
|
||||
if 'data' in kwargs:
|
||||
self.__data = kwargs['data']
|
||||
|
||||
if 'install_path' in kwargs:
|
||||
self.__install_root = kwargs['install_path']
|
||||
|
||||
|
||||
def path(self):
|
||||
return self.__data.get('path', None)
|
||||
|
||||
|
||||
def cmake(self):
|
||||
return self.__data.get('cmake', None)
|
||||
@@ -0,0 +1,2 @@
|
||||
tomli
|
||||
colorama
|
||||
@@ -0,0 +1,219 @@
|
||||
import os
|
||||
import sys
|
||||
import tomli
|
||||
from dependency import *
|
||||
from cmake import CMakeBuildSystem
|
||||
from publish import Publish
|
||||
from build import UnknownBuildSystemError
|
||||
from env import Environment
|
||||
from source_only import SourceOnlyBuildSystem
|
||||
from generic import GenericBuildSystem
|
||||
|
||||
|
||||
all_seeds = {}
|
||||
|
||||
|
||||
class SeedParseError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Seed(DependencyItem):
|
||||
def all_seeds():
|
||||
return all_seeds
|
||||
|
||||
|
||||
def get(name):
|
||||
if name in all_seeds:
|
||||
return all_seeds[name]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def load_file(self, path):
|
||||
with open(path, mode='rb') as f:
|
||||
self.__data = tomli.load(f)
|
||||
|
||||
|
||||
def __init_dependencies(self):
|
||||
self.__dependencies = {}
|
||||
|
||||
if 'dependency' not in self.__data:
|
||||
return
|
||||
|
||||
dependency = self.__data['dependency']
|
||||
if 'seeds' in dependency:
|
||||
seeds = dependency['seeds']
|
||||
self.__dependencies = {}
|
||||
for s in seeds:
|
||||
self.__dependencies[s] = SeedDependency(parent=self.name(), name=s)
|
||||
|
||||
|
||||
def __init_build_system(self):
|
||||
self.__build_system = None
|
||||
if 'build' not in self.__data:
|
||||
return
|
||||
|
||||
build = self.__data['build']
|
||||
if 'build_system' not in build:
|
||||
return
|
||||
|
||||
source_dir = os.path.dirname(self.__seed_path)
|
||||
bin_dir = os.path.join(Environment.build_root(), self.name())
|
||||
install = self.__data.get('install', None)
|
||||
|
||||
if 'source_dir' in build:
|
||||
source_dir = build['source_dir']
|
||||
|
||||
match build['build_system']:
|
||||
case 'none':
|
||||
self.__build_system = None
|
||||
case 'cmake':
|
||||
self.__build_system = CMakeBuildSystem(
|
||||
parent=self,
|
||||
name=self.name(),
|
||||
source_dir=source_dir,
|
||||
bin_dir=bin_dir,
|
||||
install=install,
|
||||
data=build)
|
||||
case 'source-only':
|
||||
self.__build_system = SourceOnlyBuildSystem(
|
||||
parent=self,
|
||||
name=self.name(),
|
||||
source_dir=source_dir,
|
||||
bin_dir=bin_dir,
|
||||
install=install,
|
||||
data=build)
|
||||
case 'generic':
|
||||
self.__build_system = GenericBuildSystem(
|
||||
parent=self,
|
||||
name=self.name(),
|
||||
source_dir=source_dir,
|
||||
bin_dir=bin_dir,
|
||||
install=install,
|
||||
data=build)
|
||||
case _:
|
||||
raise UnknownBuildSystemError(
|
||||
'Seed {} has unrecognised build system "{}"'.format(self.name(), build['build_system']))
|
||||
|
||||
|
||||
def __init_publish(self):
|
||||
install_path = Environment.system_root()
|
||||
if 'build' in self.__data and 'build_for' in self.__data['build']:
|
||||
build_for = self.__data['build']['build_for']
|
||||
if build_for == 'host':
|
||||
install_path = Environment.native_root()
|
||||
|
||||
self.__publish = None
|
||||
if 'publish' not in self.__data:
|
||||
return
|
||||
|
||||
self.__publish = Publish(install_path=install_path, data=self.__data['publish'])
|
||||
|
||||
|
||||
def add_dependency(self, name, dep):
|
||||
self.__dependencies[name] = dep
|
||||
|
||||
|
||||
def collect_dependencies(self, **kwargs):
|
||||
ctx = None
|
||||
if 'ctx' in kwargs:
|
||||
ctx = kwargs['ctx']
|
||||
else:
|
||||
ctx = {}
|
||||
|
||||
for k, d in self.__dependencies.items():
|
||||
if k in ctx:
|
||||
continue
|
||||
|
||||
ctx[d.name()] = d.target()
|
||||
if isinstance(d.target(), Seed):
|
||||
d.target().collect_dependencies(ctx=ctx)
|
||||
|
||||
return list(ctx.values())
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__()
|
||||
|
||||
if not 'path' in kwargs:
|
||||
return
|
||||
|
||||
self.__seed_path = kwargs['path']
|
||||
self.load_file(kwargs['path'])
|
||||
self.__init_dependencies()
|
||||
self.__init_build_system()
|
||||
self.__init_publish()
|
||||
|
||||
|
||||
def seed_path(self):
|
||||
return self.__seed_path
|
||||
|
||||
|
||||
def name(self):
|
||||
if not 'seed' in self.__data:
|
||||
return None
|
||||
|
||||
s = self.__data['seed']
|
||||
if 'name' in s:
|
||||
return s['name']
|
||||
return None
|
||||
|
||||
|
||||
def type(self):
|
||||
if not 'seed' in self.__data:
|
||||
return None
|
||||
|
||||
s = self.__data['seed']
|
||||
if 'type' in s:
|
||||
return s['type']
|
||||
return 'component'
|
||||
|
||||
|
||||
def dependencies(self):
|
||||
return self.__dependencies
|
||||
|
||||
|
||||
def publish(self):
|
||||
return self.__publish
|
||||
|
||||
|
||||
def install(self):
|
||||
return self.__data.get('install', None)
|
||||
|
||||
|
||||
def should_include_standard_dependencies(self):
|
||||
if 'dependency' not in self.__data:
|
||||
return True
|
||||
|
||||
s = self.__data['dependency']
|
||||
if 'no_standard_dependencies' in s:
|
||||
return not s['no_standard_dependencies']
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def build_system(self):
|
||||
return self.__build_system
|
||||
|
||||
|
||||
def scan_directory(paths):
|
||||
for p in paths:
|
||||
for root, dirs, files in os.walk(p):
|
||||
for f in files:
|
||||
if not f.endswith('.seed'):
|
||||
continue
|
||||
seed_path = os.path.join(root, f)
|
||||
seed = None
|
||||
try:
|
||||
seed = Seed(path=seed_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
raise SeedParseError('Err: Failed to parse seed file {}: {}'.format(seed_path, e))
|
||||
|
||||
all_seeds[seed.name()] = seed
|
||||
|
||||
|
||||
def resolve_all():
|
||||
for s in all_seeds.values():
|
||||
deps = s.dependencies()
|
||||
for k, v in deps.items():
|
||||
v.resolve()
|
||||
@@ -0,0 +1,119 @@
|
||||
import os
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from build import *
|
||||
from pathlib import Path as SysPath
|
||||
from cache import Cache
|
||||
from env import Environment
|
||||
from platform import Platform
|
||||
from target import Target
|
||||
from path import Path
|
||||
|
||||
class SourceOnlyBuildSystem(BuildSystem):
|
||||
def __init__(self, **kwargs):
|
||||
self.__data = kwargs.get('data', None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def __get_watched_files(self):
|
||||
result = []
|
||||
ns = self.get_path_namespaces()
|
||||
|
||||
if 'watch_files' in self.__data:
|
||||
watch_list = self.__data['watch_files']
|
||||
for p in watch_list:
|
||||
path = Path(p)
|
||||
|
||||
real_paths = path.expand_path(relative_to=ns)
|
||||
for p2 in real_paths:
|
||||
result.append(p2)
|
||||
|
||||
manifest_path = os.path.join(self.binary_dir(), 'compile_commands.json')
|
||||
manifest_file = None
|
||||
manifest = None
|
||||
try:
|
||||
manifest_file = open(manifest_path, mode='r')
|
||||
except:
|
||||
return result
|
||||
|
||||
try:
|
||||
manifest = json.load(manifest_file)
|
||||
except:
|
||||
return result
|
||||
|
||||
for v in manifest:
|
||||
if 'file' not in v:
|
||||
continue
|
||||
|
||||
path = v['file']
|
||||
result.append(path)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def __get_mtime(self):
|
||||
files = self.__get_watched_files()
|
||||
result = 0
|
||||
|
||||
for path in files:
|
||||
mtime = os.path.getmtime(path)
|
||||
|
||||
if mtime > result:
|
||||
result = mtime
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _is_configuration_out_of_date(self):
|
||||
parent = self.parent()
|
||||
seed_path = parent.seed_path()
|
||||
seed_mtime = os.path.getmtime(seed_path)
|
||||
target_mtime = Cache.get(f'component.{self.name()}.configure-mtime')
|
||||
if target_mtime is None:
|
||||
return True
|
||||
|
||||
return seed_mtime > target_mtime
|
||||
|
||||
|
||||
def _is_build_out_of_date(self):
|
||||
current_mtime = self.__get_mtime()
|
||||
target_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if target_mtime is None:
|
||||
return True
|
||||
|
||||
if current_mtime > target_mtime:
|
||||
return True
|
||||
|
||||
for d in self.parent().collect_dependencies():
|
||||
build_system = d.build_system()
|
||||
if build_system is None:
|
||||
continue
|
||||
|
||||
if build_system.is_build_out_of_date() or build_system.is_configuration_out_of_date():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def configure(self, **kwargs):
|
||||
parent = self.parent()
|
||||
seed_path = parent.seed_path()
|
||||
seed_mtime = os.path.getmtime(seed_path)
|
||||
Cache.set(f'component.{self.name()}.configure-mtime', seed_mtime)
|
||||
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def install(self, **kwargs):
|
||||
self.install_from_seed()
|
||||
|
||||
previous_mtime = Cache.get(f'component.{self.name()}.build-mtime')
|
||||
if previous_mtime is None:
|
||||
previous_mtime = 0
|
||||
|
||||
new_mtime = self.__get_mtime()
|
||||
if new_mtime > previous_mtime:
|
||||
Cache.set(f'component.{self.name()}.build-mtime', new_mtime)
|
||||
@@ -0,0 +1,105 @@
|
||||
import os
|
||||
import sys
|
||||
import tomli
|
||||
from dependency import *
|
||||
from config import Config
|
||||
from path import Path
|
||||
|
||||
|
||||
all_targets = {}
|
||||
|
||||
|
||||
class Target(DependencyItem):
|
||||
def all_targets():
|
||||
global all_targets
|
||||
return all_targets
|
||||
|
||||
|
||||
def current_target():
|
||||
name = Config.get('target.name')
|
||||
if not name or name not in all_targets:
|
||||
return None
|
||||
|
||||
return all_targets[name]
|
||||
|
||||
|
||||
def load_file(self, path):
|
||||
with open(path, mode='rb') as f:
|
||||
self.__data = tomli.load(f)
|
||||
|
||||
|
||||
def __init_dependencies(self):
|
||||
self.__dependencies = {}
|
||||
|
||||
if 'dependency' not in self.__data:
|
||||
return
|
||||
|
||||
dependency = self.__data['dependency']
|
||||
if 'seeds' in dependency:
|
||||
seeds = dependency['seeds']
|
||||
self.__dependencies = {}
|
||||
for s in seeds:
|
||||
self.__dependencies[s] = SeedDependency(parent=self.name(), name=s)
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__()
|
||||
|
||||
if 'path' not in kwargs:
|
||||
return
|
||||
|
||||
self.load_file(kwargs['path'])
|
||||
self.__init_dependencies()
|
||||
|
||||
|
||||
def name(self):
|
||||
if not 'target' in self.__data:
|
||||
return None
|
||||
|
||||
s = self.__data['target']
|
||||
if 'name' in s:
|
||||
return s['name']
|
||||
return None
|
||||
|
||||
|
||||
def dependencies(self):
|
||||
return self.__dependencies
|
||||
|
||||
|
||||
def base_components(self):
|
||||
if not 'target' in self.__data:
|
||||
return None
|
||||
|
||||
s = self.__data['target']
|
||||
if 'base_components' in s:
|
||||
return s['base_components']
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def install_prefix(self, **kwargs):
|
||||
make_relative = kwargs.get('make_relative', False)
|
||||
path = self.__data.get('target', {}).get('default_prefix', '/')
|
||||
|
||||
if make_relative:
|
||||
path = Path(path).remove_root().get_path
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def scan_directory(root_path):
|
||||
global all_targets
|
||||
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for f in files:
|
||||
if not f.endswith('.target'):
|
||||
continue
|
||||
target_path = os.path.join(root, f)
|
||||
target = None
|
||||
try:
|
||||
target = Target(path=target_path)
|
||||
except tomli.TOMLDecodeError as e:
|
||||
print('Err: Failed to parse target file {}\n {}'.format(target_path, e))
|
||||
continue
|
||||
|
||||
all_targets[target.name()] = target
|
||||
@@ -0,0 +1,41 @@
|
||||
class Args:
|
||||
def __init__(self, argv):
|
||||
self.__argv = argv
|
||||
|
||||
|
||||
def get_positional(self, index):
|
||||
if len(self.__argv) > index:
|
||||
return self.__argv[index]
|
||||
return None
|
||||
|
||||
|
||||
def get_named(self, name, index, nr_args):
|
||||
found_name = False
|
||||
values = []
|
||||
|
||||
for s in self.__argv:
|
||||
if found_name:
|
||||
if len(values) < nr_args:
|
||||
values.append(s)
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
if s == '--{}'.format(name):
|
||||
if index > 0:
|
||||
index -= 1
|
||||
continue
|
||||
|
||||
found_name = True
|
||||
continue
|
||||
|
||||
if nr_args == 0:
|
||||
return found_name
|
||||
|
||||
if len(values) < nr_args or not found_name:
|
||||
return None
|
||||
|
||||
if len(values) == 1:
|
||||
return values[0]
|
||||
|
||||
return values
|
||||
@@ -0,0 +1,98 @@
|
||||
import os
|
||||
import struct
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
from elf import ELF64Image
|
||||
|
||||
|
||||
class BSPWriteError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BSP:
|
||||
def __init__(self, out_path, **kwargs):
|
||||
if os.path.exists(out_path):
|
||||
os.remove(out_path)
|
||||
|
||||
self.__bootstrap_exec_path = None
|
||||
self.__path = out_path
|
||||
self.__sysroot = kwargs.get('sysroot', None)
|
||||
|
||||
out_dir = os.path.dirname(out_path)
|
||||
Path(out_dir).mkdir(parents=True, exist_ok=True)
|
||||
self.__tarfile = tarfile.open(name=out_path, mode='x')
|
||||
|
||||
|
||||
def add_file(self, src, dst):
|
||||
if self.__sysroot is not None:
|
||||
while src[0] == '/':
|
||||
src = src[1:]
|
||||
src = os.path.join(self.__sysroot, src)
|
||||
print(f'tarfile.add({src}, arcname={dst})')
|
||||
self.__tarfile.add(src, arcname=dst)
|
||||
|
||||
|
||||
def set_bootstrap_program(self, path):
|
||||
if self.__sysroot is not None:
|
||||
while path[0] == '/':
|
||||
path = path[1:]
|
||||
path = os.path.join(self.__sysroot, path)
|
||||
self.__bootstrap_exec_path = path
|
||||
|
||||
|
||||
def __write_trailer(self):
|
||||
bootstrap_offset = os.path.getsize(self.__path)
|
||||
print(f'bootstrap_offset was {bootstrap_offset}')
|
||||
bsp = open(self.__path, mode='ab')
|
||||
prog = open(self.__bootstrap_exec_path, mode='rb')
|
||||
|
||||
padding = 0x1000 - (bootstrap_offset % 0x1000)
|
||||
bsp.write(b'\0' * padding)
|
||||
bootstrap_offset += padding
|
||||
prog_len = 0
|
||||
print(f'bootstrap_offset is now {bootstrap_offset}')
|
||||
|
||||
while True:
|
||||
data = prog.read(1024)
|
||||
bsp.write(data)
|
||||
prog_len += len(data)
|
||||
|
||||
if len(data) < 1024:
|
||||
break
|
||||
|
||||
prog.close()
|
||||
|
||||
prog_elf = ELF64Image()
|
||||
if prog_elf.load(self.__bootstrap_exec_path) != 0:
|
||||
raise BSPWriteError(f'{self.__bootstrap_exec_path} is not a valid ELF binary')
|
||||
|
||||
for ph in prog_elf.ph_list:
|
||||
print('{}: {}/{} ({}/{} bytes) {}'.format(
|
||||
ph.type,
|
||||
ph.offset, ph.vaddr,
|
||||
ph.filesz, ph.memsz, ph.flags))
|
||||
|
||||
trailer = struct.pack('>IQIQIQQQQQQQ',
|
||||
0xcafebabe,
|
||||
0, bootstrap_offset,
|
||||
bootstrap_offset, prog_len,
|
||||
prog_elf.text.offset, prog_elf.text.vaddr, prog_elf.text.memsz,
|
||||
prog_elf.data.offset, prog_elf.data.vaddr, prog_elf.data.memsz,
|
||||
prog_elf.entry)
|
||||
|
||||
bsp.write(trailer)
|
||||
|
||||
bsp.close()
|
||||
prog.close()
|
||||
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
|
||||
def close(self):
|
||||
self.__tarfile.close()
|
||||
if self.__bootstrap_exec_path is None:
|
||||
return
|
||||
|
||||
self.__write_trailer()
|
||||
@@ -0,0 +1,102 @@
|
||||
from enum import Enum, Flag
|
||||
import struct
|
||||
|
||||
class ELFPType(Enum):
|
||||
NULL = 0
|
||||
LOAD = 1
|
||||
DYNAMIC = 2
|
||||
INTERP = 3
|
||||
NOTE = 4
|
||||
SHLIB = 5
|
||||
PHDR = 6
|
||||
TLS = 7
|
||||
|
||||
|
||||
class ELFPFlag(Flag):
|
||||
NONE = 0
|
||||
EXEC = 1
|
||||
WRITE = 2
|
||||
READ = 4
|
||||
|
||||
|
||||
class ELFEndian(Enum):
|
||||
LITTLE = 1
|
||||
BIG = 2
|
||||
|
||||
|
||||
class ELF64Phdr:
|
||||
def __init__(self):
|
||||
self.type = ELFPType.NULL
|
||||
self.flags = 0
|
||||
self.offset = 0
|
||||
self.vaddr = 0
|
||||
self.paddr = 0
|
||||
self.filesz = 0
|
||||
self.memsz = 0
|
||||
self.align = 0
|
||||
|
||||
return
|
||||
|
||||
def parse(self, buf, endian):
|
||||
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||||
entry = struct.unpack('{}IIQQQQQQ'.format(endian_marker), buf)
|
||||
|
||||
self.type = ELFPType(entry[0])
|
||||
self.flags = ELFPFlag.NONE
|
||||
self.offset = entry[2]
|
||||
self.vaddr = entry[3]
|
||||
self.paddr = entry[4]
|
||||
self.filesz = entry[5]
|
||||
self.memsz = entry[6]
|
||||
self.align = entry[7]
|
||||
|
||||
if entry[1] & ELFPFlag.READ.value: self.flags |= ELFPFlag.READ
|
||||
if entry[1] & ELFPFlag.WRITE.value: self.flags |= ELFPFlag.WRITE
|
||||
if entry[1] & ELFPFlag.EXEC.value: self.flags |= ELFPFlag.EXEC
|
||||
|
||||
|
||||
class ELF64Image:
|
||||
def __init__(self):
|
||||
self.ph_list = []
|
||||
self.text = None
|
||||
self.data = None
|
||||
self.entry = None
|
||||
|
||||
def load(self, path):
|
||||
f = open(path, mode='rb')
|
||||
ident_bytes = f.read(16)
|
||||
|
||||
ident = struct.unpack('BBBBBBBBBBBBBBBB', ident_bytes)
|
||||
|
||||
if ident[0] != 0x7F or ident[1] != ord('E') or ident[2] != ord('L') or ident[3] != ord('F'):
|
||||
f.close()
|
||||
return -1
|
||||
|
||||
endian = ELFEndian(ident[5])
|
||||
endian_marker = '>' if endian == ELFEndian.BIG else '<'
|
||||
|
||||
hdr_bytes = f.read(48)
|
||||
hdr = struct.unpack('{}HHIQQQIHHHHHH'.format(endian_marker), hdr_bytes)
|
||||
|
||||
self.entry = hdr[3]
|
||||
phoff = hdr[4]
|
||||
phnum = hdr[9]
|
||||
phentsize = hdr[8]
|
||||
|
||||
for i in range(0, phnum):
|
||||
f.seek(phoff + (i * phentsize))
|
||||
phdr_bytes = f.read(phentsize)
|
||||
|
||||
phdr = ELF64Phdr()
|
||||
phdr.parse(phdr_bytes, endian)
|
||||
|
||||
if phdr.flags == ELFPFlag.READ | ELFPFlag.EXEC:
|
||||
self.text = phdr
|
||||
if phdr.flags == ELFPFlag.READ | ELFPFlag.WRITE:
|
||||
self.data = phdr
|
||||
|
||||
self.ph_list.append(phdr)
|
||||
|
||||
f.close()
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import sys
|
||||
import os
|
||||
import tomli
|
||||
from colorama import init as colorama_init
|
||||
from colorama import Fore, Style
|
||||
from args import Args
|
||||
from preset import Preset
|
||||
from bsp import BSP
|
||||
|
||||
|
||||
def main():
|
||||
colorama_init()
|
||||
|
||||
args = Args(sys.argv)
|
||||
|
||||
preset_path = args.get_named('preset', 0, 1)
|
||||
if preset_path is None:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} no preset specified')
|
||||
return -1
|
||||
|
||||
out_path = args.get_named('out', 0, 1)
|
||||
if out_path is None:
|
||||
print(f'{Fore.RED}Err:{Style.RESET_ALL} no output path specified')
|
||||
return -1
|
||||
|
||||
sysroot_path = args.get_named('sysroot', 0, 1)
|
||||
if sysroot_path is None:
|
||||
sysroot_path = '/'
|
||||
|
||||
preset = Preset(preset_path)
|
||||
|
||||
bsp = BSP(out_path, sysroot=sysroot_path)
|
||||
for dst, src in preset.contents().items():
|
||||
for src_filepath in src:
|
||||
src_filename = os.path.basename(src_filepath)
|
||||
dst_filepath = os.path.join(dst, src_filename)
|
||||
bsp.add_file(src_filepath, dst_filepath)
|
||||
|
||||
bsp.set_bootstrap_program(preset.bootstrap_program())
|
||||
bsp.close()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOURCE_ROOT="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/../.."
|
||||
|
||||
if [ ! -d "$SOURCE_ROOT/build" ]; then
|
||||
mkdir build
|
||||
fi
|
||||
|
||||
if [ ! -d "$SOURCE_ROOT/build/mkbsp_venv" ]; then
|
||||
echo 'Initialising mkbsp...'
|
||||
python3 -m venv $SOURCE_ROOT/build/mkbsp_venv
|
||||
source $SOURCE_ROOT/build/mkbsp_venv/bin/activate
|
||||
pip install -r $SOURCE_ROOT/toolchain/mkbsp/requirements.txt
|
||||
else
|
||||
source $SOURCE_ROOT/build/mkbsp_venv/bin/activate
|
||||
fi
|
||||
|
||||
python3 $SOURCE_ROOT/toolchain/mkbsp/main.py "$@"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user