@ -4,6 +4,7 @@
from configparser import ConfigParser
from configparser import ConfigParser
from pathlib import Path
from pathlib import Path
from unittest import mock
from unittest import mock
import argparse
import contextlib
import contextlib
import io
import io
import json
import json
@ -13,6 +14,7 @@ import pickle
import stat
import stat
import subprocess
import subprocess
import tempfile
import tempfile
import textwrap
import typing as T
import typing as T
import unittest
import unittest
@ -23,6 +25,7 @@ import mesonbuild.dependencies.factory
import mesonbuild . envconfig
import mesonbuild . envconfig
import mesonbuild . environment
import mesonbuild . environment
import mesonbuild . modules . gnome
import mesonbuild . modules . gnome
import mesonbuild . scripts . env2mfile
from mesonbuild import coredata
from mesonbuild import coredata
from mesonbuild . compilers . c import ClangCCompiler , GnuCCompiler
from mesonbuild . compilers . c import ClangCCompiler , GnuCCompiler
from mesonbuild . compilers . cpp import VisualStudioCPPCompiler
from mesonbuild . compilers . cpp import VisualStudioCPPCompiler
@ -1715,3 +1718,391 @@ class InternalTests(unittest.TestCase):
for raw , expected in cases :
for raw , expected in cases :
with self . subTest ( raw ) :
with self . subTest ( raw ) :
self . assertEqual ( OptionKey . from_string ( raw ) , expected )
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 )