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
|
||||||
.pybuilder/
|
.pybuilder/
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
# Jupyter Notebook
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
@@ -341,5 +340,6 @@ pyrightconfig.json
|
|||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/c,vim,linux,macos,windows,cmake,python
|
# End of https://www.toptal.com/developers/gitignore/api/c,vim,linux,macos,windows,cmake,python
|
||||||
|
|
||||||
build*
|
build
|
||||||
|
build-native
|
||||||
.cache
|
.cache
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
set(CMAKE_SYSTEM_NAME Rosetta)
|
set(CMAKE_SYSTEM_NAME Rosetta)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
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(C_COMPILER x86_64-rosetta-gcc REQUIRED)
|
||||||
find_program(CXX_COMPILER x86_64-elf-g++ REQUIRED)
|
find_program(CXX_COMPILER x86_64-rosetta-g++ REQUIRED)
|
||||||
#find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
#find_program(ASM_COMPILER x86_64-elf-as REQUIRED)
|
||||||
|
|
||||||
add_compile_definitions(__magenta__=1 __rosetta__=1)
|
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_CXX_COMPILER ${CXX_COMPILER})
|
||||||
#set(CMAKE_ASM_COMPILER ${ASM_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_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 "-Wl,-shared" 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_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_OPTIONS_PIE "-pie")
|
||||||
set(CMAKE_C_LINK_PIE_SUPPORTED TRUE)
|
set(CMAKE_C_LINK_PIE_SUPPORTED TRUE)
|
||||||
set(CMAKE_C_LINK_NO_PIE_SUPPORTED TRUE)
|
set(CMAKE_C_LINK_NO_PIE_SUPPORTED TRUE)
|
||||||
SET(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
|
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_C_OUTPUT_EXTENSION .o)
|
||||||
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
set(CMAKE_CXX_OUTPUT_EXTENSION .o)
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
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)
|
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})
|
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
add_dependencies(iflib-${arg_NAME} ifgen-${arg_NAME})
|
add_dependencies(iflib-${arg_NAME} ifgen-${arg_NAME})
|
||||||
add_library(interface::${arg_NAME} ALIAS iflib-${arg_NAME})
|
add_library(interface::${arg_NAME} ALIAS iflib-${arg_NAME})
|
||||||
|
install(FILES ${header_path} DESTINATION include/${arg_PARENT_DIR})
|
||||||
endfunction(add_interface)
|
endfunction(add_interface)
|
||||||
|
|
||||||
function(iface_get_header_path)
|
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)
|
file(GLOB if_files *.xpc)
|
||||||
|
|
||||||
foreach (file ${if_files})
|
foreach (file ${if_files})
|
||||||
get_filename_component(name ${file} NAME_WLE)
|
get_filename_component(name ${file} NAME_WLE)
|
||||||
add_interface(NAME ${name} PATH ${file} PARENT_DIR rosetta)
|
add_interface(NAME ${name} PATH ${file} PARENT_DIR rosetta)
|
||||||
sysroot_add_interface(NAME ${name} DEST_DIR /usr/include)
|
|
||||||
endforeach (file)
|
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(source_dirs core malloc io exec)
|
||||||
|
|
||||||
|
set(LIBC_STANDALONE FALSE)
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
add_subdirectory(runtime)
|
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
add_subdirectory(${dir})
|
add_subdirectory(${dir})
|
||||||
set(sources ${sources} ${component_sources})
|
set(sources ${sources} ${component_sources})
|
||||||
@@ -12,22 +14,11 @@ foreach (dir ${source_dirs})
|
|||||||
set(public_include_dirs ${public_include_dirs} ${component_public_include_dirs})
|
set(public_include_dirs ${public_include_dirs} ${component_public_include_dirs})
|
||||||
endforeach (dir)
|
endforeach (dir)
|
||||||
|
|
||||||
rosetta_add_library(SHARED
|
add_library(libc SHARED ${sources} ${headers})
|
||||||
NAME libc
|
target_include_directories(libc PUBLIC ${public_include_dirs})
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
target_link_libraries(libc PRIVATE rosetta libxpc.a liblaunch.a libmagenta.a)
|
||||||
SOURCES ${sources}
|
target_compile_options(libc PRIVATE -ffreestanding -nostdlib)
|
||||||
HEADERS ${headers})
|
target_link_options(libc PRIVATE -ffreestanding -nostdlib)
|
||||||
|
target_compile_definitions(libc PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_SHARED=1)
|
||||||
sysroot_add_library(
|
set_target_properties(libc PROPERTIES PREFIX "")
|
||||||
NAME libc
|
install(TARGETS 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)
|
|
||||||
|
|||||||
@@ -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)
|
set(source_dirs assert stdio stdlib string errno ctype wctype unistd)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
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}/*.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
|
if (NOT LIBC_STANDALONE)
|
||||||
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
set(component_sources ${sources} ${sys_sources} PARENT_SCOPE)
|
||||||
set(component_headers ${headers} PARENT_SCOPE)
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
|
return ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
add_library(libc-core STATIC ${sources} ${sys_sources} ${headers})
|
||||||
NAME libc-core
|
target_include_directories(libc-core PUBLIC ${public_include_dirs})
|
||||||
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)
|
|
||||||
|
|
||||||
target_link_libraries(libc-core PRIVATE libmagenta librosetta)
|
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)
|
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)
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
@@ -13,21 +18,17 @@ endforeach (dir)
|
|||||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||||
set(headers ${headers} ${sub_headers})
|
set(headers ${headers} ${sub_headers})
|
||||||
|
|
||||||
|
if (NOT LIBC_STANDALONE)
|
||||||
set(component_sources ${sources} PARENT_SCOPE)
|
set(component_sources ${sources} PARENT_SCOPE)
|
||||||
set(component_headers ${headers} PARENT_SCOPE)
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
add_library(libc-exec STATIC ${sources} ${headers})
|
||||||
NAME libc-exec
|
target_include_directories(libc-exec PUBLIC
|
||||||
PUBLIC_INCLUDE_DIRS
|
|
||||||
${public_include_dirs}
|
${public_include_dirs}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
SOURCES ${sources}
|
|
||||||
HEADERS ${headers})
|
|
||||||
|
|
||||||
sysroot_add_library(
|
|
||||||
NAME libc-exec
|
|
||||||
HEADER_DIR /usr/include
|
|
||||||
LIB_DIR /usr/lib)
|
|
||||||
|
|
||||||
target_link_libraries(libc-exec libc-core libc-io libmagenta liblaunch-static)
|
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
|
||||||
+15
-13
@@ -1,5 +1,10 @@
|
|||||||
set(source_dirs unistd stdio)
|
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)
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
@@ -13,21 +18,18 @@ endforeach (dir)
|
|||||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||||
set(headers ${headers} ${sub_headers})
|
set(headers ${headers} ${sub_headers})
|
||||||
|
|
||||||
|
if (NOT LIBC_STANDALONE)
|
||||||
set(component_sources ${sources} PARENT_SCOPE)
|
set(component_sources ${sources} PARENT_SCOPE)
|
||||||
set(component_headers ${headers} PARENT_SCOPE)
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||||
|
return ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
add_library(libc-io STATIC ${sources} ${headers})
|
||||||
NAME libc-io
|
target_include_directories(libc-io PUBLIC
|
||||||
PUBLIC_INCLUDE_DIRS
|
|
||||||
${public_include_dirs}
|
${public_include_dirs}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
SOURCES ${sources}
|
target_link_libraries(libc-io libc-core libxpc.a libmagenta)
|
||||||
HEADERS ${headers})
|
target_compile_definitions(libc-io PRIVATE ENABLE_GLOBAL_HEAP=1 BUILD_STATIC=1)
|
||||||
|
set_target_properties(libc-io PROPERTIES PREFIX "")
|
||||||
sysroot_add_library(
|
install(TARGETS libc-io)
|
||||||
NAME libc-io
|
|
||||||
HEADER_DIR /usr/include
|
|
||||||
LIB_DIR /usr/lib)
|
|
||||||
|
|
||||||
target_link_libraries(libc-io libc-core interface::fs libxpc-static libmagenta)
|
|
||||||
|
|||||||
@@ -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)
|
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)
|
file(GLOB sources *.c *.h)
|
||||||
|
|
||||||
foreach (dir ${source_dirs})
|
foreach (dir ${source_dirs})
|
||||||
@@ -13,22 +18,17 @@ endforeach (dir)
|
|||||||
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
file(GLOB_RECURSE sub_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
|
||||||
set(headers ${headers} ${sub_headers})
|
set(headers ${headers} ${sub_headers})
|
||||||
|
|
||||||
|
if (NOT LIBC_STANDALONE)
|
||||||
set(component_sources ${sources} PARENT_SCOPE)
|
set(component_sources ${sources} PARENT_SCOPE)
|
||||||
set(component_headers ${headers} PARENT_SCOPE)
|
set(component_headers ${headers} PARENT_SCOPE)
|
||||||
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
set(component_public_include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
add_library(libc-malloc STATIC ${sources} ${headers})
|
||||||
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)
|
|
||||||
|
|
||||||
target_compile_definitions(libc-malloc PRIVATE LIBC_STATIC=1 ENABLE_GLOBAL_HEAP=1)
|
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)
|
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})
|
foreach (dir ${pthread_source_dirs})
|
||||||
file(GLOB dir_sources ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/*.c)
|
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_headers ${pthread_headers} ${CMAKE_CURRENT_SOURCE_DIR}/include/pthread.h)
|
||||||
set(pthread_public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
set(pthread_public_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
rosetta_add_library(STATIC
|
if (PTHREAD_STATIC)
|
||||||
NAME libc-pthread
|
add_library(libc-pthread STATIC ${pthread_sources} ${pthread_headers})
|
||||||
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})
|
|
||||||
|
|
||||||
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(libc-pthread PRIVATE libc-io libmagenta)
|
||||||
target_link_libraries(libpthread PRIVATE libmagenta)
|
target_include_directories(libc-pthread PUBLIC
|
||||||
target_link_libraries(libpthread PUBLIC libc)
|
${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 ()
|
||||||
|
|
||||||
|
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
|
file(GLOB runtime_sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_SYSTEM_PROCESSOR}/*.s)
|
||||||
|
|
||||||
rosetta_add_object_library(
|
foreach (s ${runtime_sources})
|
||||||
NAME libc-runtime STATIC
|
get_filename_component(object_name ${s} NAME)
|
||||||
SOURCES ${runtime_sources})
|
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(
|
add_library(libc-runtime OBJECT ${runtime_sources})
|
||||||
NAME libc-runtime
|
|
||||||
LIB_DIR /usr/lib)
|
|
||||||
|
|||||||
@@ -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
|
file(GLOB sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/interface/*.c)
|
${CMAKE_CURRENT_SOURCE_DIR}/interface/*.c)
|
||||||
file(GLOB headers
|
file(GLOB headers
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/fs/*.h)
|
${CMAKE_CURRENT_SOURCE_DIR}/include/fs/*.h)
|
||||||
|
file(GLOB public_headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/fs/*.h)
|
||||||
|
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
rosetta_add_library(
|
if (FS_STATIC)
|
||||||
NAME libfs SHARED STATIC
|
add_library(fs STATIC ${sources} ${headers})
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
target_link_libraries(fs magenta libc-core libxpc.a)
|
||||||
SOURCES ${sources}
|
set_target_properties(fs PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
||||||
HEADERS ${headers})
|
else ()
|
||||||
|
add_library(fs SHARED ${sources} ${headers})
|
||||||
|
target_link_libraries(fs magenta c xpc)
|
||||||
|
endif ()
|
||||||
|
|
||||||
sysroot_add_library(
|
target_include_directories(fs PUBLIC include)
|
||||||
NAME libfs
|
install(TARGETS fs)
|
||||||
HEADER_DIR /usr/include
|
install(FILES ${public_headers} DESTINATION include/fs)
|
||||||
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)
|
|
||||||
|
|||||||
@@ -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
|
file(GLOB sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
file(GLOB headers
|
file(GLOB headers
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h
|
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||||
|
file(GLOB public_headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/launch.h)
|
||||||
|
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
rosetta_add_library(
|
if (LAUNCH_STATIC)
|
||||||
NAME liblaunch SHARED STATIC
|
add_library(launch STATIC ${sources} ${headers})
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
target_link_libraries(launch PRIVATE librosetta libmagenta libc-core)
|
||||||
SOURCES ${sources}
|
else ()
|
||||||
HEADERS ${headers})
|
add_library(launch SHARED ${sources} ${headers})
|
||||||
|
target_link_libraries(launch PRIVATE rosetta magenta c)
|
||||||
|
endif ()
|
||||||
|
|
||||||
sysroot_add_library(
|
target_include_directories(launch PUBLIC include)
|
||||||
NAME liblaunch
|
install(TARGETS launch)
|
||||||
HEADER_DIR /usr/include
|
install(FILES ${public_headers} DESTINATION 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)
|
|
||||||
|
|||||||
@@ -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 sources *.c)
|
||||||
file(GLOB headers include/rosetta/*.h)
|
file(GLOB headers include/rosetta/*.h)
|
||||||
|
|
||||||
rosetta_add_library(
|
add_library(rosetta STATIC ${sources} ${headers})
|
||||||
NAME librosetta STATIC
|
target_include_directories(rosetta PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
PUBLIC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
||||||
SOURCES ${sources}
|
|
||||||
HEADERS ${headers})
|
|
||||||
|
|
||||||
sysroot_add_library(
|
target_link_libraries(rosetta PRIVATE libmagenta)
|
||||||
NAME librosetta
|
|
||||||
HEADER_DIR /usr/include
|
|
||||||
LIB_DIR /usr/lib)
|
|
||||||
|
|
||||||
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
|
file(GLOB sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
${CMAKE_CURRENT_SOURCE_DIR}/*.c)
|
||||||
file(GLOB headers
|
file(GLOB headers
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||||
|
|
||||||
|
file(GLOB public_headers
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/xpc/*.h)
|
||||||
|
|
||||||
set(public_include_dirs
|
set(public_include_dirs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
rosetta_add_library(
|
if (XPC_STATIC)
|
||||||
NAME libxpc SHARED STATIC
|
add_library(xpc STATIC ${sources} ${headesr})
|
||||||
PUBLIC_INCLUDE_DIRS ${public_include_dirs}
|
target_link_libraries(xpc magenta libc-core)
|
||||||
SOURCES ${sources}
|
else ()
|
||||||
HEADERS ${headers})
|
add_library(xpc SHARED ${sources} ${headesr})
|
||||||
|
target_link_libraries(xpc magenta c)
|
||||||
|
endif ()
|
||||||
|
|
||||||
sysroot_add_library(
|
target_include_directories(xpc PUBLIC ${public_include_dirs})
|
||||||
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)
|
|
||||||
|
|
||||||
|
install(TARGETS xpc)
|
||||||
|
install(FILES ${public_headers} DESTINATION include/xpc)
|
||||||
#set_target_properties(libxpc-static PROPERTIES POSITION_INDEPENDENT_CODE FALSE)
|
#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_interactive 0)
|
||||||
set(bshell_verbose 0)
|
set(bshell_verbose 0)
|
||||||
set(bshell_enable_floating_point 0)
|
set(bshell_enable_floating_point 0)
|
||||||
|
set(bshell_enable_native_commands 0)
|
||||||
|
|
||||||
foreach(item ${items})
|
foreach(item ${items})
|
||||||
if (NOT IS_DIRECTORY ${item})
|
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(
|
cmake_minimum_required(VERSION 3.31)
|
||||||
NAME bshell-test
|
project(bshell-test)
|
||||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bshell-test.service)
|
|
||||||
|
|
||||||
rosetta_service_add_file(
|
install(
|
||||||
NAME bshell-test
|
FILES ${CMAKE_CURRENT_SOURCE_DIR}/bshell-test.service
|
||||||
SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/test.bshell
|
DESTINATION etc/herdd/services)
|
||||||
DEST_DIR /sbin)
|
install(
|
||||||
|
FILES ${CMAKE_CURRENT_SOURCE_DIR}/test.bshell
|
||||||
sysroot_add_service(
|
DESTINATION sbin)
|
||||||
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)
|
|
||||||
|
|||||||
@@ -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)
|
cmake_minimum_required(VERSION 3.31)
|
||||||
rosetta_add_service(
|
project(devmd C)
|
||||||
NAME devmd
|
|
||||||
SOURCES ${sources}
|
|
||||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/devmd.service)
|
|
||||||
target_link_libraries(devmd libc libc-runtime)
|
|
||||||
|
|
||||||
sysroot_add_service(
|
file(GLOB sources *.c)
|
||||||
NAME devmd
|
add_executable(devmd ${sources})
|
||||||
BIN_DIR /usr/bin
|
target_link_libraries(devmd c -l:crt0.o)
|
||||||
SVC_DIR /etc/herdd/services)
|
install(TARGETS devmd)
|
||||||
bsp_add_service(
|
|
||||||
NAME devmd
|
|
||||||
BIN_DIR /usr/bin
|
|
||||||
SVC_DIR /etc/herdd/services)
|
|
||||||
|
|||||||
@@ -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)
|
file(GLOB sources *.c)
|
||||||
add_executable(herdd ${sources})
|
add_executable(herdd ${sources})
|
||||||
target_link_libraries(herdd
|
target_link_libraries(herdd
|
||||||
libc libc-runtime
|
c -l:crt0.o
|
||||||
libmagenta libpthread liblaunch librosetta
|
magenta pthread launch rosetta
|
||||||
fx.runtime fx.collections fx.serial)
|
fx.runtime fx.collections fx.serial)
|
||||||
|
|
||||||
sysroot_add_program(
|
install(TARGETS herdd)
|
||||||
NAME herdd
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
bsp_add_program(
|
|
||||||
NAME herdd
|
|
||||||
BIN_DIR /usr/bin)
|
|
||||||
|
|||||||
@@ -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)
|
cmake_minimum_required(VERSION 3.31)
|
||||||
rosetta_add_service(
|
project(nsd C)
|
||||||
NAME nsd
|
|
||||||
SOURCES ${sources}
|
|
||||||
CFG_FILE ${CMAKE_CURRENT_SOURCE_DIR}/nsd.service)
|
|
||||||
target_link_libraries(nsd libc libc-runtime)
|
|
||||||
|
|
||||||
sysroot_add_service(
|
file(GLOB sources *.c)
|
||||||
NAME nsd
|
add_executable(nsd ${sources})
|
||||||
BIN_DIR /usr/bin
|
target_link_libraries(nsd c -l:crt0.o)
|
||||||
SVC_DIR /etc/herdd/services)
|
install(TARGETS nsd)
|
||||||
bsp_add_service(
|
|
||||||
NAME nsd
|
|
||||||
BIN_DIR /usr/bin
|
|
||||||
SVC_DIR /etc/herdd/services)
|
|
||||||
|
|||||||
@@ -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 c_sources *.c *.h)
|
||||||
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
add_executable(bootstrap ${c_sources} ${arch_sources})
|
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
|
target_link_libraries(bootstrap
|
||||||
libmagenta librosetta
|
"$<LINK_GROUP:cross_refs,${static_deps}>")
|
||||||
libc-core libc-malloc libc-pthread
|
|
||||||
libfs-static
|
|
||||||
liblaunch-static
|
|
||||||
libxpc-static
|
|
||||||
interface::fs)
|
|
||||||
|
|
||||||
target_compile_options(bootstrap PRIVATE
|
target_compile_options(bootstrap PRIVATE
|
||||||
-fno-stack-protector -nostdlib -ffreestanding -fno-PIC)
|
-fno-stack-protector -nostdlib -ffreestanding -fno-PIC)
|
||||||
@@ -17,3 +21,4 @@ target_link_options(bootstrap PRIVATE
|
|||||||
-static -nostdlib -ffreestanding)
|
-static -nostdlib -ffreestanding)
|
||||||
|
|
||||||
set_target_properties(bootstrap PROPERTIES POSITIION_INDEPENDENT_CODE FALSE)
|
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 c_sources *.c *.h)
|
||||||
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
file(GLOB arch_sources arch/${CMAKE_SYSTEM_PROCESSOR}/*.S)
|
||||||
|
|
||||||
@@ -7,9 +10,11 @@ set_target_properties(ld PROPERTIES
|
|||||||
OUTPUT_NAME "ld64"
|
OUTPUT_NAME "ld64"
|
||||||
SUFFIX ".so")
|
SUFFIX ".so")
|
||||||
|
|
||||||
|
set(libc_deps
|
||||||
|
libc-core.a libc-malloc.a libc-io.a)
|
||||||
target_link_libraries(ld
|
target_link_libraries(ld
|
||||||
libc-core libc-malloc libc-io libmagenta librosetta libxpc-static
|
"$<LINK_GROUP:cross_refs,${libc_deps}>"
|
||||||
interface::fs)
|
libmagenta.a librosetta.a -l:libxpc.a)
|
||||||
|
|
||||||
target_compile_options(ld PRIVATE
|
target_compile_options(ld PRIVATE
|
||||||
-fvisibility=hidden
|
-fvisibility=hidden
|
||||||
@@ -19,10 +24,4 @@ target_link_options(ld PRIVATE
|
|||||||
# -Wl,--entry="_ld_start"
|
# -Wl,--entry="_ld_start"
|
||||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR}/layout.ld
|
-T ${CMAKE_CURRENT_SOURCE_DIR}/arch/${CMAKE_SYSTEM_PROCESSOR}/layout.ld
|
||||||
-fPIC -nostdlib -ffreestanding -Wl,-shared)
|
-fPIC -nostdlib -ffreestanding -Wl,-shared)
|
||||||
|
install(TARGETS ld DESTINATION lib)
|
||||||
sysroot_add_program(
|
|
||||||
NAME ld
|
|
||||||
BIN_DIR /lib)
|
|
||||||
bsp_add_program(
|
|
||||||
NAME ld
|
|
||||||
BIN_DIR /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