1#
2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7cmake_minimum_required(VERSION 3.7.2)
8
9set(CMAKE_SYSTEM_NAME Generic)
10# For a generic system this is unused, so define it to something that will be
11# obvious if someone accidentally uses it
12set(CMAKE_SYSTEM_PROCESSOR seL4CPU)
13
14set(CMAKE_SYSROOT "${CMAKE_BINARY_DIR}")
15set(CMAKE_STAGING_PREFIX "${CMAKE_BINARY_DIR}/staging")
16
17# When this file is passed to configure_file in cmake, these variables get set to
18# the kernel platform configuration.
19set(sel4_arch @KernelSel4Arch@)
20set(arch @KernelArch@)
21set(mode @KernelWordSize@)
22set(cross_prefix @CROSS_COMPILER_PREFIX@)
23
24# If this file is used without templating, then cross_prefix will
25# have an invalid value and should only be assigned to CROSS_COMPILER_PREFIX
26# if it has been set to something different.
27# We need to build the test string dynamically otherwise the templating would
28# overwrite it.
29set(cross_prefix_test @CROSS_COMPILER_PREFIX)
30string(APPEND cross_prefix_test @)
31if(NOT "${cross_prefix}" STREQUAL "${cross_prefix_test}")
32    set(CROSS_COMPILER_PREFIX ${cross_prefix})
33endif()
34
35# This function hunts for an extant `gcc` with one of the candidate prefixes
36# specified in `ARGN`, allowing us to try different target triple prefixes for
37# cross-compilers built in various ways.
38function(FindPrefixedGCC out_var)
39    set("${out_var}" "PrefixedGCC-NOTFOUND")
40    foreach(prefix ${ARGN})
41        set("test_var" "_GCC_${prefix}")
42        find_program("${test_var}" "${prefix}gcc")
43        if(${test_var})
44            message(STATUS "Found GCC with prefix ${prefix}")
45            set("${out_var}" "${prefix}")
46            break()
47        endif()
48    endforeach()
49    if(${out_var})
50        set("${out_var}" "${${out_var}}" PARENT_SCOPE)
51    else()
52        message(FATAL_ERROR "Unable to find valid cross-compiling GCC")
53    endif()
54endfunction(FindPrefixedGCC)
55
56if("${CROSS_COMPILER_PREFIX}" STREQUAL "")
57    if(("${arch}" STREQUAL "arm") OR ("${arch}" STREQUAL "x86") OR ("${arch}" STREQUAL "riscv"))
58        if(${sel4_arch} STREQUAL "aarch32" OR ${sel4_arch} STREQUAL "arm_hyp")
59            FindPrefixedGCC(CROSS_COMPILER_PREFIX "arm-linux-gnueabi-" "arm-linux-gnu-")
60        elseif(${sel4_arch} STREQUAL "aarch64")
61            set(CROSS_COMPILER_PREFIX "aarch64-linux-gnu-")
62        elseif(${arch} STREQUAL "riscv")
63            FindPrefixedGCC(
64                CROSS_COMPILER_PREFIX "riscv64-unknown-linux-gnu-" "riscv64-unknown-elf-"
65            )
66        endif()
67    else()
68        # For backwards compatibility reasons we allow this file to work without templating.
69        # If initialised with -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/gcc.cmake" this script
70        # understood the following arguments: ARM, AARCH32, AARCH32HF, AARCH64, RISCV32, RISCV64, APPLE
71        if(AARCH32 OR ARM)
72            FindPrefixedGCC(CROSS_COMPILER_PREFIX "arm-linux-gnueabi-" "arm-linux-gnu-")
73            if(ARM)
74                message("ARM flag is deprecated, please use AARCH32")
75            endif()
76        elseif(AARCH64)
77            set(CROSS_COMPILER_PREFIX "aarch64-linux-gnu-")
78        elseif(RISCV32 OR RISCV64)
79            FindPrefixedGCC(
80                CROSS_COMPILER_PREFIX "riscv64-unknown-linux-gnu-" "riscv64-unknown-elf-"
81            )
82        endif()
83    endif()
84    if(AARCH32HF)
85        FindPrefixedGCC(
86            CROSS_COMPILER_PREFIX
87            "arm-linux-gnueabihf-"
88            "arm-linux-gnu-" # Later checks should confirm this has `hardfp`
89        )
90    endif()
91
92    if("${CROSS_COMPILER_PREFIX}" STREQUAL "")
93        # If we haven't set a target above we assume x86_64/ia32 target
94        if(APPLE)
95            # APPLE is a CMake variable that evaluates to True on a Mac OSX system
96            set(CROSS_COMPILER_PREFIX "x86_64-unknown-linux-gnu-")
97        endif()
98    endif()
99endif()
100
101set(CMAKE_C_COMPILER ${CROSS_COMPILER_PREFIX}gcc)
102set(CMAKE_ASM_COMPILER ${CROSS_COMPILER_PREFIX}gcc)
103set(CMAKE_CXX_COMPILER ${CROSS_COMPILER_PREFIX}g++)
104
105set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
106set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
107set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
108set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
109
110set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
111
112mark_as_advanced(FORCE CMAKE_TOOLCHAIN_FILE)
113
114# Invoke compiler via ccache. This has no effect if ccache cannot be found.
115# Projects can override this effect by resetting the RULE_LAUNCH_COMPILE and
116# RULE_LAUNCH_LINK properties.
117find_program(CCACHE ccache)
118if(NOT ("${CCACHE}" STREQUAL CCACHE-NOTFOUND))
119    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
120    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
121endif()
122mark_as_advanced(CCACHE)
123
124# GCC color options:
125# Ninja and ccache cause gcc to not emit colored output when -fdiagnostics-color=auto.
126# We upgrade this to -fdiagnostics-color=always if FORCE_COLORED_OUTPUT is set
127# We default FORCE_COLORED_OUTPUT=ON if GCC_COLORS is set in the environment
128# otherwise FORCE_COLORED_OUTPUT is left off.
129if($ENV{GCC_COLORS})
130    set(coloured_output ON)
131else()
132    set(coloured_output OFF)
133endif()
134option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored output." ${coloured_output})
135mark_as_advanced(FORCE_COLORED_OUTPUT)
136if(${FORCE_COLORED_OUTPUT})
137    include_guard(GLOBAL)
138    add_compile_options(-fdiagnostics-color=always)
139endif()
140