Skip to content

Commit

Permalink
Feature/language (#16028)
Browse files Browse the repository at this point in the history
* wip

* wip

* wip

* Test for BazelDeps in the build context (#16025)

* feat add test to bazeldeps

* Fixed several bugs. Improved tests coverage

* Reverted

* Better name

---------

Co-authored-by: Francisco Ramirez de Anton <franchuti688@gmail.com>

* copy only if different (#16031)

* allow conf in exports-sources and export (#16034)

* refactor apple_min_version_flag() (#16017)

* refactor apple_min_version_flag()

* Refactored all the apple module and where it was being used (AutotoolsToolchain and MesonToolchain for now)

* Fixed bad return

* Fixing tests

* Keeping legacy behavior in apple_min_version_flag function

* Preventing possible breaking change

---------

Co-authored-by: Francisco Ramirez de Anton <franchuti688@gmail.com>

* Allow to unhide git url (#16038)

* Add hide_url tests for git scm tool

* Add hide_url flag to clone and fetch_commit.

Resolves #15684

* Update conans/test/functional/tools/scm/test_git.py

* Update conans/test/functional/tools/scm/test_git.py

---------

Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

* wip

* wip

* wip

* fix

* Update conan/tools/build/cstd.py

Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

* Update conan/tools/build/cstd.py

Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

* Update conan/tools/build/cstd.py

Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

---------

Co-authored-by: Ernesto de Gracia Herranz <vivalaburocracia@hotmail.com>
Co-authored-by: Francisco Ramirez de Anton <franchuti688@gmail.com>
Co-authored-by: Sebastian Höffner <info@sebastian-hoeffner.de>
Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>
  • Loading branch information
5 people committed Jun 4, 2024
1 parent 2dcaf42 commit b88c8bb
Show file tree
Hide file tree
Showing 20 changed files with 447 additions and 17 deletions.
2 changes: 2 additions & 0 deletions conan/tools/build/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from conan.tools.build.flags import cppstd_flag
from conan.tools.build.cppstd import check_max_cppstd, check_min_cppstd, \
valid_max_cppstd, valid_min_cppstd, default_cppstd, supported_cppstd
from conan.tools.build.cstd import check_max_cstd, check_min_cstd, \
valid_max_cstd, valid_min_cstd, supported_cstd
from conan.tools.build.cpu import build_jobs
from conan.tools.build.cross_building import cross_building, can_run
from conan.tools.build.stdcpp_library import stdcpp_library
Expand Down
176 changes: 176 additions & 0 deletions conan/tools/build/cstd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import operator

from conan.errors import ConanInvalidConfiguration, ConanException
from conans.model.version import Version


def check_min_cstd(conanfile, cstd, gnu_extensions=False):
""" Check if current cstd fits the minimal version required.
In case the current cstd doesn't fit the minimal version required
by cstd, a ConanInvalidConfiguration exception will be raised.
1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
default from cstd_default)
3. If not settings.compiler is present (not declared in settings) will raise because it
cannot compare.
4. If can not detect the default cstd for settings.compiler, a exception will be raised.
:param conanfile: The current recipe object. Always use ``self``.
:param cstd: Minimal cstd version required
:param gnu_extensions: GNU extension is required (e.g gnu17)
"""
_check_cstd(conanfile, cstd, operator.lt, gnu_extensions)


def check_max_cstd(conanfile, cstd, gnu_extensions=False):
""" Check if current cstd fits the maximum version required.
In case the current cstd doesn't fit the maximum version required
by cstd, a ConanInvalidConfiguration exception will be raised.
1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
default from cstd_default)
3. If not settings.compiler is present (not declared in settings) will raise because it
cannot compare.
4. If can not detect the default cstd for settings.compiler, a exception will be raised.
:param conanfile: The current recipe object. Always use ``self``.
:param cstd: Maximum cstd version required
:param gnu_extensions: GNU extension is required (e.g gnu17)
"""
_check_cstd(conanfile, cstd, operator.gt, gnu_extensions)


def valid_min_cstd(conanfile, cstd, gnu_extensions=False):
""" Validate if current cstd fits the minimal version required.
:param conanfile: The current recipe object. Always use ``self``.
:param cstd: Minimal cstd version required
:param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.
:return: True, if current cstd matches the required cstd version. Otherwise, False.
"""
try:
check_min_cstd(conanfile, cstd, gnu_extensions)
except ConanInvalidConfiguration:
return False
return True


def valid_max_cstd(conanfile, cstd, gnu_extensions=False):
""" Validate if current cstd fits the maximum version required.
:param conanfile: The current recipe object. Always use ``self``.
:param cstd: Maximum cstd version required
:param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.
:return: True, if current cstd matches the required cstd version. Otherwise, False.
"""
try:
check_max_cstd(conanfile, cstd, gnu_extensions)
except ConanInvalidConfiguration:
return False
return True


def supported_cstd(conanfile, compiler=None, compiler_version=None):
"""
Get a list of supported ``compiler.cstd`` for the "conanfile.settings.compiler" and
"conanfile.settings.compiler_version" or for the parameters "compiler" and "compiler_version"
if specified.
:param conanfile: The current recipe object. Always use ``self``.
:param compiler: Name of the compiler e.g: gcc
:param compiler_version: Version of the compiler e.g: 12
:return: a list of supported ``cstd`` values.
"""
compiler = compiler or conanfile.settings.get_safe("compiler")
compiler_version = compiler_version or conanfile.settings.get_safe("compiler.version")
if not compiler or not compiler_version:
raise ConanException("Called supported_cstd with no compiler or no compiler.version")

func = {"apple-clang": _apple_clang_supported_cstd,
"gcc": _gcc_supported_cstd,
"msvc": _msvc_supported_cstd,
"clang": _clang_supported_cstd,
}.get(compiler)
if func:
return func(Version(compiler_version))
return None


def _check_cstd(conanfile, cstd, comparator, gnu_extensions):
""" Check if current cstd fits the version required according to a given comparator.
In case the current cstd doesn't fit the maximum version required
by cstd, a ConanInvalidConfiguration exception will be raised.
1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare
2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the
default from cstd_default)
3. If not settings.compiler is present (not declared in settings) will raise because it
cannot compare.
4. If can not detect the default cstd for settings.compiler, a exception will be raised.
:param conanfile: The current recipe object. Always use ``self``.
:param cstd: Required cstd version.
:param comparator: Operator to use to compare the detected and the required cstd versions.
:param gnu_extensions: GNU extension is required (e.g gnu17)
"""
if not str(cstd).isdigit():
raise ConanException("cstd parameter must be a number")

def compare(lhs, rhs, comp):
def extract_cpp_version(_cstd):
return str(_cstd).replace("gnu", "")

def add_millennium(_cstd):
return "19%s" % _cstd if _cstd == "99" else "20%s" % _cstd

lhs = add_millennium(extract_cpp_version(lhs))
rhs = add_millennium(extract_cpp_version(rhs))
return not comp(lhs, rhs)

current_cstd = conanfile.settings.get_safe("compiler.cstd")
if current_cstd is None:
raise ConanInvalidConfiguration("The compiler.cstd is not defined for this configuration")

if gnu_extensions and "gnu" not in current_cstd:
raise ConanInvalidConfiguration("The cstd GNU extension is required")

if not compare(current_cstd, cstd, comparator):
raise ConanInvalidConfiguration(
"Current cstd ({}) is {} than the required C standard ({}).".format(
current_cstd, "higher" if comparator == operator.gt else "lower", cstd))


def _apple_clang_supported_cstd(version):
# TODO: Per-version support
return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]


def _gcc_supported_cstd(version):
if version < "4.7":
return ["99", "gnu99"]
if version < "8":
return ["99", "gnu99", "11", "gnu11"]
if version < "14":
return ["99", "gnu99", "11", "gnu11", "17", "gnu17"]
return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]


def _msvc_supported_cstd(version):
if version < "192":
return []
return ["11", "17"]


def _clang_supported_cstd(version):
if version < "3":
return ["99", "gnu99"]
if version < "6":
return ["99", "gnu99", "11", "gnu11"]
if version < "18":
return ["99", "gnu99", "11", "gnu11", "17", "gnu17"]
return ["99", "gnu99", "11", "gnu11", "17", "gnu17", "23", "gnu23"]
73 changes: 73 additions & 0 deletions conan/tools/build/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,76 @@ def _cppstd_intel_cc(_, cppstd):
"20": v20, "gnu20": vgnu20,
"23": v23, "gnu23": vgnu23}.get(cppstd)
return f'-std={flag}' if flag else None


def cstd_flag(conanfile) -> str:
"""
Returns flags specific to the C+standard based on the ``conanfile.settings.compiler``,
``conanfile.settings.compiler.version`` and ``conanfile.settings.compiler.cstd``.
It also considers when using GNU extension in ``settings.compiler.cstd``, reflecting it in the
compiler flag. Currently, it supports GCC, Clang, AppleClang, MSVC, Intel, MCST-LCC.
In case there is no ``settings.compiler`` or ``settings.cstd`` in the profile, the result will
be an **empty string**.
:param conanfile: The current recipe object. Always use ``self``.
:return: ``str`` with the standard C flag used by the compiler.
"""
compiler = conanfile.settings.get_safe("compiler")
compiler_version = conanfile.settings.get_safe("compiler.version")
cstd = conanfile.settings.get_safe("compiler.cstd")

if not compiler or not compiler_version or not cstd:
return ""

func = {"gcc": _cstd_gcc,
"clang": _cstd_clang,
"apple-clang": _cstd_apple_clang,
"msvc": _cstd_msvc}.get(compiler)
flag = None
if func:
flag = func(Version(compiler_version), str(cstd))
return flag


def _cstd_gcc(gcc_version, cstd):
# TODO: Verify flags per version
flag = {"99": "c99",
"11": "c11",
"17": "c17",
"23": "c23"}.get(cstd, cstd)
return f'-std={flag}' if flag else None


def _cstd_clang(gcc_version, cstd):
# TODO: Verify flags per version
flag = {"99": "c99",
"11": "c11",
"17": "c17",
"23": "c23"}.get(cstd, cstd)
return f'-std={flag}' if flag else None


def _cstd_apple_clang(gcc_version, cstd):
# TODO: Verify flags per version
flag = {"99": "c99",
"11": "c11",
"17": "c17",
"23": "c23"}.get(cstd, cstd)
return f'-std={flag}' if flag else None


def cstd_msvc_flag(visual_version, cstd):
if cstd == "17":
if visual_version >= "192":
return "c17"
elif cstd == "11":
if visual_version >= "192":
return "c11"
return None


def _cstd_msvc(visual_version, cstd):
flag = cstd_msvc_flag(visual_version, cstd)
return f'/std:{flag}' if flag else None
35 changes: 25 additions & 10 deletions conan/tools/cmake/toolchain/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,24 +249,39 @@ def context(self):

class CppStdBlock(Block):
template = textwrap.dedent("""
{% if cppstd %}
message(STATUS "Conan toolchain: C++ Standard {{ cppstd }} with extensions {{ cppstd_extensions }}")
set(CMAKE_CXX_STANDARD {{ cppstd }})
set(CMAKE_CXX_EXTENSIONS {{ cppstd_extensions }})
set(CMAKE_CXX_STANDARD_REQUIRED ON)
{% endif %}
{% if cstd %}
message(STATUS "Conan toolchain: C Standard {{ cstd }} with extensions {{ cstd_extensions }}")
set(CMAKE_C_STANDARD {{ cstd }})
set(CMAKE_C_EXTENSIONS {{ cstd_extensions }})
set(CMAKE_C_STANDARD_REQUIRED ON)
{% endif %}
""")

def context(self):
compiler_cppstd = self._conanfile.settings.get_safe("compiler.cppstd")
if compiler_cppstd is None:
return None

if compiler_cppstd.startswith("gnu"):
cppstd = compiler_cppstd[3:]
cppstd_extensions = "ON"
else:
cppstd = compiler_cppstd
cppstd_extensions = "OFF"
return {"cppstd": cppstd, "cppstd_extensions": cppstd_extensions}
compiler_cstd = self._conanfile.settings.get_safe("compiler.cstd")
result = {}
if compiler_cppstd is not None:
if compiler_cppstd.startswith("gnu"):
result["cppstd"] = compiler_cppstd[3:]
result["cppstd_extensions"] = "ON"
else:
result["cppstd"] = compiler_cppstd
result["cppstd_extensions"] = "OFF"
if compiler_cstd is not None:
if compiler_cstd.startswith("gnu"):
result["cstd"] = compiler_cstd[3:]
result["cstd_extensions"] = "ON"
else:
result["cstd"] = compiler_cstd
result["cstd_extensions"] = "OFF"
return result or None


class SharedLibBock(Block):
Expand Down
6 changes: 3 additions & 3 deletions conan/tools/gnu/autotoolstoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
from conan.tools.build import cmd_args_to_string, save_toolchain_args
from conan.tools.build.cross_building import cross_building
from conan.tools.build.flags import architecture_flag, build_type_flags, cppstd_flag, \
build_type_link_flags, \
libcxx_flags
build_type_link_flags, libcxx_flags, cstd_flag
from conan.tools.env import Environment
from conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet
from conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc
Expand Down Expand Up @@ -49,6 +48,7 @@ def __init__(self, conanfile, namespace=None, prefix="/"):
self.build_type_link_flags = build_type_link_flags(self._conanfile.settings)

self.cppstd = cppstd_flag(self._conanfile)
self.cstd = cstd_flag(self._conanfile)
self.arch_flag = architecture_flag(self._conanfile.settings)
self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)
self.fpic = self._conanfile.options.get_safe("fPIC")
Expand Down Expand Up @@ -130,7 +130,7 @@ def cxxflags(self):
@property
def cflags(self):
fpic = "-fPIC" if self.fpic else None
ret = [self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
ret = [self.cstd, self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag]
apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]
conf_flags = self._conanfile.conf.get("tools.build:cflags", default=[], check_type=list)
vs_flag = self._add_msvc_flags(self.extra_cflags)
Expand Down
15 changes: 14 additions & 1 deletion conan/tools/meson/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from conan.tools.build.flags import cppstd_msvc_flag
from conans.model.options import _PackageOption

__all__ = ["to_meson_machine", "to_meson_value", "to_cppstd_flag"]
__all__ = ["to_meson_machine", "to_meson_value", "to_cppstd_flag", "to_cstd_flag"]

# https://mesonbuild.com/Reference-tables.html#operating-system-names
_meson_system_map = {
Expand Down Expand Up @@ -126,3 +126,16 @@ def to_cppstd_flag(compiler, compiler_version, cppstd):
return 'v%s' % flag if flag else None
else:
return _cppstd_map.get(cppstd)


def to_cstd_flag(cstd):
""" possible values
none, c89, c99, c11, c17, c18, c2x, c23, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23
"""
_cstd_map = {
'99': "c99",
'11': "c11",
'17': "c17",
'23': "c23",
}
return _cstd_map.get(cstd, cstd)
7 changes: 7 additions & 0 deletions conan/tools/meson/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ class MesonToolchain(object):
{% if cpp_std %}
cpp_std = '{{cpp_std}}'
{% endif %}
{% if c_std %}
c_std = '{{c_std}}'
{% endif %}
{% if backend %}
backend = '{{backend}}'
{% endif %}
Expand Down Expand Up @@ -188,6 +191,9 @@ def __init__(self, conanfile, backend=None, native=False):
cppstd = self._conanfile.settings.get_safe("compiler.cppstd")
self._cpp_std = to_cppstd_flag(compiler, compiler_version, cppstd)

cstd = self._conanfile.settings.get_safe("compiler.cstd")
self._c_std = to_cstd_flag(cstd)

self._b_vscrt = None
if compiler in ("msvc", "clang"):
vscrt = msvc_runtime_flag(self._conanfile)
Expand Down Expand Up @@ -505,6 +511,7 @@ def _context(self):
"b_ndebug": to_meson_value(self._b_ndebug), # boolean as string
# https://mesonbuild.com/Builtin-options.html#compiler-options
"cpp_std": self._cpp_std,
"c_std": self._c_std,
"c_args": to_meson_value(self._filter_list_empty_fields(self.c_args)),
"c_link_args": to_meson_value(self._filter_list_empty_fields(self.c_link_args)),
"cpp_args": to_meson_value(self._filter_list_empty_fields(self.cpp_args)),
Expand Down
Loading

0 comments on commit b88c8bb

Please sign in to comment.