From e97c0fdf4f6d80d9948cdf231431ce7ed6f908e9 Mon Sep 17 00:00:00 2001
From: Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
Date: Wed, 10 Aug 2016 15:09:18 +0200
Subject: [PATCH] build-system: replace toolchain files by detect

Change-Id: I7255bbaca5c984c54c349bfe1716b3bd695f5986
---
 CMakeLists.txt                      |  53 ++++++---
 arch/arm/CMakeLists.txt             |  26 +----
 arch/i386/CMakeLists.txt            |  29 ++---
 arch/i386/idt.cc                    |   5 +-
 arch/patmos/CMakeLists.txt          |  32 +++---
 arch/posix/CMakeLists.txt           |  10 +-
 config/model.py                     |   2 +-
 generator/attributor/CMakeLists.txt |  15 +--
 generator/extractor/CMakeLists.txt  |  11 +-
 generator/stats_binary.py           |  13 +--
 static_analysis/CMakeLists.txt      |   5 +-
 toolchain/ARM.cmake                 |  90 ---------------
 toolchain/app.cmake                 |   2 +-
 toolchain/detect                    | 172 ++++++++++++++++++++++++++++
 toolchain/host.cmake                |  42 -------
 toolchain/i386.cmake                | 112 ------------------
 toolchain/llvm-link.py              |  54 ++++-----
 toolchain/patmos.cmake              |  69 -----------
 toolchain/posix.cmake               | 106 -----------------
 19 files changed, 285 insertions(+), 563 deletions(-)
 delete mode 100644 toolchain/ARM.cmake
 create mode 100755 toolchain/detect
 delete mode 100644 toolchain/host.cmake
 delete mode 100644 toolchain/i386.cmake
 delete mode 100644 toolchain/patmos.cmake
 delete mode 100644 toolchain/posix.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d85236..f7b00a8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.6.2)
 PROJECT(dOSEK)
 
 # Include the configuration
-include(${CMAKE_CURRENT_BINARY_DIR}/config.cmake)
+include(${PROJECT_BINARY_DIR}/config.cmake)
 
 # ASM language defaults to the clang assembler in the Bellolabs.
 # It is required since arch/i386/idt.S uses macros that do not
@@ -18,7 +18,45 @@ if (NOT(${CONFIG_ARCH} STREQUAL "patmos"))
   enable_language(ASM-ATT)
 endif()
 
-enable_testing()
+# Generate the toolchain configuration (toolchain.cmake, etc.)
+execute_process(COMMAND ${PROJECT_SOURCE_DIR}/toolchain/detect ${CONFIG_ARCH} ${PROJECT_BINARY_DIR}/)
+
+include(${PROJECT_BINARY_DIR}/toolchain.cmake)
+
+# Set the default compiler toolchain to target
+SET(CMAKE_C_COMPILER ${TC_TARGET_CC})
+set(CMAKE_C_FLAGS "${TC_TARGET_CFLAGS} -g -c -emit-llvm -include ${PROJECT_BINARY_DIR}/dosek_config.h")
+
+SET(CMAKE_CXX_COMPILER ${TC_TARGET_CXX})
+set(CMAKE_CXX_FLAGS "${TC_TARGET_CXXFLAGS} -std=c++11 -g -c -emit-llvm  -include ${PROJECT_BINARY_DIR}/dosek_config.h")
+
+SET(CMAKE_ASM_COMPILER ${TC_TARGET_AS})
+set(CMAKE_ASM_FLAGS "${TC_TARGET_ASMFLAGS} -include ${PROJECT_BINARY_DIR}/dosek_config.h")
+set(CMAKE_ASM-ATT_FLAGS "${TC_TARGET_ASM_ATTFLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS "${TC_TARGET_LDFLAGS}")
+set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
+
+# we use our own linker (python) script, that calls llvm-link, llc and the system linker
+# setting CMAKE_*_LINK_EXECUTABLE at this point in the CMake run seems a bit unusual, but works as intended
+set(LINK_EXECUTABLE "${PROJECT_SOURCE_DIR}/toolchain/llvm-link.py --toolchain-file ${PROJECT_BINARY_DIR}/toolchain.pydict  <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o <TARGET>")
+set(CMAKE_C_LINK_EXECUTABLE_HOST "${CMAKE_C_LINK_EXECUTABLE}")
+set(CMAKE_CXX_LINK_EXECUTABLE_HOST "${CMAKE_CXX_LINK_EXECUTABLE}")
+set(CMAKE_C_LINK_EXECUTABLE "${LINK_EXECUTABLE}")
+set(CMAKE_CXX_LINK_EXECUTABLE "${LINK_EXECUTABLE}")
+
+
+# Subdirectories can use this macro to use the host compiler
+macro(USE_HOST_COMPILER)
+  SET(CMAKE_C_COMPILER ${TC_HOST_CC})
+  SET(CMAKE_CXX_COMPILER ${TC_HOST_CXX})
+  set(CMAKE_C_FLAGS "")
+  set(CMAKE_CXX_FLAGS "-std=c++11")
+  set(CMAKE_EXE_LINKER_FLAGS "")
+  set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "")
+  set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE_HOST}")
+  set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE_HOST}")
+endmacro()
+
 set(PROJECT_VERSION "1.1" CACHE STRING "Project version number")
 set(PROJECT_RELEASE "stable" CACHE STRING "Project release")
 
@@ -48,15 +86,8 @@ set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
 
 # Search path for custom cmake scripts
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/toolchain")
-include(host)
 
 ## Setup platform independent compiler flags
-# ffunction/data-sections needed to link functions/data into different sections based on name(space)
-# fno-zero-initialized-in-bss puts all variables into data instead of bss section (for data-section grouping)
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ISA_C_FLAGS} -ffunction-sections -fdata-sections -fno-zero-initialized-in-bss -nostdlib -fno-builtin")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ISA_CXX_FLAGS} ${CMAKE_C_FLAGS}  -fno-exceptions -std=c++11")
-set(CMAKE_ASM-ATT_FLAGS "${CMAKE_ASM-ATT_FLAGS} ${ISA_ASM-ATT_FLAGS}")
-set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${ISA_ASM_FLAGS}")
 
 # Find python
 find_program(PYTHON "python")
@@ -73,10 +104,6 @@ include(helpers)
 dosek_include_dir(${PROJECT_SOURCE_DIR})
 dosek_include_dir(${PROJECT_SOURCE_DIR}/os)
 dosek_include_dir(${PROJECT_BINARY_DIR})
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include ${PROJECT_BINARY_DIR}/dosek_config.h")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -include ${PROJECT_BINARY_DIR}/dosek_config.h")
-set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -include ${PROJECT_BINARY_DIR}/dosek_config.h")
-
 
 # Documentation
 add_subdirectory(toolchain/doxygen)
diff --git a/arch/arm/CMakeLists.txt b/arch/arm/CMakeLists.txt
index b399f02..3fdf2e3 100644
--- a/arch/arm/CMakeLists.txt
+++ b/arch/arm/CMakeLists.txt
@@ -66,9 +66,6 @@ set(ARCH_INCLUDE_DIRS ${ARCH_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} CACHE INT
 # Set linker script template
 set(LINKER_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld.in CACHE INTERNAL STRING)
 
-# Find objdump for pagetable generation
-find_program(OBJDUMP "${ARCH_PREFIX}objdump")
-
 # ARM dOSEK executable macro
 # usage: dosek_executable(ELFFILE ... [DEFINTIONS ...])
 # Creates dOSEK executable named ELFFILE. All parameters after ELFFILE until
@@ -100,18 +97,8 @@ macro(dosek_executable ELFFILE)
 	set_target_properties(${PRELINK} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 	target_link_libraries(${PRELINK} ${TARGET_LIBS})
 
-	# Generate pagetables from first executable
-	# set(PAGETABLES ${ELFNAME}-pagetables.cc)
-	# set(GENERATOR ${PROJECT_SOURCE_DIR}/arch/i386/generate-pagetables.py)
-	# add_custom_command(
-	# 	DEPENDS ${PRELINK} ${GENERATOR}
-	# 	COMMAND ${PYTHON} ${GENERATOR} -o ${OBJDUMP} -c ${PAGETABLES} -e ${PRELINK}
-	# 	COMMENT "Generating static page tables for ${ELFFILE}"
-	# 	OUTPUT ${PAGETABLES}
-	# )
-
 	# The actual executable
-	add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES} )# ${PAGETABLES})
+	add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES} )
 	target_link_libraries(${ELFFILE} ${TARGET_LIBS})
 
 	# set definitions
@@ -127,16 +114,10 @@ macro(dosek_executable ELFFILE)
 		set(LINKER_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/${ELFNAME}_linker.ld)
 	endif()
 	set_target_properties(${ELFFILE} ${PRELINK} PROPERTIES
-		LINK_FLAGS "-lgcc -Wl,-T ${LINKER_SCRIPT} ${ISA_LD_FLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
+		LINK_FLAGS "-lgcc -Wl,-T ${LINKER_SCRIPT} ${TC_TARGET_LDFLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
 		LINK_DEPENDS ${LINKER_SCRIPT})
 
-	# we use our own linker (python) script, that calls llvm-link, llc and the system linker
-	# setting CMAKE_*_LINK_EXECUTABLE at this point in the CMake run seems a bit unusual, but works as intended
-	set(LINK_EXECUTABLE "${PROJECT_SOURCE_DIR}/toolchain/llvm-link.py --clang ${CMAKE_C_COMPILER} --llvm-dir ${CCDIR} <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o <TARGET>")
-	set(CMAKE_C_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_C_LINK_FLAGS>")
-	set(CMAKE_CXX_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_CXX_LINK_FLAGS>")
-
-	# add to executables list
+        # add to executables list
 	set(EXECUTABLES ${EXECUTABLES} ${ELFFILE} CACHE INTERNAL STRING)
 
     # Add Platform specific stuff
@@ -152,4 +133,3 @@ macro(dosek_add_test FN)
     set_tests_properties(${FN} PROPERTIES PASS_REGULAR_EXPRESSION "SUCCESS.+ALL OK" FAIL_REGULAR_EXPRESSION "FAIL" TIMEOUT 20)
     add_dependencies( tests ${FN} )
 endmacro()
-
diff --git a/arch/i386/CMakeLists.txt b/arch/i386/CMakeLists.txt
index 0852751..5753553 100644
--- a/arch/i386/CMakeLists.txt
+++ b/arch/i386/CMakeLists.txt
@@ -33,7 +33,7 @@ set(SRCS
 	mp.s
 	constructors.cc
 	startup.cc
-    startup.S
+        startup.S
 	gdt.cc
 	idt.cc
 	idt.S
@@ -47,8 +47,8 @@ set(SRCS
 	dispatch.cc
 	syscall.cc
 	reschedule-ast.cc
-    machine.cc
-    memutil.cc
+        machine.cc
+        memutil.cc
     )
 
 # If Paging is disabled, we do not add the paging routines
@@ -105,7 +105,7 @@ macro(dosek_executable ELFFILE)
 	add_custom_command(
 		DEPENDS ${PRELINK} ${GENERATOR}
         COMMAND ${PYTHON} ${GENERATOR}
-               -o ${CROSS_OBJDUMP} -c ${PAGETABLES} -e ${PRELINK}
+               -o ${TC_TARGET_GNU_OBJDUMP} -c ${PAGETABLES} -e ${PRELINK}
                --config "${PROJECT_BINARY_DIR}/config.dict"
 		COMMENT "Generating static page tables for ${ELFFILE}"
 		OUTPUT ${PAGETABLES}
@@ -113,12 +113,12 @@ macro(dosek_executable ELFFILE)
 
   # The actual executable.
   # If we build with an pagetable, we add it as a dependency
-if(CONFIG_ARCH_MPU)
-  add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES} ${PAGETABLES})
-else()
-  add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES})
-endif()
-	target_link_libraries(${ELFFILE} ${TARGET_LIBS})
+  if(CONFIG_ARCH_MPU)
+    add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES} ${PAGETABLES})
+  else()
+    add_executable(${ELFFILE} ${ADD_EXECUTABLE_OPTIONS} ${SOURCES})
+  endif()
+  target_link_libraries(${ELFFILE} ${TARGET_LIBS})
 
 	# set definitions
 	if(DOSEK_EXECUTABLE_DEFINITIONS)
@@ -133,15 +133,9 @@ endif()
 		set(LINKER_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/${ELFNAME}_linker.ld)
 	endif()
 	set_target_properties(${ELFFILE} ${PRELINK} PROPERTIES
-		LINK_FLAGS "-lgcc -Wl,-T ${LINKER_SCRIPT} ${ISA_LD_FLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
+		LINK_FLAGS "-lgcc -Wl,-T ${LINKER_SCRIPT} ${TC_TARGET_LDFLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
 		LINK_DEPENDS ${LINKER_SCRIPT})
 
-	# we use our own linker (python) script, that calls llvm-link, llc and the system linker
-	# setting CMAKE_*_LINK_EXECUTABLE at this point in the CMake run seems a bit unusual, but works as intended
-    set(LINK_EXECUTABLE "${PROJECT_SOURCE_DIR}/toolchain/llvm-link.py --clang ${CMAKE_C_COMPILER} --march x86 --mcpu ${CMAKE_C_ARCH} -mattr=+popcnt --llvm-dir ${CCDIR} --ar ${CMAKE_AR} <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o <TARGET>")
-	set(CMAKE_C_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_C_LINK_FLAGS>")
-	set(CMAKE_CXX_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_CXX_LINK_FLAGS>")
-
 	# add to executables list
 	set(EXECUTABLES ${EXECUTABLES} ${ELFFILE} CACHE INTERNAL STRING)
 endmacro()
@@ -152,4 +146,3 @@ macro(dosek_add_test FN)
     set_tests_properties(${FN} PROPERTIES PASS_REGULAR_EXPRESSION "SUCCESS.+ALL OK" FAIL_REGULAR_EXPRESSION "FAIL" TIMEOUT 20)
     add_dependencies( tests ${FN} )
 endmacro()
-
diff --git a/arch/i386/idt.cc b/arch/i386/idt.cc
index e5ac94f..7432678 100644
--- a/arch/i386/idt.cc
+++ b/arch/i386/idt.cc
@@ -25,7 +25,6 @@ ISR(unhandled) {
 	// send end-of-interrupt (unless exception)
 	if(intno > 31) LAPIC::send_eoi();
 
-	CALL_HOOK(FaultDetectedHook, TRAPdetected, intno, cpu->eip);
 
 	// print and halt when debugging
 	uint32_t ip = cpu->eip;
@@ -35,6 +34,8 @@ ISR(unhandled) {
 	kout << hex << ip;
 	kout << endl;
 
+        CALL_HOOK(FaultDetectedHook, TRAPdetected, intno, cpu->eip);
+
 	Machine::halt();
 }
 
@@ -43,8 +44,6 @@ ISR(unhandled) {
 // NMI error handler
 IRQ_HANDLER(2) {
 	CALL_HOOK(FaultDetectedHook, TRAPdetected, 0, 0);
-	// TODO: anything useful left to do?
-	debug << "PANIC" << endl;
 
 	Machine::halt();
 }
diff --git a/arch/patmos/CMakeLists.txt b/arch/patmos/CMakeLists.txt
index 84b3480..6fe1325 100644
--- a/arch/patmos/CMakeLists.txt
+++ b/arch/patmos/CMakeLists.txt
@@ -66,24 +66,20 @@ macro(dosek_executable ELFFILE)
     COMMAND platin extract-symbols -i ${SYSTEM_PML_wo_symbols} -o ${SYSTEM_PML} ${PROJECT_BINARY_DIR}/${ELFFILE}
     )
 
-  # Copy the gcfg.pml to the main directory
-  SET(GCFG_PML "${PROJECT_BINARY_DIR}/${ELFFILE}-gcfg.pml")
-
-  add_custom_command(TARGET ${ELFFILE} POST_BUILD
-    OUTPUTS ${GCFG_PML}
-    COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}/gcfg.pml ${PROJECT_BINARY_DIR}/${ELFFILE}-gcfg.pml
-    )
-
-  # we use our own linker (python) script, that calls llvm-link, llc and the system linker
-  # setting CMAKE_*_LINK_EXECUTABLE at this point in the CMake run seems a bit unusual, but works as intended
-  set(LINK_EXECUTABLE "${PROJECT_SOURCE_DIR}/toolchain/llvm-link.py --careful-ld  -Xc,-mforce-block-labels --clang ${CMAKE_C_COMPILER} --llvm-dir ${CCDIR} <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o <TARGET>")
-  set(CMAKE_C_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_C_LINK_FLAGS>")
-  set(CMAKE_CXX_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_CXX_LINK_FLAGS>")
-
-  add_custom_target(wcet-${ELFFILE}
-    COMMENT "Timing Analysis for ${ELFFILE}"
-    DEPENDS ${ELFFILE}
-    COMMAND platin wcet -i ${SYSTEM_PML} -i ${GCFG_PML} --binary ${ELFFILE} --wca-disable-cache --disable-ait -e GCFG:timing-`printenv CIRCUIT`)
+  if(CONFIG_TIMING_GENERATE_PML)
+    # Copy the gcfg.pml to the main directory
+    SET(GCFG_PML "${PROJECT_BINARY_DIR}/${ELFFILE}-gcfg.pml")
+
+    add_custom_command(TARGET ${ELFFILE} POST_BUILD
+      OUTPUTS ${GCFG_PML}
+      COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}/gcfg.pml ${PROJECT_BINARY_DIR}/${ELFFILE}-gcfg.pml
+      )
+
+    add_custom_target(wcet-${ELFFILE}
+      COMMENT "Timing Analysis for ${ELFFILE}"
+      DEPENDS ${ELFFILE}
+      COMMAND platin wcet -i ${SYSTEM_PML} -i ${GCFG_PML} --binary ${ELFFILE} --wca-disable-cache --disable-ait -e GCFG:timing-`printenv CIRCUIT`)
+  endif()
 
   # add to executables list
   set(EXECUTABLES ${EXECUTABLES} ${ELFFILE} CACHE INTERNAL STRING)
diff --git a/arch/posix/CMakeLists.txt b/arch/posix/CMakeLists.txt
index eb29df1..285fd64 100644
--- a/arch/posix/CMakeLists.txt
+++ b/arch/posix/CMakeLists.txt
@@ -68,18 +68,10 @@ macro(dosek_executable ELFFILE)
 		set_target_properties(${ELFFILE} PROPERTIES COMPILE_DEFINITIONS ${DOSEK_EXECUTABLE_DEFINITIONS})
 	endif()
 
-
 	# Set custom linker script/flags
 	# libgcc added here to be used as needed (compiler helper functions)and not included in full
 	set_target_properties(${ELFFILE} PROPERTIES LINK_FLAGS
-		"-lgcc  ${ISA_LD_FLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}")
-
-
-	# we use our own linker (python) script, that calls llvm-link, llc and the system linker
-	# setting CMAKE_*_LINK_EXECUTABLE at this point in the CMake run seems a bit unusual, but works as intended
-	set(LINK_EXECUTABLE "${PROJECT_SOURCE_DIR}/toolchain/llvm-link.py -Wl,-T${LINKER_SCRIPT} --clang ${CMAKE_C_COMPILER} --march x86 --mcpu ${CMAKE_C_ARCH} --llvm-dir ${CCDIR} <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -o <TARGET>")
-	set(CMAKE_C_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_C_LINK_FLAGS>")
-	set(CMAKE_CXX_LINK_EXECUTABLE "${LINK_EXECUTABLE} <CMAKE_CXX_LINK_FLAGS>")
+		"-lgcc  ${TC_TARGET_LDFLAGS} --linker-prefix=${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}")
 
 	# add to executables list
 	set(EXECUTABLES ${EXECUTABLES} ${ELFFILE} CACHE INTERNAL STRING)
diff --git a/config/model.py b/config/model.py
index 76538f3..4ec069c 100644
--- a/config/model.py
+++ b/config/model.py
@@ -11,7 +11,7 @@ model = ConfigurationTree({
         "self" : OneOf(["i386", "ARM", "posix", "patmos"],
                        short_help = "CPU Architecture"),
         'mpu': Boolean(short_help = "Use Memory Protection"),
-        # config-constraint-: (arch.self == patmos || arch.self == posix) => !arch.mpu
+        # config-constraint-: (arch.self == patmos || arch.self == posix) -> !arch.mpu
 
         'idle-halt': Boolean(short_help = "Idle loop halts processor",
                              default_value = expr("self == i386 || self == ARM")),
diff --git a/generator/attributor/CMakeLists.txt b/generator/attributor/CMakeLists.txt
index d6978a8..1904598 100644
--- a/generator/attributor/CMakeLists.txt
+++ b/generator/attributor/CMakeLists.txt
@@ -1,23 +1,24 @@
+# WARNING: THIS SUBDIRECTORY IS COMPILED FOR HOST
+USE_HOST_COMPILER()
+
 # Get the directory of llvm by using llvm-config. also remove whitespaces.
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --includedir
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --includedir
                 OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --cxxflags
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --cxxflags
                 OUTPUT_VARIABLE LLVM_CXX_FLAGS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
- execute_process(COMMAND ${HOST_LLVM_CONFIG} --ldflags
+ execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --ldflags
                 OUTPUT_VARIABLE LLVM_LD_FLAGS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --libs all
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --libs all
                 OUTPUT_VARIABLE LLVM_LIBS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
 
-
 include_directories(${LLVM_INCLUDE_DIRS})
 
-USE_HOST_COMPILER()
 
-set(CMAKE_CXX_FLAGS "-fno-rtti -std=c++11 ${LLVM_CXX_FLAGS}")
+set(CMAKE_CXX_FLAGS "-fno-rtti -std=c++11 ${LLVM_CXX_FLAGS} -Wl,-rpath=${TC_TARGET_LLVM_ROOT}/lib")
 set(CMAKE_EXE_LINKER_FLAGS "${LLVM_LD_FLAGS}")
 
 # Now build our tools
diff --git a/generator/extractor/CMakeLists.txt b/generator/extractor/CMakeLists.txt
index fbd7455..ecc13ed 100644
--- a/generator/extractor/CMakeLists.txt
+++ b/generator/extractor/CMakeLists.txt
@@ -2,24 +2,23 @@
 USE_HOST_COMPILER()
 
 # Get the directory of llvm by using llvm-config. also remove whitespaces.
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --includedir
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --includedir
                 OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --cxxflags
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --cxxflags
                 OUTPUT_VARIABLE LLVM_CXX_FLAGS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
- execute_process(COMMAND ${HOST_LLVM_CONFIG} --ldflags
+ execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --ldflags
                 OUTPUT_VARIABLE LLVM_LD_FLAGS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-execute_process(COMMAND ${HOST_LLVM_CONFIG} --libs all
+execute_process(COMMAND ${TC_TARGET_LLVM_CONFIG} --libs all
                 OUTPUT_VARIABLE LLVM_LIBS
                 OUTPUT_STRIP_TRAILING_WHITESPACE )
 
 
 include_directories(${LLVM_INCLUDE_DIRS})
 
-
-set(CMAKE_CXX_FLAGS "-fno-rtti -std=c++11 ${LLVM_CXX_FLAGS}")
+set(CMAKE_CXX_FLAGS "-fno-rtti -std=c++11 ${LLVM_CXX_FLAGS} -Wl,-rpath=${TC_TARGET_LLVM_ROOT}/lib")
 set(CMAKE_EXE_LINKER_FLAGS "${LLVM_LD_FLAGS}")
 
 # Now build our tools
diff --git a/generator/stats_binary.py b/generator/stats_binary.py
index a0aeae6..ffce5a1 100755
--- a/generator/stats_binary.py
+++ b/generator/stats_binary.py
@@ -45,7 +45,7 @@ def read_regions(objdump, elf_file):
     return regions
 
 
-def read_symbols(elffile, nm = "nm"):
+def read_symbols(elffile, nm):
     out =  subprocess.check_output([nm, "-t", "dec", "-C", "-S", "-f", "sysv", elffile])
     ret = []
     for line in out.split("\n"):
@@ -94,8 +94,8 @@ if __name__ == "__main__":
                       metavar="STATS_DICT", help="the dict with the statistics")
     parser.add_option("", "--elf",
                       metavar="ELF", help="The elf file")
-    parser.add_option("", "--nm",
-                      metavar="NM", help="The nm program (e.g., i386-elf-nm")
+    parser.add_option("", "--toolchain-file",
+                      metavar="Toolchain")
 
     (options, args) = parser.parse_args()
 
@@ -103,10 +103,8 @@ if __name__ == "__main__":
         parser.print_help()
         sys.exit(-1)
 
-    if options.nm:
-        symbols = read_symbols(options.elf, options.nm)
-    else:
-        symbols = read_symbols(options.elf)
+    toolchain = eval(open(options.toolchain_file).read())
+    symbols = read_symbols(options.elf, toolchain['target']['gnu-nm'])
     stats = Statistics.load(options.stats_dict)
 
     for abb in stats.find_all("AtomicBasicBlock").values():
@@ -117,4 +115,3 @@ if __name__ == "__main__":
             abb["generated-codesize"] += get_size(symbols, func)
 
     stats.save(options.stats_dict)
-
diff --git a/static_analysis/CMakeLists.txt b/static_analysis/CMakeLists.txt
index 69d8a10..392fca3 100644
--- a/static_analysis/CMakeLists.txt
+++ b/static_analysis/CMakeLists.txt
@@ -16,10 +16,8 @@ if(CPPCHECK)
     foreach(dir ${INCLUDEDIRS})
         file(APPEND ${CPPINCLUDES} "${dir}\n")
     endforeach()
-#    if(BUILD_posix)
         file(APPEND ${CPPINCLUDES} "/usr/include\n")
         file(APPEND ${CPPINCLUDES} "/usr/include/linux\n")
-#    endif()
 
 
     add_custom_target( cppcheck
@@ -100,7 +98,7 @@ endif()
 find_program(PYLINT /proj/i4danceos/tools/pylint/pylint pylint)
 if(PYLINT)
   add_custom_command(
-	  COMMAND find ./ -iname \"*.py\" | PYTHONPATH=${PROJECT_SOURCE_DIR} xargs ${PYLINT} 
+	  COMMAND find ./ -iname \"*.py\" | PYTHONPATH=${PROJECT_SOURCE_DIR} xargs ${PYLINT}
         --msg-template=\"{path}:{line}: [{msg_id}({symbol}) , {obj}] {msg}\"
 		--rcfile=${PROJECT_SOURCE_DIR}/static_analysis/pylint.rc
 		   > ${PROJECT_BINARY_DIR}/pylint.txt
@@ -116,4 +114,3 @@ else()
   message(STATUS "[${PROJECT_NAME}] pylint executable not found")
 
 endif()
-
diff --git a/toolchain/ARM.cmake b/toolchain/ARM.cmake
deleted file mode 100644
index e43cb1f..0000000
--- a/toolchain/ARM.cmake
+++ /dev/null
@@ -1,90 +0,0 @@
-# Prepare cross compiler
-set(CMAKE_SYSTEM_NAME Generic)
-set(BUILD_ARM TRUE CACHE BOOL "")
-set(CMAKE_C_ARCH "armv7a-none-elf")
-set(ARCH_PREFIX "arm-none-eabi-")
-
-find_program(CROSS_GCC "${ARCH_PREFIX}gcc")
-
-# gcc -print-search-dirs first line: install: ...
-execute_process(COMMAND ${CROSS_GCC} -print-search-dirs OUTPUT_VARIABLE GCC_SEARCH_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
-STRING(REGEX REPLACE "^install: ([^ ]+)\n.*" "\\1" CROSS_ROOT_PATH ${GCC_SEARCH_PATH})
-
-find_program(CROSS_AR "${ARCH_PREFIX}ar")
-find_program(CROSS_AS "${ARCH_PREFIX}as")
-find_program(CROSS_NM "${ARCH_PREFIX}nm")
-find_program(CROSS_RANLIB "${ARCH_PREFIX}ranlib")
-# Find objdump for pagetable generation
-find_program(CROSS_OBJDUMP "${ARCH_PREFIX}objdump")
-find_program(CROSS_OBJCOPY "${ARCH_PREFIX}objcopy")
-
-
-message(STATUS "Cross compiler root: ${CROSS_ROOT_PATH}")
-
-# Setup LLVM Tooling
-SET(LLVM_RECOMMENDED_VERSION 3.4)
-
-if(NOT DEFINED ${LLVM_ROOT})
-  # find llvm-config. prefers to the one with version suffix, Ex:llvm-config-3.4
-  find_program(LLVM_CONFIG_EXE NAMES "llvm-config-${LLVM_RECOMMENDED_VERSION}" "llvm-config")
-
-  # Get the directory of llvm by using llvm-config. also remove whitespaces.
-  execute_process(COMMAND ${LLVM_CONFIG_EXE} --prefix OUTPUT_VARIABLE LLVM_ROOT
-                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-endif()
-
-message(STATUS "LLVM root: ${LLVM_ROOT}")
-
-# Find a compiler which compiles c++ source into llvm bitcode.
-# It first finds clang, then it finds llvm-g++ if there is no clang.
-find_program(LLVM_C_COMPILER "clang-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang llvm-gcc
-                HINTS ${LLVM_ROOT}/bin )
-
-find_program(LLVM_CXX_COMPILER "clang++-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang++ llvm-g++
-                HINTS ${LLVM_ROOT}/bin )
-
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${LLVM_C_COMPILER} STREQUAL "LLVM_COMPILER-NOTFOUND")
-  message(WARNING "Could not find clang or llvm-gcc."
-                " Please install one of them !")
-endif()
-
-message(STATUS "LLVM C/C++ compiler: ${LLVM_C_COMPILER} ${LLVM_CXX_COMPILER}")
-
-
-# Setup ARM specific flags
-set(COMMON_ARM_FLAGS "-target ${CMAKE_C_ARCH} -I/usr/lib/arm-none-eabi/include -mcpu=cortex-a9 -mfloat-abi=soft -mthumb  -Xclang -no-implicit-float -ccc-gcc-name ${ARCH_PREFIX}gcc -no-integrated-as -include ${PROJECT_SOURCE_DIR}/arch/arm/types.h")
-set(CMAKE_C_FLAGS "${COMMON_ARM_FLAGS} -mfloat-abi=soft -ffreestanding -Wall -Wextra -Qunused-arguments -Wno-undefined-inline" CACHE STRING "CFLAGS")
-set(CMAKE_CXX_FLAGS " -fno-exceptions -fno-unwind-tables -fno-rtti" CACHE STRING "CXXFLAGS")
-set(CMAKE_ASM_FLAGS "${COMMON_ARM_FLAGS} -Qunused-arguments" CACHE STRING "ASMFLAGS")
-
-set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles -Wl,--gc-sections" CACHE STRING "LDFLAGS")
-
-# Setup compilers
-set(CCDIR "${LLVM_ROOT}")
-set(CMAKE_C_COMPILER  ${LLVM_C_COMPILER})
-set(CMAKE_CXX_COMPILER ${LLVM_CXX_COMPILER})
-set(CMAKE_RANLIB "${CCDIR}/bin/llvm-ranlib" CACHE INTERNAL STRING)
-set(CMAKE_AR "${CCDIR}/bin/llvm-ar" CACHE INTERNAL STRING)
-
-SET(CMAKE_FIND_ROOT_PATH ${CROSS_ROOT_PATH})
-SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-## Add *additional* architecture specific compiler flags here.
-# Note that the flags set in toolchain.cmake are still present and used.
-set(ISA_C_FLAGS "-S -emit-llvm -O0" CACHE INTERNAL STRING)
-set(ISA_CXX_FLAGS "" CACHE INTERNAL STRING)
-set(ISA_ASM_FLAGS "${COMMON_ARM_FLAGS}" CACHE INTERNAL STRING)
-set(ISA_LD_FLAGS "${COMMON_ARM_FLAGS} -static -nostdlib -Qunused-arguments -Wl,--build-id=none" CACHE INTERNAL STRING)
-
-# ENABLE ARM platform
-set(BUILD_ARM "on" CACHE INTERNAL STRING)
-set(DOSEK_ARCHITECTURE "ARM")
-
diff --git a/toolchain/app.cmake b/toolchain/app.cmake
index 5c66cd6..2a98841 100644
--- a/toolchain/app.cmake
+++ b/toolchain/app.cmake
@@ -137,7 +137,7 @@ MACRO(DOSEK_BINARY)
     COMMAND ${DOSEK_GENERATOR_DIR}/stats_binary.py
          --stats-dict ${DOSEK_OUTPUT_DIR}/stats.dict.py
          --elf ${PROJECT_BINARY_DIR}/${NAME}
-         --nm  ${CROSS_NM}
+         --toolchain-file ${PROJECT_BINARY_DIR}/toolchain.pydict
     )
 
   if((${DOSEK_BINARY_FAIL} STREQUAL "TRUE") OR FAIL_TRACE_ALL)
diff --git a/toolchain/detect b/toolchain/detect
new file mode 100755
index 0000000..0212612
--- /dev/null
+++ b/toolchain/detect
@@ -0,0 +1,172 @@
+#!/usr/bin/python3
+
+# This command is used to detect a valid toolchain for building DOSEK.
+# It furthermore constructs all tool flags and generates CMake, as
+# well as yaml output.
+
+import sys
+import os
+import yaml
+import subprocess
+
+def find_program(toolname, path=None):
+    """Find an absolute path to a toolchain. If no path is given, the
+       environment path is used to detect the binary"""
+
+    def is_exe(fpath):
+        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+    if path:
+        paths = [path]
+    else:
+        paths = os.environ["PATH"].split(os.pathsep)
+    for path in paths:
+        path = path.strip('"')
+        exe_file = os.path.join(path, toolname)
+        if is_exe(exe_file):
+            return exe_file
+
+def must(value, msg):
+    assert value is not None, "detect.py: NOT FOUND: " + msg
+    return value
+
+
+def cmake_dump(data, stream=None, prefix="TC_"):
+    def norm(s):
+        return s.upper().replace("-", "_")
+    if not stream:
+        stream = sys.stdout
+    for k, v in data.items():
+        if type(v) is dict:
+            cmake_dump(v, stream, prefix + norm(k) + "_")
+        else:
+            stream.write("SET(%s%s \"%s\" CACHE INTERNAL \"\")\n" % (
+                prefix,
+                norm(k),
+                repr(str(v))[1:-1]
+            ))
+
+
+# Toolchain detection steps
+def gcc_as_host_compiler(toolchain):
+    toolchain['host']['cc']  = must(find_program('gcc'), "Host C Compiler")
+    toolchain['host']['cxx'] = must(find_program('g++'), "Host CXX Compiler")
+
+# LLVM Config
+def llvm_config(toolchain, base="llvm-config", recommended="3.4", hint=None, arch_prefix=""):
+    # First we find the llvm-config tool
+    config = find_program("%s-%s" %(arch_prefix+base, recommended), hint) \
+             or find_program(arch_prefix+base, hint) \
+             or find_program("%s-%s" %(arch_prefix+base, recommended)) \
+             or find_program(arch_prefix+base)
+    must(config, "LLVM Config Tool")
+    toolchain['target']['llvm-config'] = config
+
+    # Find LLVM Root Directory
+    llvm_root = subprocess.check_output([config, "--prefix"]).strip().decode('ascii')
+    llvm_bin = os.path.join(llvm_root, "bin")
+    toolchain['target']['llvm-root'] = llvm_root
+    # Find diverse llvm tools
+    def tool(name):
+        return must(find_program(arch_prefix + name + "-" + recommended, llvm_bin ) \
+                    or find_program(arch_prefix + name, llvm_bin) , name)
+
+    toolchain['target']['cc']      = tool('clang')
+    toolchain['target']['cxx']     = tool('clang++')
+
+    toolchain['target']['opt']      = tool('opt')
+    toolchain['target']['llc']      = tool('llc')
+    toolchain['target']['llvm-link']    = tool('llvm-link')
+    toolchain['target']['llvm-ar']      = tool('llvm-ar')
+    toolchain['target']['llvm-objdump'] = tool('llvm-objdump')
+
+def arch_posix(toolchain):
+    toolchain["target"]["cflags"] = "-Wall -Wextra -m32 -ffunction-sections -fdata-sections -fno-builtin"
+    toolchain["target"]["cxxflags"] = toolchain["target"]["cflags"] + " -stdlib=libc++ -fno-exceptions -fno-rtti"
+    toolchain["target"]["asm-attflags"] = "--32"
+    toolchain["target"]["asmflags"] = "-m32"
+    toolchain["target"]["ldflags"] = "-m32"
+
+    toolchain['target']['gnu-nm'] = must(find_program("nm"), "Binutils NM")
+    toolchain['target']['as'] = must(find_program("gcc"), "Binutils AS")
+
+
+def arch_i386(toolchain):
+    toolchain["target"]["cflags"] = "-m32 -Wall -Wextra -ffreestanding -ffunction-sections -fdata-sections -fno-builtin"
+    toolchain["target"]["cxxflags"] = toolchain["target"]["cflags"] + " -fno-exceptions -fno-rtti"
+    toolchain["target"]["asm-attflags"] = "--32"
+    toolchain["target"]["asmflags"] = "-m32"
+
+    toolchain["target"]["ldflags"] = "-m32 -static -nostdlib -Wl,--build-id=none"
+    toolchain["target"]["ldflags"] += " -mattr=+popcnt -nozero-initialized-in-bss"
+    toolchain["target"]["ldflags"] += " -ffreestanding -nostartfiles -march=x86 -mcpu=i386 -Wl,--gc-sections"
+
+    toolchain['target']['gnu-nm'] = must(find_program("nm"), "Binutils NM")
+    toolchain['target']['as'] = must(find_program("gcc"), "Binutils AS")
+
+
+    # Required for the Page Table generation
+    toolchain['target']['gnu-objdump'] = must(find_program("objdump"), "Binutils OBJDUMP")
+
+def arch_ARM_A9(toolchain):
+    p = "arm-none-eabi-"
+    common = "-target armv7a-none-elf -mcpu=cortex-a9 -mfloat-abi=soft -mthumb -ccc-gcc-name arm-none-eabi-gcc -no-integrated-as"
+    toolchain["target"]["cflags"] = common + " -Wall -Wextra -I/usr/lib/arm-none-eabi/include " \
+                                    + " -Xclang -no-implicit-float -ffreestanding"
+    toolchain["target"]["cxxflags"] = toolchain["target"]["cflags"] + " -fno-unwind-tables -fno-exceptions -fno-rtti"
+    toolchain["target"]["asm-attflags"] = ""
+    toolchain["target"]["asmflags"] = "-mcpu=cortex-a9 -mthumb"
+
+    toolchain["target"]["ldflags"] = common+ "  -nostdlib -static -Wl,--gc-sections"
+
+    toolchain['target']['gnu-nm'] = must(find_program(p + "nm"), "Binutils NM")
+    toolchain['target']['as'] = must(find_program(p + "gcc"), "Binutils AS")
+
+    # toolchain['target']['gnu-objdump'] = must(find_program(p + "objdump"), "Binutils OBJDUMP")
+
+
+def arch_patmos(toolchain):
+    toolchain["target"]["cflags"] = "-Wall -Wextra"
+    toolchain["target"]["cxxflags"] = "-Wall -Wextra -fno-exceptions -fno-rtti"
+    toolchain["target"]["asm-attflags"] = ""
+    toolchain["target"]["asmflags"] = ""
+
+    toolchain["target"]["ldflags"] = "-Xgold,-gc-sections -nostdlib -nostartfiles -Xc,-mforce-block-labels"
+    toolchain["target"]["no-start-group"] = "true"
+
+
+    toolchain['target']['gnu-nm'] = must(find_program("patmos-nm"), "Binutils NM")
+    toolchain['target']['as'] = must(find_program("patmos-llvm-as"), "Binutils AS")
+
+if __name__ == "__main__":
+    arches = {"i386":  [(llvm_config, {"hint": "/proj/i4danceos/tools/llvm-3.4/bin"}),
+                        arch_i386],
+              "ARM":   [(llvm_config, {"hint": "/proj/i4danceos/tools/llvm-3.4/bin"}),
+                        arch_ARM_A9],
+              "posix": [(llvm_config, {"hint": "/proj/i4danceos/tools/llvm-3.4/bin"}),
+                        arch_posix,
+                       ],
+              "patmos": [(llvm_config, {"arch_prefix": "patmos-"}),
+                         arch_patmos]}
+    if len(sys.argv) < 3 or sys.argv[1] not in arches:
+        sys.exit("%s <arch> <prefix-dir/>; arches = %s" % (sys.argv[0], arches))
+
+    toolchain = {'host': {}, 'target': {}}
+
+    generic = [gcc_as_host_compiler]
+
+    # Execute all toolchain detection steps
+    for P in generic + arches[sys.argv[1]]:
+        if type(P) is tuple:
+            P[0](toolchain, **P[1])
+        else:
+            P(toolchain)
+
+    with open(os.path.join(sys.argv[2], "toolchain.cmake"), "w+") as fd:
+              cmake_dump(toolchain, stream=fd)
+    with open(os.path.join(sys.argv[2], "toolchain.yaml"), "w+") as fd:
+              yaml.dump(toolchain, stream=fd)
+    with open(os.path.join(sys.argv[2], "toolchain.pydict"), "w+") as fd:
+              fd.write(repr(toolchain) + "\n")
+
+    sys.stderr.write("Target CC: %s\n" % toolchain['target']['cc'])
+    sys.stderr.write("Target CXX: %s\n" % toolchain['target']['cxx'])
diff --git a/toolchain/host.cmake b/toolchain/host.cmake
deleted file mode 100644
index 5390530..0000000
--- a/toolchain/host.cmake
+++ /dev/null
@@ -1,42 +0,0 @@
-# TOOLCHAIN Parts that are common to all architectures
-# SET Host LLVM
-find_program(HOST_LLVM_CONFIG
-  NAMES "llvm-config-${LLVM_RECOMMENDED_VERSION}"
-  PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin
-)
-if (NOT HOST_LLVM_CONFIG)
-  find_program(HOST_LLVM_CONFIG
-    NAMES "llvm-config"
-    PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin
-)
-endif()
-if (NOT HOST_LLVM_CONFIG)
-  message(FATAL_ERROR "HOST: Could not find llvm-config")
-endif()
-
-find_program(HOST_C_COMPILER NAMES clang gcc)
-find_program(HOST_CXX_COMPILER NAMES clang++ g++)
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${HOST_C_COMPILER} STREQUAL "HOST_C_COMPILER-NOTFOUND")
-  message(FATAL "Could not find Host compiler!")
-endif()
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${HOST_CXX_COMPILER} STREQUAL "HOST_CXX_COMPILER-NOTFOUND")
-  message(FATAL "Could not find Host C++ compiler!")
-endif()
-
-
-macro(USE_HOST_COMPILER)
-  SET(CMAKE_C_COMPILER ${HOST_C_COMPILER})
-  SET(CMAKE_CXX_COMPILER ${HOST_CXX_COMPILER})
-  set(CMAKE_C_FLAGS "")
-  set(CMAKE_CXX_FLAGS "-std=c++11")
-  set(CMAKE_EXE_LINKER_FLAGS "")
-  set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "")
-endmacro()
diff --git a/toolchain/i386.cmake b/toolchain/i386.cmake
deleted file mode 100644
index 9bd6ddb..0000000
--- a/toolchain/i386.cmake
+++ /dev/null
@@ -1,112 +0,0 @@
-# Generic system
-# removes -rdynamic from the linker, which llvm-ld does not support.
-set(CMAKE_SYSTEM_NAME Generic)
-
-# LLVM version.
-SET(LLVM_RECOMMENDED_VERSION 3.4)
-
-if(NOT DEFINED ${LLVM_ROOT})
-  # find llvm-config. prefers to the one with version suffix, Ex:llvm-config-3.4
-    # find llvm-config. prefers to the one with version suffix, Ex:llvm-config-3.4
-  find_program(LLVM_CONFIG_EXE NAMES "llvm-config-${LLVM_RECOMMENDED_VERSION}"
-    PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin)
-  if (NOT LLVM_CONFIG_EXE)
-    find_program(LLVM_CONFIG_EXE NAMES "llvm-config"
-      PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin)
-  endif()
-
-  # Get the directory of llvm by using llvm-config. also remove whitespaces.
-  execute_process(COMMAND ${LLVM_CONFIG_EXE} --prefix OUTPUT_VARIABLE LLVM_ROOT
-    OUTPUT_STRIP_TRAILING_WHITESPACE )
-endif()
-
-message(STATUS "LLVM root: ${LLVM_ROOT}")
-
-# Find a compiler which compiles c source into llvm bitcode.
-# It first finds clang, then it finds llvm-g++ if there is no clang.
-find_program(LLVM_C_COMPILER "clang-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang
-                HINTS ${LLVM_ROOT}/bin )
-# Find a compiler which compiles c++ source into llvm bitcode.
-# It first finds clang, then it finds llvm-g++ if there is no clang.
-find_program(LLVM_CXX_COMPILER "clang++-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang++
-                HINTS ${LLVM_ROOT}/bin )
-
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${LLVM_C_COMPILER} STREQUAL "LLVM_C_COMPILER-NOTFOUND")
-  message(FATAL "Could not find clang or llvm-g++."
-                " Please install one of them !")
-endif()
-
-message(STATUS "LLVM compiler: ${LLVM_C_COMPILER}")
-
-
-if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin")
-  set(ARCH_PREFIX "i386-elf-")
-  find_program(CROSS_GCC "${ARCH_PREFIX}gcc")
-  # gcc -print-search-dirs first line: install: ...
-  execute_process(COMMAND ${CROSS_GCC} -print-search-dirs OUTPUT_VARIABLE GCC_SEARCH_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
-  message(status "search dirs: ${GCC_SEARCH_PATH}")
-  STRING(REGEX REPLACE "^install: ([^ ]+)\n.*" "\\1" CROSS_ROOT_PATH ${GCC_SEARCH_PATH})
-
-  find_program(CROSS_AR "${ARCH_PREFIX}ar")
-  find_program(CROSS_NM "${ARCH_PREFIX}nm")
-  find_program(CROSS_RANLIB "${ARCH_PREFIX}ranlib")
-  # Find objdump for pagetable generation
-  find_program(CROSS_OBJDUMP "${ARCH_PREFIX}objdump")
-
-  set(CROSS_COMPILER_FLAGS "-ccc-gcc-name ${ARCH_PREFIX}gcc -target i386-pc-none")
-
-  set(CMAKE_ASM_COMPILER ${ARCH_PREFIX}gcc)
-
-  message(STATUS "Cross compiler root: ${CROSS_ROOT_PATH}")
-elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
-  set(CROSS_RANLIB ${LLVM_ROOT}/bin/llvm-ranlib)
-  set(CROSS_AR ${LLVM_ROOT}/bin/llvm-ar)
-  find_program(CROSS_OBJDUMP objdump)
-  find_program(CROSS_NM "${ARCH_PREFIX}nm" "nm")
-else()
-  message(FATAL "Host system not found :(")
-endif()
-
-set(CMAKE_C_ARCH "i386")
-set(CMAKE_C_FLAGS  "${CROSS_COMPILER_FLAGS} -ffreestanding -march=${CMAKE_C_ARCH} -m32 -Wall -Wextra -Qunused-arguments -Wno-undefined-inline" CACHE STRING "CFLAGS")
-set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -fno-rtti" CACHE STRING "CXXFLAGS")
-set(CMAKE_ASM_FLAGS "-Qunused-arguments -fno-builtin " CACHE STRING "ASMFLAGS")
-set(CMAKE_ASM-ATT_FLAGS "-Qunused-arguments" CACHE STRING "ASMFLAGS")
-set(CMAKE_EXE_LINKER_FLAGS "-nostartfiles ${CMAKE_CXX_FLAGS}" CACHE STRING "LDFLAGS")
-
-set(CCDIR "${LLVM_ROOT}")
-set(CMAKE_C_COMPILER  ${LLVM_C_COMPILER})
-set(CMAKE_CXX_COMPILER ${LLVM_CXX_COMPILER})
-set(CMAKE_RANLIB "${CROSS_RANLIB}" CACHE INTERNAL STRING)
-set(CMAKE_AR "${CROSS_AR}" CACHE INTERNAL STRING)
-
-SET(CMAKE_FIND_ROOT_PATH ${CROSS_ROOT_PATH})
-SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-## Add *additional* architecture specific compiler flags here.
-# Note that the flags set in toolchain.cmake are still present and used.
-set(ISA_C_FLAGS "-S -emit-llvm -O0 -m32" CACHE INTERNAL STRING)
-set(ISA_CXX_FLAGS "-m32" CACHE INTERNAL STRING)
-set(ISA_ASM_FLAGS "-m32" CACHE INTERNAL STRING)
-set(ISA_ASM-ATT_FLAGS "--32" CACHE INTERNAL STRING)
-set(ISA_LD_FLAGS "-fno-builtin -m32 -static -nostdlib -Qunused-arguments -Wl,--build-id=none" CACHE INTERNAL STRING)
-
-set(LD_OUTPUT_FORMAT "elf32-i386" CACHE INTERNAL "LD output format for linker script")
-
-## The kernel will live at 3GB + 1MB in the virtual
-##   address space, which will be mapped to 1MB in the
-##   physical address space.
-set(LD_KERNEL_START_ADDRESS 0x100000 CACHE INTERNAL "Start address of the first section.")
-
-# ENABLE x86 32 platform
-set(BUILD_i386 "on" CACHE INTERNAL STRING)
-set(DOSEK_ARCHITECTURE "i386")
-
diff --git a/toolchain/llvm-link.py b/toolchain/llvm-link.py
index 08bbacc..6dca244 100755
--- a/toolchain/llvm-link.py
+++ b/toolchain/llvm-link.py
@@ -6,6 +6,7 @@ import shutil
 import subprocess
 import os
 import glob
+from collections import OrderedDict
 
 def is_llvm_file(file):
     if not os.path.exists(file):
@@ -59,31 +60,27 @@ def check_output(*args, **kwargs):
     return subprocess.check_output(*args, **kwargs)
 
 def llvm_link(files, output):
-    check_output([os.path.join(args.llvm_dir, "bin", "patmos-llvm-link"),
-                             "-o", output] + files)
+    check_output([toolchain['target']['llvm-link'], "-o", output] + files)
     return output
 
 def llvm_opt(input, output):
-    check_output([os.path.join(args.llvm_dir, "bin", "patmos-opt"),
-                      "-std-compile-opts", "-always-inline", "-o", output, input])
+    check_output([toolchain['target']['opt'], "-std-compile-opts", "-always-inline", "-o", output, input])
     return output
 
 def llvm_opt_careful(input, output):
-    check_output([os.path.join(args.llvm_dir, "bin", "patmos-opt"),
-                 "-inline",  "-constprop", "-dse",
-                  "-o", output, input])
+    check_output([toolchain['target']['opt'], "-inline",  "-constprop", "-dse", "-o", output, input])
     return output
 
 def llvm_llc(file, output, flags):
-    check_output([os.path.join(args.llvm_dir, "bin", "patmos-llc")] + flags + ["-o", output, file])
+    check_output([toolchain['target']['llc']] + flags + ["-o", output, file])
     return output
 
 def start_ld(flags, objects, output):
-    check_output([args.clang, "-Wl,--start-group"] + objects + ["-Wl,--end-group"]
-                 + flags + ["-o", output, "-Wl,-gc-sections"])
+    check_output([toolchain['target']['cc'], "-Wl,--start-group"] + objects + ["-Wl,--end-group"]
+                 + flags + ["-o", output])
 
 def link_with_clang(bitcode, flags, output):
-    check_output([args.clang, bitcode] + flags + ["-o", output])
+    check_output([toolchain['target']['cc'], bitcode] + flags + ["-o", output])
 
 
 if __name__ == "__main__":
@@ -92,57 +89,48 @@ if __name__ == "__main__":
     parser = argparse.ArgumentParser(description='Linker for dOSEK.')
     parser.add_argument("--output", "-o", metavar='OUT', help='The file to generate')
     parser.add_argument("--linker-prefix", metavar='PREFIX', help='Output file prefix')
-    parser.add_argument("--llvm-dir", metavar='LLVM_DIR', help='Where are the llvm binaries located')
-    parser.add_argument("--march", metavar='MARCH', help='Target Architecture for llc [arm|x86]')
-    parser.add_argument("--mcpu", metavar='MCPU', help='Target CPU for llc [cortex-a9|i386')
-    parser.add_argument("--clang", metavar='CLANG_BINARY', help='Clang binary location')
-    parser.add_argument("--ar", default="/usr/bin/ar", help="ar binary location", metavar="AR")
-    parser.add_argument("--careful-ld", default=False, action="store_true",
-                        help="Be conservartive with the linker")
-
+    parser.add_argument("--toolchain-file", metavar='TOOLCHAIN', help="Toolchain configuration")
 
     args, unkown_args = parser.parse_known_args()
+    unkown_args = [x for x in unkown_args if not x == "-rdynamic"]
     archives = [x for x in unkown_args if x.endswith(".a")]
     elf_files = [x for x in unkown_args if is_elf_file(x)]
     llvm_files = [x for x in unkown_args if is_llvm_file(x)]
     compiler_flags = [x for x in unkown_args if \
                       x.startswith("-mattr") \
+                      or x.startswith("-mcpu") \
+                      or x.startswith("-march") \
                       or x.startswith("-mserialize") \
                       or x.startswith("-mforce-block-labels") \
+                      or x in ("-nozero-initialized-in-bss", "-ffunction-sections", "-fdata-sections")
                       or x.startswith("-O")]
+    # unique
+    compiler_flags = list(OrderedDict.fromkeys(compiler_flags))
 
 
     # Remove file arguments from unkown args
     linker_flags = [x for x in unkown_args
                    if not(x in archives + elf_files + llvm_files + compiler_flags)]
 
-    if args.march:
-        llc_march = "-march=" + args.march
-    else:
-        llc_march = ""
-
-    if args.mcpu:
-        llc_mcpu = "-mcpu=" + args.mcpu
-    else:
-        llc_mcpu = ""
+    global toolchain
+    toolchain = eval(open(args.toolchain_file).read())
 
     try:
         tempdir = tempfile.mkdtemp()
-        (elf_, llvm_) = aggregate_bitcode(archives, args.ar)
+        (elf_, llvm_) = aggregate_bitcode(archives, toolchain['target']['llvm-ar'])
         elf_files += elf_
         llvm_files += llvm_
         # Link all bitcode files together
         bitcode     = llvm_link(llvm_files, args.linker_prefix + "-stage1.bc")
 
-        if args.careful_ld:
+        if toolchain['target'].get("no-start-group", False):
             assert len(elf_files) == 0, "There are ELF files" + elf_files
             bitcode_opt = llvm_opt_careful(bitcode, args.linker_prefix + "-stage2.bc")
-            flags = ["-ffunction-sections", "-fdata-sections"]
-            flags += compiler_flags + linker_flags
+            flags = compiler_flags + linker_flags
             link_with_clang(bitcode_opt, flags, args.output)
         else:
             bitcode_opt = llvm_opt(bitcode, args.linker_prefix + "-stage2.bc")
-            llc_flags = [llc_march, llc_mcpu, "-filetype=obj", "-ffunction-sections", "-fdata-sections", "-nozero-initialized-in-bss"]
+            llc_flags = ["-filetype=obj"]
             llc_flags += compiler_flags
             llc_flags = [x for x in llc_flags if not x == ""]
             system_object = llvm_llc(bitcode_opt, args.linker_prefix + ".obj", llc_flags)
diff --git a/toolchain/patmos.cmake b/toolchain/patmos.cmake
deleted file mode 100644
index 28f22a3..0000000
--- a/toolchain/patmos.cmake
+++ /dev/null
@@ -1,69 +0,0 @@
-# Generic system
-# removes -rdynamic from the linker, which llvm-ld does not support.
-set(CMAKE_SYSTEM_NAME Generic)
-
-# LLVM version.
-SET(LLVM_RECOMMENDED_VERSION 3.4)
-
-find_program(HOST_LLVM_CONFIG NAMES "patmos-llvm-config-${LLVM_RECOMMENDED_VERSION}")
-if (NOT LLVM_CONFIG)
-  find_program(LLVM_CONFIG NAMES "patmos-llvm-config")
-endif()
-if (NOT LLVM_CONFIG)
-  message(FATAL_ERROR "Could not find patmos-llvm-config")
-endif()
-
-find_program(LLVM_CONFIG NAMES "llvm-config-${LLVM_RECOMMENDED_VERSION}")
-if (NOT LLVM_CONFIG)
-  find_program(LLVM_CONFIG NAMES "patmos-llvm-config")
-endif()
-if (NOT LLVM_CONFIG)
-  message(FATAL_ERROR "Could not find patmos-llvm-config")
-endif()
-
-
-# Get the directory of llvm by using llvm-config. also remove whitespaces.
-execute_process(COMMAND ${LLVM_CONFIG} --prefix
-  OUTPUT_VARIABLE LLVM_ROOT
-  OUTPUT_STRIP_TRAILING_WHITESPACE )
-
-message(STATUS "LLVM root: ${LLVM_ROOT}")
-
-find_program(LLVM_C_COMPILER "patmos-clang-${LLVM_RECOMMENDED_VERSION}"
-                NAMES patmos-clang
-                HINTS ${LLVM_ROOT}/bin )
-find_program(LLVM_CXX_COMPILER "patmos-clang++-${LLVM_RECOMMENDED_VERSION}"
-                NAMES patmos-clang++ clang++
-                HINTS ${LLVM_ROOT}/bin )
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${LLVM_C_COMPILER} STREQUAL "LLVM_C_COMPILER-NOTFOUND")
-  message(FATAL "Could not find patmos-clang!")
-endif()
-
-message(STATUS "LLVM compiler: ${LLVM_C_COMPILER}")
-
-
-set(CROSS_RANLIB ${LLVM_ROOT}/bin/patmos-llvm-ranlib)
-set(CROSS_AR ${LLVM_ROOT}/bin/patmos-llvm-ar)
-find_program(CROSS_OBJDUMP patmos-llvm-objdump)
-find_program(CROSS_NM "patmos-nm" "nm")
-
-set(CMAKE_C_FLAGS  "${CROSS_COMPILER_FLAGS} -Wall -Wextra -Qunused-arguments -Wno-undefined-inline" CACHE STRING "CFLAGS")
-set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}       -fno-exceptions -fno-rtti" CACHE STRING "CXXFLAGS")
-set(CMAKE_ASM_FLAGS "-Qunused-arguments -fno-builtin " CACHE STRING "ASMFLAGS")
-set(CMAKE_ASM-ATT_FLAGS "-Qunused-arguments" CACHE STRING "ASMFLAGS")
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_CXX_FLAGS} -Xgold,-gc-sections  -nostdlib -nostartfiles" CACHE STRING "LDFLAGS")
-
-set(CCDIR "${LLVM_ROOT}")
-set(CMAKE_C_COMPILER  ${LLVM_C_COMPILER})
-set(CMAKE_CXX_COMPILER ${LLVM_CXX_COMPILER})
-set(CMAKE_RANLIB "${CROSS_RANLIB}" CACHE INTERNAL STRING)
-set(CMAKE_AR "${CROSS_AR}" CACHE INTERNAL STRING)
-
-## Add *additional* architecture specific compiler flags here.
-# Note that the flags set in toolchain.cmake are still present and used.
-set(ISA_C_FLAGS "-c -nostdinc" CACHE INTERNAL STRING)
-set(ISA_CXX_FLAGS "-nostdinc" CACHE INTERNAL STRING)
diff --git a/toolchain/posix.cmake b/toolchain/posix.cmake
deleted file mode 100644
index 9ad909c..0000000
--- a/toolchain/posix.cmake
+++ /dev/null
@@ -1,106 +0,0 @@
-# Generic system
-set(ARCH_PREFIX "")
-
-
-message(STATUS "Cross compiler root: ${CROSS_ROOT_PATH}")
-
-# LLVM version.
-SET(LLVM_RECOMMENDED_VERSION 3.4)
-
-if(NOT DEFINED ${LLVM_ROOT})
-  # find llvm-config. prefers to the one with version suffix, Ex:llvm-config-3.4
-  find_program(LLVM_CONFIG_EXE NAMES "llvm-config-${LLVM_RECOMMENDED_VERSION}"
-    PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin)
-  if (NOT LLVM_CONFIG_EXE)
-    find_program(LLVM_CONFIG_EXE NAMES "llvm-config"
-      PATHS /proj/i4danceos/tools/llvm-${LLVM_RECOMMENDED_VERSION}/bin)
-  endif()
-
-  # Get the directory of llvm by using llvm-config. also remove whitespaces.
-  execute_process(COMMAND ${LLVM_CONFIG_EXE} --prefix OUTPUT_VARIABLE LLVM_ROOT
-                 OUTPUT_STRIP_TRAILING_WHITESPACE )
-endif()
-
-
-message(STATUS "LLVM root: ${LLVM_ROOT}")
-
-# Find a compiler which compiles c source into llvm bitcode.
-# It first finds clang, then it finds llvm-g++ if there is no clang.
-find_program(LLVM_C_COMPILER "clang-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang
-                HINTS ${LLVM_ROOT}/bin )
-
-
-# Find a compiler which compiles c++ source into llvm bitcode.
-# It first finds clang, then it finds llvm-g++ if there is no clang.
-find_program(LLVM_CXX_COMPILER "clang++-${LLVM_RECOMMENDED_VERSION}"
-                NAMES clang++
-                HINTS ${LLVM_ROOT}/bin )
-
-# Checks whether a LLVM_COMPILER is found, give a warning if not found.
-# A warning instread of error is beceuse that we don't need clang during
-# building pinavm.
-if(${LLVM_C_COMPILER} STREQUAL "LLVM_C_COMPILER-NOTFOUND")
-  message(WARNING "Could not find clang or llvm-g++."
-                " Please install one of them !")
-endif()
-
-
-set(CMAKE_C_ARCH "i386")
-set(CMAKE_C_FLAGS "-Wall -m32 -Wextra -Qunused-arguments -Wno-undefined-inline" CACHE STRING "CFLAGS")
-set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -fno-rtti" CACHE STRING "CXXFLAGS")
-set(CMAKE_ASM_FLAGS "-Qunused-arguments" CACHE STRING "ASMFLAGS")
-set(CMAKE_ASM-TT_FLAGS "-Qunused-arguments" CACHE STRING "ASMFLAGS")
-
-find_program(CROSS_AR "llvm-ar" HINTS ${LLVM_ROOT}/bin)
-find_program(CROSS_NM "nm")
-find_program(CROSS_RANLIB "llvm-ranlib" HINTS ${LLVM_ROOT}/bin)
-# Find objdump for pagetable generation
-find_program(CROSS_OBJDUMP "llvm-objdump")
-
-
-set(CCDIR "${LLVM_ROOT}")
-set(CMAKE_C_COMPILER  ${LLVM_C_COMPILER})
-set(CMAKE_CXX_COMPILER ${LLVM_CXX_COMPILER})
-set(CMAKE_RANLIB "${CROSS_RANLIB}" CACHE INTERNAL STRING)
-set(CMAKE_AR "${CROSS_AR}" CACHE INTERNAL STRING)
-
-
-SET(CMAKE_FIND_ROOT_PATH ${CCDIR})
-SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-#set(CCDIR "/proj/i4danceos/tools/llvm-3.4")
-#set(CMAKE_C_COMPILER  ${CCDIR}/bin/clang)
-#set(CMAKE_CXX_COMPILER ${CCDIR}/bin/clang++)
-#set(CMAKE_CXX_COMPILER ${CCDIR}/bin/clang++)
-#set(CMAKE_RANLIB "${CCDIR}/bin/llvm-ranlib" CACHE INTERNAL STRING)
-#set(CMAKE_AR "${CCDIR}/bin/llvm-ar" CACHE INTERNAL STRING)
-#
-#SET(CMAKE_FIND_ROOT_PATH ${CCDIR})
-#SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-#SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-#SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
-## Add *additional* architecture specific compiler flags here.
-# Note that the flags set in toolchain.cmake are still present and used.
-set(ISA_C_FLAGS "-g -c -emit-llvm" CACHE INTERNAL STRING)
-set(ISA_CXX_FLAGS "-g -stdlib=libc++" CACHE INTERNAL STRING)
-set(ISA_ASM-ATT_FLAGS "--32" CACHE INTERNAL STRING)
-set(ISA_ASM_FLAGS "-m32" CACHE INTERNAL STRING)
-set(ISA_LD_FLAGS "-m32 -Qunused-arguments" CACHE INTERNAL STRING)
-
-#set(LD_OUTPUT_FORMAT "elf32-i386" CACHE INTERNAL "LD output format for linker script")
-
-## The kernel will live at 3GB + 1MB in the virtual
-##   address space, which will be mapped to 1MB in the
-##   physical address space.
-#set(LD_KERNEL_START_ADDRESS 0x100000 CACHE INTERNAL "Start address of the first section.")
-
-# ENABLE posix platform
-set(BUILD_posix "on" CACHE INTERNAL STRING)
-set(DOSEK_ARCHITECTURE "posix")
-
-
-
-- 
GitLab