Exemple #1
0
def extract_files(signature,
                  cache_params,
                  prefix="",
                  path=os.curdir,
                  categories=("inc", "src", "lib", "log")):
    """Make a copy of files stored under this signature.

    Target filenames are '<path>/<prefix>-<signature>.*'
    """
    path = os.path.join(path, prefix + signature)
    make_dirs(path)

    if "inc" in categories:
        inc_filename = create_inc_filename(signature, cache_params)
        try_copy_file(inc_filename, path)
    if "src" in categories:
        src_filename = create_src_filename(signature, cache_params)
        if not os.path.exists(src_filename):
            src_filename = src_filename + ".gz"
        if os.path.exists(src_filename):
            try_copy_file(src_filename, path)
            if src_filename.endswith(".gz"):
                gunzip_file(os.path.join(path, os.path.basename(src_filename)))
    if "lib" in categories:
        lib_filename = create_lib_filename(signature, cache_params)
        try_copy_file(lib_filename, path)
    if "log" in categories:
        log_filename = create_log_filename(signature, cache_params)
        try_copy_file(log_filename, path)

    return path
Exemple #2
0
def make_log_dir(cache_params):
    d = os.path.join(cache_params["cache_dir"], cache_params["log_dir"])
    make_dirs(d)
    return d
Exemple #3
0
def build_shared_library(signature, header, source, dependencies, params):
    """Build shared library from a source file and store library in
    cache.

    """
    cache_params = params["cache"]
    build_params = params["build"]

    # Create basenames
    inc_basename = create_inc_basename(signature, cache_params)
    src_basename = create_src_basename(signature, cache_params)
    lib_basename = create_lib_basename(signature, cache_params)

    # Create a temp directory and filenames within it
    tmpdir = temp_dir(cache_params)
    temp_inc_filename = os.path.join(tmpdir, inc_basename)
    temp_src_filename = os.path.join(tmpdir, src_basename)
    temp_lib_filename = os.path.join(tmpdir, lib_basename)

    # Store source and header in temp dir
    if header:
        store_textfile(temp_inc_filename, header)
    store_textfile(temp_src_filename, source)

    # Build final command as list of arguments
    cmd = make_compile_command(temp_src_filename, temp_lib_filename,
                               dependencies, build_params, cache_params)

    # Execute command to compile generated source code to dynamic
    # library
    status, output = get_status_output(cmd)

    # Move files to cache on success or a local dir on failure,
    # using safe lockfree move
    if status == 0:
        # Ensure dirnames exist in cache dirs
        ensure_dirs(cache_params)

        # Move library first
        lib_filename = create_lib_filename(signature, cache_params)
        assert os.path.exists(os.path.dirname(lib_filename))
        lockfree_move_file(temp_lib_filename, lib_filename)

        # Write header only if there is one
        if header:
            inc_filename = create_inc_filename(signature, cache_params)
            assert os.path.exists(os.path.dirname(inc_filename))
            lockfree_move_file(temp_inc_filename, inc_filename)
        else:
            inc_filename = None

        # Compress or delete source code based on params
        temp_src_filename = compress_source_code(temp_src_filename,
                                                 cache_params)
        if temp_src_filename:
            src_filename = create_src_filename(signature, cache_params)
            if temp_src_filename.endswith(".gz"):
                src_filename = src_filename + ".gz"
            assert os.path.exists(os.path.dirname(src_filename))
            lockfree_move_file(temp_src_filename, src_filename)
        else:
            src_filename = None

        # Write compiler command and output to log file
        if cache_params["enable_build_log"]:
            # Recreate compiler command without the tempdir
            cmd = make_compile_command(src_basename, lib_basename,
                                       dependencies, build_params,
                                       cache_params)

            log_contents = "%s\n\n%s" % (" ".join(cmd), output)
            log_filename = create_log_filename(signature, cache_params)
            assert os.path.exists(os.path.dirname(log_filename))
            store_textfile(log_filename, log_contents)
        else:
            log_filename = None

        files = set((inc_filename, src_filename, lib_filename, log_filename))
        files = files - set((None, ))
        files = sorted(files)
        debug("Compilation succeeded. Files written to cache:\n" +
              "\n".join(files))
        err_info = None
    else:
        # Create filenames in a local directory to store files for
        # reproducing failure
        fail_dir = create_fail_dir_path(signature, cache_params)
        make_dirs(fail_dir)

        # Library name is returned below
        lib_filename = None

        # Write header only if there is one
        if header:
            inc_filename = os.path.join(fail_dir, inc_basename)
            lockfree_move_file(temp_inc_filename, inc_filename)

        # Always write source for inspection after compilation failure
        src_filename = os.path.join(fail_dir, src_basename)
        lockfree_move_file(temp_src_filename, src_filename)

        # Write compile command to failure dir, adjusted to use local
        # source file name so it can be rerun
        cmd = make_compile_command(src_basename, lib_basename, dependencies,
                                   build_params, cache_params)
        cmds = " ".join(cmd)
        script = "#!/bin/bash\n# Execute this file to recompile locally\n" + cmds
        cmd_filename = os.path.join(fail_dir, "recompile.sh")
        store_textfile(cmd_filename, script)
        make_executable(cmd_filename)

        # Write readme file with instructions
        readme = "Run or source recompile.sh to compile locally and reproduce the build failure.\n"
        readme_filename = os.path.join(fail_dir, "README")
        store_textfile(readme_filename, readme)

        # Write compiler output to failure dir (will refer to temp paths)
        log_filename = os.path.join(fail_dir, "error.log")
        store_textfile(log_filename, output)

        info(
            "------------------- Start compiler output ------------------------"
        )
        info(output)
        info(
            "-------------------  End compiler output  ------------------------"
        )
        warning("Compilation failed! Sources, command, and "
                "errors have been written to: %s" % (fail_dir, ))

        err_info = {
            'src_filename': src_filename,
            'cmd_filename': cmd_filename,
            'readme_filename': readme_filename,
            'fail_dir': fail_dir,
            'log_filename': log_filename
        }

    return status, output, lib_filename, err_info