Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericson2314 committed Dec 18, 2019
1 parent 04e08f5 commit af74617
Show file tree
Hide file tree
Showing 20 changed files with 216 additions and 163 deletions.
23 changes: 10 additions & 13 deletions docs/markdown/howtox.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@ When first running Meson, set it in an environment variable.
$ CC=mycc meson <options>
```

Note that environment variables like `CC` _always_ refer to the native
compiler. That is, the compiler used to compile programs that run on
the current machine. The compiler used in cross compilation is set
with the cross file.

This behaviour is different from e.g. Autotools, where cross
compilation is done by setting `CC` to point to the cross compiler
(such as `/usr/bin/arm-linux-gnueabihf-gcc`). The reason for this is
that Meson supports natively the case where you compile helper tools
(such as code generators) and use the results during the
build. Because of this Meson needs to know both the native and the
cross compiler. The former is set via the environment variables or
native-files and the latter via the cross file only.
Note that environment variables like `CC` only refer to the host platform in
cross builds. That is, the `CC` refers compiler used to compile programs that
run on the machine we will eventually install the project on. The compiler used
to build things that run on the machine we do the building can be specified
with `CC_FOR_BUILD`. You can always used `CC_FOR_BUILD`, but for native builds
it is less well known because Meson (and Autotools) will default `CC_FOR_BUILD`
with `CC`.

Note that environment variables are never the idiomatic way to do anything with
Meson, however. It is better to use the native and cross files.

## Set dynamic linker

Expand Down
12 changes: 12 additions & 0 deletions docs/markdown/snippets/env_vars_and_cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Environment Variables with Cross Builds

Previously in Meson, variables like `CC` effected both the host and build
platforms for native builds, but the just the build platform for cross builds.
Now `CC` always effects the host platform, and `CC_FOR_BUILD` always affects
the build platform, with `CC` also effecting the build platform for native
builds only when `CC_FOR_BUILD` is not defined.

This old behavior is inconsistent with the way Autotools works, which
undermines the purpose of distro-integration that is the only reason
environment variables are supported at all in Meson. The new behavior is
consistent.
2 changes: 1 addition & 1 deletion mesonbuild/backend/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ def run_postconf_scripts(self):
subprocess.check_call(cmd, env=child_env)

def create_install_data(self):
strip_bin = self.environment.binaries.host.lookup_entry('strip')
strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip')
if strip_bin is None:
if self.environment.is_cross_build():
mlog.warning('Cross file does not specify strip binary, result will not be stripped.')
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/cmake/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def find_cmake_binary(self, environment: Environment, silent: bool = False) -> T
# Create an iterator of options
def search():
# Lookup in cross or machine file.
potential_cmakepath = environment.binaries[self.for_machine].lookup_entry('cmake')
potential_cmakepath = environment.lookup_binary_entry(self.for_machine, 'cmake')
if potential_cmakepath is not None:
mlog.debug('CMake binary for %s specified from cross file, native file, or env var as %s.', self.for_machine, potential_cmakepath)
yield ExternalProgram.from_entry('cmake', potential_cmakepath)
Expand Down
3 changes: 2 additions & 1 deletion mesonbuild/compilers/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from .. import coredata
from ..mesonlib import MachineChoice, MesonException, mlog, version_compare
from ..linkers import LinkerEnvVarsMixin
from .c_function_attributes import C_FUNC_ATTRIBUTES
from .mixins.clike import CLikeCompiler
from .mixins.ccrx import CcrxCompiler
Expand All @@ -27,7 +28,7 @@
from .mixins.clang import ClangCompiler
from .mixins.elbrus import ElbrusCompiler
from .mixins.pgi import PGICompiler
from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin
from .mixins.islinker import BasicLinkerIsCompilerMixin
from .mixins.emscripten import EmscriptenMixin
from .compilers import (
gnu_winlibs,
Expand Down
62 changes: 30 additions & 32 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
import collections.abc
import typing

from ..linkers import StaticLinker, GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
from ..linkers import (
GnuLikeDynamicLinkerMixin, LinkerEnvVarsMixin, SolarisDynamicLinker,
StaticLinker,
)
from .. import coredata
from .. import mlog
from .. import mesonlib
Expand All @@ -25,7 +28,7 @@
Popen_safe, split_args
)
from ..envconfig import (
Properties,
Properties, get_env_var
)

if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -74,7 +77,9 @@
clink_suffixes += ('h', 'll', 's')

# Languages that should use LDFLAGS arguments when linking.
languages_using_ldflags = ('objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda')
languages_using_ldflags = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'}
# Languages that should use CPPFLAGS arguments when linking.
languages_using_cppflags = {'c', 'cpp', 'objc', 'objcpp'}
soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')

# Environment variables that each lang uses.
Expand Down Expand Up @@ -796,8 +801,10 @@ def gen_import_library_args(self, implibname):
"""
return []

def get_linker_args_from_envvars(self) -> typing.List[str]:
return self.linker.get_args_from_envvars()
def get_linker_args_from_envvars(self,
for_machine: MachineChoice,
is_cross: bool) -> typing.List[str]:
return self.linker.get_args_from_envvars(for_machine, is_cross)

def get_options(self) -> typing.Dict[str, coredata.UserOption]:
return {}
Expand Down Expand Up @@ -1128,37 +1135,27 @@ def get_largefile_args(compiler):
return []


def get_args_from_envvars(lang: str, use_linker_args: bool) -> typing.Tuple[typing.List[str], typing.List[str]]:
def get_args_from_envvars(lang: str,
for_machine: MachineChoice,
is_cross: bool,
use_linker_args: bool) -> typing.Tuple[typing.List[str], typing.List[str]]:
"""
Returns a tuple of (compile_flags, link_flags) for the specified language
from the inherited environment
"""
def log_var(var, val: typing.Optional[str]):
if val:
mlog.log('Appending {} from environment: {!r}'.format(var, val))
else:
mlog.debug('No {} in the environment, not changing global flags.'.format(var))

if lang not in cflags_mapping:
return [], []

compile_flags = [] # type: typing.List[str]
link_flags = [] # type: typing.List[str]

env_compile_flags = os.environ.get(cflags_mapping[lang])
log_var(cflags_mapping[lang], env_compile_flags)
env_compile_flags = get_env_var(for_machine, is_cross, cflags_mapping[lang])
if env_compile_flags is not None:
compile_flags += split_args(env_compile_flags)

# Link flags (same for all languages)
if lang in languages_using_ldflags:
# This is duplicated between the linkers, but I'm not sure how else
# to handle this
env_link_flags = split_args(os.environ.get('LDFLAGS', ''))
else:
env_link_flags = []
log_var('LDFLAGS', env_link_flags)
link_flags += env_link_flags
link_flags += LinkerEnvVarsMixin.get_args_from_envvars(for_machine, is_cross)
if use_linker_args:
# When the compiler is used as a wrapper around the linker (such as
# with GCC and Clang), the compile flags can be needed while linking
Expand All @@ -1167,16 +1164,18 @@ def log_var(var, val: typing.Optional[str]):
link_flags = compile_flags + link_flags

# Pre-processor flags for certain languages
if lang in {'c', 'cpp', 'objc', 'objcpp'}:
env_preproc_flags = os.environ.get('CPPFLAGS')
log_var('CPPFLAGS', env_preproc_flags)
if lang in languages_using_cppflags:
env_preproc_flags = get_env_var(for_machine, is_cross, 'CPPFLAGS')
if env_preproc_flags is not None:
compile_flags += split_args(env_preproc_flags)

return compile_flags, link_flags


def get_global_options(lang: str, comp: typing.Type[Compiler],
def get_global_options(lang: str,
comp: typing.Type[Compiler],
for_machine: MachineChoice,
is_cross: bool,
properties: Properties) -> typing.Dict[str, coredata.UserOption]:
"""Retreive options that apply to all compilers for a given language."""
description = 'Extra arguments passed to the {}'.format(lang)
Expand All @@ -1189,13 +1188,12 @@ def get_global_options(lang: str, comp: typing.Type[Compiler],
[], split_args=True, user_input=True, allow_dups=True),
}

if properties.fallback:
# Get from env vars.
# XXX: True here is a hack
compile_args, link_args = get_args_from_envvars(lang, comp.INVOKES_LINKER)
else:
compile_args = []
link_args = []
# Get from env vars.
compile_args, link_args = get_args_from_envvars(
lang,
for_machine,
is_cross,
comp.INVOKES_LINKER)

for k, o in opts.items():
if k in properties:
Expand Down
3 changes: 2 additions & 1 deletion mesonbuild/compilers/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .. import mlog
from ..mesonlib import MesonException, MachineChoice, version_compare

from ..linkers import LinkerEnvVarsMixin
from .compilers import (
gnu_winlibs,
msvc_winlibs,
Expand All @@ -36,7 +37,7 @@
from .mixins.clang import ClangCompiler
from .mixins.elbrus import ElbrusCompiler
from .mixins.pgi import PGICompiler
from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin
from .mixins.islinker import BasicLinkerIsCompilerMixin
from .mixins.emscripten import EmscriptenMixin

if typing.TYPE_CHECKING:
Expand Down
3 changes: 2 additions & 1 deletion mesonbuild/compilers/d.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
EnvironmentException, MachineChoice, version_compare,
)

from ..linkers import LinkerEnvVarsMixin
from .compilers import (
d_dmd_buildtype_args,
d_gdc_buildtype_args,
Expand All @@ -28,7 +29,7 @@
CompilerArgs,
)
from .mixins.gnu import GnuCompiler
from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin
from .mixins.islinker import BasicLinkerIsCompilerMixin

if typing.TYPE_CHECKING:
from ..envconfig import MachineInfo
Expand Down
12 changes: 0 additions & 12 deletions mesonbuild/compilers/mixins/islinker.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
classes for those cases.
"""

import os
import typing

from ... import mesonlib
Expand All @@ -30,17 +29,6 @@
from ...environment import Environment


class LinkerEnvVarsMixin:

"""Mixin reading LDFLAGS from the environment."""

def get_linker_args_from_envvars(self) -> typing.List[str]:
flags = os.environ.get('LDFLAGS')
if not flags:
return []
return mesonlib.split_args(flags)


class BasicLinkerIsCompilerMixin:

"""Provides a baseline of methods that a linker would implement.
Expand Down
32 changes: 21 additions & 11 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2012-2019 The Meson development team
# Copyrighs 2012-2019 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -22,6 +22,7 @@
MesonException, MachineChoice, PerMachine,
default_libdir, default_libexecdir, default_prefix, split_args
)
from .envconfig import get_env_var
from .wrap import WrapMode
import ast
import argparse
Expand Down Expand Up @@ -719,15 +720,19 @@ def set_default_options(self, default_options, subproject, env):
# unset, set those now. These will either be overwritten
# below, or they won't. These should only be set on the first run.
if env.first_invocation:
p_env = os.environ.get('PKG_CONFIG_PATH')
if p_env:
# PKG_CONFIG_PATH may contain duplicates, which must be
# removed, else a duplicates-in-array-option warning arises.
pkg_config_paths = []
for k in p_env.split(':'):
if k not in pkg_config_paths:
pkg_config_paths.append(k)
options['pkg_config_path'] = pkg_config_paths
for for_machine in MachineChoice:
p_env = get_env_var(for_machine, self.is_cross_build(), 'PKG_CONFIG_PATH')
if p_env is not None:
key = 'pkg_config_path'
if for_machine == MachineChoice.BUILD:
key = 'build.' + key
# PKG_CONFIG_PATH may contain duplicates, which must be
# removed, else a duplicates-in-array-option warning arises.
pkg_config_paths = []
for k in p_env.split(':'):
if k not in pkg_config_paths:
pkg_config_paths.append(k)
options[key] = pkg_config_paths

for k, v in env.cmd_line_options.items():
if subproject:
Expand All @@ -750,7 +755,12 @@ def add_lang_args(self, lang: str, comp: Type['Compiler'],
from .compilers import compilers

optprefix = lang + '_'
for k, o in compilers.get_global_options(lang, comp, env.properties[for_machine]).items():
for k, o in compilers.get_global_options(
lang,
comp,
for_machine,
env.is_cross_build(),
env.properties[for_machine]).items():
if not k.startswith(optprefix):
raise MesonException('Internal error, %s has incorrect prefix.' % k)
# prefixed compiler options affect just this machine
Expand Down
26 changes: 19 additions & 7 deletions mesonbuild/dependencies/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from .. import mlog
from .. import mesonlib
from ..compilers import clib_langs
from ..envconfig import get_env_var
from ..environment import BinaryTable, Environment, MachineInfo
from ..cmake import CMakeExecutor, CMakeTraceParser, CMakeException
from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
Expand Down Expand Up @@ -458,7 +459,7 @@ def find_config(self, versions=None):
if not isinstance(versions, list) and versions is not None:
versions = listify(versions)

tool = self.env.binaries[self.for_machine].lookup_entry(self.tool_name)
tool = self.env.lookup_binary_entry(self.for_machine, self.tool_name)
if tool is not None:
tools = [tool]
else:
Expand Down Expand Up @@ -592,7 +593,7 @@ def __init__(self, name, environment, kwargs, language=None):
# Create an iterator of options
def search():
# Lookup in cross or machine file.
potential_pkgpath = environment.binaries[self.for_machine].lookup_entry('pkgconfig')
potential_pkgpath = environment.lookup_binary_entry(self.for_machine, 'pkgconfig')
if potential_pkgpath is not None:
mlog.debug('Pkg-config binary for {} specified from cross file, native file, '
'or env var as {}'.format(self.for_machine, potential_pkgpath))
Expand Down Expand Up @@ -797,7 +798,10 @@ def _search_libs(self, out, out_raw):
#
# Only prefix_libpaths are reordered here because there should not be
# too many system_libpaths to cause library version issues.
pkg_config_path = os.environ.get('PKG_CONFIG_PATH')
pkg_config_path = get_env_var(
self.for_machine,
self.env.is_cross_build(),
'PKG_CONFIG_PATH')
if pkg_config_path:
pkg_config_path = pkg_config_path.split(os.pathsep)
else:
Expand Down Expand Up @@ -1110,8 +1114,12 @@ def __init__(self, name: str, environment: Environment, kwargs, language: str =
cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path))

pref_path = self.env.coredata.builtins_per_machine[self.for_machine]['cmake_prefix_path'].value
if 'CMAKE_PREFIX_PATH' in os.environ:
env_pref_path = os.environ['CMAKE_PREFIX_PATH'].split(os.pathsep)
env_pref_path = get_env_var(
self.for_machine,
self.env.is_cross_build(),
'CMAKE_PREFIX_PATH')
if env_pref_path is not None:
env_pref_path = env_pref_path.split(os.pathsep)
env_pref_path = [x for x in env_pref_path if x] # Filter out empty strings
if not pref_path:
pref_path = []
Expand Down Expand Up @@ -1808,8 +1816,12 @@ def description(self) -> str:
return ' '.join(self.command)

@classmethod
def from_bin_list(cls, bt: BinaryTable, name):
command = bt.lookup_entry(name)
def from_bin_list(cls, env: Environment, for_machine: MachineChoice, name):
# There is a static `for_machine` for this class because the binary
# aways runs on the build platform. (It's host platform is our build
# platform.) But some external programs have a target platform, so this
# is what we are specifying here.
command = env.lookup_binary_entry(for_machine, name)
if command is None:
return NonExistingExternalProgram()
return cls.from_entry(name, command)
Expand Down
Loading

0 comments on commit af74617

Please sign in to comment.