이 페이지에서는 Windows 호환 규칙 작성, 포팅 가능한 규칙 작성의 일반적인 문제 및 일부 솔루션에 중점을 둡니다.
경로
문제:
길이 제한: 최대 경로 길이는 259자(영문 기준)입니다.
Windows는 더 긴 경로 (최대 32,767자)도 지원하지만, 많은 프로그램이 더 낮은 수준으로 빌드됩니다.
작업에서 실행하는 프로그램에 관해 알고 있어야 합니다.
작업 디렉터리: 259자로 제한됩니다.
프로세스는 259자를 초과하는 디렉터리에
cd
할 수 없습니다.대소문자 구분: Windows 경로는 대소문자를 구분하지 않으며 Unix 경로는 대소문자를 구분합니다.
작업의 명령줄을 만들 때 이에 유의하세요.
경로 구분자: 백슬래시(
\`), not forward slash (
/`)입니다.Bazel은
/
구분자를 사용하여 Unix 스타일의 경로를 저장합니다. 일부 Windows 프로그램은 Unix 경로를 지원하지만 다른 Windows 프로그램은 지원하지 않습니다. cmd.exe의 일부 내장 명령어가 지원되며 일부는 지원되지 않습니다.작업에 명령줄 및 환경 변수를 만들 때는 항상
\` separators on Windows: replace
/with
`를 사용하는 것이 가장 좋습니다.절대 경로: 슬래시 (
/
)로 시작하지 마세요.Windows의 절대 경로는 드라이브 문자로 시작합니다(예:
C:\foo\bar.txt
). 단일 파일 시스템 루트는 없습니다.규칙이 절대 경로인지 규칙을 확인하면 이를 인지해야 합니다. 절대 경로는 이동할 수 없는 경우가 많으므로 피해야 합니다.
해결 방법:
경로를 짧게 유지합니다.
긴 디렉터리 이름, 복잡하게 중첩된 디렉터리 구조, 긴 파일 이름, 긴 작업공간 이름, 긴 대상 이름은 사용하지 않습니다.
모두 작업 입력 파일의 경로 구성요소가 될 수 있으며 경로 길이 제한이 소진될 수 있습니다.
짧은 출력 루트를 사용하세요.
--output_user_root=<path>
플래그를 사용하여 Bazel 출력의 짧은 경로를 지정합니다. Bazel 출력 (예:D:\`), and adding this line to your
.bazelrc` 파일) 전용 드라이브 (또는 가상 드라이브)를 사용하는 것이 좋습니다.build --output_user_root=D:/
또는
build --output_user_root=C:/_bzl
교차로를 사용합니다.
교차로는 대략적으로[1] 디렉터리 심볼릭 링크입니다. 교차로는 쉽게 만들 수 있으며 경로가 긴 디렉터리 (같은 컴퓨터에 있음)를 가리킬 수도 있습니다. 빌드 작업이 경로가 짧지만 타겟이 긴 정션을 생성하는 경우 경로 제한이 짧은 도구가 정션 디렉터리의 디렉터리에 있는 파일에 액세스할 수 있습니다.
.bat
파일 또는 cmd.exe에서 다음과 같이 정션을 만들 수 있습니다.mklink /J c:\path\to\junction c:\path\to\very\long\target\path
[1]: 엄밀히 말하면 연결은 심볼릭 링크가 아닙니다. 그러나 빌드 작업을 위해 정션을 디렉터리 심볼릭 링크로 고려할 수 있습니다.
작업/환경의 경로에서
/
을 `` 로 바꿉니다.작업에 명령줄 또는 환경 변수를 만들 때 경로를 Windows 스타일로 만듭니다. 예:
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
환경 변수
문제:
대소문자 구분: Windows 환경 변수 이름은 대소문자를 구분하지 않습니다.
예를 들어 자바에서
System.getenv("SystemRoot")
및System.getenv("SYSTEMROOT")
는 동일한 결과를 생성합니다. 이는 다른 언어에도 적용됩니다.과도성: 작업은 가능한 한 적은 수의 맞춤 환경 변수를 사용해야 합니다.
환경 변수는 작업의 캐시 키에 포함됩니다. 작업이 자주 변경되거나 사용자에게 맞춤설정된 환경 변수를 사용하면 규칙을 캐시할 수 있는 범위가 줄어듭니다.
해결 방법:
대문자 환경 변수 이름만 사용하세요.
이 기능은 Windows, macOS, Linux에서 작동합니다.
작업 환경을 최소화합니다.
ctx.actions.run
를 사용할 때 환경을ctx.configuration.default_shell_env
로 설정합니다. 작업에 더 많은 환경 변수가 필요한 경우 사전에 모두 넣고 작업에 전달합니다. 예:load("@bazel_skylib//lib:dicts.bzl", "dicts") def _make_env(ctx, output_file, is_windows): out_path = output_file.path if is_windows: out_path = out_path.replace("/", "\\") return dicts.add(ctx.configuration.default_shell_env, {"MY_OUTPUT": out_path})
작업
문제:
실행 파일 출력: 모든 실행 파일에는 실행 파일 확장자가 있어야 합니다.
가장 일반적인 확장 프로그램은
.exe
(바이너리 파일) 및.bat
(일괄 스크립트)입니다.셸 스크립트(
.sh
)는 Windows에서 실행할 수 없습니다.ctx.actions.run
의executable
로 지정할 수 없습니다. 파일에 부여할 수 있는+x
권한도 없으므로 Linux와 같은 임의의 파일을 실행할 수 없습니다.Bash 명령어: 이동성을 위해 Bash 명령어를 작업에서 직접 실행하지 마세요.
Bash는 Unix와 유사한 시스템에서 널리 사용되고 있지만 Windows에서는 사용할 수 없는 경우가 많습니다. Bazel 자체는 Bash (MSYS2)에 대한 의존도가 낮으므로 향후 사용자는 Bazel과 함께 MSYS2를 설치할 가능성이 낮습니다. Windows에서 규칙을 더 쉽게 사용할 수 있도록 하려면 실행 중인 Bash 명령어를 실행하지 마세요.
줄 끝: Windows는 CRLF(
\r\n
), Unix 유사 시스템은 LF(\n
)를 사용합니다.텍스트 파일을 비교할 때 이 점에 유의하세요. Git 설정, 특히 체크아웃하거나 커밋할 때 라인 엔딩에 유의하세요. (Git의
core.autocrlf
설정을 참고하세요.)
해결 방법:
Bash가 사용되지 않는 전용 규칙을 사용합니다.
native.genrule()
는 Bash 명령어의 래퍼이며 파일을 복사하거나 텍스트 파일을 작성하는 등의 간단한 문제를 해결하는 데 자주 사용됩니다. Bash에 의존하지 않고 불필요한 작업을 피할 수 있습니다. bazel-skylib에 니즈에 맞는 규칙이 있는지 확인하세요. 둘 다 Windows에서 빌드/테스트할 때 Bash에 종속되지 않습니다.빌드 규칙 예시:
write_file()
(소스, 문서): 원하는 줄 끝 (auto
,unix
,windows
)으로 텍스트 파일을 작성하고 필요에 따라 실행 파일로 만듭니다 (스크립트인 경우).run_binary()
(소스, 문서): 지정된 입력과 예상 출력을 빌드 작업으로 사용하여 바이너리 (또는*_binary
규칙)를 실행합니다(ctx.actions.run
의 빌드 규칙 래퍼).native_binary()
(소스, 문서):bazel run
에서 또는run_binary()
의tool
속성 또는native.genrule()
의tools
속성에 사용할 수 있는*_binary
규칙으로 네이티브 바이너리를 래핑합니다.
테스트 규칙 예:
Windows에서는 사소한 작업에
.bat
스크립트를 사용하는 것이 좋습니다..sh
스크립트 대신.bat
스크립트를 사용하여 사소한 작업을 해결할 수 있습니다.예를 들어 아무 작업도 하지 않거나 메시지를 출력하거나 수정된 오류 코드로 종료되는 스크립트가 필요한 경우 간단한
.bat
파일로 충분합니다. 규칙에서DefaultInfo()
제공자를 반환하는 경우executable
필드는 Windows에서 해당.bat
파일을 참조할 수도 있습니다.파일 확장자는 macOS 및 Linux에서 중요하지 않으므로 셸 스크립트의 경우에도 언제든지
.bat
를 확장 프로그램으로 사용할 수 있습니다.빈
.bat
파일은 실행할 수 없습니다. 빈 스크립트가 필요하다면 공백을 하나 씁니다.Bash를 원칙에 따라 사용합니다.
Starlark 빌드 및 테스트 규칙에서
ctx.actions.run_shell
를 사용하여 Bash 스크립트와 Bash 명령어를 작업으로 실행합니다.Starlark 매크로에서 Bash 스크립트와 명령어를
native.sh_binary()
또는native.genrule()
로 래핑합니다. Bazel은 Bash를 사용할 수 있는지 확인하고 Bash를 통해 스크립트 또는 명령어를 실행합니다.Starlark 저장소 규칙에서 Bash를 피하는 것이 좋습니다. Bazel은 현재 저장소 규칙에 원칙적으로 Bash 명령어를 실행할 수 있는 방법을 제공하지 않습니다.
파일 삭제
문제:
파일을 연 후에는 파일을 삭제할 수 없습니다.
열린 파일은 기본적으로 삭제할 수 없으며 '액세스 거부' 오류가 발생합니다. 파일을 삭제할 수 없는 경우 실행 중인 프로세스에서 계속 열어 두었을 수 있습니다.
실행 중인 프로세스의 작업 디렉터리를 삭제할 수 없습니다.
프로세스에는 작업 디렉터리에 개방된 핸들이 있으며 프로세스가 종료될 때까지 디렉터리를 삭제할 수 없습니다.
해결 방법:
코드에서 파일을 닫아봅니다.
자바에서는
try-with-resources
를 사용합니다. Python에서는with open(...) as f:
를 사용합니다. 원칙적으로 가능한 한 빨리 핸들을 닫아 보세요.