<filename>rust/build_rustc_target.py<gh_stars>0
#!/usr/bin/env python
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import json
import os
import subprocess
import sys

# Updates the path of the main target in the depfile to the relative path
# from base_path build_output_path
def fix_depfile(depfile_path, base_path, build_output_path):
    with open(depfile_path, "r") as depfile:
        content = depfile.read()
    content_split = content.split(': ', 1)
    target_path = os.path.relpath(build_output_path, start=base_path)
    new_content = "%s: %s" % (target_path, content_split[1])
    with open(depfile_path, "w") as depfile:
        depfile.write(new_content)

# Creates the directory containing the given file.
def create_base_directory(file):
    path = os.path.dirname(file)
    try:
        os.makedirs(path)
    except os.error:
        # Already existed.
        pass

# Runs the given command and returns its return code and output.
def run_command(args, env):
    job = subprocess.Popen(args, env=env, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    stdout, stderr = job.communicate()
    return (job.returncode, stdout, stderr)

def main():
    parser = argparse.ArgumentParser("Compiles a Rust crate")
    parser.add_argument("--rustc",
                        help="Path to rustc",
                        required=True)
    parser.add_argument("--cipd-version",
                        help="CIPD version of Rust toolchain",
                        required=False)
    parser.add_argument("--crate-root",
                        help="Path to source directory",
                        required=True)
    parser.add_argument("--cargo-toml-dir",
                        help="Path to directory in which a Cargo.toml for this target may be generated",
                        required=True)
    parser.add_argument("--crate-type",
                        help="Type of crate to build",
                        required=True,
                        choices=["bin", "rlib", "staticlib", "proc-macro"])
    parser.add_argument("--package-name",
                        help="Name of package to build",
                        required=True)
    parser.add_argument("--crate-name",
                        help="Name of crate to build",
                        required=True)
    parser.add_argument("--version",
                        help="Semver version of the crate being built",
                        required=True)
    parser.add_argument("--edition",
                        help="Edition of rust to use when compiling the crate",
                        required=True,
                        choices=["2015", "2018"])
    parser.add_argument("--opt-level",
                        help="Optimization level",
                        required=True,
                        choices=["0", "1", "2", "3", "s", "z"])
    parser.add_argument("--lto",
                        help="Use LTO",
                        required=False,
                        choices=["thin", "fat"])
    parser.add_argument("--output-file",
                        help="Path at which the output file should be stored",
                        required=True)
    parser.add_argument("--depfile",
                        help="Path at which the output depfile should be stored",
                        required=True)
    parser.add_argument("--root-out-dir",
                        help="Root output dir on which depfile paths should be rebased",
                        required=True)
    parser.add_argument("--test-output-file",
                        help="Path at which the unit test output file should be stored if --with-unit-tests is supplied",
                        required=False)
    parser.add_argument("--with-unit-tests",
                        help="Whether or not to build unit tests",
                        action="store_true",
                        required=False)
    parser.add_argument("--target",
                        help="Target for which this crate is being compiled",
                        required=True)
    parser.add_argument("--cmake-dir",
                        help="Path to the directory containing cmake",
                        required=True)
    parser.add_argument("--clang_prefix",
                        help="Path to the clang prefix",
                        required=True)
    parser.add_argument("--sysroot",
                        help="Path to the sysroot",
                        required=True)
    parser.add_argument("--shared-libs-root",
                        help="Path to the location of shared libraries",
                        required=True)
    parser.add_argument("--first-party-crate-root",
                        help="Path to directory containing the libs for first-party dependencies",
                        required=True)
    parser.add_argument("--third-party-deps-data",
                        help="Path to output of third_party_crates.py",
                        required=True)
    parser.add_argument("--out-info",
                        help="Path metadata output",
                        required=True)
    parser.add_argument("--dep-data",
                        action="append",
                        help="Path to metadata from a crate dependency",
                        required=False)
    parser.add_argument("--mmacosx-version-min",
                        help="Select macosx framework version",
                        required=False)

    parser.add_argument
    args = parser.parse_args()

    env = os.environ.copy()
    env["CC"] = os.path.join(args.clang_prefix, "clang")
    env["CXX"] = os.path.join(args.clang_prefix, "clang++")
    env["AR"] = os.path.join(args.clang_prefix, "llvm-ar")
    env["RANLIB"] = os.path.join(args.clang_prefix, "llvm-ranlib")
    if args.cmake_dir:
        env["PATH"] = "%s:%s" % (env["PATH"], args.cmake_dir)
    env["RUST_BACKTRACE"] = "1"

    create_base_directory(args.output_file)

    call_args = [
        args.rustc,
        args.crate_root,
        "--edition=%s" % args.edition,
        "--crate-type=%s" % args.crate_type,
        "--crate-name=%s" % args.crate_name,
        "--target=%s" % args.target,
        "-Clinker=%s" % os.path.join(args.clang_prefix, "clang"),
        "-Clink-arg=--target=%s" % args.target,
        "-Clink-arg=--sysroot=%s" % args.sysroot,
        "-Copt-level=%s" % args.opt_level,
        "-Lnative=%s" % args.shared_libs_root,
        "--color=always",
    ]
    if args.mmacosx_version_min:
        call_args += [
            "-Clink-arg=-mmacosx-version-min=%s" % args.mmacosx_version_min,
        ]

    if args.lto:
        call_args += ["-Clto=%s" % args.lto]

    third_party_json = json.load(open(args.third_party_deps_data))
    search_paths = third_party_json["deps_folders"] + [ args.first_party_crate_root ]
    for path in search_paths:
        call_args += ["-L", "dependency=%s" % path]

    externs = []

    # Collect externs
    if args.dep_data:
        for data_path in args.dep_data:
            dep_data = json.load(open(data_path))
            if dep_data["third_party"]:
                package_name = dep_data["package_name"]
                crate_data = third_party_json["crates"][package_name]
                crate = crate_data["crate_name"]
                lib_path = crate_data["lib_path"]
            else:
                crate = dep_data["crate_name"]
                lib_path = dep_data["lib_path"]
            crate_underscore = crate.replace("-", "_")
            externs.append("%s=%s" % (crate_underscore, lib_path))

    # add externs to arguments
    for extern in externs:
        call_args += ["--extern", extern]

    # Build the depfile
    depfile_args = call_args + [
        "-o%s" % args.depfile,
        "--emit=dep-info",
    ]
    retcode, stdout, stderr = run_command(depfile_args, env)
    if retcode != 0:
        print(stdout + stderr)
        return retcode
    fix_depfile(args.depfile, os.getcwd(), args.output_file)

    # Build the desired output
    build_args = call_args + ["-o%s" % args.output_file]
    retcode, stdout, stderr = run_command(build_args, env)
    if retcode != 0:
        print(stdout + stderr)
        return retcode

    # Build the test harness
    if args.with_unit_tests:
        build_test_args = call_args + [
            "-o%s" % args.test_output_file,
            "--test",
        ]
        retcode, stdout, stderr = run_command(build_test_args, env)
        if retcode != 0:
            print(stdout + stderr)
            return retcode

    # Write output dependency info
    create_base_directory(args.out_info)
    with open(args.out_info, "w") as file:
        file.write(json.dumps({
            "crate_name": args.crate_name,
            "package_name": args.package_name,
            "third_party": False,
            "cargo_toml_dir": args.cargo_toml_dir,
            "lib_path": args.output_file,
            "version": args.version,
        }, sort_keys=True, indent=4, separators=(",", ": ")))

if __name__ == '__main__':
    sys.exit(main())

<filename>rust/build_rustc_target.py<gh_stars>0
#!/usr/bin/env python
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import json
import os
import subprocess
import sys

# Updates the path of the main target in the depfile to the relative path
# from base_path build_output_path
def fix_depfile(depfile_path, base_path, build_output_path):
    with open(depfile_path, "r") as depfile:
        content = depfile.read()
    content_split = content.split(': ', 1)
    target_path = os.path.relpath(build_output_path, start=base_path)
    new_content = "%s: %s" % (target_path, content_split[1])
    with open(depfile_path, "w") as depfile:
        depfile.write(new_content)

# Creates the directory containing the given file.
def create_base_directory(file):
    path = os.path.dirname(file)
    try:
        os.makedirs(path)
    except os.error:
        # Already existed.
        pass

# Runs the given command and returns its return code and output.
def run_command(args, env):
    job = subprocess.Popen(args, env=env, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    stdout, stderr = job.communicate()
    return (job.returncode, stdout, stderr)

def main():
    parser = argparse.ArgumentParser("Compiles a Rust crate")
    parser.add_argument("--rustc",
                        help="Path to rustc",
                        required=True)
    parser.add_argument("--cipd-version",
                        help="CIPD version of Rust toolchain",
                        required=False)
    parser.add_argument("--crate-root",
                        help="Path to source directory",
                        required=True)
    parser.add_argument("--cargo-toml-dir",
                        help="Path to directory in which a Cargo.toml for this target may be generated",
                        required=True)
    parser.add_argument("--crate-type",
                        help="Type of crate to build",
                        required=True,
                        choices=["bin", "rlib", "staticlib", "proc-macro"])
    parser.add_argument("--package-name",
                        help="Name of package to build",
                        required=True)
    parser.add_argument("--crate-name",
                        help="Name of crate to build",
                        required=True)
    parser.add_argument("--version",
                        help="Semver version of the crate being built",
                        required=True)
    parser.add_argument("--edition",
                        help="Edition of rust to use when compiling the crate",
                        required=True,
                        choices=["2015", "2018"])
    parser.add_argument("--opt-level",
                        help="Optimization level",
                        required=True,
                        choices=["0", "1", "2", "3", "s", "z"])
    parser.add_argument("--lto",
                        help="Use LTO",
                        required=False,
                        choices=["thin", "fat"])
    parser.add_argument("--output-file",
                        help="Path at which the output file should be stored",
                        required=True)
    parser.add_argument("--depfile",
                        help="Path at which the output depfile should be stored",
                        required=True)
    parser.add_argument("--root-out-dir",
                        help="Root output dir on which depfile paths should be rebased",
                        required=True)
    parser.add_argument("--test-output-file",
                        help="Path at which the unit test output file should be stored if --with-unit-tests is supplied",
                        required=False)
    parser.add_argument("--with-unit-tests",
                        help="Whether or not to build unit tests",
                        action="store_true",
                        required=False)
    parser.add_argument("--target",
                        help="Target for which this crate is being compiled",
                        required=True)
    parser.add_argument("--cmake-dir",
                        help="Path to the directory containing cmake",
                        required=True)
    parser.add_argument("--clang_prefix",
                        help="Path to the clang prefix",
                        required=True)
    parser.add_argument("--sysroot",
                        help="Path to the sysroot",
                        required=True)
    parser.add_argument("--shared-libs-root",
                        help="Path to the location of shared libraries",
                        required=True)
    parser.add_argument("--first-party-crate-root",
                        help="Path to directory containing the libs for first-party dependencies",
                        required=True)
    parser.add_argument("--third-party-deps-data",
                        help="Path to output of third_party_crates.py",
                        required=True)
    parser.add_argument("--out-info",
                        help="Path metadata output",
                        required=True)
    parser.add_argument("--dep-data",
                        action="append",
                        help="Path to metadata from a crate dependency",
                        required=False)
    parser.add_argument("--mmacosx-version-min",
                        help="Select macosx framework version",
                        required=False)

    parser.add_argument
    args = parser.parse_args()

    env = os.environ.copy()
    env["CC"] = os.path.join(args.clang_prefix, "clang")
    env["CXX"] = os.path.join(args.clang_prefix, "clang++")
    env["AR"] = os.path.join(args.clang_prefix, "llvm-ar")
    env["RANLIB"] = os.path.join(args.clang_prefix, "llvm-ranlib")
    if args.cmake_dir:
        env["PATH"] = "%s:%s" % (env["PATH"], args.cmake_dir)
    env["RUST_BACKTRACE"] = "1"

    create_base_directory(args.output_file)

    call_args = [
        args.rustc,
        args.crate_root,
        "--edition=%s" % args.edition,
        "--crate-type=%s" % args.crate_type,
        "--crate-name=%s" % args.crate_name,
        "--target=%s" % args.target,
        "-Clinker=%s" % os.path.join(args.clang_prefix, "clang"),
        "-Clink-arg=--target=%s" % args.target,
        "-Clink-arg=--sysroot=%s" % args.sysroot,
        "-Copt-level=%s" % args.opt_level,
        "-Lnative=%s" % args.shared_libs_root,
        "--color=always",
    ]
    if args.mmacosx_version_min:
        call_args += [
            "-Clink-arg=-mmacosx-version-min=%s" % args.mmacosx_version_min,
        ]

    if args.lto:
        call_args += ["-Clto=%s" % args.lto]

    third_party_json = json.load(open(args.third_party_deps_data))
    search_paths = third_party_json["deps_folders"] + [ args.first_party_crate_root ]
    for path in search_paths:
        call_args += ["-L", "dependency=%s" % path]

    externs = []

    # Collect externs
    if args.dep_data:
        for data_path in args.dep_data:
            dep_data = json.load(open(data_path))
            if dep_data["third_party"]:
                package_name = dep_data["package_name"]
                crate_data = third_party_json["crates"][package_name]
                crate = crate_data["crate_name"]
                lib_path = crate_data["lib_path"]
            else:
                crate = dep_data["crate_name"]
                lib_path = dep_data["lib_path"]
            crate_underscore = crate.replace("-", "_")
            externs.append("%s=%s" % (crate_underscore, lib_path))

    # add externs to arguments
    for extern in externs:
        call_args += ["--extern", extern]

    # Build the depfile
    depfile_args = call_args + [
        "-o%s" % args.depfile,
        "--emit=dep-info",
    ]
    retcode, stdout, stderr = run_command(depfile_args, env)
    if retcode != 0:
        print(stdout + stderr)
        return retcode
    fix_depfile(args.depfile, os.getcwd(), args.output_file)

    # Build the desired output
    build_args = call_args + ["-o%s" % args.output_file]
    retcode, stdout, stderr = run_command(build_args, env)
    if retcode != 0:
        print(stdout + stderr)
        return retcode

    # Build the test harness
    if args.with_unit_tests:
        build_test_args = call_args + [
            "-o%s" % args.test_output_file,
            "--test",
        ]
        retcode, stdout, stderr = run_command(build_test_args, env)
        if retcode != 0:
            print(stdout + stderr)
            return retcode

    # Write output dependency info
    create_base_directory(args.out_info)
    with open(args.out_info, "w") as file:
        file.write(json.dumps({
            "crate_name": args.crate_name,
            "package_name": args.package_name,
            "third_party": False,
            "cargo_toml_dir": args.cargo_toml_dir,
            "lib_path": args.output_file,
            "version": args.version,
        }, sort_keys=True, indent=4, separators=(",", ": ")))

if __name__ == '__main__':
    sys.exit(main())

#!/usr/bin/env python # Copyright 2018 The Fuchsia Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Updates the path of the main target in the depfile to the relative path # from base_path build_output_path # Creates the directory containing the given file. # Already existed. # Runs the given command and returns its return code and output. # Collect externs # add externs to arguments # Build the depfile # Build the desired output # Build the test harness # Write output dependency info