summaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/cuda.py
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2025-07-03 15:38:32 -0700
committerDylan Baker <dylan@pnwbakers.com>2025-10-06 09:03:07 -0700
commit806289a5d27958a084bc6cba41b7cf9ccee4ecf4 (patch)
treed6193d9aa67a6fb26e539d8b936f58aea19f2958 /mesonbuild/compilers/cuda.py
parentbe50d0e23737dc0fc5f074a291644d7fde39ef7b (diff)
downloadmeson-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.py114
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