1#
2# Copyright 2017, Data61
3# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4# ABN 41 687 119 230.
5#
6# This software may be distributed and modified according to the terms of
7# the BSD 2-Clause license. Note that NO WARRANTY is provided.
8# See "LICENSE_BSD2.txt" for details.
9#
10# @TAG(DATA61_BSD)
11#
12
13cmake_minimum_required(VERSION 3.5.1)
14
15project(rumprun NONE)
16
17if(KernelArchX86)
18    if(Kernel64)
19        set(rumprun_arch "x86_64")
20        set(rumprun_sel4_arch "${rumprun_arch}")
21        set(rumprun_tuple "x86_64-rumprun-netbsd")
22        list(APPEND RUMPKERNEL_FLAGS -F ACLFLAGS=-m64)
23    else()
24        set(rumprun_arch "i486")
25        set(rumprun_sel4_arch "i386")
26        set(rumprun_tuple "i486-rumprun-netbsdelf")
27        list(
28            APPEND
29                RUMPKERNEL_FLAGS
30                -F
31                ACLFLAGS=-m32
32                -F
33                ACLFLAGS=-fno-pic
34        )
35    endif()
36    set(rumprun_tool_prefix "${rumprun_sel4_arch}--netbsd")
37elseif(KernelArchARM)
38    if(Kernel32)
39        set(rumprun_arch "arm")
40        set(rumprun_sel4_arch "aarch32")
41        set(rumprun_tuple "arm-rumprun-netbsdelf-eabi")
42        set(rumprun_tool_prefix "arm--netbsdelf-eabi")
43        # Suppress warnings that would otherwise stop the compilation
44        list(APPEND RUMPKERNEL_FLAGS -F CWARNFLAGS=-w)
45    endif()
46    # Append -march flag to ensure Rump is built properly for the specific CPU arch
47    list(APPEND RUMPKERNEL_FLAGS -F ACFLAGS='-march=${KernelArmArmV}')
48else()
49    # Stop processing this file the target platform isn't supported.
50    return()
51endif()
52
53# Build for release (Without debug symbols)
54if("${CMAKE_BUILD_TYPE}" IN_LIST "Release;MinSizeRel")
55    list(APPEND RUMPKERNEL_FLAGS -r)
56endif()
57
58# Ignore errors that cause compile to fail for GCC 8
59if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 8.0)
60    list(
61        APPEND
62            RUMPKERNEL_FLAGS
63            -F
64            CFLAGS='-Wno-cast-function-type
65            -Wno-packed-not-aligned
66            -Wno-tautological-compare'
67    )
68endif()
69
70set(configure_string "")
71config_string(RumprunTMPFSNumMiB RUMPRUN_TMPFS_NUM_MiB "Set this to the size of memory \
72    you want to back the tmpfs at /tmp." DEFAULT 1 UNQUOTE)
73
74config_string(RumprunCookfsDir RUMPRUN_COOKFS_DIR "cookfs directory" DEFAULT " ")
75
76config_option(
77    UseLargePages
78    USE_LARGE_PAGES
79    "Use large pages for rumprun backing memory.  This reduces the amount of book keeping required \
80        to track the pages created and also reduces initialisation time.  However, mprotect depends on \
81        4k pages in order to remap the pages with new permissions.  Thus, enabling large pages results in \
82        disabling the stack guard page functionality.  Use at own risk."
83    DEFAULT
84    OFF
85)
86
87add_config_library(rumprun "${configure_string}")
88
89# Only set FULLDIRPATH if the COOKFS dir is set to something proper
90if(NOT ${RumprunCookfsDir} STREQUAL " ")
91    set(FULLDIRPATH ${CMAKE_SOURCE_DIR}/${RumprunCookfsDir})
92    file(GLOB_RECURSE FULLDIR_DEPS ${FULLDIRPATH}/*)
93
94endif()
95
96file(GLOB_RECURSE ROOTFS_DEPS lib/librumprunfs_base/rootfs/*)
97
98add_custom_command(
99    OUTPUT build-temp/.librumrunfs.stamp
100    COMMAND
101        mkdir -p ${rumprun_sel4_arch}/sel4-obj/rootfs/ && rsync -av ${FULLDIRPATH}
102        ${CMAKE_CURRENT_SOURCE_DIR}/lib/librumprunfs_base/rootfs/
103        ${rumprun_sel4_arch}/sel4-obj//rootfs/
104        --delete
105    COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/build-temp/.librumrunfs.stamp
106    VERBATIM
107    DEPENDS ${ROOTFS_DEPS} ${FULLDIR_DEPS}
108    COMMENT "[Copying files to rootfs: ${FULLDIRPATH}]"
109)
110
111file(RELATIVE_PATH BUILD_DIRECTORY_RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
112
113set(
114    RR_ENV_VARS
115    PATH=$ENV{PATH}
116    SEL4_ARCH=${rumprun_sel4_arch}
117    RUMPRUN_BASE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
118    RUMP_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}
119    CC=${CMAKE_C_COMPILER}
120    CXX=${CMAKE_CXX_COMPILER}
121)
122
123set(
124    RUMPRUN_SEL4LIBS
125    sel4
126    sel4runtime
127    sel4muslcsys
128    sel4allocman
129    platsupport
130    sel4platsupport
131    platsupport
132    sel4serialserver
133    sel4sync
134    sel4utils
135    sel4vspace
136    sel4vka
137    sel4simple-default
138    sel4simple
139    sel4debug
140    utils
141    cpio
142    elf
143)
144
145set(LDFLAGS_SEL4 "")
146set(CFLAGS_SEL4 "")
147foreach(RUMPRUN_SEL4LIB IN LISTS RUMPRUN_SEL4LIBS)
148    string(
149        APPEND CFLAGS_SEL4
150        " -I$<JOIN:$<TARGET_PROPERTY:${RUMPRUN_SEL4LIB},INTERFACE_INCLUDE_DIRECTORIES>, -I>"
151    )
152    string(APPEND LDFLAGS_SEL4 " -L$<TARGET_FILE_DIR:${RUMPRUN_SEL4LIB}> -l${RUMPRUN_SEL4LIB}")
153endforeach()
154string(APPEND LDFLAGS_SEL4 " $<TARGET_PROPERTY:muslc_imported,IMPORTED_LOCATION>")
155string(APPEND CFLAGS_SEL4 " -I${CMAKE_CURRENT_SOURCE_DIR}/platform/sel4/include/sel4")
156
157string(
158    APPEND CFLAGS_SEL4
159    " -I$<JOIN:$<TARGET_PROPERTY:sel4_autoconf,INTERFACE_INCLUDE_DIRECTORIES>, -I>"
160)
161string(
162    APPEND CFLAGS_SEL4
163    " -I$<JOIN:$<TARGET_PROPERTY:rumprun_Config,INTERFACE_INCLUDE_DIRECTORIES>, -I>"
164)
165
166# Create a custom target that invokes a rumprun build command from ./build-rr.sh
167# command_name is the name of the command to run
168# command_description is the command description printed out by ninja
169# There are optional arguments:
170# PHONY will cause the target to always be stale so that it will always rerun the command
171# TARGET_NAME overrides the target name. Otherwise the command_name is used as the target name
172# RUMP_TARGETS are
173# FILE_DEPS are files that get passed to DEPENDS of the internal custom_command definition
174# ENV_VARS are extra environment variables that get set when build-rr.sh is called
175function(CreateRumprunBuildCommand command_name command_description)
176    cmake_parse_arguments(
177        PARSE_ARGV
178        2
179        RUMP_BUILD
180        "PHONY"
181        "TARGET_NAME"
182        "RUMP_TARGETS;FILE_DEPS;ENV_VARS;OUTPUT_FILES"
183    )
184    if(NOT "${RUMP_BUILD_UNPARSED_ARGUMENTS}" STREQUAL "")
185        message(FATAL_ERROR "Unknown arguments to CreateRumprunBuildCommand")
186    endif()
187
188    # Suppress rump build output
189    # TODO find a way to disable this when the verbose flag is passed to ninja
190    set(QUIET -q -q)
191
192    # Create command line that will be invoked
193    set(
194        BUILD_RR_CMD_LINE
195        ${CMAKE_COMMAND}
196        -E
197        env
198        ${RR_ENV_VARS}
199        ${RUMP_BUILD_ENV_VARS}
200        ./build-rr.sh
201        ${QUIET}
202        -d
203        ${BUILD_DIRECTORY_RELATIVE}/${rumprun_sel4_arch}/rumprun
204        -o
205        ${BUILD_DIRECTORY_RELATIVE}/${rumprun_sel4_arch}/sel4-obj
206        sel4
207        ${command_name}
208        --
209        ${RUMPKERNEL_FLAGS}
210    )
211
212    # Add stampfiles from other rump targets to rump_deps list to be used in custom_command depends field
213    foreach(RUMP_TARGET IN LISTS RUMP_BUILD_RUMP_TARGETS)
214        get_target_property(stamp ${RUMP_TARGET} STAMP_FILE)
215        list(APPEND rump_deps ${stamp})
216    endforeach()
217
218    # We support overriding the target name if neccessary
219    set(STAMP build-temp/${command_name}.stamp)
220    Set(TARGET_NAME ${command_name})
221    if(NOT "${RUMP_BUILD_TARGET_NAME}" STREQUAL "")
222        set(TARGET_NAME ${RUMP_BUILD_TARGET_NAME})
223        set(STAMP build-temp/${RUMP_BUILD_TARGET_NAME}.stamp)
224    endif()
225
226    # custom_command doesn't have a BUILD_ALWAYS option, so we emulate it by creating a phony dependency
227    # That is then deleted at the end of each build.  This is used when we cannot correctly track dependencies
228    if(RUMP_BUILD_PHONY)
229        set(STAMP_PHONY ${CMAKE_CURRENT_BINARY_DIR}/build-temp/${TARGET_NAME}.phony.stamp)
230        set(TOUCHSTAMP_PHONY ${CMAKE_COMMAND} -E remove ${STAMP_PHONY})
231        add_custom_command(
232            OUTPUT ${STAMP_PHONY}
233            COMMAND
234                ${CMAKE_COMMAND} -E touch ${STAMP_PHONY}
235            COMMENT "[Calling phony rule]"
236        )
237    endif()
238
239    # Create custom command.  It deletes the PHONY stampfile if one exists, runs the rump command and then touches the output ${STAMP} file
240    add_custom_command(
241        OUTPUT ${STAMP} ${RUMP_BUILD_OUTPUT_FILES}
242        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
243        COMMAND ${TOUCHSTAMP_PHONY}
244        COMMAND ${BUILD_RR_CMD_LINE}
245        COMMAND
246            ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${STAMP}
247        DEPENDS
248            ${RUMP_BUILD_RUMP_TARGETS}
249            ${rump_deps}
250            ${RUMP_BUILD_FILE_DEPS}
251            ${STAMP_PHONY}
252        COMMENT "[Calling ./build-rr.sh - ${command_description}]"
253    )
254
255    # Add Target for custom_command.
256    add_custom_target(
257        ${TARGET_NAME}
258        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${STAMP} ${RUMP_BUILD_RUMP_TARGETS}
259    )
260
261    # Set STAMP_FILE property on custom target so that other RUMP_TARGETS can depend on it
262    set_target_properties(${TARGET_NAME} PROPERTIES STAMP_FILE ${CMAKE_CURRENT_BINARY_DIR}/${STAMP})
263
264endfunction()
265
266# Glob all of the different files in the rumprun sources
267# We use a glob as it isn't practical to keep a full list of files up to date
268file(GLOB APP_TOOLS_FILES app-tools/*)
269file(GLOB_RECURSE SEL4_PLATFORM_FILES platform/sel4/*)
270
271set(
272    RUMPRUN_GLOB_NETBSD_SOURCES OFF
273    CACHE BOOL "This flag causes CMake to add lots of source files to its dependency lists
274     which noticeably slows down its configuration times (up to 4 times slower).
275     When not making changes in the rumprun directory, it is likely not necessary
276     to have this enabled."
277)
278if(RUMPRUN_GLOB_NETBSD_SOURCES)
279    file(GLOB_RECURSE RUMPRUN_LIB_FILES lib/*)
280    file(GLOB_RECURSE RUMPRUN_INCLUDE_FILES include/*)
281    file(GLOB_RECURSE SRC_NETBSD_FILES src-netbsd/*)
282    file(GLOB_RECURSE BUILD_RR_FILES buildrump.sh/*)
283endif()
284
285# Create rumprun build targets
286CreateRumprunBuildCommand(tools "Rump kernel tools" FILE_DEPS ${BUILD_RR_FILES} ${SRC_NETBSD_FILES})
287
288CreateRumprunBuildCommand(toolsconfig "Extra Rumprun tools configuration" RUMP_TARGETS tools)
289
290CreateRumprunBuildCommand(rumplibs "Rump kernel modules" RUMP_TARGETS toolsconfig)
291
292CreateRumprunBuildCommand(
293    apptools
294    "Rumprun app toolchains"
295    RUMP_TARGETS
296    rumplibs
297    FILE_DEPS
298    ${APP_TOOLS_FILES}
299)
300
301CreateRumprunBuildCommand(userspace "Rumprun userspace libraries" RUMP_TARGETS rumplibs)
302
303CreateRumprunBuildCommand(
304    platformtoplevel
305    "platform toplevel"
306    RUMP_TARGETS
307    userspace
308    toolsconfig
309    FILE_DEPS
310    ${RUMPRUN_LIB_FILES}
311    ${CMAKE_CURRENT_SOURCE_DIR}/platform/makepseudolinkstubs.sh
312)
313
314CreateRumprunBuildCommand(
315    platformheaders
316    "Platform headers"
317    RUMP_TARGETS
318    toolsconfig
319    FILE_DEPS
320    ${SEL4_PLATFORM_FILES}
321    ${RUMPRUN_LIB_FILES}
322    ${RUMPRUN_INCLUDE_FILES}
323)
324
325CreateRumprunBuildCommand(
326    platformlibs
327    "Rumprun platform libraries"
328    RUMP_TARGETS
329    platformheaders
330    rumplibs
331    userspace
332    platformtoplevel
333    FILE_DEPS
334    ${CMAKE_CURRENT_BINARY_DIR}/build-temp/.librumrunfs.stamp
335    ${RUMPRUN_LIB_FILES}
336    ${RUMPRUN_INCLUDE_FILES}
337)
338
339# platformobj, rump_pci, and extralibs targets all depend on seL4 header files that we can't easily track
340# therefore these rules need to be marked as PHONY and rerun everytime
341CreateRumprunBuildCommand(
342    platformobj
343    "Platform object files"
344    PHONY
345    ENV_VARS
346    "LDFLAGS_SEL4=${LDFLAGS_SEL4}"
347    "CRTOBJFILES_SEL4=${CRTObjFiles}"
348    "FINOBJFILES_SEL4=${FinObjFiles}"
349    "CFLAGS_SEL4=${CFLAGS_SEL4}"
350    RUMP_TARGETS
351    userspace
352    platformheaders
353    rumplibs
354    FILE_DEPS
355    ${SEL4_PLATFORM_FILES}
356    ${RUMPRUN_LIB_FILES}
357    ${RUMPRUN_INCLUDE_FILES}
358    ${RUMPRUN_SEL4LIBS}
359    muslc
360    OUTPUT_FILES
361    ${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/sel4-obj/rumprun-intermediate.o
362)
363
364CreateRumprunBuildCommand(
365    extralibs
366    "extra rump kernel modules"
367    PHONY
368    ENV_VARS
369    "CFLAGS_SEL4=${CFLAGS_SEL4}"
370    RUMP_TARGETS
371    platformheaders
372    rumplibs
373    FILE_DEPS
374    ${SEL4_PLATFORM_FILES}
375    ${RUMPRUN_LIB_FILES}
376    ${RUMPRUN_INCLUDE_FILES}
377    ${SRC_NETBSD_FILES}
378    ${RUMPRUN_SEL4LIBS}
379    muslc
380)
381
382CreateRumprunBuildCommand(
383    platforminstall
384    "Install Platform files"
385    RUMP_TARGETS
386    platformlibs
387    platformobj
388    extralibs
389)
390
391CreateRumprunBuildCommand(
392    pci
393    "PCI rump kernel modules"
394    PHONY
395    TARGET_NAME
396    rump_pci
397    ENV_VARS
398    "CFLAGS_SEL4=${CFLAGS_SEL4}"
399    RUMP_TARGETS
400    platformheaders
401    rumplibs
402    FILE_DEPS
403    ${SEL4_PLATFORM_FILES}
404    ${RUMPRUN_LIB_FILES}
405    ${RUMPRUN_INCLUDE_FILES}
406    ${SRC_NETBSD_FILES}
407    ${RUMPRUN_SEL4LIBS}
408    muslc
409)
410
411# Install commands install artifacts to the rumprun install directory.  Top level is everything required to build rumprun applications
412# bottom level is everything required to link a rumprun app with the bottom level platform libraries and basefiles.
413CreateRumprunBuildCommand(
414    install
415    "install toplevel"
416    RUMP_TARGETS
417    userspace
418    apptools
419    platformtoplevel
420    TARGET_NAME
421    rumprun_install_toplevel
422)
423CreateRumprunBuildCommand(
424    install
425    "install bottomlevel"
426    PHONY
427    RUMP_TARGETS
428    platforminstall
429    rump_pci
430    rumplibs
431    rumprun_install_toplevel
432    TARGET_NAME
433    rumprun_install_bottomlevel
434)
435
436# Add toplevel and bottomlevel libraries.  The IMPORTED_LOCATION property is important because it forces the downstream dependencies
437# to be rebuilt if any of the rumprun commands have been run.  This is also why these are libraries and not custom targets.
438add_library(rumprun_toplevel_support STATIC IMPORTED GLOBAL)
439add_dependencies(rumprun_toplevel_support rumprun_install_toplevel)
440get_target_property(stamp rumprun_install_toplevel STAMP_FILE)
441set_property(TARGET rumprun_toplevel_support PROPERTY IMPORTED_LOCATION "${stamp}")
442
443add_library(rumprun_bottomlevel_support STATIC IMPORTED GLOBAL)
444add_dependencies(rumprun_bottomlevel_support rumprun_install_bottomlevel rumprun_toplevel_support)
445get_target_property(stamp rumprun_install_bottomlevel STAMP_FILE)
446set_property(TARGET rumprun_bottomlevel_support PROPERTY IMPORTED_LOCATION "${stamp}")
447
448# Add interface library to make seL4 rumprun headers available to loader apps
449add_library(rumprun INTERFACE)
450add_dependencies(rumprun rumprun_bottomlevel_support)
451target_include_directories(rumprun INTERFACE "platform/sel4/include/sel4")
452
453# TODO: Figure out way to better handle target properties for install locations.  We currently hard code them as it would be too
454# convoluted to pull them out of the generated config files and use in generator expressions.
455set_property(
456    TARGET rumprun_toplevel_support
457    PROPERTY RUMPRUN_TOOLCHAIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/rumprun/bin"
458)
459set_property(
460    TARGET rumprun_toplevel_support
461    PROPERTY
462        RUMPRUN_TOOLCHAIN_CMAKE
463        "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/rumprun/rumprun-${rumprun_arch}/share/${rumprun_tuple}-toolchain.cmake"
464)
465set_property(TARGET rumprun_toplevel_support PROPERTY RUMPRUN_TOOLCHAIN_TUPLE "${rumprun_tuple}")
466set_property(
467    TARGET rumprun_bottomlevel_support
468    PROPERTY RUMPRUN_BASEDIR "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/sel4-obj"
469)
470
471set(
472    RUMPRUN_TOOLS_DIR "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/sel4-obj/rumptools/bin"
473    CACHE INTERNAL ""
474    FORCE
475)
476set(
477    RUMPRUN_BASEDIR "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/sel4-obj"
478    CACHE INTERNAL ""
479    FORCE
480)
481set(RUMPRUN_TOOLS_PREFIX "${rumprun_tool_prefix}" CACHE INTERNAL "" FORCE)
482set(
483    RUMPRUN_TOOLCHAIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/rumprun/bin"
484    CACHE INTERNAL ""
485    FORCE
486)
487
488add_library(rumprun_intermediate_file STATIC IMPORTED GLOBAL)
489target_link_libraries(
490    rumprun_intermediate_file
491    INTERFACE
492        rumprun
493        ${RUMPRUN_SEL4LIBS}
494        rumprun_Config
495        sel4_autoconf
496)
497set_property(
498    TARGET rumprun_intermediate_file
499    PROPERTY
500        IMPORTED_LOCATION
501        "${CMAKE_CURRENT_BINARY_DIR}/${rumprun_sel4_arch}/sel4-obj/rumprun-intermediate.o"
502)
503add_dependencies(rumprun_intermediate_file platformobj)
504