규칙
- <ph type="x-smartling-placeholder"></ph> 별칭
- <ph type="x-smartling-placeholder"></ph> config_setting
- <ph type="x-smartling-placeholder"></ph> 파일 그룹
- <ph type="x-smartling-placeholder"></ph> 생성형 쿼리
- <ph type="x-smartling-placeholder"></ph> genrule
- <ph type="x-smartling-placeholder"></ph> test_suite
alias
alias(name, actual, compatible_with, deprecation, features, restricted_to, tags, target_compatible_with, testonly, visibility)
alias
규칙은 규칙이 참조할 수 있는 다른 이름을 만듭니다.
별칭은 'regular'에서만 작동합니다. 있습니다 특히 package_group
는
및 test_suite
에는 별칭을 지정할 수 없습니다.
별칭 규칙에는 자체 공개 상태 선언이 있습니다. 다른 모든 측면에서는 참조하는 규칙과 마찬가지로 (예: 별칭의 testonly는 무시되고, testonly-ness는 대신 사용) 일부 사소한 예외가 있습니다.
-
별칭이 명령줄에 언급되면 테스트가 실행되지 않습니다. 별칭을 정의하려면 다음 단계를 따르세요.
test_suite
를 사용합니다.tests
에 단일 대상이 있는 규칙 속성의 값을 제공합니다. -
환경 그룹을 정의할 때
environment
규칙에 대한 별칭은 지원됩니다.--target_environment
명령줄에서 지원되지 않음 선택할 수 있습니다
예
filegroup( name = "data", srcs = ["data.txt"], ) alias( name = "other", actual = ":data", )
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. |
actual
|
|
config_setting
config_setting(name, constraint_values, define_values, deprecation, distribs, features, flag_values, licenses, tags, testonly, values, visibility)
다음의 예상 구성 상태 (빌드 플래그 또는 플랫폼 제약 조건으로 표현됨)와 일치합니다. 구성 가능한 속성을 트리거하는 목적으로 사용됩니다. 다음 경우에 select를 참조하세요. 이 규칙과 일반 기능의 개요는 Configurable 속성을 참조하세요.
예
다음은 --compilation_mode=opt
또는
-c opt
(명령줄에서 명시적으로 또는 .bazelrc 파일에서 암시적으로):
config_setting( name = "simple", values = {"compilation_mode": "opt"} )
다음은 ARM을 대상으로 하고 사용자설정 정의를 적용하는 모든 빌드와 일치합니다.
FOO=bar
(예: bazel build --cpu=arm --define FOO=bar ...
):
config_setting( name = "two_conditions", values = { "cpu": "arm", "define": "FOO=bar" } )
다음은
사용자 정의 플래그
--//custom_flags:foo=1
(명령줄에서 명시적으로 또는 암시적으로
.bazelrc 파일).
config_setting( name = "my_custom_flag_is_set", flag_values = { "//custom_flags:foo": "1" }, )
다음은 x86_64 아키텍처 및 glibc가 있는 플랫폼을 대상으로 하는 모든 빌드와 일치합니다.
버전 2.25, 라벨이 있는 constraint_value
가 있다고 가정합니다.
//example:glibc_2_25
플랫폼은 추가
제약 값이 존재합니다.
config_setting( name = "64bit_glibc_2_25", constraint_values = [ "@platforms//cpu:x86_64", "//example:glibc_2_25", ] )
config_setting
는 최상위 명령줄 플래그와 일치하지 않지만 일치할 수도 있습니다.
살펴보겠습니다
참고
- 여러 번 선택했을 때 발생하는 결과는 선택을 참고하세요.
config_setting
은 현재 구성 상태와 일치합니다. - 약식 형식을 지원하는 플래그 (예:
--compilation_mode
vs.-c
),values
정의는 전체 형식을 사용해야 합니다. 이러한 항목은 자동으로 두 형식 중 하나를 사용하여 호출을 매칭할 수 있습니다. -
플래그가 여러 값 (예:
--copt=-Da --copt=-Db
또는 목록 유형)을 사용하는 경우 <ph type="x-smartling-placeholder"></ph> Starlark 플래그),"a"
가 다음과 같은 경우values = { "flag": "a" }
는 일치합니다. 실제 목록의 어딘가에 있어야 합니다.values = { "myflag": "a,b" }
도 같은 방식으로 작동하며--myflag=a --myflag=b
,--myflag=a --myflag=b --myflag=c
--myflag=a,b
,--myflag=c,b,a
정확한 의미 체계는 있습니다. 예를 들어--copt
는 같은 위치에 있는 여러 값을 지원하지 않습니다. 인스턴스:--copt=a,b
는["a,b"]
를 생성하지만--copt=a --copt=b
은["a", "b"]
를 생성합니다 (따라서values = { "copt": "a,b" }
전자와 일치하지만 후자는 일치하지 않음). 하지만--ios_multi_cpus
(Apple 규칙의 경우) 실행:-ios_multi_cpus=a,b
및ios_multi_cpus=a --ios_multi_cpus=b
모두["a", "b"]
를 생성합니다. 플래그 정의를 확인하고 조건을 주의 깊게 검토하여 정확한 기대치를 확인합니다. - 기본 제공 빌드 플래그로 모델링되지 않는 조건을 정의해야 하는 경우
<ph type="x-smartling-placeholder"></ph>
Starlark 정의 플래그.
--define
를 사용할 수도 있지만 성능이 더 낮습니다. 권장되지 않습니다 자세한 내용은 자세한 내용은 여기를 참고하세요. - 여러 패키지에서 동일한
config_setting
정의를 반복하지 않습니다. 대신 표준 패키지에 정의된 공통config_setting
를 참조합니다. values
님,define_values
및constraint_values
같은config_setting
에서 어떤 조합으로든 사용할 수 있지만 적어도 하나는 반드시 특정config_setting
에 대해 설정되어야 합니다.
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. |
constraint_values
|
constraint_values 세트
이 config_setting 에 일치시킵니다. (실행 플랫폼은
여기에서 고려됨) 플랫폼의 모든 추가 제약조건 값은 무시됩니다. 자세한 내용은
<ph type="x-smartling-placeholder"></ph>
구성 가능한 빌드 속성을 참조하세요.
두 |
define_values
|
values 와 동일하지만
특히 --define 플래그에 관한 것입니다.
이는 다음을 의미합니다. config_setting( name = "a_and_b", values = { "define": "a=1", "define": "b=2", }) 같은 키 ( config_setting( name = "a_and_b", define_values = { "a": "1", "b": "2", })
|
flag_values
|
values 와 동일하지만
(용)
사용자 정의 빌드 플래그를 참고하세요.
이것은 고유한 속성입니다. 사용자 정의 플래그는 라벨로 참조되는 반면 내장 플래그는 임의의 문자열로 참조됩니다. |
values
|
이 규칙은 설정된 대상의 구성을 상속합니다.
편의를 위해 구성 값은 빌드 플래그로 지정됩니다(
이전 명령줄에서 플래그를 명시적으로 설정하지 않으면 기본값이 사용됩니다.
키가 사전에 여러 번 표시되면 마지막 인스턴스만 사용됩니다.
키가 명령줄에서 여러 번 설정할 수 있는 플래그 (예:
|
파일 그룹
filegroup(name, srcs, data, compatible_with, deprecation, distribs, features, licenses, output_group, restricted_to, tags, target_compatible_with, testonly, visibility)
filegroup
을 사용하여 타겟 컬렉션에 편리한 이름을 지정합니다.
그런 다음 다른 규칙에서 이를 참조할 수 있습니다.
디렉터리를 직접 참조하는 대신 filegroup
를 사용하는 것이 좋습니다.
빌드 시스템이 모든 파일을 완전히 알지 못하기 때문에 후자는 바람직하지 않습니다.
이러한 파일이 변경될 때 다시 빌드되지 않을 수 있습니다. 결합 시
glob, filegroup
는 모든 파일이
빌드 시스템에 명시적으로 알려져 있습니다
예
두 개의 소스 파일로 구성된 filegroup
를 만들려면 다음을 실행합니다.
filegroup( name = "mygroup", srcs = [ "a_file.txt", "some/subdirectory/another_file.txt", ], )
또는 glob
를 사용하여 testdata 디렉터리를 탐색합니다.
filegroup( name = "exported_testdata", srcs = glob([ "testdata/*.dat", "testdata/logs/**/*.log", ]), )
이러한 정의를 활용하려면 규칙의 라벨로 filegroup
를 참조합니다.
cc_library( name = "my_library", srcs = ["foo.cc"], data = [ "//my_package:exported_testdata", "//my_package:mygroup", ], )
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. |
srcs
|
glob 표현식의 결과를 사용하는 것이 일반적입니다.
|
data
|
|
output_group
|
'출력 그룹' 대상의 출력 아티팩트 카테고리이며, 확인할 수 있습니다. |
Genquery
genquery(name, deps, data, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, expression, features, licenses, opts, restricted_to, scope, strict, tags, target_compatible_with, testonly, visibility)
genquery()
는
Blaze 쿼리 언어 및 결과를 덤프
할 수 있습니다.
빌드를 일관성 있게 유지하기 위해 쿼리는 다음 방문에만 허용됩니다.
scope
에 지정된 타겟의 전이적 종료
속성의 값을 제공합니다. 이 규칙을 위반하는 쿼리는 다음과 같은 경우 실행 중에 실패합니다.
strict
가 지정되지 않았거나 true입니다 (strict
가 false인 경우
지원 범위 외 대상은 경고와 함께 건너뜁니다.) 이
이를 방지하는 가장 쉬운 방법은 동일한 라벨을 언급하는 것입니다.
할 수 있습니다.
여기에서 허용되는 쿼리와 명령어에서 허용되는 쿼리의 유일한 차이점은
와일드 카드 타겟 사양 (예:
//pkg:*
또는 //pkg:all
)은 여기에서 허용되지 않습니다.
그 이유는 두 가지입니다. 첫 번째는 genquery
가
는
출력에 영향을 줄 수 있습니다. 두 번째는 BUILD
파일이
와일드 카드 종속 항목 (예: deps=["//a/..."]
)을 지원하지 않음
허용되지 않음).
genquery의 출력은 다음에서 --order_output=full
를 사용하여 정렬됩니다.
확정적인 출력을 적용합니다
출력 파일의 이름은 규칙의 이름입니다.
예
이 예에서는 대상에 추가합니다.
genquery( name = "kiwi-deps", expression = "deps(//kiwi:kiwi_lib)", scope = ["//kiwi:kiwi_lib"], )
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. |
expression
|
a/BUILD 파일에서 이 속성의 :b 라벨은
타겟 //:b .
|
opts
|
bazel query 에 전달할 수 있는 옵션입니다. 일부 쿼리 옵션이 허용되지 않음
위치: --keep_going , --query_file , --universe_scope ,
--order_results 및 --order_output 여기에 지정되지 않은 옵션
bazel query 의 명령줄과 마찬가지로 기본값을 갖습니다.
|
scope
|
|
strict
|
|
Genrule
genrule(name, srcs, outs, cmd, cmd_bash, cmd_bat, cmd_ps, compatible_with, deprecation, distribs, exec_compatible_with, exec_properties, exec_tools, executable, features, licenses, local, message, output_licenses, output_to_bindir, restricted_to, tags, target_compatible_with, testonly, toolchains, tools, visibility)
genrule
는 사용자 정의 Bash 명령어를 사용하여 하나 이상의 파일을 생성합니다.
Genrule은 작업에 대한 특정 규칙이 없는 경우 사용할 수 있는 일반적인 빌드 규칙입니다.
예를 들어 Bash 한 줄 줄을 실행할 수 있습니다. 그러나 C++ 파일을 컴파일해야 하는 경우에는
기존 cc_*
규칙에 대한 권한만 부여합니다. 이는 모든 어려운 작업이 이미 완료되었기 때문입니다.
있습니다.
테스트 실행에 genrule을 사용하지 마세요. 테스트 및 테스트를 위한 특별 조제가 있습니다.
캐싱 정책 및 환경 변수를 포함하여 이러한 결과를
수행할 수 있습니다 일반적으로 테스트는
대상 아키텍처에서 빌드가 완료된 후 대상 아키텍처에서 실행되는 반면,
빌드와 호스트 아키텍처 (이 둘은 다를 수 있음)에 따라 다릅니다. 범용
테스트 규칙인 경우 sh_test
를 사용합니다.
크로스 컴파일 고려사항
다음에 대한 자세한 내용은 사용자 설명서를 참조하세요. 크로스 컴파일이 가능합니다.
genrule이 빌드 중에 실행되지만 해당 출력은 빌드 이후에 배포 또는 있습니다. 마이크로컨트롤러의 C 코드를 컴파일하는 예를 생각해 보세요. 컴파일러는 C를 허용합니다. 소스 파일을 빌드하고 마이크로컨트롤러에서 실행되는 코드를 생성합니다. 생성된 코드는 빌드하는 데 사용된 CPU에서는 실행할 수 없지만 C 컴파일러 (소스에서 컴파일된 경우)는 알아내야 합니다
빌드 시스템은 호스트 구성을 사용하여 빌드가 실행되는 머신을 설명합니다. 빌드의 출력이 생성되는 머신을 설명하는 대상 구성 있습니다 각 구성요소를 구성할 수 있는 옵션을 제공하며 해당 파일을 별도의 디렉터리로 옮겨 충돌을 방지합니다.
genrule의 경우 빌드 시스템에서 종속 항목이 적절하게 빌드되도록 합니다.
srcs
는 대상 구성을 위해 빌드됩니다 (필요한 경우).
tools
는 호스트 구성용으로 빌드되며 출력은
대상 구성용입니다. 또한
'만들기' 변수를 생성합니다.
genrule이 deps
속성을 정의하지 않도록 의도된 것입니다. 다른 기본 제공 규칙은
규칙 간에 전달되는 언어별 메타 정보로
하지만 genrule에 대해 이러한 수준의 자동화가 불가능합니다. Genrule 작동
순전히 파일 및 실행 파일 수준에서만 작동합니다.
특수 사례
호스트 호스트 컴파일: 경우에 따라 빌드 시스템은
출력은 빌드 중에도 실행될 수 있습니다. 예를 들어 genrule이 커스텀 컴파일러를 빌드한다면
다른 genrule이 사용하는 경우, 첫 번째 Genrule은
다른 genrule에서 컴파일러가 실행되기 때문입니다. 이 경우
빌드 시스템이 자동으로 올바른 작업을 실행합니다. srcs
를 빌드하고
대상 대신 호스트 구성에 대한 첫 번째 genrule의 outs
구성할 수 있습니다 자세한 내용은 사용자 설명서를 참고하세요.
확인할 수 있습니다
JDK 및 C++ 도구: JDK 또는 C++ 컴파일러 제품군의 도구를 사용하려면 빌드 시스템 사용할 변수 집합을 제공합니다. '만들기'를 참고하세요. 변수의 경우 확인하세요.
Genrule 환경
genrule 명령어는 명령어 실행 시 실패하도록 구성된 Bash 셸에 의해 실행됩니다.
set -e -o pipefail
를 사용하여 파이프라인이 실패하는 경우
빌드 툴은
PATH
, PWD
,
TMPDIR
외 몇 명입니다.
빌드를 재현할 수 있도록 하기 위해, 대부분의 변수는 사용자의 셸에 정의되어 있습니다.
환경은 genrule의 명령어에 전달되지 않습니다. 그러나 Bazel (단, Bazel은
Blaze)에서 사용자의 PATH
환경 변수 값을 전달합니다.
PATH
값을 변경하면 Bazel에서 명령어를 다시 실행합니다.
확인할 수 있습니다.
genrule 명령어는 작동 중인 프로세스를 연결하는 경우를 제외하고 네트워크에 액세스해서는 안 됩니다. 명령어 자체의 하위 요소이며, 이는 현재 시행되지 않습니다.
빌드 시스템은 기존 출력 파일을 자동으로 삭제하지만 필요한 상위 파일을 생성합니다. 디렉터리를 생성합니다. 또한 장애가 발생할 경우 모든 출력 파일을 삭제합니다.
일반 도움말
- genrule에서 실행하는 도구가 확정적이고 밀폐되어야 합니다. 타임스탬프를 출력에 추가하고, 집합과 맵에 안정적인 순서를 사용해야 하며, 절대 경로 없이 상대 파일 경로만 출력에 씁니다. 이 규칙을 따르지 않으면 예기치 않은 빌드 동작 (Bazel이 생각했던 genrule을 다시 빌드하지 않음)이 발생하는 경우 및 캐시 성능이 저하될 수 있습니다
- 출력, 도구, 소스에
$(location)
를 광범위하게 사용합니다. 이로 인해 여러 구성에 대해 출력 파일을 분리할 수 있으므로 genrule이 하드 코딩된 절대 경로일 수 있습니다. - 다음과 같거나 매우 유사한 genrule이 사용되는 경우 공통 Starlark 매크로를 작성합니다. 액세스할 수 있습니다 genrule이 복잡하면 스크립트나 스타라크 법칙. 따라서 가독성과 테스트 가능성이 향상됩니다.
- 종료 코드가 genrule의 성공 또는 실패를 올바르게 나타내는지 확인하세요.
- stdout 또는 stderr에 정보 메시지를 작성하지 마세요. 이는 디버깅에는 유용하지만 노이즈가 되기 쉽습니다. 성공적인 genrule은 조용해야 합니다. 반면에 실패한 genrule은 좋은 오류 메시지를 표시합니다.
$$
evaluates to a$
, a literal dollar-sign, so in order to invoke a shell command containing dollar-signs such asls $(dirname $x)
, one must escape it thus:ls $$(dirname $$x)
.- 심볼릭 링크와 디렉터리를 만들지 않는 것이 좋습니다. Bazel이 디렉터리/심볼릭 링크를 복사하지 않음 genrules로 만든 구조와 디렉터리의 종속 항목 검사가 올바르지 않습니다.
- 다른 규칙에서 genrule을 참조할 때 genrule의 라벨 또는
지정할 수도 있습니다 한 가지 접근 방식이 더 읽기 쉽고
기타: 소비 규칙의
srcs
에서 이름으로 출력을 참조하면 안 됩니다. genrule의 다른 출력을 의도치 않게 가져오는 것이지만 이 생성 규칙이 많은 출력을 생성합니다.
예
이 예시에서는 foo.h
를 생성합니다. 이 명령어는
모든 입력. '바이너리' genrule과 동일한 패키지의 PERL 스크립트입니다.
genrule( name = "foo", srcs = [], outs = ["foo.h"], cmd = "./$(location create_foo.pl) > \"$@\"", tools = ["create_foo.pl"], )
다음 예는 filegroup
를 사용하는 방법을 보여줍니다.
및 다른 genrule
의 출력을 생성합니다. 대신 $(SRCS)
사용
명시적 $(location)
지시어도 작동합니다. 이 예에서는 후자를
보여드렸습니다.
genrule( name = "concat_all_files", srcs = [ "//some:files", # a filegroup with multiple files in it ==> $(locations) "//other:gen", # a genrule with a single output ==> $(location) ], outs = ["concatenated.txt"], cmd = "cat $(locations //some:files) $(location //other:gen) > $@", )
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. 다른 BUILD 의 srcs 또는 deps 섹션
있습니다. 규칙이 소스 파일을 생성하는 경우
srcs 속성
|
srcs
|
이 속성은
빌드 시스템은 genrule을 실행하기 전에 이러한 기본 요건이 빌드되었는지 확인합니다.
명령어; 원래 빌드 요청과 동일한 구성을 사용하여 빌드됩니다. 이
이러한 사전 요구 사항의 파일 이름은 명령에
|
outs
|
출력 파일은 패키지 경계를 넘지 않아야 합니다. 출력 파일 이름은 패키지를 기준으로 해석됩니다.
genrule 명령어는 사전에 결정된 위치에 각 출력 파일을 생성합니다.
위치는 |
cmd
|
$(location)
및 'Make' 적용 변수 대체를 지원합니다.
cmd_bash , cmd_ps , cmd_bat 의 대체입니다.
해당 사항이 없는 경우
명령줄 길이가 플랫폼 제한 (Linux/macOS에서 64K, Windows에서 8K)을 초과하는 경우
genrule이 명령어를 스크립트에 작성하고 해당 스크립트를 실행하여 문제를 해결합니다. 이
모든 cmd 속성 ( |
cmd_bash
|
이 속성의 우선순위가 |
cmd_bat
|
이 속성의 우선순위가
|
cmd_ps
|
이 속성의 우선순위가
Powershell을 더 쉽게 사용하고 오류 발생 가능성을 줄이기 위해 다음을 실행합니다. 명령어를 사용하여 환경을 설정한 다음 genrule에서 Powershell 명령어를 실행합니다.
|
exec_tools
|
tools 속성(단, 이러한 종속 항목은 제외)
호스트 구성이 아닌 규칙의 실행 플랫폼에 맞게 구성됩니다.
즉, exec_tools 의 종속 항목은 동일한 영향을 받지 않습니다.
tools 의 종속 항목으로 인한 제한사항을 확인합니다. 특히
자체 전이 종속 항목에 호스트 구성을 사용합니다 자세한 내용은
tools 에서 자세한 내용을 확인하세요.
Blaze팀에서 |
executable
|
이 플래그를 True로 설정하면 출력이 실행 파일이며 다음을 사용하여 실행할 수 있습니다.
생성된 실행 파일의 데이터 종속 항목을 선언하는 것은 지원되지 않습니다. |
local
|
True로 설정하면 이 옵션은 'local'을 사용하여 이
이것은 'local'을 제공하는 것과 같습니다. 태그 ( |
message
|
이 빌드 단계가 실행될 때 출력될 진행률 메시지입니다. 기본적으로
'출력 생성 중'이라는 메시지가 표시됩니다. (또는 똑같이 단조로운 느낌) 그러나
더 구체적입니다. |
output_licenses
|
common attributes
참조
|
output_to_bindir
|
True로 설정하면 이 옵션을 사용하면 출력 파일이 |
tools
|
빌드 시스템은 genrule 명령어를 실행하기 전에 이러한 기본 요건이 빌드되었는지 확인합니다.
호스트
구성 - 이러한 도구는 빌드의 일부로 실행되기 때문입니다.
개별
|
test_suite
test_suite(name, compatible_with, deprecation, distribs, features, licenses, restricted_to, tags, target_compatible_with, testonly, tests, visibility)
test_suite
는 '유용'한 것으로 간주되는 테스트 세트를 정의합니다. 제공합니다. 이
프로젝트에서 '체크인 전에 실행해야 하는 테스트', '
프로젝트의 스트레스 테스트" 지정할 수 있습니다 blaze test
명령어는 이 정렬을 따릅니다.
조직: blaze test //some/test:suite
등의 호출의 경우 Blaze 우선
//some/test:suite
타겟에 의해 전이적으로 포함된 모든 테스트 타겟을 열거합니다 (이
'test_suite 확장'이라고 하면 Blaze가 해당 타겟을 빌드하고 테스트합니다.
예
현재 패키지의 모든 소규모 테스트를 실행하는 테스트 모음입니다.
test_suite( name = "small_tests", tags = ["small"], )
지정된 테스트 세트를 실행하는 테스트 모음:
test_suite( name = "smoke_tests", tests = [ "system_unittest", "public_api_unittest", ], )
현재 패키지에서 불안정하지 않은 모든 테스트를 실행하는 테스트 모음입니다.
test_suite( name = "non_flaky_test", tags = ["-flaky"], )
인수
속성 | |
---|---|
name |
이 대상의 고유한 이름입니다. |
tags
|
'-'로 시작하는 태그 제외 태그로 간주됩니다 이 앞에 '-' 문자는 태그의 일부로 간주되지 않으므로 도구 모음 태그는 '-small' 테스트의 'small'과 일치 있습니다. 다른 모든 태그가 고려됨 포함할 수 있습니다. 포함 태그를 더 명시적으로 만들기 위해 태그가 '+' 이 문자는 태그 텍스트의 일부로 평가되지 않습니다. 그것은 긍정적이든 부정적이든 구분하기 쉽도록 할 뿐입니다. 모든 양성 태그 및 제외 태그 없음과 일치하는 규칙만 테스트하세요. 태그가 테스트 모음에 포함됩니다. 이것이 오류를 검사한다고 해서 필터링된 테스트의 종속 항목은 건너뜁니다. 건너뛴 테스트는 여전히 합법적이어야 합니다 (예: 공개 상태 제약으로 차단되지 않음).
테스트의
상호 배타적인 태그가 있는 테스트가 포함된 |
tests
|
언어와 상관없이 모든
|