Back to index

enigmail  1.4.3
build-gcc.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 # The directories end up in the debug info, so the easy way of getting
00004 # a reproducible build is to run it in a know absolute directory.
00005 # We use a directory in /builds/slave because the mozilla infrastructure
00006 # cleans it up automatically.
00007 base_dir = "/builds/slave/moz-toolchain"
00008 
00009 source_dir = base_dir + "/src"
00010 build_dir  = base_dir + "/build"
00011 aux_inst_dir = build_dir + '/aux_inst'
00012 old_make = aux_inst_dir + '/bin/make'
00013 
00014 ##############################################
00015 
00016 import urllib
00017 import os
00018 import os.path
00019 import shutil
00020 import tarfile
00021 import subprocess
00022 
00023 def download_uri(uri):
00024     fname = uri.split('/')[-1]
00025     if (os.path.exists(fname)):
00026         return fname
00027     urllib.urlretrieve(uri, fname)
00028     return fname
00029 
00030 def extract(tar, path):
00031     t = tarfile.open(tar)
00032     t.extractall(path)
00033 
00034 def check_run(args):
00035     r = subprocess.call(args)
00036     assert r == 0
00037 
00038 def run_in(path, args):
00039     d = os.getcwd()
00040     os.chdir(path)
00041     check_run(args)
00042     os.chdir(d)
00043 
00044 def patch(patch, plevel, srcdir):
00045     patch = os.path.realpath(patch)
00046     check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0',
00047                '-s'])
00048 
00049 def build_package(package_source_dir, package_build_dir, configure_args,
00050                    make = old_make):
00051     os.mkdir(package_build_dir)
00052     run_in(package_build_dir,
00053            ["%s/configure" % package_source_dir] + configure_args)
00054     run_in(package_build_dir, [make, "-j8"])
00055     run_in(package_build_dir, [make, "install"])
00056 
00057 def build_aux_tools(base_dir):
00058     make_build_dir = base_dir + '/make_build'
00059     build_package(make_source_dir, make_build_dir,
00060                   ["--prefix=%s" % aux_inst_dir], "make")
00061 
00062     run_in(unifdef_source_dir, ["make"])
00063     run_in(unifdef_source_dir, ["make", "prefix=%s" % aux_inst_dir, "install"])
00064 
00065     tar_build_dir = base_dir + '/tar_build'
00066     build_package(tar_source_dir, tar_build_dir,
00067                   ["--prefix=%s" % aux_inst_dir])
00068 
00069 def with_env(env, f):
00070     old_env = os.environ.copy()
00071     os.environ.update(env)
00072     f()
00073     os.environ.clear()
00074     os.environ.update(old_env)
00075 
00076 def build_glibc(env, stage_dir, inst_dir):
00077     def f():
00078         build_glibc_aux(stage_dir, inst_dir)
00079     with_env(env, f)
00080 
00081 def build_glibc_aux(stage_dir, inst_dir):
00082     glibc_build_dir = stage_dir + '/glibc'
00083     build_package(glibc_source_dir, glibc_build_dir,
00084                   ["--disable-profile",
00085                    "--enable-add-ons=nptl",
00086                    "--without-selinux",
00087                    "--enable-kernel=%s" % linux_version,
00088                    "--libdir=%s/lib64" % inst_dir,
00089                    "--prefix=%s" % inst_dir])
00090 
00091 def build_linux_headers_aux(inst_dir):
00092     run_in(linux_source_dir, [old_make, "headers_check"])
00093     run_in(linux_source_dir, [old_make, "INSTALL_HDR_PATH=dest",
00094                                "headers_install"])
00095     shutil.move(linux_source_dir + "/dest", inst_dir)
00096 
00097 def build_linux_headers(inst_dir):
00098     def f():
00099         build_linux_headers_aux(inst_dir)
00100     with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f)
00101 
00102 def build_gcc(stage_dir, is_stage_one):
00103     gcc_build_dir = stage_dir + '/gcc'
00104     tool_inst_dir = stage_dir + '/inst'
00105     lib_inst_dir = stage_dir + '/libinst'
00106     gcc_configure_args = ["--prefix=%s" % tool_inst_dir,
00107                           "--enable-__cxa_atexit",
00108                           "--with-gmp=%s" % lib_inst_dir,
00109                           "--with-mpfr=%s" % lib_inst_dir,
00110                           "--with-mpc=%s" % lib_inst_dir,
00111                           "--enable-languages=c,c++",
00112                           "--disable-multilib",
00113                           "--disable-bootstrap"]
00114     if is_stage_one:
00115         # We build the stage1 gcc without shared libraries. Otherwise its
00116         # libgcc.so would depend on the system libc.so, which causes problems
00117         # when it tries to use that libgcc.so and the libc we are about to
00118         # build.
00119         gcc_configure_args.append("--disable-shared")
00120 
00121     build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args)
00122 
00123     if is_stage_one:
00124         # The glibc build system uses -lgcc_eh, but at least in this setup
00125         # libgcc.a has all it needs.
00126         d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/"
00127         os.symlink(d + "libgcc.a", d + "libgcc_eh.a")
00128 
00129 def build_one_stage(env, stage_dir, is_stage_one):
00130     def f():
00131         build_one_stage_aux(stage_dir, is_stage_one)
00132     with_env(env, f)
00133 
00134 def build_one_stage_aux(stage_dir, is_stage_one):
00135     os.mkdir(stage_dir)
00136 
00137     lib_inst_dir = stage_dir + '/libinst'
00138 
00139     gmp_build_dir = stage_dir + '/gmp'
00140     build_package(gmp_source_dir, gmp_build_dir,
00141                   ["--prefix=%s" % lib_inst_dir, "--disable-shared"])
00142     mpfr_build_dir = stage_dir + '/mpfr'
00143     build_package(mpfr_source_dir, mpfr_build_dir,
00144                   ["--prefix=%s" % lib_inst_dir, "--disable-shared",
00145                    "--with-gmp=%s" % lib_inst_dir])
00146     mpc_build_dir = stage_dir + '/mpc'
00147     build_package(mpc_source_dir, mpc_build_dir,
00148                   ["--prefix=%s" % lib_inst_dir, "--disable-shared",
00149                    "--with-gmp=%s" % lib_inst_dir,
00150                    "--with-mpfr=%s" % lib_inst_dir])
00151 
00152     tool_inst_dir = stage_dir + '/inst'
00153     build_linux_headers(tool_inst_dir)
00154 
00155     binutils_build_dir = stage_dir + '/binutils'
00156     build_package(binutils_source_dir, binutils_build_dir,
00157                   ["--prefix=%s" % tool_inst_dir])
00158 
00159     # During stage one we have to build gcc first, this glibc doesn't even
00160     # build with gcc 4.6. During stage two, we have to build glibc first.
00161     # The problem is that libstdc++ is built with xgcc and if glibc has
00162     # not been built yet xgcc will use the system one.
00163     if is_stage_one:
00164         build_gcc(stage_dir, is_stage_one)
00165         build_glibc({"CC"  : tool_inst_dir + "/bin/gcc",
00166                      "CXX" : tool_inst_dir + "/bin/g++"},
00167                     stage_dir, tool_inst_dir)
00168     else:
00169         build_glibc({}, stage_dir, tool_inst_dir)
00170         build_gcc(stage_dir, is_stage_one)
00171 
00172 def build_tar_package(tar, name, base, directory):
00173     name = os.path.realpath(name)
00174     run_in(base, [tar, "-cf", name, "--mtime=2012-01-01", "--owner=root",
00175                   directory])
00176 
00177 ##############################################
00178 
00179 def build_source_dir(prefix, version):
00180     return source_dir + '/' + prefix + version
00181 
00182 binutils_version = "2.21.1"
00183 glibc_version = "2.5.1"
00184 linux_version = "2.6.18"
00185 tar_version = "1.26"
00186 make_version = "3.81"
00187 gcc_version = "4.5.2"
00188 mpfr_version = "2.4.2"
00189 gmp_version = "5.0.1"
00190 mpc_version = "0.8.1"
00191 unifdef_version = "2.6"
00192 
00193 binutils_source_uri = "http://ftp.gnu.org/gnu/binutils/binutils-%sa.tar.bz2" % \
00194     binutils_version
00195 glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \
00196     glibc_version
00197 linux_source_uri = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-%s.tar.bz2" % \
00198     linux_version
00199 tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \
00200     tar_version
00201 make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \
00202     make_version
00203 unifdef_source_uri = "http://dotat.at/prog/unifdef/unifdef-%s.tar.gz" % \
00204     unifdef_version
00205 gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \
00206     (gcc_version, gcc_version)
00207 mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \
00208     (mpfr_version, mpfr_version)
00209 gmp_source_uri = "http://ftp.gnu.org/gnu/gmp/gmp-%s.tar.bz2" % gmp_version
00210 mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \
00211     mpc_version
00212 
00213 binutils_source_tar = download_uri(binutils_source_uri)
00214 glibc_source_tar = download_uri(glibc_source_uri)
00215 linux_source_tar = download_uri(linux_source_uri)
00216 tar_source_tar = download_uri(tar_source_uri)
00217 make_source_tar = download_uri(make_source_uri)
00218 unifdef_source_tar = download_uri(unifdef_source_uri)
00219 mpc_source_tar = download_uri(mpc_source_uri)
00220 mpfr_source_tar = download_uri(mpfr_source_uri)
00221 gmp_source_tar = download_uri(gmp_source_uri)
00222 gcc_source_tar = download_uri(gcc_source_uri)
00223 
00224 binutils_source_dir  = build_source_dir('binutils-', binutils_version)
00225 glibc_source_dir  = build_source_dir('glibc-', glibc_version)
00226 linux_source_dir  = build_source_dir('linux-', linux_version)
00227 tar_source_dir  = build_source_dir('tar-', tar_version)
00228 make_source_dir  = build_source_dir('make-', make_version)
00229 unifdef_source_dir  = build_source_dir('unifdef-', unifdef_version)
00230 mpc_source_dir  = build_source_dir('mpc-', mpc_version)
00231 mpfr_source_dir = build_source_dir('mpfr-', mpfr_version)
00232 gmp_source_dir  = build_source_dir('gmp-', gmp_version)
00233 gcc_source_dir  = build_source_dir('gcc-', gcc_version)
00234 
00235 if not os.path.exists(source_dir):
00236     os.makedirs(source_dir)
00237     extract(binutils_source_tar, source_dir)
00238     patch('binutils-deterministic.patch', 1, binutils_source_dir)
00239     extract(glibc_source_tar, source_dir)
00240     extract(linux_source_tar, source_dir)
00241     patch('glibc-deterministic.patch', 1, glibc_source_dir)
00242     run_in(glibc_source_dir, ["autoconf"])
00243     extract(tar_source_tar, source_dir)
00244     extract(make_source_tar, source_dir)
00245     extract(unifdef_source_tar, source_dir)
00246     extract(mpc_source_tar, source_dir)
00247     extract(mpfr_source_tar, source_dir)
00248     extract(gmp_source_tar, source_dir)
00249     extract(gcc_source_tar, source_dir)
00250     patch('plugin_finish_decl.diff', 0, gcc_source_dir)
00251     patch('pr49911.diff', 1, gcc_source_dir)
00252     patch('r159628-r163231-r171807.patch', 1, gcc_source_dir)
00253     patch('gcc-fixinc.patch', 1, gcc_source_dir)
00254     patch('gcc-include.patch', 1, gcc_source_dir)
00255 
00256 if os.path.exists(build_dir):
00257     shutil.rmtree(build_dir)
00258 os.makedirs(build_dir)
00259 
00260 build_aux_tools(build_dir)
00261 
00262 stage1_dir = build_dir + '/stage1'
00263 build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
00264 
00265 stage1_tool_inst_dir = stage1_dir + '/inst'
00266 stage2_dir = build_dir + '/stage2'
00267 build_one_stage({"CC"     : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
00268                  "CXX"    : stage1_tool_inst_dir + "/bin/g++",
00269                  "AR"     : stage1_tool_inst_dir + "/bin/ar",
00270                  "RANLIB" : "true" },
00271                 stage2_dir, False)
00272 
00273 build_tar_package(aux_inst_dir + "/bin/tar",
00274                   "toolchain.tar", stage2_dir, "inst")