From a54c0d6480185baece88b26a1bc3c3875ce20ddd Mon Sep 17 00:00:00 2001 From: xinyangli Date: Sat, 13 Apr 2024 21:15:56 +0800 Subject: [PATCH] build: build am for multiple platform in parallel --- abstract-machine/.gitignore | 2 + abstract-machine/CMakeLists.txt | 82 ++++++++++-------- abstract-machine/CMakePresets.json | 6 +- abstract-machine/CMakeUserPresets.json | 15 ++++ abstract-machine/am/CMakeLists.txt | 32 +++++-- abstract-machine/am/src/CMakeLists.txt | 54 +----------- abstract-machine/am/src/native/CMakeLists.txt | 5 +- abstract-machine/am/src/riscv/CMakeLists.txt | 12 +++ .../am/src/riscv/nemu/CMakeLists.txt | 38 +++++--- .../am/src/riscv/npc/CMakeLists.txt | 39 +++++++++ .../am/src/riscv/npc/libgcc/CMakeLists.txt | 14 +++ abstract-machine/am/src/riscv/npc/trm.c | 9 +- abstract-machine/cmake/am-config.cmake.in | 1 + abstract-machine/default.nix | 11 +-- abstract-machine/klib/CMakeLists.txt | 11 --- abstract-machine/klib/src/CMakeLists.txt | 3 +- abstract-machine/klib/tests/CMakeLists.txt | 9 +- abstract-machine/out/install/lib/libklib.a | Bin 87486 -> 0 bytes flake.nix | 9 +- 19 files changed, 206 insertions(+), 146 deletions(-) create mode 100644 abstract-machine/CMakeUserPresets.json create mode 100644 abstract-machine/am/src/riscv/CMakeLists.txt create mode 100644 abstract-machine/am/src/riscv/npc/CMakeLists.txt create mode 100644 abstract-machine/am/src/riscv/npc/libgcc/CMakeLists.txt delete mode 100644 abstract-machine/out/install/lib/libklib.a diff --git a/abstract-machine/.gitignore b/abstract-machine/.gitignore index bcba0ab..0990b71 100644 --- a/abstract-machine/.gitignore +++ b/abstract-machine/.gitignore @@ -2,5 +2,7 @@ **/build/ **/.envrc **/.cache +out/ .vscode compile_commands.json +cmakeUserh diff --git a/abstract-machine/CMakeLists.txt b/abstract-machine/CMakeLists.txt index 508bc68..6eb89d7 100644 --- a/abstract-machine/CMakeLists.txt +++ b/abstract-machine/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 11) include(CMakeDependentOption) include(CMakePackageConfigHelpers) # Used to find libcheck include(CTest) +include(GNUInstallDirs) # -- General options set(ISA CACHE STRING "Target ISA") @@ -17,12 +18,15 @@ string(TOUPPER ${ISA} ISA_UPPER) cmake_dependent_option( __PLATFORM_NEMU__ "Run on NEMU" ON "ISA MATCHES \"(riscv | x86)\"" OFF) +cmake_dependent_option( + __PLATFORM_NPC__ "Run on NPC" + ON "ISA MATCHES riscv" OFF) cmake_dependent_option( __PLATFORM_NATIVE__ "Run on native" ON "ISA MATCHES native" OFF) # -- Set PLATFORM according to options -set(MATCH_PLATFORM_PATTERN "^__PLATFORM_([A-Z]*)__") +set(MATCH_PLATFORM_PATTERN "^__PLATFORM_([A-Z]*)__$") get_cmake_property(CACHE_VARS CACHE_VARIABLES) message(STATUS "ISA: ${ISA}") @@ -32,16 +36,27 @@ foreach(VAR IN LISTS CACHE_VARS) get_property(VAR_VALUE CACHE ${VAR} PROPERTY VALUE) set(PLATFORM_UPPER ${CMAKE_MATCH_1}) string(TOLOWER ${PLATFORM_UPPER} PLATFORM) + list(APPEND PLATFORMS ${PLATFORM}) message(STATUS "Variable: ${VAR}=${VAR_VALUE}, Platform: ${PLATFORM}") endif() endforeach() -if(${PLATFORM} MATCHES "native") -set(ARCH "native") -else() -set(ARCH ${ISA}-${PLATFORM}) +if((NOT PLATFORM) AND (NOT ISA MATCHES native)) + message(FATAL_ERROR "Platform not given!") endif() -string(TOUPPER ${ARCH} ARCH_UPPER) + +set(SUPPORTED_ARCH "riscv-nemu" "riscv-npc" "native") +foreach(PLATFORM IN LISTS PLATFORMS) + if(${ISA} MATCHES "native") + set(ARCH "native") + else() + set(ARCH ${ISA}-${PLATFORM}) + endif() + + if(NOT ARCH IN_LIST SUPPORTED_ARCH) + message(FATAL_ERROR "Given ISA-PLATFORM (${ISA}-${PLATFORM}) does not match one of the following: ${SUPPORTED_ARCH}") + endif() +endforeach() # -- Target specific options cmake_dependent_option( @@ -49,39 +64,34 @@ cmake_dependent_option( ON "NOT __ISA_NATIVE__" OFF) # -- Add compile definitions based on options -add_compile_definitions( - $ - __ISA_${ISA_UPPER}__ - __PLATFORM_${PLATFORM_UPPER}__ -) - -add_compile_definitions( - $<$:__NATIVE_USE_KLIB__> -) - -# -- Required compiler flags -add_compile_options( - # -Werror - -Wno-main - -fno-asynchronous-unwind-tables - -fno-builtin - -fno-stack-protector - -U_FORTIFY_SOURCE - $<$:-fno-exceptions> - $<$:-ffreestanding> - $<$:-fno-rtti>) - -add_link_options( - -znoexecstack -) - -# -- Include linker script here. Use this linker script at link time if INCLUDE_LINKER_SCRIPT is set to true -set(LINKER_SCRIPT linker.ld) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -add_compile_options(-march=rv32if -mabi=ilp32) -add_link_options(-march=rv32if -mabi=ilp32) +# NOTE: klib and am include header files in each other, +# so we need to create interface libraries for correct dependency +add_library(am_interface INTERFACE) +target_include_directories(am_interface INTERFACE + $ + $ + $) +target_compile_definitions(am_interface INTERFACE ARCH_H=) + +add_library(klib_interface INTERFACE) +target_include_directories(klib_interface + INTERFACE + $ + $) + +install(TARGETS am_interface klib_interface + EXPORT interfaceTargets + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/abstract-machine) + +install(EXPORT interfaceTargets + FILE interfaceTargets.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) add_subdirectory(klib) add_subdirectory(am) + +# -- Test depends on klib and am should be added last. +add_subdirectory(klib/tests) diff --git a/abstract-machine/CMakePresets.json b/abstract-machine/CMakePresets.json index d14c0b6..73dab56 100644 --- a/abstract-machine/CMakePresets.json +++ b/abstract-machine/CMakePresets.json @@ -14,14 +14,14 @@ } }, { - "name": "riscv-nemu", - "displayName": "Riscv32 NEMU", + "name": "riscv", + "displayName": "RV32 all platform", "generator": "Unix Makefiles", "binaryDir": "${sourceDir}/out/build/${presetName}", - "installDir": "/home/xin/repo/ysyx-workbench/abstract-machine/out/install", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "ISA": "riscv", + "__PLATFORM_NPC__": true, "__PLATFORM_NEMU__": true } } diff --git a/abstract-machine/CMakeUserPresets.json b/abstract-machine/CMakeUserPresets.json new file mode 100644 index 0000000..3f222ce --- /dev/null +++ b/abstract-machine/CMakeUserPresets.json @@ -0,0 +1,15 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "Native install", + "inherits": "native", + "installDir": "/home/xin/repo/ysyx-workbench/abstract-machine/out/install" + }, + { + "name": "RISCV install", + "inherits": "riscv", + "installDir": "/home/xin/repo/ysyx-workbench/abstract-machine/out/install" + } + ] +} \ No newline at end of file diff --git a/abstract-machine/am/CMakeLists.txt b/abstract-machine/am/CMakeLists.txt index b0462e4..25895b7 100644 --- a/abstract-machine/am/CMakeLists.txt +++ b/abstract-machine/am/CMakeLists.txt @@ -1,10 +1,26 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -add_library(am_interface INTERFACE) -target_include_directories(am_interface INTERFACE - $ - $) - add_subdirectory(src) -install(DIRECTORY include/ DESTINATION include/abstract-machine) +install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/abstract-machine) + +foreach(PLATFORM IN LISTS PLATFORMS) + if(ISA MATCHES "native") + set(ARCH "native") + else() + set(ARCH ${ISA}-${PLATFORM}) + endif() + install(TARGETS am-${ARCH} + EXPORT amTargets-${ARCH} + LIBRARY DESTINATION lib) + + install(EXPORT amTargets-${ARCH} + FILE amTargets.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) + + configure_package_config_file( + ${CMAKE_SOURCE_DIR}/cmake/am-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/am-${ARCH}-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/am-${ARCH}-config.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) +endforeach() diff --git a/abstract-machine/am/src/CMakeLists.txt b/abstract-machine/am/src/CMakeLists.txt index 533dd3b..4988276 100644 --- a/abstract-machine/am/src/CMakeLists.txt +++ b/abstract-machine/am/src/CMakeLists.txt @@ -1,53 +1 @@ -if(ISA MATCHES "native") -set(SOURCEDIR "./${PLATFORM}") -else() -set(SOURCEDIR "./${ISA}/${PLATFORM}") -endif() - -add_subdirectory(${SOURCEDIR}) - -target_include_directories(am-${ARCH} - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC - $ - $) -target_link_libraries(am-${ARCH} - PUBLIC klib_interface - INTERFACE m) - -# TODO: Check -target_link_options(am-${ARCH} INTERFACE - $ - $) - -# Interface compile flags -target_link_options(am-${ARCH} INTERFACE - -znoexecstack) - -target_compile_options(am-${ARCH} INTERFACE - -fno-asynchronous-unwind-tables - -fno-builtin - -fno-stack-protector - -U_FORTIFY_SOURCE - $<$:-fno-exceptions> - $<$:-ffreestanding> - $<$:-fno-rtti>) - -install(TARGETS am-${ARCH} klib_interface am_interface - EXPORT amTargets - LIBRARY DESTINATION lib) - -install(EXPORT amTargets - FILE amTargets.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) - -configure_package_config_file(${CMAKE_SOURCE_DIR}/cmake/am-config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/am-${ARCH}-config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) - -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/am-${ARCH}-config.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) - -# TODO: check -install(FILES ${CMAKE_SOURCE_DIR}/scripts/${LINKER_SCRIPT} - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/am-${ARCH}) +add_subdirectory(${ISA}) diff --git a/abstract-machine/am/src/native/CMakeLists.txt b/abstract-machine/am/src/native/CMakeLists.txt index e3c9303..706aa80 100644 --- a/abstract-machine/am/src/native/CMakeLists.txt +++ b/abstract-machine/am/src/native/CMakeLists.txt @@ -1,6 +1,3 @@ -include(CheckPIESupported) -check_pie_supported() - set(SOURCES trap.S cte.c @@ -23,4 +20,4 @@ set_target_properties(am-native PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE TRUE) find_package(SDL2 REQUIRED) -target_link_libraries(am-${ARCH} PUBLIC SDL2::SDL2) +target_link_libraries(am-native PUBLIC SDL2::SDL2 PRIVATE klib_interface am_interface) diff --git a/abstract-machine/am/src/riscv/CMakeLists.txt b/abstract-machine/am/src/riscv/CMakeLists.txt new file mode 100644 index 0000000..ced867e --- /dev/null +++ b/abstract-machine/am/src/riscv/CMakeLists.txt @@ -0,0 +1,12 @@ +foreach(PLATFORM IN LISTS PLATFORMS) + string(TOUPPER ${ARCH} ARCH_UPPER) + set(AM_COMMON_COMPILE_DEF + # -- Arch related + $ + __ISA_${ISA_UPPER}__ + __PLATFORM_${PLATFORM_UPPER}__ + + $<$:__NATIVE_USE_KLIB__> + ) + add_subdirectory(${PLATFORM}) +endforeach() diff --git a/abstract-machine/am/src/riscv/nemu/CMakeLists.txt b/abstract-machine/am/src/riscv/nemu/CMakeLists.txt index a6992db..79db40f 100644 --- a/abstract-machine/am/src/riscv/nemu/CMakeLists.txt +++ b/abstract-machine/am/src/riscv/nemu/CMakeLists.txt @@ -1,7 +1,7 @@ include(nemu-settings) include(riscv-settings) -add_library(am-${ISA}-nemu +add_library(am-riscv-nemu cte.c start.S trap.S @@ -9,26 +9,44 @@ add_library(am-${ISA}-nemu ${NEMU_SOURCES} ) -target_compile_options(am-${ISA}-nemu PRIVATE +target_compile_options(am-riscv-nemu PRIVATE ${NEMU_COMPILE_OPTIONS} ${RISCV_COMPILE_OPTIONS}) -target_link_options(am-${ISA}-nemu PRIVATE + +target_link_options(am-riscv-nemu PRIVATE ${NEMU_LINK_OPITIONS} ${RISCV_LINK_OPTIONS}) -target_include_directories(am-${ISA}-nemu PRIVATE + +target_include_directories(am-riscv-nemu PRIVATE ${NEMU_INCLUDE_DIRECTORIES}) -target_link_options(am-${ISA}-nemu INTERFACE + +target_link_options(am-riscv-nemu INTERFACE LINKER:--defsym=_pmem_start=0x80000000 LINKER:--defsym=_entry_offset=0x0 LINKER:--gc-sections LINKER:-e _start -nostartfiles) -target_compile_definitions(am-${ISA}-nemu PUBLIC - ARCH_H="arch/riscv.h") -target_compile_definitions(am-${ISA}-nemu PRIVATE - ISA_H="riscv/riscv.h") +target_link_options(am-riscv-nemu INTERFACE + $ + $) -set_target_properties(am-${ISA}-nemu PROPERTIES +target_include_directories(am-riscv-nemu + PUBLIC + $ + $) + +target_link_libraries(am-riscv-nemu + PUBLIC am_interface klib_interface + INTERFACE m) + +target_compile_definitions(am-riscv-nemu PRIVATE + ISA_H=) + +set_target_properties(am-riscv-nemu PROPERTIES POSITION_INDEPENDENT_CODE OFF INTERFACE_POSITION_INDEPENDENT_CODE OFF) + +install(FILES ${CMAKE_SOURCE_DIR}/scripts/linker.ld + DESTINATION ${CMAKE_INSTALL_DATADIR}) + diff --git a/abstract-machine/am/src/riscv/npc/CMakeLists.txt b/abstract-machine/am/src/riscv/npc/CMakeLists.txt new file mode 100644 index 0000000..0859c11 --- /dev/null +++ b/abstract-machine/am/src/riscv/npc/CMakeLists.txt @@ -0,0 +1,39 @@ +include(riscv-settings) + +add_subdirectory(libgcc) + +add_library(am-riscv-npc + cte.c + input.c + ioe.c + mpe.c + start.S + timer.c + trap.S + trm.c + vme.c +) + +target_link_libraries(am-riscv-npc PRIVATE npcgcc PUBLIC am_interface klib_interface) + +target_link_options(am-riscv-npc INTERFACE + $ + $) + +target_link_options(am-riscv-npc INTERFACE + LINKER:--defsym=_pmem_start=0x80000000 + LINKER:--defsym=_entry_offset=0x0 + LINKER:--gc-sections + LINKER:-e _start + -nostartfiles) + +target_link_options(am-riscv-npc INTERFACE + $ + $) + +target_compile_definitions(am-riscv-npc + PUBLIC ${AM_COMMON_COMPILE_DEF} ARCH_H= +) + +install(FILES ${CMAKE_SOURCE_DIR}/scripts/linker.ld + DESTINATION ${CMAKE_INSTALL_DATADIR}) diff --git a/abstract-machine/am/src/riscv/npc/libgcc/CMakeLists.txt b/abstract-machine/am/src/riscv/npc/libgcc/CMakeLists.txt new file mode 100644 index 0000000..841adb6 --- /dev/null +++ b/abstract-machine/am/src/riscv/npc/libgcc/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(npcgcc + ashldi3.c + div.S + muldi3.S + multi3.c + unused.c +) + +target_link_libraries(npcgcc PRIVATE klib_interface am_interface) +target_link_options(npcgcc INTERFACE -nolibc -nostdlib) + +install(TARGETS npcgcc + EXPORT amTargets-riscv-npc + LIBRARY DESTINATION lib) diff --git a/abstract-machine/am/src/riscv/npc/trm.c b/abstract-machine/am/src/riscv/npc/trm.c index 0efe6e7..a5f4fac 100644 --- a/abstract-machine/am/src/riscv/npc/trm.c +++ b/abstract-machine/am/src/riscv/npc/trm.c @@ -6,7 +6,7 @@ int main(const char *args); extern char _pmem_start; #define PMEM_SIZE (128 * 1024 * 1024) -#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE) +#define PMEM_END ((uintptr_t)&_pmem_start + PMEM_SIZE) Area heap = RANGE(&_heap_start, PMEM_END); #ifndef MAINARGS @@ -14,11 +14,12 @@ Area heap = RANGE(&_heap_start, PMEM_END); #endif static const char mainargs[] = MAINARGS; -void putch(char ch) { -} +void putch(char ch) {} void halt(int code) { - while (1); + asm volatile("mv a0, %0; ebreak" : : "r"(code)); + while (1) + ; } void _trm_init() { diff --git a/abstract-machine/cmake/am-config.cmake.in b/abstract-machine/cmake/am-config.cmake.in index f2fbb32..0445b66 100644 --- a/abstract-machine/cmake/am-config.cmake.in +++ b/abstract-machine/cmake/am-config.cmake.in @@ -6,4 +6,5 @@ find_dependency(SDL2 REQUIRED) endif() # Include the targets file +include("${CMAKE_CURRENT_LIST_DIR}/../interfaceTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/amTargets.cmake") diff --git a/abstract-machine/default.nix b/abstract-machine/default.nix index 1f1f67d..2b614ac 100644 --- a/abstract-machine/default.nix +++ b/abstract-machine/default.nix @@ -1,9 +1,9 @@ -{ stdenv, +{ stdenv, lib, cmake, SDL2, isa ? "native", - platform ? "NEMU" + platform ? [ ] }: stdenv.mkDerivation { pname = "abstract-machine"; @@ -13,8 +13,7 @@ stdenv.mkDerivation { cmakeFlags = [ (lib.cmakeFeature "ISA" isa) - (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper platform}__" true) - ]; + ] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform; nativeBuildInputs = [ cmake @@ -22,5 +21,7 @@ stdenv.mkDerivation { buildInputs = [ - ] ++ (if platform=="native" then [ SDL2 ] else [ ]); + ] ++ (if isa=="native" then [ SDL2 ] else [ ]); + + doCheck = true; } diff --git a/abstract-machine/klib/CMakeLists.txt b/abstract-machine/klib/CMakeLists.txt index 2cf4a78..febd4f0 100644 --- a/abstract-machine/klib/CMakeLists.txt +++ b/abstract-machine/klib/CMakeLists.txt @@ -1,12 +1 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -add_library(klib_interface INTERFACE) -target_include_directories(klib_interface - INTERFACE - $ - $) - add_subdirectory(src) -# add_subdirectory(tests) - -install(DIRECTORY include/ DESTINATION include/abstract-machine) diff --git a/abstract-machine/klib/src/CMakeLists.txt b/abstract-machine/klib/src/CMakeLists.txt index bf7e136..b3a59fd 100644 --- a/abstract-machine/klib/src/CMakeLists.txt +++ b/abstract-machine/klib/src/CMakeLists.txt @@ -13,8 +13,7 @@ set(SOURCES ) add_library(klib ${SOURCES}) -target_include_directories(klib PUBLIC $) -target_compile_definitions(klib PUBLIC $) +target_link_libraries(klib PRIVATE am_interface klib_interface) install(TARGETS klib EXPORT klibTargets diff --git a/abstract-machine/klib/tests/CMakeLists.txt b/abstract-machine/klib/tests/CMakeLists.txt index f72c555..6cb0e40 100644 --- a/abstract-machine/klib/tests/CMakeLists.txt +++ b/abstract-machine/klib/tests/CMakeLists.txt @@ -4,14 +4,11 @@ set(TEST_SOURCES ) foreach(TEST IN LISTS TEST_SOURCES) - add_executable(${TEST} ${TEST}.c) - target_link_libraries(${TEST} am-${ARCH} klib m) - target_include_directories(${TEST} - PRIVATE $ - PRIVATE $ - ) # TODO: Run tests in other configurations if(__PLATFORM_NATIVE__) + add_executable(${TEST} ${TEST}.c) + target_link_libraries(${TEST} PRIVATE am_interface klib_interface klib m) + target_link_libraries(${TEST} PRIVATE am-native) add_test(NAME ${TEST} COMMAND ${TEST}) endif() endforeach() diff --git a/abstract-machine/out/install/lib/libklib.a b/abstract-machine/out/install/lib/libklib.a deleted file mode 100644 index 5023a30456119001268273724f42950c73659d18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87486 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 Ma&}3=V&(PzA8GXE6951J diff --git a/flake.nix b/flake.nix index c824872..58652b3 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,8 @@ src = ./.; hooks = { trim-trailing-whitespace.enable = true; + end-of-file-fixer.enable = true; + cmake-format.enable = true; clang-format = { enable = true; types_or = pkgs.lib.mkForce [ "c" "c++" ]; @@ -52,7 +54,8 @@ packages.nemu = pkgs.callPackage ./nemu { am-kernels = self.packages.${system}.am-kernels; }; packages.nemu-lib = pkgs.callPackage ./nemu { am-kernels = self.packages.${system}.am-kernels; defconfig = "riscv32-lib_defconfig"; }; - packages.abstract-machine = crossPkgs.callPackage ./abstract-machine { isa = "riscv"; platform = "nemu"; }; + packages.abstract-machine = crossPkgs.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; }; + packages.abstract-machine-native = pkgs.callPackage ./abstract-machine { isa = "native"; }; packages.am-kernels = crossPkgs.stdenv.mkDerivation rec { pname = "am-kernels-cmake"; @@ -67,7 +70,6 @@ cmakeFlags = [ (pkgs.lib.cmakeFeature "ISA" "riscv") (pkgs.lib.cmakeFeature "PLATFORM" "nemu") - (pkgs.lib.cmakeFeature "CMAKE_INSTALL_DATADIR" "share") ]; buildInputs = [ @@ -87,13 +89,12 @@ IMAGES_PATH = "${self.packages.${system}.am-kernels}/share/binary"; }; - devShells.npc = with pkgs; mkShell { + devShells.npc = with pkgs; mkShell.override { stdenv = ccacheStdenv; } { inherit (self.checks.${system}.pre-commit-check) shellHook; CHISEL_FIRTOOL_PATH = "${nixpkgs-circt162.legacyPackages.${system}.circt}/bin"; packages = [ clang-tools cmake - ninja coursier espresso bloop