Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a --toolchain-variant option to select the compiler for C/C++ #6800

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e78a483
add a --toolchain-variant option to select the compiler for C/C++
cosmicexplorer Nov 21, 2018
a799016
add some logging around the compiler selection to validate toolchain …
cosmicexplorer Nov 22, 2018
71ca371
extend the exe checking to the link task
cosmicexplorer Nov 22, 2018
bf9e9a7
remove completed TODO
cosmicexplorer Nov 22, 2018
363c940
add magic linking lib dirs args to gcc and make the other test work f…
cosmicexplorer Nov 26, 2018
1de3799
add crti.o back to the command line
cosmicexplorer Nov 27, 2018
6ed4110
refactor libc resolution and make tests pass on osx
cosmicexplorer Nov 27, 2018
c4b4f28
enable libc search in the link testing
cosmicexplorer Nov 27, 2018
ebeb2fa
use repr for debug logs
cosmicexplorer Nov 27, 2018
282e9db
if this makes travis work finally we need to add a linter for this im…
cosmicexplorer Nov 27, 2018
b53b5c0
fix error introduced by incorrect git rebase operation
cosmicexplorer Nov 28, 2018
7ee1dd9
try resetting the toolchain_variant to llvm for now and fix some tests
cosmicexplorer Nov 29, 2018
1b9804e
move --tooldchain-variant to NativeToolchain to remove boilerplate in…
cosmicexplorer Nov 29, 2018
8375a62
make toolchain variant selection more declarative by moving the logic…
cosmicexplorer Nov 29, 2018
b32d643
separate extra object files from extra_args on the linker
cosmicexplorer Nov 29, 2018
1a2108d
pipe ToolchainVariantRequest into BuildLocalPythonDistributions
cosmicexplorer Nov 29, 2018
15632fe
move from explicit crti.o file paths to adding it to the LIBRARY_PATH
cosmicexplorer Nov 29, 2018
0e3c3e8
gcc on osx needs a bit more help to work at runtime
cosmicexplorer Nov 29, 2018
0703beb
enable search for libc so gcc can pass these tests
cosmicexplorer Nov 29, 2018
6af5aca
fix the last couple tests
cosmicexplorer Nov 29, 2018
9a25d32
fill out ???s and link to issues for TODOs
cosmicexplorer Nov 30, 2018
64e3e54
expand docstrings and add types to Executable properties
cosmicexplorer Dec 5, 2018
5473093
remove some of the include dir dark magic by standardizing options
cosmicexplorer Dec 5, 2018
55e6908
add TODO links
cosmicexplorer Dec 5, 2018
3cd803a
don't add buggy include search flags to the clang invoke, and test bo…
cosmicexplorer Dec 7, 2018
408f4cd
remove notes to self
cosmicexplorer Dec 7, 2018
a3b4339
remove remaining -nostdinc args and add a more concise TODO
cosmicexplorer Dec 7, 2018
45e4c7a
fix issue link
cosmicexplorer Dec 7, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pants.ini
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,7 @@ fragment: True

[sitegen]
config_path: src/docs/docsite.json

# TODO(#6848): this should be removed when we can fully support both toolchains.
[native-build-settings]
toolchain_variant: llvm
1 change: 1 addition & 0 deletions src/python/pants/backend/native/config/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ python_library(
dependencies=[
'3rdparty/python:future',
'src/python/pants/engine:rules',
'src/python/pants/util:meta',
'src/python/pants/util:objects',
'src/python/pants/util:osutil',
],
Expand Down
78 changes: 49 additions & 29 deletions src/python/pants/backend/native/config/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

import os
from abc import abstractproperty
from builtins import object

from pants.engine.rules import SingletonRule
from pants.util.meta import AbstractClass
from pants.util.objects import datatype
from pants.util.osutil import all_normalized_os_names, get_normalized_os_name
from pants.util.strutil import create_path_env_var
Expand Down Expand Up @@ -42,34 +42,53 @@ def resolve_platform_specific(self, platform_specific_funs):
return fun_for_platform()


class Executable(object):
class Executable(AbstractClass):

@abstractproperty
def path_entries(self):
"""A list of directory paths containing this executable, to be used in a subprocess's PATH.

This may be multiple directories, e.g. if the main executable program invokes any subprocesses.

:rtype: list of str
"""

@abstractproperty
def exe_filename(self):
"""The "entry point" -- which file to invoke when PATH is set to `path_entries()`.

:rtype: str
"""

# TODO: rename this to 'runtime_library_dirs'!
@abstractproperty
def library_dirs(self):
"""Directories containing shared libraries that must be on the runtime library search path.

Note: this is for libraries needed for the current Executable to run -- see LinkerMixin below
for libraries that are needed at link time."""
for libraries that are needed at link time.

@abstractproperty
def exe_filename(self):
"""The "entry point" -- which file to invoke when PATH is set to `path_entries()`."""
:rtype: list of str
"""

@property
def extra_args(self):
"""Additional arguments used when invoking this Executable.

These are typically placed before the invocation-specific command line arguments.

:rtype: list of str
"""
return []

_platform = Platform.create()

@property
def as_invocation_environment_dict(self):
"""A dict to use as this Executable's execution environment.

:rtype: dict of string -> string
"""
lib_env_var = self._platform.resolve_platform_specific({
'darwin': lambda: 'DYLD_LIBRARY_PATH',
'linux': lambda: 'LD_LIBRARY_PATH',
Expand All @@ -92,15 +111,31 @@ class LinkerMixin(Executable):

@abstractproperty
def linking_library_dirs(self):
"""Directories to search for libraries needed at link time."""
"""Directories to search for libraries needed at link time.

:rtype: list of str
"""

@abstractproperty
jsirois marked this conversation as resolved.
Show resolved Hide resolved
def extra_object_files(self):
"""A list of object files required to perform a successful link.

This includes crti.o from libc for gcc on Linux, for example.

:rtype: list of str
"""
jsirois marked this conversation as resolved.
Show resolved Hide resolved

@property
def as_invocation_environment_dict(self):
ret = super(LinkerMixin, self).as_invocation_environment_dict.copy()

full_library_path_dirs = self.linking_library_dirs + [
os.path.dirname(f) for f in self.extra_object_files
]

ret.update({
'LDSHARED': self.exe_filename,
'LIBRARY_PATH': create_path_env_var(self.linking_library_dirs),
'LIBRARY_PATH': create_path_env_var(full_library_path_dirs),
})

return ret
Expand All @@ -112,14 +147,18 @@ class Linker(datatype([
'library_dirs',
'linking_library_dirs',
'extra_args',
'extra_object_files',
]), LinkerMixin): pass


class CompilerMixin(Executable):

@abstractproperty
def include_dirs(self):
"""Directories to search for header files to #include during compilation."""
"""Directories to search for header files to #include during compilation.

:rtype: list of str
"""

@property
def as_invocation_environment_dict(self):
Expand Down Expand Up @@ -165,34 +204,15 @@ def as_invocation_environment_dict(self):
return ret


# NB: These wrapper classes for LLVM and GCC toolchains are performing the work of variants. A
# CToolchain cannot be requested directly, but native_toolchain.py provides an LLVMCToolchain,
# which contains a CToolchain representing the clang compiler and a linker paired to work with
# objects compiled by that compiler.
class CToolchain(datatype([('c_compiler', CCompiler), ('c_linker', Linker)])): pass


class LLVMCToolchain(datatype([('c_toolchain', CToolchain)])): pass


class GCCCToolchain(datatype([('c_toolchain', CToolchain)])): pass


class CppToolchain(datatype([('cpp_compiler', CppCompiler), ('cpp_linker', Linker)])): pass


class LLVMCppToolchain(datatype([('cpp_toolchain', CppToolchain)])): pass


class GCCCppToolchain(datatype([('cpp_toolchain', CppToolchain)])): pass


# TODO: make this an @rule, after we can automatically produce LibcDev and other subsystems in the
# v2 engine (see #5788).
class HostLibcDev(datatype(['crti_object', 'fingerprint'])):

def get_lib_dir(self):
return os.path.dirname(self.crti_object)
class HostLibcDev(datatype(['crti_object', 'fingerprint'])): pass


def create_native_environment_rules():
Expand Down
5 changes: 5 additions & 0 deletions src/python/pants/backend/native/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pants.backend.native.subsystems.binaries.binutils import create_binutils_rules
from pants.backend.native.subsystems.binaries.gcc import create_gcc_rules
from pants.backend.native.subsystems.binaries.llvm import create_llvm_rules
from pants.backend.native.subsystems.native_build_settings import NativeBuildSettings
from pants.backend.native.subsystems.native_toolchain import create_native_toolchain_rules
from pants.backend.native.subsystems.xcode_cli_tools import create_xcode_cli_tools_rules
from pants.backend.native.targets.external_native_library import ExternalNativeLibrary
Expand All @@ -34,6 +35,10 @@ def build_file_aliases():
)


def global_subsystems():
return {NativeBuildSettings}


def register_goals():
# TODO(#5962): register these under the 'compile' goal when we eliminate the product transitive
# dependency from export -> compile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ def linker(self):
exe_filename='ld',
library_dirs=[],
linking_library_dirs=[],
extra_args=[])
extra_args=[],
extra_object_files=[],
)


@rule(Assembler, [Select(Binutils)])
Expand Down
2 changes: 2 additions & 0 deletions src/python/pants/backend/native/subsystems/binaries/gcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ def _cpp_include_dirs(self):
('include/c++', self.version()),
])

# TODO(#6143): determine whether there is any manual explaining when any of these file paths are
# necessary.
# This file is needed for C++ compilation.
cpp_config_header_path = self._file_mapper.assert_single_path_by_glob(
# NB: There are multiple paths matching this glob unless we provide the full path to
Expand Down
4 changes: 3 additions & 1 deletion src/python/pants/backend/native/subsystems/binaries/llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def linker(self, platform):
self._PLATFORM_SPECIFIC_LINKER_NAME),
library_dirs=[],
linking_library_dirs=[],
extra_args=[])
extra_args=[],
extra_object_files=[],
)

@memoized_property
def _common_include_dirs(self):
Expand Down
13 changes: 4 additions & 9 deletions src/python/pants/backend/native/subsystems/libc_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pants.base.hash_utils import hash_file
from pants.option.custom_types import dir_option
from pants.subsystem.subsystem import Subsystem
from pants.util.memo import memoized_property
from pants.util.memo import memoized_method, memoized_property


class LibcDev(Subsystem):
Expand Down Expand Up @@ -99,11 +99,6 @@ def _host_libc(self):

return self._get_host_libc_from_host_compiler()

def get_libc_dirs(self, platform):
if not self.get_options().enable_libc_search:
return []

return platform.resolve_platform_specific({
'darwin': lambda: [],
'linux': lambda: [self._host_libc.get_lib_dir()],
})
@memoized_method
def get_libc_objects(self):
return [self._host_libc.crti_object] if self.get_options().enable_libc_search else []
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@
from pants.backend.native.subsystems.utils.mirrored_target_option_mixin import \
MirroredTargetOptionMixin
from pants.subsystem.subsystem import Subsystem
from pants.util.memo import memoized_property
from pants.util.objects import enum


class ToolchainVariant(enum('descriptor', ['gnu', 'llvm'])):

@property
def is_gnu(self):
return self.descriptor == 'gnu'


class NativeBuildSettings(Subsystem, MirroredTargetOptionMixin):
"""Any settings relevant to a compiler and/or linker invocation."""
"""Settings which affect both the compile and link phases."""
options_scope = 'native-build-settings'

mirrored_option_to_kwarg_map = {
Expand All @@ -28,5 +37,15 @@ def register_options(cls, register):
"are used when compiling and linking native code. C and C++ targets may override "
"this behavior with the strict_deps keyword argument as well.")

register('--toolchain-variant', type=str, fingerprint=True, advanced=True,
choices=ToolchainVariant.allowed_values,
default=ToolchainVariant.default_value,
help="Whether to use gcc (gnu) or clang (llvm) to compile C and C++. Currently all "
"linking is done with binutils ld on Linux, and the XCode CLI Tools on MacOS.")

def get_strict_deps_value_for_target(self, target):
return self.get_target_mirrored_option('strict_deps', target)

@memoized_property
def toolchain_variant(self):
return ToolchainVariant.create(self.get_options().toolchain_variant)
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


class NativeBuildStepSettings(CompilerOptionSetsMixin, MirroredTargetOptionMixin, Subsystem):
"""Settings which are specific to a target and do not need to be the same for compile and link."""

options_scope = 'native-build-step'

Expand Down
Loading