diff options
author | Mad Camel <madcamel@gmail.com> | 2024-02-18 16:49:33 +0000 |
---|---|---|
committer | Mad Camel <madcamel@gmail.com> | 2024-02-18 16:49:33 +0000 |
commit | 8edebcaf5ecdb7bcc731142921e16390436fc7a3 (patch) | |
tree | eba669dc30a217af0d8a958b324dcaf9772f6c54 /attoconf/lib/c.py | |
parent | 208f846464b96721d93436006365705fde3b6b2c (diff) | |
parent | f1a54c378b7b51b36103ad8111d66aef63e7f041 (diff) | |
download | attobuild-master.tar.gz attobuild-master.tar.bz2 attobuild-master.tar.xz attobuild-master.zip |
Import from specing's attoconf branch
See merge request legacy/attobuild!1
Diffstat (limited to 'attoconf/lib/c.py')
-rw-r--r-- | attoconf/lib/c.py | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/attoconf/lib/c.py b/attoconf/lib/c.py new file mode 100644 index 0000000..98d88df --- /dev/null +++ b/attoconf/lib/c.py @@ -0,0 +1,281 @@ +# Copyright 2013-2014 Ben Longbons <b.r.longbons@gmail.com> +# +# This file is part of attoconf. +# +# attoconf is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# attoconf is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with attoconf. If not, see <http://www.gnu.org/licenses/>. + + + +import errno +import os +import subprocess + +from .arches import Arches2 +from ..types import ShellList + +class TestError(Exception): + pass + +def do_exec(build, args): + p = subprocess.Popen(args.list, cwd=build.builddir, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, _ = p.communicate() + retcode = p.wait() + return retcode, out + + +class TempFile: + ''' context manager that optionally creates and then removes a file + ''' + __slots__ = ('filename') + + def __init__(self, filename, content): + self.filename = filename + if content is not None: + with open(filename, 'x') as of: + of.write(content) + else: + # TODO: raise OSError(errno.EEXIST) if file already exists + pass + + def __enter__(self): + pass + + def __exit__(self, type, value, traceback): + try: + os.remove(self.filename) + except OSError as e: + if e.errno != errno.ENOENT: + raise + + +def try_compile_c(build, body, CFLAGS=[], CPPFLAGS=[]): + CC = build.vars['CC'] + CFLAGS = build.vars['CFLAGS'] + CFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + in_ = 'atto-test.c' + ins = [in_] + out = 'atto-test.o' + + args = CC + CFLAGS + CPPFLAGS + ['-c', '-o', out, in_] + with TempFile(in_, body), TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +def try_compile_link_c(build, body, CFLAGS=[], CPPFLAGS=[], LDFLAGS=[], LIBS=[]): + CC = build.vars['CC'] + CFLAGS = build.vars['CFLAGS'] + CFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + in_ = 'atto-test.c' + ins = [in_] + out = 'atto-test' + + args = CC + CFLAGS + CPPFLAGS + LDFLAGS + ins + LIBS + ['-o', out] + with TempFile(in_, body), TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +def try_compile_cxx(build, body, CXXFLAGS=[], CPPFLAGS=[]): + CXX = build.vars['CXX'] + CXXFLAGS = build.vars['CXXFLAGS'] + CXXFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + in_ = 'atto-test.cxx' + out = 'atto-test.o' + + args = CXX + CXXFLAGS + CPPFLAGS + ['-c', '-o', out, in_] + with TempFile(in_, body), TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +def try_compile_link_cxx(build, body, CXXFLAGS=[], CPPFLAGS=[], LDFLAGS=[], LIBS=[]): + CXX = build.vars['CXX'] + CXXFLAGS = build.vars['CXXFLAGS'] + CXXFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + in_ = 'atto-test.cxx' + ins = [in_] + out = 'atto-test' + + args = CXX + CXXFLAGS + CPPFLAGS + LDFLAGS + ins + LIBS + ['-o', out] + with TempFile(in_, body), TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +if 0: + def try_linkonly_c(build, ins, LDFLAGS=[], LIBS=[]): + CC = build.vars['CC'] + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + out = 'atto-test' + + args = CC + LDFLAGS + ins + LIBS + ['-o', out] + with TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +def try_compile_link2_c(build, body, CFLAGS=[], CPPFLAGS=[], LDFLAGS=[], LIBS=[]): + CC = build.vars['CC'] + CFLAGS = build.vars['CFLAGS'] + CFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + in_ = 'atto-test.c' + ins = [in_] + mid = 'atto-test.o' + mids = [mid] + out = 'atto-test' + + args1 = CC + CFLAGS + CPPFLAGS + ['-c', '-o', mid, in_] + args2 = CC + LDFLAGS + mids + LIBS + ['-o', out] + with TempFile(mid, None): + with TempFile(in_, body): + status, error = do_exec(build, args1) + if status: + raise TestError(error) + + with TempFile(out, None): + status, error = do_exec(build, args2) + if status: + raise TestError(error) + +if 0: + def try_linkonly_cxx(build, ins, LDFLAGS=[], LIBS=[]): + CXX = build.vars['CXX'] + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + out = 'atto-test' + + args = CXX + LDFLAGS + ins + LIBS + ['-o', out] + with TempFile(out, None): + status, error = do_exec(build, args) + if status: + raise TestError(error) + +def try_compile_link2_cxx(build, body, CXXFLAGS=[], CPPFLAGS=[], LDFLAGS=[], LIBS=[]): + CXX = build.vars['CXX'] + CXXFLAGS = build.vars['CXXFLAGS'] + CXXFLAGS + CPPFLAGS = build.vars['CPPFLAGS'] + CPPFLAGS + LDFLAGS = build.vars['LDFLAGS'] + LDFLAGS + LIBS = build.vars['LIBS'] + LIBS + in_ = 'atto-test.cxx' + ins = [in_] + mid = 'atto-test.o' + mids = [mid] + out = 'atto-test' + + args1 = CXX + CXXFLAGS + CPPFLAGS + ['-c', '-o', mid, in_] + args2 = CXX + LDFLAGS + mids + LIBS + ['-o', out] + with TempFile(mid, None): + with TempFile(in_, body): + status, error = do_exec(build, args1) + if status: + raise TestError(error) + + with TempFile(out, None): + status, error = do_exec(build, args2) + if status: + raise TestError(error) + + +def ldflags(build, LDFLAGS): + pass + +def libs(build, LIBS): + # compatibility + build.vars['LDLIBS'] = LIBS + +def cppflags(build, CPPFLAGS): + pass + +def cc(build, CC): + if CC.list == []: + HOST = build.vars['HOST'] + if HOST: + build.vars['CC'].list = [HOST + '-gcc'] + else: + build.vars['CC'].list = ['gcc'] + +def cflags(build, CFLAGS): + try_compile_c(build, 'int main() {}\n') + try_compile_link_c(build, 'int main() {}\n') + try_compile_link2_c(build, 'int main() {}\n') + +def cxx(build, CXX): + if CXX.list == []: + HOST = build.vars['HOST'] + if HOST: + build.vars['CXX'].list = [HOST + '-g++'] + else: + build.vars['CXX'].list = ['g++'] + +def cxxflags(build, CXXFLAGS): + try_compile_cxx(build, 'int main() {}\n') + try_compile_link_cxx(build, 'int main() {}\n') + try_compile_link2_cxx(build, 'int main() {}\n') + +class Link(Arches2): + __slots__ = () + def vars(self): + super(Link, self).vars() + self.add_option('LDFLAGS', init=[], + type=ShellList, check=ldflags, + help='linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir>', + hidden=False) + self.add_option('LIBS', init=[], + type=ShellList, check=libs, + help='libraries to pass to the linker, e.g. -l<library>', + hidden=False) + self.order.append('LDLIBS') #TODO remove for 1.0 + +class Preprocess(Arches2): + __slots__ = () + def vars(self): + super(Preprocess, self).vars() + self.add_option('CPPFLAGS', init=[], + type=ShellList, check=cppflags, + help='C/C++/Objective C preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir>', + hidden=False) + +class C(Link, Preprocess): + __slots__ = () + def vars(self): + super(C, self).vars() + self.add_option('CC', init=[], + type=ShellList, check=cc, + help='C compiler command', hidden=False, + help_def='HOST-gcc') + self.add_option('CFLAGS', init=['-O2', '-g'], + type=ShellList, check=cflags, + help='C compiler flags', hidden=False) + +class Cxx(Link, Preprocess): + __slots__ = () + def vars(self): + super(Cxx, self).vars() + self.add_option('CXX', init=[], + type=ShellList, check=cxx, + help='C++ compiler command', hidden=False, + help_def='HOST-g++') + self.add_option('CXXFLAGS', init=['-O2', '-g'], + type=ShellList, check=cxxflags, + help='C++ compiler flags', hidden=False) |