• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14# Add a panda assembly to the project using the specified source file
15#
16# Example usage:
17#
18#   add_panda_assembly(TARGET <name> SOURCE <source> INDIR <input directory> OUTDIR <output directory> TARGETNAME <target file name>)
19#
20# Adds a panda assembly target called <name> to be build from <source> file
21# listed in the command invocation.
22function(add_panda_assembly)
23    set(prefix ARG)
24    set(noValues)
25    set(singleValues TARGET SOURCE INDIR OUTDIR TARGETNAME)
26    set(multiValues)
27    cmake_parse_arguments(${prefix}
28                          "${noValues}"
29                          "${singleValues}"
30                          "${multiValues}"
31                          ${ARGN})
32    if (NOT DEFINED ARG_TARGET)
33        message(FATAL_ERROR "Mandatory TARGET argument is not defined.")
34    endif()
35
36    if (NOT DEFINED ARG_SOURCE)
37        message(FATAL_ERROR "Mandatory SOURCE argument is not defined.")
38    endif()
39
40    set(source_file_dir "${CMAKE_CURRENT_SOURCE_DIR}")
41
42    if (DEFINED ARG_INDIR)
43        set(source_file_dir "${ARG_INDIR}")
44    endif()
45
46    set(binary_file_dir "${CMAKE_CURRENT_BINARY_DIR}")
47
48    if (DEFINED ARG_OUTDIR)
49        set(binary_file_dir "${ARG_OUTDIR}")
50    endif()
51
52    set(target_file_name "${ARG_TARGET}")
53
54    if (DEFINED ARG_TARGETNAME)
55        set(target_file_name "${ARG_TARGETNAME}")
56    endif()
57
58    if (TARGET ARG_TARGET)
59        message(FATAL_ERROR "Target ${ARG_TARGET} is already defined.")
60    endif()
61
62    set(source_file "${source_file_dir}/${ARG_SOURCE}")
63    set(binary_file "${binary_file_dir}/${target_file_name}.abc")
64
65    if(CMAKE_CROSSCOMPILING)
66        ExternalProject_Get_Property(panda_host_tools binary_dir)
67        set(assembler_target panda_host_tools)
68        set(assembler_bin    "${binary_dir}/assembler/ark_asm")
69    else()
70        set(assembler_target ark_asm)
71        set(assembler_bin    $<TARGET_FILE:${assembler_target}>)
72    endif()
73
74    add_custom_command(OUTPUT "${binary_file}"
75                       COMMENT "Building ${ARG_TARGET}"
76                       COMMAND "${assembler_bin}" "${source_file}" "${binary_file}"
77                       DEPENDS ${assembler_target} "${source_file}")
78
79    add_custom_target(${ARG_TARGET} DEPENDS "${binary_file}")
80endfunction()
81
82# Use `mkdir` instead of `file(MAKE_DIRECTORY)` to create dependency on the directory existence:
83set(COMPILER_STATS_DIR "${CMAKE_BINARY_DIR}/compiler/stats/csv")
84add_custom_target(compiler_stats_dir
85                  COMMAND mkdir -p "${COMPILER_STATS_DIR}")
86
87# Add a single buildable and runnable Panda Assembly file to the build tree.
88#
89# Usage:
90#
91#   panda_add_asm_file(
92#        FILE <source>
93#        TARGET <target>
94#        [ENTRY <entry_point>]
95#        [SUBDIR <subdir>]
96#        [OUTPUT_FILE_VARIABLE <variable>]
97#        [ERROR_FILE_VARIABLE <variable>]
98#        [SKIP_BUILD TRUE|FALSE]
99#        [AOT_MODE TRUE|FALSE]
100#        [AOT_STATS TRUE|FALSE]
101#        [DEPENDS <dependency>...]
102#        [RUNTIME_OPTIONS <option>...]
103#        [COMPILER_OPTIONS <option>...]
104#        [AOT_GC_OPTION <option>]
105#        [ENTRY_ARGUMENTS <argument>...]
106#        [TIMEOUT <timeout>]
107#        [LANGUAGE_CONTEXT <language>]
108#    )
109#
110# Adds a target <target> which assembles the assembly file <source>
111# with Panda assembler and runs it with Panda interpreter.
112#
113# Options:
114#
115# ENTRY
116#   Entry point to execute in format <Class>::<method>. By default _GLOBAL::main is used
117#
118# SUBDIR
119#   Subdirectory in the current binary directory that is used to store build artifacts.
120#   Full path to directory with artifacts: ${CMAKE_CURRENT_BINARY_DIR}/<subdir>/<target>
121#
122# OUTPUT_FILE_VARIABLE, ERROR_FILE_VARIABLE
123#   The variable named will be set with the paths to files with contents of the stdout and
124#   stderr of the program respectively
125#
126# SKIP_BUILD
127#   Do not run assembly
128#
129# AOT_MODE
130#   Run test in AOT mode
131#
132# AOT_STATS
133#   Creates additional independent target `${TARGET}-stats`.
134#   `stats`-target dumps AOT compiler statistics in `${COMPILER_STATS_DIR}/${TARGET}.csv`
135#
136# DEPENDS
137#   List of additional dependences (exclude assembler and interpreter)
138#
139# RUNTIME_OPTIONS
140#   Runtime options
141#
142# COMPILER_OPTIONS
143#   Options for compiler, given both to panda and paoc
144#
145# AOT_GC_OPTION
146#  Type of a gc
147#
148# ENTRY_ARGUMENTS
149#   List of arguments that will be passed to program's entry point
150#
151# TIMEOUT
152#   If specified, the program will be run and terminated with the signal 10 (corresponds
153#   to SIGUSR1 on most platforms) after the given timeout. The format of the value
154#   must match the `timeout` command. The run will be considered successful if the program
155#   exits before the timeout with the successful exit code or if it is terminated
156#   after the timeout with the signal 10.
157#
158# LANGUAGE_CONTEXT
159#   Set the language-dependent semantics for the code. Possible values: core, java.
160#
161function(panda_add_asm_file)
162    set(prefix ARG)
163    set(noValues)
164    set(singleValues FILE ENTRY TARGET SUBDIR OUTPUT_FILE_VARIABLE ERROR_FILE_VARIABLE SKIP_BUILD AOT_MODE AOT_STATS TIMEOUT LANGUAGE_CONTEXT AOT_GC_OPTION)
165    set(multiValues DEPENDS RUNTIME_OPTIONS COMPILER_OPTIONS ENTRY_ARGUMENTS PRLIMIT_OPTIONS ADDITIONAL_STDLIBS)
166    cmake_parse_arguments(${prefix}
167                          "${noValues}"
168                          "${singleValues}"
169                          "${multiValues}"
170                          ${ARGN})
171
172    if (NOT DEFINED ARG_FILE)
173        message(FATAL_ERROR "Mandatory FILE argument is not defined.")
174    endif()
175
176    if (NOT DEFINED ARG_TARGET)
177        message(FATAL_ERROR "Mandatory TARGET argument is not defined.")
178    endif()
179
180    if (TARGET ARG_TARGET)
181        message(FATAL_ERROR "Target ${ARG_TARGET} is already defined.")
182    endif()
183
184    set(build_dir   "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBDIR}/${ARG_TARGET}")
185    set(build_log   "${build_dir}/build.log")
186    set(build_out   "${build_dir}/build.out")
187    set(build_err   "${build_dir}/build.err")
188    set(binary_file "${build_dir}/test.abc")
189    set(launch_file "${build_dir}/launch.sh")
190    set(output_file "${build_dir}/run.out")
191    set(error_file  "${build_dir}/run.err")
192
193    file(MAKE_DIRECTORY "${build_dir}")
194
195    if (DEFINED ARG_OUTPUT_FILE_VARIABLE)
196        set(${ARG_OUTPUT_FILE_VARIABLE} "${output_file}" PARENT_SCOPE)
197    endif()
198
199    if (DEFINED ARG_ERROR_FILE_VARIABLE)
200        set(${ARG_ERROR_FILE_VARIABLE} "${error_file}" PARENT_SCOPE)
201    endif()
202
203    if (ARG_SKIP_BUILD)
204        set(binary_file "${ARG_FILE}")
205    else()
206        set(assembler ark_asm)
207        add_custom_command(OUTPUT "${binary_file}"
208                          COMMENT "Building ${ARG_TARGET}"
209                          COMMAND ${PANDA_RUN_PREFIX} $<TARGET_FILE:${assembler}> --verbose --log-file "${build_log}" "${ARG_FILE}" "${binary_file}" 1>"${build_out}" 2>"${build_err}"
210                          DEPENDS ${assembler} "${ARG_FILE}")
211    endif()
212
213    if (DEFINED ARG_TIMEOUT AND NOT "${ARG_TIMEOUT}" STREQUAL "")
214        set(timeout_signal 10)
215        set(timeout_prefix "timeout --preserve-status --signal=${timeout_signal} --kill-after=10s ${ARG_TIMEOUT}")
216        set(timeout_suffix "|| [ `expr \$? % 128` -eq ${timeout_signal} ]")
217    else()
218        set(timeout_prefix "")
219        set(timeout_suffix "")
220    endif()
221
222    if (NOT DEFINED ARG_ENTRY)
223        set(ARG_ENTRY "_GLOBAL::main")
224    endif()
225
226    set(panda_stdlib   arkstdlib)
227    set(panda_cli      ark)
228    set(panda_verifier verifier)
229
230    set(stdlibs "${${panda_stdlib}_BINARY_DIR}/${panda_stdlib}.abc")
231    if (DEFINED ARG_ADDITIONAL_STDLIBS)
232        list(APPEND stdlibs ${ARG_ADDITIONAL_STDLIBS})
233    endif()
234
235    set(spaces "core")
236    if (NOT "core" STREQUAL "${ARG_LANGUAGE_CONTEXT}")
237        set(spaces "${ARG_LANGUAGE_CONTEXT}")
238    endif()
239
240    string(REPLACE ";" ":" boot_stdlibs "${stdlibs}")
241    string(REPLACE ";" ":" boot_spaces  "${spaces}")
242
243    if (ARG_AOT_MODE)
244        set(aot_compiler ark_aot)
245        set(launch_aot_file "${build_dir}/launch_aot.sh")
246        set(aot_file        "${build_dir}/test.an")
247        set(aot_file_stats  "${build_dir}/test_stats.an")
248        set(launcher_aot
249            "${PANDA_RUN_PREFIX}"
250            "$<TARGET_FILE:${aot_compiler}>"
251            "--boot-panda-files \"${boot_stdlibs}\""
252            "--load-runtimes=${boot_spaces}"
253            "--paoc-panda-files \"${binary_file}\""
254            "--paoc-output \"${aot_file}\""
255            "--compiler-ignore-failures=false"
256            "${ARG_COMPILER_OPTIONS}"
257            "${ARG_AOT_GC_OPTION}"
258            "1>>\"${build_out}\""
259            "2>>\"${build_err}\""
260        )
261        string(REPLACE ";" " " launcher_aot "${launcher_aot}")
262        file(GENERATE OUTPUT ${launch_aot_file} CONTENT "${launcher_aot}")
263
264        # TODO(msherstennikov): enable for arm64
265        # Problem in arm64 is that ark_aotdump cannot open aot elf file with error: "undefined symbol: aot"
266        if (NOT PANDA_MINIMAL_VIXL AND PANDA_TARGET_AMD64)
267            set(aotdump_command
268                    "${PANDA_RUN_PREFIX}"
269                    "$<TARGET_FILE:ark_aotdump>"
270                    "--output-file=/dev/null"
271                    "--show-code" "disasm"
272                    "${aot_file}")
273        endif()
274
275        set(aot_compile_depends "${aot_compiler}" "${binary_file}")
276        if (NOT PANDA_MINIMAL_VIXL)
277            list(APPEND aot_compile_depends "ark_aotdump")
278        endif()
279
280        add_custom_command(OUTPUT "${aot_file}"
281                COMMENT "Running aot compiler for ${ARG_TARGET}"
282                COMMAND . ${launch_aot_file} || (cat ${build_err} && false)
283                COMMAND ${aotdump_command}
284                DEPENDS ${aot_compile_depends})
285        list(APPEND ARG_RUNTIME_OPTIONS "--aot-file=${aot_file}")
286
287        if (ARG_AOT_STATS)
288            set(launch_aot_stats_file "${build_dir}/launch_aot_stats.sh")
289            set(launcher_aot_stats
290                "${PANDA_RUN_PREFIX}"
291                "$<TARGET_FILE:${aot_compiler}>"
292                "--boot-panda-files \"${boot_stdlibs}\""
293                "--load-runtimes=${boot_spaces}"
294                "--paoc-panda-files \"${binary_file}\""
295                "--paoc-output \"${aot_file_stats}\""
296                "--compiler-ignore-failures=false"
297                "--compiler-dump-stats-csv=\"${COMPILER_STATS_DIR}/${ARG_TARGET}.csv\""
298                "${ARG_COMPILER_OPTIONS}"
299                "${ARG_AOT_GC_OPTION}"
300                "1>>\"${build_out}\""
301                "2>>\"${build_err}\""
302            )
303            string(REPLACE ";" " " launcher_aot_stats "${launcher_aot_stats}")
304            file(GENERATE OUTPUT ${launch_aot_stats_file} CONTENT "${launcher_aot_stats}")
305            add_custom_target(${ARG_TARGET}-stats
306                              COMMENT "Gathering AOT-statistics for ${ARG_TARGET}"
307                              COMMAND . ${launch_aot_stats_file}
308                              DEPENDS ${aot_compiler} "${binary_file}" compiler_stats_dir)
309        endif()
310    endif()
311
312    # NB! The lines below imply that we cannot handle ";" properly
313    # in both Panda's own options and the runned program's options.
314    # TODO: Fix this once this becomes an issue.
315    string(REPLACE ";" " " runtime_options "${ARG_COMPILER_OPTIONS} ${ARG_RUNTIME_OPTIONS}")
316    string(REPLACE ";" " " entry_arguments "${ARG_ENTRY_ARGUMENTS}")
317
318    set(prlimit_cmd "")
319    if (DEFINED ARG_PRLIMIT_OPTIONS)
320        set(prlimit_cmd "prlimit ${ARG_PRLIMIT_OPTIONS}")
321        string(REPLACE ";" " " prlimit_cmd "${prlimit_cmd}")
322    endif()
323
324    if (${runtime_options} MATCHES ".*events-output=csv.*")
325        set(runtime_options "${runtime_options} --events-file=${build_dir}/events.csv")
326    endif()
327
328    set(launcher
329        "${timeout_prefix}"
330        "${prlimit_cmd}"
331        "${PANDA_RUN_PREFIX}"
332        $<TARGET_FILE:${panda_cli}>
333        "--boot-panda-files \"${boot_stdlibs}\""
334        "--load-runtimes=${boot_spaces}"
335        "--compiler-ignore-failures=false"
336        "${runtime_options}"
337        "\"${binary_file}\""
338        "\"${ARG_ENTRY}\""
339        "${entry_arguments}"
340        "1>\"${output_file}\""
341        "2>\"${error_file}\""
342        "${timeout_suffix}"
343    )
344    string(REPLACE ";" " " launcher "${launcher}")
345    file(GENERATE OUTPUT ${launch_file} CONTENT "${launcher}")
346
347    add_custom_target(${ARG_TARGET}
348                      COMMENT "Running ${ARG_TARGET}"
349                      COMMAND . ${launch_file} || (cat ${error_file} && false)
350                      DEPENDS ${panda_cli} ${panda_stdlib} "${binary_file}" ${aot_file})
351
352    if (DEFINED ARG_DEPENDS)
353        add_dependencies(${ARG_TARGET} ${ARG_DEPENDS})
354    endif()
355
356
357endfunction()
358
359# Add a single buildable and verifiable Panda Assembly file to the build tree.
360#
361# Usage:
362#
363#   verifier_add_asm_file(
364#        FILE <source>
365#        TARGET <target>
366#        [RUNTIME_OPTIONS <runtime options>]
367#        [VERIFIER_OPTIONS <verifier options>]
368#        [SUBDIR <subdir>]
369#        [OUTPUT_FILE_VARIABLE <variable>]
370#        [ERROR_FILE_VARIABLE <variable>]
371#        [DEPENDS <dependency>...]
372#        [TIMEOUT <timeout>]
373#        [LANGUAGE_CONTEXT <language>]
374#    )
375#
376# Adds a target <target> which assembles the assembly file <source>
377# with Panda assembler and verifies it with verifier.
378#
379# Options:
380#
381# SUBDIR
382#   Subdirectory in the current binary directory that is used to store build artifacts.
383#   Full path to directory with artifacts: ${CMAKE_CURRENT_BINARY_DIR}/<subdir>/<target>
384#
385# OUTPUT_FILE_VARIABLE, ERROR_FILE_VARIABLE
386#   The variable named will be set with the paths to files with contents of the stdout and
387#   stderr of the program respectively
388#
389# DEPENDS
390#   List of additional dependences (exclude assembler and interpreter)
391#
392# RUNTIME_OPTIONS
393#   Runtime initialization options
394#
395# VERIFIER_OPTIONS
396#   Verifier CLI options
397#
398# VERIFIER_FAIL_TEST
399#   If true, verifier is allowed to exit with non-0 exit code
400#
401# TIMEOUT
402#   If specified, the program will be run and terminated with the signal 10 (corresponds
403#   to SIGUSR1 on most platforms) after the given timeout. The format of the value
404#   must match the `timeout` command. The run will be considered successful if the program
405#   exits before the timeout with the successful exit code or if it is terminated
406#   after the timeout with the signal 10.
407#
408# LANGUAGE_CONTEXT
409#   Set the language-dependent semantics for the code. Possible values: core, java.
410#
411function(verifier_add_asm_file)
412    set(prefix ARG)
413    set(noValues VERIFIER_FAIL_TEST)
414    set(singleValues
415        FILE
416        TARGET
417        SUBDIR
418        OUTPUT_FILE_VARIABLE
419        ERROR_FILE_VARIABLE
420        TIMEOUT
421        LANGUAGE_CONTEXT)
422    set(multiValues DEPENDS RUNTIME_OPTIONS VERIFIER_OPTIONS STDLIBS)
423    cmake_parse_arguments(${prefix}
424                          "${noValues}"
425                          "${singleValues}"
426                          "${multiValues}"
427                          ${ARGN})
428
429    if (NOT DEFINED ARG_FILE)
430        message(FATAL_ERROR "Mandatory FILE argument is not defined.")
431    endif()
432
433    if (NOT DEFINED ARG_TARGET)
434        message(FATAL_ERROR "Mandatory TARGET argument is not defined.")
435    endif()
436
437    if (TARGET ARG_TARGET)
438        message(FATAL_ERROR "Target ${ARG_TARGET} is already defined.")
439    endif()
440
441    set(build_dir   "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBDIR}/${ARG_TARGET}")
442    set(build_out   "${build_dir}/build.out")
443    set(build_err   "${build_dir}/build.err")
444    set(binary_file "${build_dir}/test.abc")
445    set(launch_file "${build_dir}/verifier_launch.sh")
446    set(output_file "${build_dir}/verify.out")
447    set(error_file  "${build_dir}/verify.err")
448
449    file(MAKE_DIRECTORY "${build_dir}")
450
451    if (DEFINED ARG_OUTPUT_FILE_VARIABLE)
452        set(${ARG_OUTPUT_FILE_VARIABLE} "${output_file}" PARENT_SCOPE)
453    endif()
454
455    if (DEFINED ARG_ERROR_FILE_VARIABLE)
456        set(${ARG_ERROR_FILE_VARIABLE} "${error_file}" PARENT_SCOPE)
457    endif()
458
459    set(assembler ark_asm)
460    add_custom_command(OUTPUT "${binary_file}"
461                      COMMENT "Building ${ARG_TARGET}"
462                      COMMAND ${PANDA_RUN_PREFIX} $<TARGET_FILE:${assembler}> "${ARG_FILE}" "${binary_file}" 1>"${build_out}" 2>"${build_err}"
463                      DEPENDS ${assembler} "${ARG_FILE}")
464
465    if (DEFINED ARG_TIMEOUT AND NOT "${ARG_TIMEOUT}" STREQUAL "")
466        set(timeout_signal 10)
467        set(timeout_prefix "timeout --preserve-status --signal=${timeout_signal} --kill-after=10s ${ARG_TIMEOUT}")
468        set(timeout_suffix "|| [ `expr \$? % 128` -eq ${timeout_signal} ]")
469    else()
470        set(timeout_prefix "")
471        set(timeout_suffix "")
472    endif()
473
474    set(panda_stdlib arkstdlib)
475    set(verifier_cli verifier)
476
477    set(spaces "core")
478    if (NOT "core" STREQUAL "${ARG_LANGUAGE_CONTEXT}")
479        set(spaces "${ARG_LANGUAGE_CONTEXT}")
480    else()
481        set(stdlibs "${${panda_stdlib}_BINARY_DIR}/${panda_stdlib}.abc")
482    endif()
483
484    list(APPEND stdlibs ${ARG_STDLIBS})
485
486    string(REPLACE ";" ":" boot_stdlibs "${stdlibs}")
487    string(REPLACE ";" ":" boot_spaces  "${spaces}")
488
489    set(launcher_verifier
490        "${PANDA_RUN_PREFIX}"
491        $<TARGET_FILE:${verifier_cli}>
492        "${ARG_VERIFIER_OPTIONS}"
493        "${ARG_RUNTIME_OPTIONS}"
494        "--boot-panda-files=\"${boot_stdlibs}\""
495        "--load-runtimes=${boot_spaces}"
496        "\"${binary_file}\""
497        "1>\"${output_file}\""
498        "2>\"${error_file}\""
499    )
500    string(REPLACE ";" " " launcher_verifier "${launcher_verifier}")
501    if (ARG_VERIFIER_FAIL_TEST)
502        string(APPEND launcher_verifier " || (exit 0)")
503    endif()
504
505    file(GENERATE OUTPUT ${launch_file} CONTENT "${launcher_verifier}")
506
507    add_custom_target(${ARG_TARGET}
508                      COMMENT "Verifying ${ARG_TARGET}"
509                      COMMAND . ${launch_file}
510                      DEPENDS ${verifier_cli} "${binary_file}")
511
512    if (DEFINED ARG_DEPENDS)
513        add_dependencies(${ARG_TARGET} ${ARG_DEPENDS})
514    endif()
515
516endfunction()
517