<commit_before>import build.shell as shell
from build.object import env
from build.error import ProjectError, ConfigError, format_block
from build.path import Path
import tempfile
import os
import io

class MakefileTarget(object):
    __slots__ = ['base_env', 'os']
    archs = None

    def __init__(self, subtarget, cfg, vars, archs):
        if archs is not None:
            raise ConfigError(
                'architecture cannot be specified for this target')
        self.base_env = default_env(cfg, vars, subtarget)
        fp = cfg.getfp(2)
        fp.write('Makefile environment:\n')
        env.dump_env(self.base_env, fp, indent='  ')
        self.os = subtarget

    def gen_build(self, cfg, proj):
        from .make import gmake
        from build.object.build import Build
        build = Build(cfg, proj, BUILDERS)
        makefile = gmake.Makefile(cfg)
        makepath = Path('/Makefile', 'builddir')
        makefile.add_build(build, makepath)
        makefile.add_clean(Path('/build', 'builddir'))
        return build

    @property
    def config_env(self):
        return self.base_env

def gen_source(prologue, body):
    fp = io.StringIO()
    for line in prologue.splitlines():
        fp.write(line + '\n')
    fp.write(
        'int main(int argc, char *argv[])\n'
        '{\n')
    for line in body.splitlines():
        fp.write(line + '\n')
    fp.write(
        '    (void) argc;\n'
        '    (void) argv;\n'
        '    return 0;\n'
        '}\n')
    return fp.getvalue()

def cc_cmd(env, output, source, sourcetype, *, depfile=None, external=False):
    """Get the command to compile the given source."""
    if sourcetype in ('c', 'objc'):
        try:
            cc = env['CC']
        except KeyError:
            raise ConfigError('CC is not set')
        cflags = env.get('CFLAGS', ())
        warn = env.get('CWARN', ())
    elif sourcetype in ('c++', 'objc++'):
        try:
            cc = env['CXX']
        except KeyError:
            raise ConfigError('CXX is not set')
        cflags = env.get('CXXFLAGS', ())
        warn = env.get('CXXWARN', ())
    else:
        assert False
    cmd = [cc, '-o', output, source, '-c']
    if depfile is not None:
        cmd.extend(('-MF', depfile, '-MMD', '-MP'))
    cmd.extend(('-I', p) for p in env.get('CPPPATH', ()))
    cmd.extend(('-F', p) for p in env.get('FPATH', ()))
    cmd.extend(mkdef(k, v) for k, v in env.get('DEFS', ()))
    cmd.extend(env.get('CPPFLAGS', ()))
    if not external:
        cmd.extend(warn)
    cmd.extend(cflags)
    return cmd

def ld_cmd(env, output, sources, sourcetypes):
    """Get the command to link the given source."""
    if 'c++' in sourcetypes or 'objc++' in sourcetypes:
        try:
            cc = env['CXX']
        except KeyError:
            raise ConfigError('CXX is not set')
    else:
        try:
            cc = env['CC']
        except KeyError:
            raise ConfigError('CC is not set')
    cmd = [cc]
    cmd.extend(env.get('LDFLAGS', ()))
    cmd.extend(('-o', output))
    cmd.extend(sources)
    cmd.extend('-F' + p for p in env.get('FPATH', ()))
    cmd.extend(env.get('LIBS', ()))
    for framework in env.get('FRAMEWORKS', ()):
        cmd.extend(('-framework', framework))
    return cmd

def default_env(cfg, vars, osname):
    """Get the default environment."""
    assert osname in ('linux', 'osx')
    config = 'debug' if cfg.config is None else cfg.config
    warnings = True if cfg.warnings is None else cfg.warnings
    werror = (config == 'debug') if cfg.werror is None else cfg.werror
    
    base_env = {}
    envs = [base_env]
    if cfg.config == 'debug':
        cflags = ('-O0', '-g')
    else:
        cflags = ('-O2', '-g')
    base_env.update({
        'CC': 'cc',
        'CXX': 'c++',
        'CFLAGS': cflags,
        'CXXFLAGS': cflags,
    })
    if warnings:
        base_env.update({
            'CWARN': tuple(
                '-Wall -Wextra -Wpointer-arith -Wno-sign-compare '
                '-Wwrite-strings -Wmissing-prototypes '
                .split()),
            'CXXWARN': tuple(
                '-Wall -Wextra -Wpointer-arith -Wno-sign-compare '
                .split()),
        })
    if werror:
        envs.append({
            'CWARN': ('-Werror',),
            'CXXWARN': ('-Werror',),
        })
    if osname == 'linux':
        envs.append({
            'LDFLAGS': ('-Wl,--as-needed', '-Wl,--gc-sections'),
        })
    if osname == 'osx':
        envs.append({
            'LDFLAGS': ('-Wl,-dead_strip', '-Wl,-dead_strip_dylibs'),
        })

    user_env = {}
    for varname in vars.items():
        try:
            varparse = env.VAR[varname].parse
        except (KeyError, AttributeError):
            continue
        user_env[varname] = varparse(vars[varname])
        try:
            del base_env[varname]
        except KeyError:
            pass
    envs.append(user_env)

    return env.merge_env(envs)

def getmachine(cfg, env):
    """Get the name of the target machine."""
    cc = env['CC']
    cmd = [cc, '-dumpmachine']
    cmd.extend(env.get('CPPFLAGS', ()))
    cmd.extend(env.get('CFLAGS', ()))
    stdout, stderr, retcode = shell.get_output(cmd)
    if retcode:
        raise ConfigError(
            'could not get machine specs',
            shell.describe_proc(cmd, stderr, retcode))
    m = stdout.splitlines()
    if m:
        m = m[0]
        i = m.find('-')
        if i >= 0:
            m = m[:i]
            if m == 'x86_64':<commit_msg>build: fix bug with Makefile env vars<commit_after>import build.shell as shell
from build.object import env
from build.error import ProjectError, ConfigError, format_block
from build.path import Path
import tempfile
import os
import io

class MakefileTarget(object):
    __slots__ = ['base_env', 'os']
    archs = None

    def __init__(self, subtarget, cfg, vars, archs):
        if archs is not None:
            raise ConfigError(
                'architecture cannot be specified for this target')
        self.base_env = default_env(cfg, vars, subtarget)
        fp = cfg.getfp(2)
        fp.write('Makefile environment:\n')
        env.dump_env(self.base_env, fp, indent='  ')
        self.os = subtarget

    def gen_build(self, cfg, proj):
        from .make import gmake
        from build.object.build import Build
        build = Build(cfg, proj, BUILDERS)
        makefile = gmake.Makefile(cfg)
        makepath = Path('/Makefile', 'builddir')
        makefile.add_build(build, makepath)
        makefile.add_clean(Path('/build', 'builddir'))
        return build

    @property
    def config_env(self):
        return self.base_env

def gen_source(prologue, body):
    fp = io.StringIO()
    for line in prologue.splitlines():
        fp.write(line + '\n')
    fp.write(
        'int main(int argc, char *argv[])\n'
        '{\n')
    for line in body.splitlines():
        fp.write(line + '\n')
    fp.write(
        '    (void) argc;\n'
        '    (void) argv;\n'
        '    return 0;\n'
        '}\n')
    return fp.getvalue()

def cc_cmd(env, output, source, sourcetype, *, depfile=None, external=False):
    """Get the command to compile the given source."""
    if sourcetype in ('c', 'objc'):
        try:
            cc = env['CC']
        except KeyError:
            raise ConfigError('CC is not set')
        cflags = env.get('CFLAGS', ())
        warn = env.get('CWARN', ())
    elif sourcetype in ('c++', 'objc++'):
        try:
            cc = env['CXX']
        except KeyError:
            raise ConfigError('CXX is not set')
        cflags = env.get('CXXFLAGS', ())
        warn = env.get('CXXWARN', ())
    else:
        assert False
    cmd = [cc, '-o', output, source, '-c']
    if depfile is not None:
        cmd.extend(('-MF', depfile, '-MMD', '-MP'))
    cmd.extend(('-I', p) for p in env.get('CPPPATH', ()))
    cmd.extend(('-F', p) for p in env.get('FPATH', ()))
    cmd.extend(mkdef(k, v) for k, v in env.get('DEFS', ()))
    cmd.extend(env.get('CPPFLAGS', ()))
    if not external:
        cmd.extend(warn)
    cmd.extend(cflags)
    return cmd

def ld_cmd(env, output, sources, sourcetypes):
    """Get the command to link the given source."""
    if 'c++' in sourcetypes or 'objc++' in sourcetypes:
        try:
            cc = env['CXX']
        except KeyError:
            raise ConfigError('CXX is not set')
    else:
        try:
            cc = env['CC']
        except KeyError:
            raise ConfigError('CC is not set')
    cmd = [cc]
    cmd.extend(env.get('LDFLAGS', ()))
    cmd.extend(('-o', output))
    cmd.extend(sources)
    cmd.extend('-F' + p for p in env.get('FPATH', ()))
    cmd.extend(env.get('LIBS', ()))
    for framework in env.get('FRAMEWORKS', ()):
        cmd.extend(('-framework', framework))
    return cmd

def default_env(cfg, vars, osname):
    """Get the default environment."""
    assert osname in ('linux', 'osx')
    config = 'debug' if cfg.config is None else cfg.config
    warnings = True if cfg.warnings is None else cfg.warnings
    werror = (config == 'debug') if cfg.werror is None else cfg.werror
    
    base_env = {}
    envs = [base_env]
    if cfg.config == 'debug':
        cflags = ('-O0', '-g')
    else:
        cflags = ('-O2', '-g')
    base_env.update({
        'CC': 'cc',
        'CXX': 'c++',
        'CFLAGS': cflags,
        'CXXFLAGS': cflags,
    })
    if warnings:
        base_env.update({
            'CWARN': tuple(
                '-Wall -Wextra -Wpointer-arith -Wno-sign-compare '
                '-Wwrite-strings -Wmissing-prototypes '
                .split()),
            'CXXWARN': tuple(
                '-Wall -Wextra -Wpointer-arith -Wno-sign-compare '
                .split()),
        })
    if werror:
        envs.append({
            'CWARN': ('-Werror',),
            'CXXWARN': ('-Werror',),
        })
    if osname == 'linux':
        envs.append({
            'LDFLAGS': ('-Wl,--as-needed', '-Wl,--gc-sections'),
        })
    if osname == 'osx':
        envs.append({
            'LDFLAGS': ('-Wl,-dead_strip', '-Wl,-dead_strip_dylibs'),
        })

    user_env = {}
    for varname in vars:
        try:
            varparse = env.VAR[varname].parse
        except (KeyError, AttributeError):
            continue
        user_env[varname] = varparse(vars[varname])
        try:
            del base_env[varname]
        except KeyError:
            pass
    envs.append(user_env)

    return env.merge_env(envs)

def getmachine(cfg, env):
    """Get the name of the target machine."""
    cc = env['CC']
    cmd = [cc, '-dumpmachine']
    cmd.extend(env.get('CPPFLAGS', ()))
    cmd.extend(env.get('CFLAGS', ()))
    stdout, stderr, retcode = shell.get_output(cmd)
    if retcode:
        raise ConfigError(
            'could not get machine specs',
            shell.describe_proc(cmd, stderr, retcode))
    m = stdout.splitlines()
    if m:
        m = m[0]
        i = m.find('-')
        if i >= 0:
            m = m[:i]
            if m == 'x86_64':
{'fraction_non_alphanumeric': 0.15275504637206766, 'fraction_numerical': 0.0018185124568103291, 'mean_word_length': 2.0068343357025697, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5292149', 'n_tokens_mistral': 3623, 'n_tokens_neox': 3554, 'n_words': 933}