diff options
| author | Dylan Baker <dylan@pnwbakers.com> | 2025-07-03 15:38:32 -0700 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2025-10-06 09:03:07 -0700 |
| commit | 806289a5d27958a084bc6cba41b7cf9ccee4ecf4 (patch) | |
| tree | d6193d9aa67a6fb26e539d8b936f58aea19f2958 /mesonbuild/compilers/cuda.py | |
| parent | be50d0e23737dc0fc5f074a291644d7fde39ef7b (diff) | |
| download | meson-806289a5d27958a084bc6cba41b7cf9ccee4ecf4.tar.gz | |
compilers: refactor sanity checking code
The goal is to reduce code duplication, and allow each language to
implement as little as possible to get good checking. The main
motivation is that half of the checks are fragile, as they add the work
directory to the paths of the generated files they want to use. This
works when run inside mesonmain because we always have an absolute build
directory, but when put into run_project_tests.py it doesn't work
because that gives a relative build directory.
Diffstat (limited to 'mesonbuild/compilers/cuda.py')
| -rw-r--r-- | mesonbuild/compilers/cuda.py | 114 |
1 files changed, 46 insertions, 68 deletions
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 7e050f140..a9e6a7669 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -5,15 +5,14 @@ from __future__ import annotations import enum -import os.path import string import typing as T from .. import options from .. import mlog +from .. import mesonlib from ..mesonlib import ( - EnvironmentException, Popen_safe, - is_windows, LibType, version_compare + EnvironmentException, is_windows, LibType, version_compare ) from .compilers import Compiler, CompileCheckMode @@ -187,6 +186,7 @@ class CudaCompiler(Compiler): host_compiler: Compiler, info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): + self.detected_cc = '' super().__init__(ccache, exelist, version, for_machine, info, linker=linker, full_version=full_version, is_cross=is_cross) self.host_compiler = host_compiler self.base_options = host_compiler.base_options @@ -499,55 +499,36 @@ class CudaCompiler(Compiler): def thread_link_flags(self, environment: 'Environment') -> T.List[str]: return self._to_host_flags(self.host_compiler.thread_link_flags(environment), Phase.LINKER) - def sanity_check(self, work_dir: str, env: 'Environment') -> None: - mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', ' '.join(self.exelist)) - mlog.debug('Is cross compiler: %s.' % str(self.is_cross)) - - sname = 'sanitycheckcuda.cu' - code = r''' - #include <cuda_runtime.h> - #include <stdio.h> - - __global__ void kernel (void) {} - - int main(void){ - struct cudaDeviceProp prop; - int count, i; - cudaError_t ret = cudaGetDeviceCount(&count); - if(ret != cudaSuccess){ - fprintf(stderr, "%d\n", (int)ret); - }else{ - for(i=0;i<count;i++){ - if(cudaGetDeviceProperties(&prop, i) == cudaSuccess){ - fprintf(stdout, "%d.%d\n", prop.major, prop.minor); + def _sanity_check_source_code(self) -> str: + return r''' + #include <cuda_runtime.h> + #include <stdio.h> + + __global__ void kernel (void) {} + + int main(void){ + struct cudaDeviceProp prop; + int count, i; + cudaError_t ret = cudaGetDeviceCount(&count); + if(ret != cudaSuccess){ + fprintf(stderr, "%d\n", (int)ret); + }else{ + for(i=0;i<count;i++){ + if(cudaGetDeviceProperties(&prop, i) == cudaSuccess){ + fprintf(stdout, "%d.%d\n", prop.major, prop.minor); + } } } + fflush(stderr); + fflush(stdout); + return 0; } - fflush(stderr); - fflush(stdout); - return 0; - } - ''' - binname = sname.rsplit('.', 1)[0] - binname += '_cross' if self.is_cross else '' - source_name = os.path.join(work_dir, sname) - binary_name = os.path.join(work_dir, binname + '.exe') - with open(source_name, 'w', encoding='utf-8') as ofile: - ofile.write(code) - - # The Sanity Test for CUDA language will serve as both a sanity test - # and a native-build GPU architecture detection test, useful later. - # - # For this second purpose, NVCC has very handy flags, --run and - # --run-args, that allow one to run an application with the - # environment set up properly. Of course, this only works for native - # builds; For cross builds we must still use the exe_wrapper (if any). - self.detected_cc = '' - flags = [] + ''' + def _sanity_check_compile_args(self, env: Environment, sourcename: str, binname: str) -> T.List[str]: # Disable warnings, compile with statically-linked runtime for minimum # reliance on the system. - flags += ['-w', '-cudart', 'static', source_name] + flags = ['-w', '-cudart', 'static', sourcename] # Use the -ccbin option, if available, even during sanity checking. # Otherwise, on systems where CUDA does not support the default compiler, @@ -562,33 +543,30 @@ class CudaCompiler(Compiler): # a ton of compiler flags to differentiate between # arm and x86_64. So just compile. flags += self.get_compile_only_args() - flags += self.get_output_args(binary_name) - - # Compile sanity check - cmdlist = self.exelist + flags - mlog.debug('Sanity check compiler command line: ', ' '.join(cmdlist)) - pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) - mlog.debug('Sanity check compile stdout: ') - mlog.debug(stdo) - mlog.debug('-----\nSanity check compile stderr:') - mlog.debug(stde) - mlog.debug('-----') - if pc.returncode != 0: - raise EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') - - # Run sanity check (if possible) - if self.is_cross: + flags += self.get_output_args(binname) + + return self.exelist + flags + + def _run_sanity_check(self, env: Environment, cmdlist: T.List[str], work_dir: str) -> None: + # Can't check binaries, so we have to assume they work + if self.is_cross and not env.has_exe_wrapper(): + mlog.debug('Cannot run cross check') return - cmdlist = self.exelist + ['--run', f'"{binary_name}"'] + cmdlist = self._sanity_check_run_with_exe_wrapper(env, cmdlist) + mlog.debug('Sanity check built target output for', self.for_machine, self.language, 'compiler') + mlog.debug(' -- Running test binary command: ', mesonlib.join_args(cmdlist)) try: - stdo, stde = self.run_sanity_check(env, cmdlist, work_dir) - except EnvironmentException: + pe, stdo, stde = mesonlib.Popen_safe_logged(cmdlist, 'Sanity check', cwd=work_dir) + mlog.debug(' -- stdout:\n', stdo) + mlog.debug(' -- stderr:\n', stde) + mlog.debug(' -- returncode:', pe.returncode) + except Exception as e: + raise EnvironmentException(f'Could not invoke sanity check executable: {e!s}.') + + if pe.returncode != 0: raise EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.') - # Interpret the result of the sanity test. - # As mentioned above, it is not only a sanity test but also a GPU - # architecture detection test. if stde == '': self.detected_cc = stdo |
