#!/usr/bin/python # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # The directories end up in the debug info, so the easy way of getting # a reproducible build is to run it in a know absolute directory. # We use a directory in /builds/slave because the mozilla infrastructure # cleans it up automatically. base_dir = "/builds/slave/moz-toolchain" source_dir = base_dir + "/src" build_dir = base_dir + "/build" aux_inst_dir = build_dir + '/aux_inst' old_make = aux_inst_dir + '/bin/make' ############################################## import urllib import os import os.path import shutil import tarfile import subprocess def download_uri(uri): fname = uri.split('/')[-1] if (os.path.exists(fname)): return fname urllib.urlretrieve(uri, fname) return fname def extract(tar, path): t = tarfile.open(tar) t.extractall(path) def check_run(args): r = subprocess.call(args) assert r == 0 def run_in(path, args): d = os.getcwd() os.chdir(path) check_run(args) os.chdir(d) def patch(patch, plevel, srcdir): patch = os.path.realpath(patch) check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0', '-s']) def build_package(package_source_dir, package_build_dir, configure_args, make = old_make): if not os.path.exists(package_build_dir): os.mkdir(package_build_dir) run_in(package_build_dir, ["%s/configure" % package_source_dir] + configure_args) run_in(package_build_dir, [make, "-j8"]) run_in(package_build_dir, [make, "install"]) def build_aux_tools(base_dir): make_build_dir = base_dir + '/make_build' build_package(make_source_dir, make_build_dir, ["--prefix=%s" % aux_inst_dir], "make") run_in(unifdef_source_dir, ["make"]) run_in(unifdef_source_dir, ["make", "prefix=%s" % aux_inst_dir, "install"]) tar_build_dir = base_dir + '/tar_build' build_package(tar_source_dir, tar_build_dir, ["--prefix=%s" % aux_inst_dir]) gawk_build_dir = base_dir + '/gawk_build' build_package(gawk_source_dir, gawk_build_dir, ["--prefix=%s" % aux_inst_dir]) def with_env(env, f): old_env = os.environ.copy() os.environ.update(env) f() os.environ.clear() os.environ.update(old_env) def build_glibc(env, stage_dir, inst_dir): def f(): build_glibc_aux(stage_dir, inst_dir) with_env(env, f) def build_glibc_aux(stage_dir, inst_dir): glibc_build_dir = stage_dir + '/glibc' build_package(glibc_source_dir, glibc_build_dir, ["--disable-profile", "--enable-add-ons=nptl", "--without-selinux", "--enable-kernel=%s" % linux_version, "--libdir=%s/lib64" % inst_dir, "--prefix=%s" % inst_dir]) def build_linux_headers_aux(inst_dir): run_in(linux_source_dir, [old_make, "headers_check"]) run_in(linux_source_dir, [old_make, "INSTALL_HDR_PATH=dest", "headers_install"]) shutil.move(linux_source_dir + "/dest/include", inst_dir + '/include') def build_linux_headers(inst_dir): def f(): build_linux_headers_aux(inst_dir) with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f) def build_gcc(stage_dir, is_stage_one): gcc_build_dir = stage_dir + '/gcc' tool_inst_dir = stage_dir + '/inst' lib_inst_dir = stage_dir + '/libinst' gcc_configure_args = ["--prefix=%s" % tool_inst_dir, "--enable-__cxa_atexit", "--with-gmp=%s" % lib_inst_dir, "--with-mpfr=%s" % lib_inst_dir, "--with-mpc=%s" % lib_inst_dir, "--enable-languages=c,c++", "--disable-lto", "--disable-multilib", "--disable-bootstrap"] if is_stage_one: # We build the stage1 gcc without shared libraries. Otherwise its # libgcc.so would depend on the system libc.so, which causes problems # when it tries to use that libgcc.so and the libc we are about to # build. gcc_configure_args.append("--disable-shared") build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args) if is_stage_one: # The glibc build system uses -lgcc_eh, but at least in this setup # libgcc.a has all it needs. d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/" os.symlink(d + "libgcc.a", d + "libgcc_eh.a") def build_one_stage(env, stage_dir, is_stage_one): def f(): build_one_stage_aux(stage_dir, is_stage_one) with_env(env, f) def build_one_stage_aux(stage_dir, is_stage_one): os.mkdir(stage_dir) lib_inst_dir = stage_dir + '/libinst' gmp_build_dir = stage_dir + '/gmp' build_package(gmp_source_dir, gmp_build_dir, ["--prefix=%s" % lib_inst_dir, "--disable-shared"]) mpfr_build_dir = stage_dir + '/mpfr' build_package(mpfr_source_dir, mpfr_build_dir, ["--prefix=%s" % lib_inst_dir, "--disable-shared", "--with-gmp=%s" % lib_inst_dir]) mpc_build_dir = stage_dir + '/mpc' build_package(mpc_source_dir, mpc_build_dir, ["--prefix=%s" % lib_inst_dir, "--disable-shared", "--with-gmp=%s" % lib_inst_dir, "--with-mpfr=%s" % lib_inst_dir]) tool_inst_dir = stage_dir + '/inst' os.mkdir(tool_inst_dir) os.mkdir(tool_inst_dir + '/lib64') os.symlink('lib64', tool_inst_dir + '/lib') build_linux_headers(tool_inst_dir) # zlib's configure only works if run from the source dir, copy the source zlib_build_dir = stage_dir + '/zlib' shutil.copytree(zlib_source_dir, zlib_build_dir) build_package(zlib_build_dir, zlib_build_dir, ["--prefix=%s" % tool_inst_dir]) binutils_build_dir = stage_dir + '/binutils' build_package(binutils_source_dir, binutils_build_dir, ["--prefix=%s" % tool_inst_dir, "--without-zlib"]) # During stage one we have to build gcc first, this glibc doesn't even # build with gcc 4.6. During stage two, we have to build glibc first. # The problem is that libstdc++ is built with xgcc and if glibc has # not been built yet xgcc will use the system one. if is_stage_one: build_gcc(stage_dir, is_stage_one) build_glibc({"CC" : tool_inst_dir + "/bin/gcc", "CXX" : tool_inst_dir + "/bin/g++"}, stage_dir, tool_inst_dir) else: build_glibc({}, stage_dir, tool_inst_dir) build_gcc(stage_dir, is_stage_one) def build_tar_package(tar, name, base, directory): name = os.path.realpath(name) run_in(base, [tar, "-cf", name, "--mtime=2012-01-01", "--owner=root", directory]) ############################################## def build_source_dir(prefix, version): return source_dir + '/' + prefix + version binutils_version = "2.21.1" glibc_version = "2.5.1" linux_version = "2.6.18" tar_version = "1.26" gawk_version = "3.1.5" make_version = "3.81" gcc_version = "4.5.2" mpfr_version = "2.4.2" zlib_version = "1.2.3" gmp_version = "5.0.1" mpc_version = "0.8.1" unifdef_version = "2.6" binutils_source_uri = "http://ftp.gnu.org/gnu/binutils/binutils-%sa.tar.bz2" % \ binutils_version glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \ glibc_version linux_source_uri = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-%s.tar.bz2" % \ linux_version tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \ tar_version gawk_source_uri = "http://ftp.gnu.org/gnu/gawk/gawk-%s.tar.bz2" % \ gawk_version make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \ make_version unifdef_source_uri = "http://dotat.at/prog/unifdef/unifdef-%s.tar.gz" % \ unifdef_version gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \ (gcc_version, gcc_version) mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \ (mpfr_version, mpfr_version) zlib_source_uri = "http://iweb.dl.sourceforge.net/project/libpng/zlib/%s/zlib-%s.tar.bz2" % (zlib_version, zlib_version) gmp_source_uri = "http://ftp.gnu.org/gnu/gmp/gmp-%s.tar.bz2" % gmp_version mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \ mpc_version binutils_source_tar = download_uri(binutils_source_uri) glibc_source_tar = download_uri(glibc_source_uri) linux_source_tar = download_uri(linux_source_uri) tar_source_tar = download_uri(tar_source_uri) gawk_source_tar = download_uri(gawk_source_uri) make_source_tar = download_uri(make_source_uri) unifdef_source_tar = download_uri(unifdef_source_uri) mpc_source_tar = download_uri(mpc_source_uri) mpfr_source_tar = download_uri(mpfr_source_uri) zlib_source_tar = download_uri(zlib_source_uri) gmp_source_tar = download_uri(gmp_source_uri) gcc_source_tar = download_uri(gcc_source_uri) binutils_source_dir = build_source_dir('binutils-', binutils_version) glibc_source_dir = build_source_dir('glibc-', glibc_version) linux_source_dir = build_source_dir('linux-', linux_version) tar_source_dir = build_source_dir('tar-', tar_version) gawk_source_dir = build_source_dir('gawk-', gawk_version) make_source_dir = build_source_dir('make-', make_version) unifdef_source_dir = build_source_dir('unifdef-', unifdef_version) mpc_source_dir = build_source_dir('mpc-', mpc_version) mpfr_source_dir = build_source_dir('mpfr-', mpfr_version) zlib_source_dir = build_source_dir('zlib-', zlib_version) gmp_source_dir = build_source_dir('gmp-', gmp_version) gcc_source_dir = build_source_dir('gcc-', gcc_version) if not os.path.exists(source_dir): os.makedirs(source_dir) extract(binutils_source_tar, source_dir) patch('binutils-deterministic.patch', 1, binutils_source_dir) extract(glibc_source_tar, source_dir) extract(linux_source_tar, source_dir) patch('glibc-deterministic.patch', 1, glibc_source_dir) run_in(glibc_source_dir, ["autoconf"]) extract(tar_source_tar, source_dir) extract(gawk_source_tar, source_dir) extract(make_source_tar, source_dir) extract(unifdef_source_tar, source_dir) extract(mpc_source_tar, source_dir) extract(mpfr_source_tar, source_dir) extract(zlib_source_tar, source_dir) extract(gmp_source_tar, source_dir) extract(gcc_source_tar, source_dir) patch('plugin_finish_decl.diff', 0, gcc_source_dir) patch('libtool-74c8993c178a1386ea5e2363a01d919738402f30.patch', 1, gcc_source_dir) patch('pr49911.diff', 1, gcc_source_dir) patch('r159628-r163231-r171807.patch', 1, gcc_source_dir) patch('gcc-fixinc.patch', 1, gcc_source_dir) patch('gcc-include.patch', 1, gcc_source_dir) if os.path.exists(build_dir): shutil.rmtree(build_dir) os.makedirs(build_dir) build_aux_tools(build_dir) basic_path = aux_inst_dir + "/bin:/bin:/usr/bin" stage1_dir = build_dir + '/stage1' build_one_stage({"PATH" : basic_path, "CC" : "gcc", "CXX" : "g++" }, stage1_dir, True) for stage_num in range(2, 4): prev_stage_dir = build_dir + '/stage' + str(stage_num - 1) prev_stage_inst_dir = prev_stage_dir + '/inst' cur_stage_dir = build_dir + '/stage' + str(stage_num) build_one_stage({"PATH" : prev_stage_inst_dir + "/bin:" + basic_path, "CC" : "gcc -fgnu89-inline", "CXX" : "g++", "RANLIB" : "true" }, cur_stage_dir, False) stage3_dir = build_dir + '/stage3' build_tar_package(aux_inst_dir + "/bin/tar", "toolchain.tar", stage3_dir, "inst")