@ -4,6 +4,7 @@
from configparser import ConfigParser
from pathlib import Path
from unittest import mock
import argparse
import contextlib
import io
import json
@ -13,6 +14,7 @@ import pickle
import stat
import subprocess
import tempfile
import textwrap
import typing as T
import unittest
@ -23,6 +25,7 @@ import mesonbuild.dependencies.factory
import mesonbuild . envconfig
import mesonbuild . environment
import mesonbuild . modules . gnome
import mesonbuild . scripts . env2mfile
from mesonbuild import coredata
from mesonbuild . compilers . c import ClangCCompiler , GnuCCompiler
from mesonbuild . compilers . cpp import VisualStudioCPPCompiler
@ -1715,3 +1718,391 @@ class InternalTests(unittest.TestCase):
for raw , expected in cases :
with self . subTest ( raw ) :
self . assertEqual ( OptionKey . from_string ( raw ) , expected )
def test_env2mfile_deb ( self ) - > None :
MachineInfo = mesonbuild . scripts . env2mfile . MachineInfo
to_machine_info = mesonbuild . scripts . env2mfile . dpkg_architecture_to_machine_info
# For testing purposes, behave as though all cross-programs
# exist in /usr/bin
def locate_path ( program : str ) - > T . List [ str ] :
if os . path . isabs ( program ) :
return [ program ]
return [ ' /usr/bin/ ' + program ]
def expected_compilers (
gnu_tuple : str ,
gcc_suffix : str = ' ' ,
) - > T . Dict [ str , T . List [ str ] ] :
return {
' c ' : [ f ' /usr/bin/ { gnu_tuple } -gcc { gcc_suffix } ' ] ,
' cpp ' : [ f ' /usr/bin/ { gnu_tuple } -g++ { gcc_suffix } ' ] ,
' objc ' : [ f ' /usr/bin/ { gnu_tuple } -gobjc { gcc_suffix } ' ] ,
' objcpp ' : [ f ' /usr/bin/ { gnu_tuple } -gobjc++ { gcc_suffix } ' ] ,
}
def expected_binaries ( gnu_tuple : str ) - > T . Dict [ str , T . List [ str ] ] :
return {
' ar ' : [ f ' /usr/bin/ { gnu_tuple } -ar ' ] ,
' strip ' : [ f ' /usr/bin/ { gnu_tuple } -strip ' ] ,
' objcopy ' : [ f ' /usr/bin/ { gnu_tuple } -objcopy ' ] ,
' ld ' : [ f ' /usr/bin/ { gnu_tuple } -ld ' ] ,
' cmake ' : [ ' /usr/bin/cmake ' ] ,
' pkg-config ' : [ f ' /usr/bin/ { gnu_tuple } -pkg-config ' ] ,
' cups-config ' : [ ' /usr/bin/cups-config ' ] ,
}
for title , dpkg_arch , gccsuffix , env , expected in [
(
# s390x is an example of the common case where the
# Meson CPU name, the GNU CPU name, the dpkg architecture
# name and uname -m all agree.
# (alpha, m68k, ppc64, riscv64, sh4, sparc64 are similar)
' s390x-linux-gnu ' ,
# Output of `dpkg-architecture -a...`, filtered to
# only the DEB_HOST_ parts because that's all we use
textwrap . dedent (
'''
DEB_HOST_ARCH = s390x
DEB_HOST_ARCH_ABI = base
DEB_HOST_ARCH_BITS = 64
DEB_HOST_ARCH_CPU = s390x
DEB_HOST_ARCH_ENDIAN = big
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = linux
DEB_HOST_GNU_CPU = s390x
DEB_HOST_GNU_SYSTEM = linux - gnu
DEB_HOST_GNU_TYPE = s390x - linux - gnu
DEB_HOST_MULTIARCH = s390x - linux - gnu
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' s390x-linux-gnu ' ) ,
binaries = expected_binaries ( ' s390x-linux-gnu ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/s390x-linux-gnu-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/s390x-linux-gnu-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' Linux ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' s390x ' ,
} ,
system = ' linux ' ,
subsystem = ' linux ' ,
kernel = ' linux ' ,
cpu = ' s390x ' ,
cpu_family = ' s390x ' ,
endian = ' big ' ,
) ,
) ,
# Debian amd64 vs. GNU, Meson, etc. x86_64.
# arm64/aarch64, hppa/parisc, i386/i686/x86, loong64/loongarch64,
# powerpc/ppc are similar.
(
' x86_64-linux-gnu ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = amd64
DEB_HOST_ARCH_ABI = base
DEB_HOST_ARCH_BITS = 64
DEB_HOST_ARCH_CPU = amd64
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = linux
DEB_HOST_GNU_CPU = x86_64
DEB_HOST_GNU_SYSTEM = linux - gnu
DEB_HOST_GNU_TYPE = x86_64 - linux - gnu
DEB_HOST_MULTIARCH = x86_64 - linux - gnu
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' x86_64-linux-gnu ' ) ,
binaries = expected_binaries ( ' x86_64-linux-gnu ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/x86_64-linux-gnu-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/x86_64-linux-gnu-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' Linux ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' x86_64 ' ,
} ,
system = ' linux ' ,
subsystem = ' linux ' ,
kernel = ' linux ' ,
# TODO: In native builds we get x86_64, but in
# cross-builds it's amd64
cpu = ' TODO ' ,
cpu_family = ' x86_64 ' ,
endian = ' little ' ,
) ,
) ,
(
' arm-linux-gnueabihf with non-default gcc and environment ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = armhf
DEB_HOST_ARCH_ABI = eabihf
DEB_HOST_ARCH_BITS = 32
DEB_HOST_ARCH_CPU = arm
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = linux
DEB_HOST_GNU_CPU = arm
DEB_HOST_GNU_SYSTEM = linux - gnueabihf
DEB_HOST_GNU_TYPE = arm - linux - gnueabihf
DEB_HOST_MULTIARCH = arm - linux - gnueabihf
'''
) ,
' -12 ' ,
{
' PATH ' : ' /usr/bin ' ,
' CPPFLAGS ' : ' -DNDEBUG ' ,
' CFLAGS ' : ' -std=c99 ' ,
' CXXFLAGS ' : ' -std=c++11 ' ,
' OBJCFLAGS ' : ' -fobjc-exceptions ' ,
' OBJCXXFLAGS ' : ' -fobjc-nilcheck ' ,
' LDFLAGS ' : ' -Wl,-O1 ' ,
} ,
MachineInfo (
compilers = expected_compilers ( ' arm-linux-gnueabihf ' , ' -12 ' ) ,
binaries = expected_binaries ( ' arm-linux-gnueabihf ' ) ,
properties = { } ,
compile_args = {
' c ' : [ ' -DNDEBUG ' , ' -std=c99 ' ] ,
' cpp ' : [ ' -DNDEBUG ' , ' -std=c++11 ' ] ,
' objc ' : [ ' -DNDEBUG ' , ' -fobjc-exceptions ' ] ,
' objcpp ' : [ ' -DNDEBUG ' , ' -fobjc-nilcheck ' ] ,
} ,
link_args = {
' c ' : [ ' -std=c99 ' , ' -Wl,-O1 ' ] ,
' cpp ' : [ ' -std=c++11 ' , ' -Wl,-O1 ' ] ,
' objc ' : [ ' -fobjc-exceptions ' , ' -Wl,-O1 ' ] ,
' objcpp ' : [ ' -fobjc-nilcheck ' , ' -Wl,-O1 ' ] ,
} ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/arm-linux-gnueabihf-gcc-12 ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/arm-linux-gnueabihf-g++-12 ' ] ,
' CMAKE_SYSTEM_NAME ' : ' Linux ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' armv7l ' ,
} ,
system = ' linux ' ,
subsystem = ' linux ' ,
kernel = ' linux ' ,
# In a native build this would often be armv8l
# (the version of the running CPU) but the architecture
# baseline in Debian is officially ARMv7
cpu = ' arm7hlf ' ,
cpu_family = ' arm ' ,
endian = ' little ' ,
) ,
) ,
(
' special cases for i386 (i686, x86) and Hurd ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = hurd - i386
DEB_HOST_ARCH_ABI = base
DEB_HOST_ARCH_BITS = 32
DEB_HOST_ARCH_CPU = i386
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = hurd
DEB_HOST_GNU_CPU = i686
DEB_HOST_GNU_SYSTEM = gnu
DEB_HOST_GNU_TYPE = i686 - gnu
DEB_HOST_MULTIARCH = i386 - gnu
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' i686-gnu ' ) ,
binaries = expected_binaries ( ' i686-gnu ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/i686-gnu-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/i686-gnu-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' GNU ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' i686 ' ,
} ,
# TODO: Currently hurd, but should be gnu as per
# https://mesonbuild.com/Reference-tables.html
system = ' TODO ' ,
subsystem = ' TODO ' ,
# TODO: Currently linux, but should be gnu/hurd/mach?
# https://github.com/mesonbuild/meson/issues/13740
kernel = ' TODO ' ,
# TODO: Currently hurd-i386, but should be i686
cpu = ' TODO ' ,
cpu_family = ' x86 ' ,
endian = ' little ' ,
) ,
) ,
(
' special cases for amd64 (x86_64) and kFreeBSD ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = kfreebsd - amd64
DEB_HOST_ARCH_ABI = base
DEB_HOST_ARCH_BITS = 64
DEB_HOST_ARCH_CPU = x86_amd64
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = kfreebsd
DEB_HOST_GNU_CPU = x86_64
DEB_HOST_GNU_SYSTEM = kfreebsd - gnu
DEB_HOST_GNU_TYPE = x86_64 - kfreebsd - gnu
DEB_HOST_MULTIARCH = x86_64 - kfreebsd - gnu
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' x86_64-kfreebsd-gnu ' ) ,
binaries = expected_binaries ( ' x86_64-kfreebsd-gnu ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/x86_64-kfreebsd-gnu-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/x86_64-kfreebsd-gnu-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' kFreeBSD ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' x86_64 ' ,
} ,
system = ' kfreebsd ' ,
subsystem = ' kfreebsd ' ,
# TODO: Currently linux but should be freebsd
kernel = ' TODO ' ,
# TODO: Currently kfreebsd-amd64 but should be x86_64
cpu = ' TODO ' ,
cpu_family = ' x86_64 ' ,
endian = ' little ' ,
) ,
) ,
(
' special case for mips64el ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = mips64el
DEB_HOST_ARCH_ABI = abi64
DEB_HOST_ARCH_BITS = 64
DEB_HOST_ARCH_CPU = mips64el
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = linux
DEB_HOST_GNU_CPU = mips64el
DEB_HOST_GNU_SYSTEM = linux - gnuabi64
DEB_HOST_GNU_TYPE = mips64el - linux - gnuabi64
DEB_HOST_MULTIARCH = mips64el - linux - gnuabi64
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' mips64el-linux-gnuabi64 ' ) ,
binaries = expected_binaries ( ' mips64el-linux-gnuabi64 ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/mips64el-linux-gnuabi64-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/mips64el-linux-gnuabi64-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' Linux ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' mips64 ' ,
} ,
system = ' linux ' ,
subsystem = ' linux ' ,
kernel = ' linux ' ,
cpu = ' mips64 ' ,
cpu_family = ' mips64 ' ,
endian = ' little ' ,
) ,
) ,
(
' special case for ppc64el ' ,
textwrap . dedent (
'''
DEB_HOST_ARCH = ppc64el
DEB_HOST_ARCH_ABI = base
DEB_HOST_ARCH_BITS = 64
DEB_HOST_ARCH_CPU = ppc64el
DEB_HOST_ARCH_ENDIAN = little
DEB_HOST_ARCH_LIBC = gnu
DEB_HOST_ARCH_OS = linux
DEB_HOST_GNU_CPU = powerpc64le
DEB_HOST_GNU_SYSTEM = linux - gnu
DEB_HOST_GNU_TYPE = powerpc64le - linux - gnu
DEB_HOST_MULTIARCH = powerpc64le - linux - gnu
'''
) ,
' ' ,
{ ' PATH ' : ' /usr/bin ' } ,
MachineInfo (
compilers = expected_compilers ( ' powerpc64le-linux-gnu ' ) ,
binaries = expected_binaries ( ' powerpc64le-linux-gnu ' ) ,
properties = { } ,
compile_args = { } ,
link_args = { } ,
cmake = {
' CMAKE_C_COMPILER ' : [ ' /usr/bin/powerpc64le-linux-gnu-gcc ' ] ,
' CMAKE_CXX_COMPILER ' : [ ' /usr/bin/powerpc64le-linux-gnu-g++ ' ] ,
' CMAKE_SYSTEM_NAME ' : ' Linux ' ,
' CMAKE_SYSTEM_PROCESSOR ' : ' ppc64le ' ,
} ,
system = ' linux ' ,
subsystem = ' linux ' ,
kernel = ' linux ' ,
# TODO: Currently ppc64el, but native builds have ppc64le,
# and maybe it should be ppc64 in both cases?
# https://github.com/mesonbuild/meson/issues/13741
cpu = ' TODO ' ,
cpu_family = ' ppc64 ' ,
endian = ' little ' ,
) ,
) ,
] :
with self . subTest ( title ) , \
unittest . mock . patch . dict ( ' os.environ ' , env , clear = True ) , \
unittest . mock . patch ( ' mesonbuild.scripts.env2mfile.locate_path ' ) as mock_locate_path :
mock_locate_path . side_effect = locate_path
options = argparse . Namespace ( )
options . gccsuffix = gccsuffix
actual = to_machine_info ( dpkg_arch , options )
if expected . system == ' TODO ' :
print ( f ' TODO: { title } : system() -> { actual . system } ' )
else :
self . assertEqual ( actual . system , expected . system )
if expected . subsystem == ' TODO ' :
print ( f ' TODO: { title } : subsystem() -> { actual . subsystem } ' )
else :
self . assertEqual ( actual . subsystem , expected . subsystem )
if expected . kernel == ' TODO ' :
print ( f ' TODO: { title } : kernel() -> { actual . kernel } ' )
else :
self . assertEqual ( actual . kernel , expected . kernel )
if expected . cpu == ' TODO ' :
print ( f ' TODO: { title } : cpu() -> { actual . cpu } ' )
else :
self . assertEqual ( actual . cpu , expected . cpu )
self . assertEqual ( actual . cpu_family , expected . cpu_family )
self . assertEqual ( actual . endian , expected . endian )
self . assertEqual ( actual . compilers , expected . compilers )
self . assertEqual ( actual . binaries , expected . binaries )
self . assertEqual ( actual . properties , expected . properties )
self . assertEqual ( actual . compile_args , expected . compile_args )
self . assertEqual ( actual . link_args , expected . link_args )
self . assertEqual ( actual . cmake , expected . cmake )