• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021 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_target(${ARG_TARGET}
75                       COMMENT "Building ${ARG_TARGET}"
76                       COMMAND "${assembler_bin}" "${source_file}" "${binary_file}"
77                       DEPENDS ${assembler_target} "${source_file}")
78endfunction()
79
80# Add a single buildable and runnable Panda Assembly file to the build tree.
81#
82# Usage:
83#
84#   panda_add_asm_file(
85#        FILE <source>
86#        TARGET <target>
87#        [ENTRY <entry_point>]
88#        [SUBDIR <subdir>]
89#        [OUTPUT_FILE_VARIABLE <variable>]
90#        [ERROR_FILE_VARIABLE <variable>]
91#        [SKIP_BUILD TRUE|FALSE]
92#        [AOT_MODE TRUE|FALSE]
93#        [DEPENDS <dependency>...]
94#        [RUNTIME_OPTIONS <option>...]
95#        [COMPILER_OPTIONS <option>...]
96#        [GC_OPTIONS <option>]
97#        [ENTRY_ARGUMENTS <argument>...]
98#        [TIMEOUT <timeout>]
99#        [LANGUAGE_CONTEXT <language>]
100#    )
101#
102# Adds a target <target> which assembles the assembly file <source>
103# with Panda assembler and runs it with Panda interpreter.
104#
105# Options:
106#
107# ENTRY
108#   Entry point to execute in format <Class>::<method>. By default _GLOBAL::main is used
109#
110# SUBDIR
111#   Subdirectory in the current binary directory that is used to store build artifacts.
112#   Full path to directory with artifacts: ${CMAKE_CURRENT_BINARY_DIR}/<subdir>/<target>
113#
114# OUTPUT_FILE_VARIABLE, ERROR_FILE_VARIABLE
115#   The variable named will be set with the paths to files with contents of the stdout and
116#   stderr of the program respectively
117#
118# DEPENDS
119#   List of additional dependences (exclude assembler and interpreter)
120#
121# RUNTIME_OPTIONS
122#   Runtime options
123#
124# COMPILER_OPTIONS
125#   Options for compiler, given both to panda and paoc
126#
127# GC_OPTIONS
128#  Type of a gc
129#
130# ENTRY_ARGUMENTS
131#   List of arguments that will be passed to program's entry point
132#
133# TIMEOUT
134#   If specified, the program will be run and terminated with the signal 10 (corresponds
135#   to SIGUSR1 on most platforms) after the given timeout. The format of the value
136#   must match the `timeout` command. The run will be considered successful if the program
137#   exits before the timeout with the successful exit code or if it is terminated
138#   after the timeout with the signal 10.
139#
140# LANGUAGE_CONTEXT
141#   Set the language-dependent semantics for the code. Possible values: panda-assembly.
142#
143function(panda_add_asm_file)
144    set(prefix ARG)
145    set(noValues)
146    set(singleValues FILE ENTRY TARGET SUBDIR OUTPUT_FILE_VARIABLE ERROR_FILE_VARIABLE SKIP_BUILD AOT_MODE TIMEOUT LANGUAGE_CONTEXT GC_OPTIONS)
147    set(multiValues DEPENDS RUNTIME_OPTIONS COMPILER_OPTIONS ENTRY_ARGUMENTS PRLIMIT_OPTIONS ADDITIONAL_STDLIBS)
148    cmake_parse_arguments(${prefix}
149                          "${noValues}"
150                          "${singleValues}"
151                          "${multiValues}"
152                          ${ARGN})
153
154    if (NOT DEFINED ARG_FILE)
155        message(FATAL_ERROR "Mandatory FILE argument is not defined.")
156    endif()
157
158    if (NOT DEFINED ARG_TARGET)
159        message(FATAL_ERROR "Mandatory TARGET argument is not defined.")
160    endif()
161
162    if (TARGET ARG_TARGET)
163        message(FATAL_ERROR "Target ${ARG_TARGET} is already defined.")
164    endif()
165
166    set(build_dir   "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBDIR}/${ARG_TARGET}")
167    set(build_log   "${build_dir}/build.log")
168    set(build_out   "${build_dir}/build.out")
169    set(build_err   "${build_dir}/build.err")
170    set(binary_file "${build_dir}/test.abc")
171    set(launch_file "${build_dir}/launch.sh")
172    set(output_file "${build_dir}/run.out")
173    set(error_file  "${build_dir}/run.err")
174
175    file(MAKE_DIRECTORY "${build_dir}")
176
177    if (DEFINED ARG_OUTPUT_FILE_VARIABLE)
178        set(${ARG_OUTPUT_FILE_VARIABLE} "${output_file}" PARENT_SCOPE)
179    endif()
180
181    if (DEFINED ARG_ERROR_FILE_VARIABLE)
182        set(${ARG_ERROR_FILE_VARIABLE} "${error_file}" PARENT_SCOPE)
183    endif()
184
185    if (ARG_SKIP_BUILD)
186        set(binary_file "${ARG_FILE}")
187    else()
188        set(assembler ark_asm)
189        add_custom_command(OUTPUT "${binary_file}"
190                          COMMENT "Building ${ARG_TARGET}"
191                          COMMAND ${PANDA_RUN_PREFIX} $<TARGET_FILE:${assembler}> --verbose --log-file "${build_log}" "${ARG_FILE}" "${binary_file}" 1>"${build_out}" 2>"${build_err}"
192                          DEPENDS ${assembler} "${ARG_FILE}")
193    endif()
194
195    if (DEFINED ARG_TIMEOUT AND NOT "${ARG_TIMEOUT}" STREQUAL "")
196        set(timeout_signal 10)
197        set(timeout_prefix "timeout --preserve-status --signal=${timeout_signal} --kill-after=10s ${ARG_TIMEOUT}")
198        set(timeout_suffix "|| [ `expr \$? % 128` -eq ${timeout_signal} ]")
199    else()
200        set(timeout_prefix "")
201        set(timeout_suffix "")
202    endif()
203
204    if (NOT DEFINED ARG_ENTRY)
205        set(ARG_ENTRY "_GLOBAL::main")
206    endif()
207
208    set(panda_stdlib   arkstdlib)
209    set(panda_cli      ark)
210    set(panda_verifier verifier)
211
212    set(stdlibs "${${panda_stdlib}_BINARY_DIR}/${panda_stdlib}.abc")
213    if (DEFINED ARG_ADDITIONAL_STDLIBS)
214        list(APPEND stdlibs ${ARG_ADDITIONAL_STDLIBS})
215    endif()
216
217    set(spaces  "core")
218    set(runtime_type "core")
219    if (DEFINED ARG_LANGUAGE_CONTEXT AND NOT "${ARG_LANGUAGE_CONTEXT}" STREQUAL "panda-assembly")
220        list(APPEND spaces "${ARG_LANGUAGE_CONTEXT}")
221        set(runtime_type "${ARG_LANGUAGE_CONTEXT}")
222    endif()
223
224    string(REPLACE ";" ":" boot_stdlibs "${stdlibs}")
225    string(REPLACE ";" ":" boot_spaces  "${spaces}")
226
227    # Note well! The lines below imply that we cannot handle ";" properly
228    # in both Panda's own options and the running program's options.
229    string(REPLACE ";" " " runtime_options "${ARG_COMPILER_OPTIONS} ${ARG_RUNTIME_OPTIONS}")
230    string(REPLACE ";" " " entry_arguments "${ARG_ENTRY_ARGUMENTS}")
231
232    set(prlimit_cmd "")
233    if (DEFINED ARG_PRLIMIT_OPTIONS)
234        set(prlimit_cmd "prlimit ${ARG_PRLIMIT_OPTIONS}")
235        string(REPLACE ";" " " prlimit_cmd "${prlimit_cmd}")
236    endif()
237
238    if (${runtime_options} MATCHES ".*events-output=csv.*")
239        set(runtime_options "${runtime_options} --events-file=${build_dir}/events.csv")
240    endif()
241
242    set(launcher
243        "${timeout_prefix}"
244        "${prlimit_cmd}"
245        "${PANDA_RUN_PREFIX}"
246        $<TARGET_FILE:${panda_cli}>
247        "--boot-panda-files \"${boot_stdlibs}\""
248        "--boot-intrinsic-spaces=${boot_spaces}"
249        "--boot-class-spaces=${boot_spaces}"
250        "--runtime-type=${runtime_type}"
251        "${runtime_options}"
252        "\"${binary_file}\""
253        "\"${ARG_ENTRY}\""
254        "${entry_arguments}"
255        "1>\"${output_file}\""
256        "2>\"${error_file}\""
257        "${timeout_suffix}"
258    )
259    string(REPLACE ";" " " launcher "${launcher}")
260    file(GENERATE OUTPUT ${launch_file} CONTENT "${launcher}")
261
262    add_custom_target(${ARG_TARGET}
263                      COMMENT "Running ${ARG_TARGET}"
264                      COMMAND . ${launch_file} || (cat ${error_file} && false)
265                      DEPENDS ${panda_cli} ${panda_stdlib} "${binary_file}" ${aot_file})
266
267    if (DEFINED ARG_DEPENDS)
268        add_dependencies(${ARG_TARGET} ${ARG_DEPENDS})
269    endif()
270
271
272endfunction()
273
274# Add a single buildable and verifiable Panda Assembly file to the build tree.
275#
276# Usage:
277#
278#   verifier_add_asm_file(
279#        FILE <source>
280#        TARGET <target>
281#        [ENTRY <entry_point>]
282#        [RUNTIME_OPTIONS <runtime options>]
283#        [VERIFIER_OPTIONS <verifier options>]
284#        [SUBDIR <subdir>]
285#        [OUTPUT_FILE_VARIABLE <variable>]
286#        [ERROR_FILE_VARIABLE <variable>]
287#        [DEPENDS <dependency>...]
288#        [TIMEOUT <timeout>]
289#        [LANGUAGE_CONTEXT <language>]
290#    )
291#
292# Adds a target <target> which assembles the assembly file <source>
293# with Panda assembler and verifies it with verifier.
294#
295# Options:
296#
297# ENTRY
298#   Entry point to execute in format <Class>::<method>. By default _GLOBAL::main is used
299#
300# SUBDIR
301#   Subdirectory in the current binary directory that is used to store build artifacts.
302#   Full path to directory with artifacts: ${CMAKE_CURRENT_BINARY_DIR}/<subdir>/<target>
303#
304# OUTPUT_FILE_VARIABLE, ERROR_FILE_VARIABLE
305#   The variable named will be set with the paths to files with contents of the stdout and
306#   stderr of the program respectively
307#
308# DEPENDS
309#   List of additional dependences (exclude assembler and interpreter)
310#
311# RUNTIME_OPTIONS
312#   Runtime initialization options
313#
314# VERIFIER_OPTIONS
315#   Verifier CLI options
316#
317# TIMEOUT
318#   If specified, the program will be run and terminated with the signal 10 (corresponds
319#   to SIGUSR1 on most platforms) after the given timeout. The format of the value
320#   must match the `timeout` command. The run will be considered successful if the program
321#   exits before the timeout with the successful exit code or if it is terminated
322#   after the timeout with the signal 10.
323#
324# LANGUAGE_CONTEXT
325#   Set the language-dependent semantics for the code. Possible values: panda-assembly.
326#
327function(verifier_add_asm_file)
328    set(prefix ARG)
329    set(noValues)
330    set(singleValues FILE ENTRY TARGET SUBDIR OUTPUT_FILE_VARIABLE ERROR_FILE_VARIABLE TIMEOUT LANGUAGE_CONTEXT)
331    set(multiValues DEPENDS RUNTIME_OPTIONS VERIFIER_OPTIONS)
332    cmake_parse_arguments(${prefix}
333                          "${noValues}"
334                          "${singleValues}"
335                          "${multiValues}"
336                          ${ARGN})
337
338    if (NOT DEFINED ARG_FILE)
339        message(FATAL_ERROR "Mandatory FILE argument is not defined.")
340    endif()
341
342    if (NOT DEFINED ARG_TARGET)
343        message(FATAL_ERROR "Mandatory TARGET argument is not defined.")
344    endif()
345
346    if (TARGET ARG_TARGET)
347        message(FATAL_ERROR "Target ${ARG_TARGET} is already defined.")
348    endif()
349
350    set(build_dir   "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBDIR}/${ARG_TARGET}")
351    set(build_out   "${build_dir}/build.out")
352    set(build_err   "${build_dir}/build.err")
353    set(binary_file "${build_dir}/test.abc")
354    set(launch_file "${build_dir}/verifier_launch.sh")
355    set(output_file "${build_dir}/verify.out")
356    set(error_file  "${build_dir}/verify.err")
357
358    file(MAKE_DIRECTORY "${build_dir}")
359
360    if (DEFINED ARG_OUTPUT_FILE_VARIABLE)
361        set(${ARG_OUTPUT_FILE_VARIABLE} "${output_file}" PARENT_SCOPE)
362    endif()
363
364    if (DEFINED ARG_ERROR_FILE_VARIABLE)
365        set(${ARG_ERROR_FILE_VARIABLE} "${error_file}" PARENT_SCOPE)
366    endif()
367
368    set(assembler ark_asm)
369    add_custom_command(OUTPUT "${binary_file}"
370                      COMMENT "Building ${ARG_TARGET}"
371                      COMMAND ${PANDA_RUN_PREFIX} $<TARGET_FILE:${assembler}> "${ARG_FILE}" "${binary_file}" 1>"${build_out}" 2>"${build_err}"
372                      DEPENDS ${assembler} "${ARG_FILE}")
373
374    if (DEFINED ARG_TIMEOUT AND NOT "${ARG_TIMEOUT}" STREQUAL "")
375        set(timeout_signal 10)
376        set(timeout_prefix "timeout --preserve-status --signal=${timeout_signal} --kill-after=10s ${ARG_TIMEOUT}")
377        set(timeout_suffix "|| [ `expr \$? % 128` -eq ${timeout_signal} ]")
378    else()
379        set(timeout_prefix "")
380        set(timeout_suffix "")
381    endif()
382
383    if (NOT DEFINED ARG_ENTRY)
384        set(ARG_ENTRY "_GLOBAL::main")
385    endif()
386
387    set(panda_stdlib arkstdlib)
388    set(verifier_cli ark)
389
390    set(stdlibs "${${panda_stdlib}_BINARY_DIR}/${panda_stdlib}.abc")
391    set(spaces  "core")
392    set(runtime_type "core")
393    if (NOT DEFINED ARG_LANGUAGE_CONTEXT)
394        set(ARG_LANGUAGE_CONTEXT "panda-assembly")
395    endif()
396
397    string(REPLACE ";" ":" boot_stdlibs "${stdlibs}")
398    string(REPLACE ";" ":" boot_spaces  "${spaces}")
399
400    if(NOT "${ARG_VERIFIER_OPTIONS}" STREQUAL "")
401        set(ARG_VERIFIER_OPTIONS ",${ARG_VERIFIER_OPTIONS}")
402    endif()
403
404    set(launcher_verifier
405        "${PANDA_RUN_PREFIX}"
406        $<TARGET_FILE:${verifier_cli}>
407        "--verification-enabled"
408        "--verification-options only-verify${ARG_VERIFIER_OPTIONS}"
409        "${ARG_RUNTIME_OPTIONS}"
410        "--boot-panda-files \"${boot_stdlibs}\""
411        "--boot-intrinsic-spaces=${boot_spaces}"
412        "--boot-class-spaces=${boot_spaces}"
413        "--runtime-type=${runtime_type}"
414        "\"${binary_file}\""
415        "\"${ARG_ENTRY}\""
416        "1>\"${output_file}\""
417        "2>\"${error_file}\""
418    )
419    string(REPLACE ";" " " launcher_verifier "${launcher_verifier}")
420    file(GENERATE OUTPUT ${launch_file} CONTENT "${launcher_verifier}")
421
422    add_custom_target(${ARG_TARGET}
423                      COMMENT "Verifying ${ARG_TARGET}"
424                      COMMAND . ${launch_file}
425                      DEPENDS ${verifier_cli} "${binary_file}")
426
427    if (DEFINED ARG_DEPENDS)
428        add_dependencies(${ARG_TARGET} ${ARG_DEPENDS})
429    endif()
430
431endfunction()
432