Clang: reliably detects a supported C ++ standard from the command line or Python

In a Python script, I am trying to determine the highest C ++ standard supported by an installed Clang .

One problem is that I cannot rely on the conclusion clang --versionto always be the same - the best example is AppleClang on OSX. An attempt to compile the world hello world .cppwith test flags, such as -std=c++11, -std=c++14... does not seem the most reliable approach, and require the creation of temporary files.

Is it possible to execute any command to check if any dialect is available without compiling anything ?

+4
source share
1

- , , , - ?

. . :

$ clang++ --version
clang version 4.0.1-6 (tags/RELEASE_401/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

$ echo '' | clang++ -x c++ -E -
# 1 "<stdin>"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 329 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "<stdin>" 2

$ echo $?
0

-std. :

$ echo '' | clang++ -std=c++98 -x c++ -E -
# 1 "<stdin>"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 326 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "<stdin>" 2

$ echo $?
0

. :

$ echo '' | clang++ -std=c++17 -x c++ -E -
error: invalid value 'c++17' in '-std=c++17'
$ echo $?
1

python script subprocess.run, , . -std, . , stderr , , , - .

, GCC, clang:

$ cat std_max.py
#!/usr/bin/python3
import subprocess

standards = ['98','03','11','14','17']
gpp_barf_pattern = "error: unrecognized command line option ‘-std=c++{0}’"
clangpp_barf_pattern = "error: invalid value 'c++{0}'"

def has_standard(compiler, std_year, barf_pattern):
    std_opt = '-std=c++' + std_year
    try:
        subprocess.run([compiler,std_opt,'-x','c++','-E','-'],\
            check=True,input=b'',stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    except subprocess.CalledProcessError as e:
        barf = barf_pattern.format(std_year)
        strerr = e.stderr.decode('utf8','strict')
        if barf in strerr:
            return False
        raise
    return True

def get_std_max(compiler,standards,barf_pattern):
    max_std = standards[0] if len(standards) else ''
    for std_year in standards:
        if not has_standard(compiler,std_year,barf_pattern):
            break
        max_std = 'c++' + std_year
    return max_std

, :

$ python3
Python 3.6.3 (default, Oct  3 2017, 21:45:48) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from std_max import *
>>> get_std_max('clang++',standards,clangpp_barf_pattern)
'c++14'
>>> get_std_max('g++',standards,gpp_barf_pattern)
'c++17'
>>>

++ 20:

>>> has_standard('g++','20',gpp_barf_pattern)
False
>>>
+2

Source: https://habr.com/ru/post/1694188/


All Articles