| author | wenzelm | 
| Sun, 11 Feb 2018 15:03:25 +0100 | |
| changeset 67600 | d515b6140381 | 
| parent 67599 | 544a0293cadc | 
| child 67609 | 738b4d4eeb61 | 
| permissions | -rw-r--r-- | 
| 64483 | 1 | /* Title: Pure/Admin/build_polyml.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Build Poly/ML from sources. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 10 | object Build_PolyML | |
| 11 | {
 | |
| 65880 | 12 | /** platform-specific build **/ | 
| 64496 | 13 | |
| 64483 | 14 | sealed case class Platform_Info( | 
| 15 | options: List[String] = Nil, | |
| 16 | options_multilib: List[String] = Nil, | |
| 64487 | 17 | setup: String = "", | 
| 64483 | 18 | copy_files: List[String] = Nil) | 
| 67598 | 19 |   {
 | 
| 20 | def platform_options(arch_64: Boolean): List[String] = | |
| 21 |       if (!arch_64 && Isabelle_System.getenv("ISABELLE_PLATFORM64") == "x86_64-linux")
 | |
| 22 | options_multilib | |
| 23 | else options | |
| 24 | } | |
| 64483 | 25 | |
| 26 | private val platform_info = Map( | |
| 27 | "x86-linux" -> | |
| 28 | Platform_Info( | |
| 29 | options_multilib = | |
| 67580 
eb64467e8bcf
more robust access to shared libraries for poly executable: avoid global change of LD_LIBRARY_PATH (e.g. relevant for subprocesses);
 wenzelm parents: 
66998diff
changeset | 30 |           List("--build=i386", "CFLAGS=-m32 -O3", "CXXFLAGS=-m32 -O3", "CCASFLAGS=-m32",
 | 
| 67597 | 31 | "LDFLAGS=-Wl,-rpath,_DUMMY_", "--enable-shared", "--without-gmp"), | 
| 32 |         options = List("LDFLAGS=-Wl,-rpath,_DUMMY_", "--enable-shared")),
 | |
| 67580 
eb64467e8bcf
more robust access to shared libraries for poly executable: avoid global change of LD_LIBRARY_PATH (e.g. relevant for subprocesses);
 wenzelm parents: 
66998diff
changeset | 33 | "x86_64-linux" -> | 
| 
eb64467e8bcf
more robust access to shared libraries for poly executable: avoid global change of LD_LIBRARY_PATH (e.g. relevant for subprocesses);
 wenzelm parents: 
66998diff
changeset | 34 | Platform_Info( | 
| 67597 | 35 |         options = List("LDFLAGS=-Wl,-rpath,_DUMMY_", "--enable-shared")),
 | 
| 64483 | 36 | "x86-darwin" -> | 
| 37 | Platform_Info( | |
| 38 | options = | |
| 64484 | 39 |           List("--build=i686-darwin", "CFLAGS=-arch i686 -O3 -I../libffi/include",
 | 
| 40 | "CXXFLAGS=-arch i686 -O3 -I../libffi/include", "CCASFLAGS=-arch i686 -O3", | |
| 67597 | 41 | "LDFLAGS=-segprot POLY rwx rwx -L/usr/local/lib32"), | 
| 64503 
365021be3c5b
clarified setup: avoid alternative C compiler tools, e.g. from Homebrew or MacPorts;
 wenzelm parents: 
64502diff
changeset | 42 | setup = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"), | 
| 64483 | 43 | "x86_64-darwin" -> | 
| 44 | Platform_Info( | |
| 45 | options = | |
| 64484 | 46 |           List("--build=x86_64-darwin", "CFLAGS=-arch x86_64 -O3 -I../libffi/include",
 | 
| 47 | "CXXFLAGS=-arch x86_64 -O3 -I../libffi/include", "CCASFLAGS=-arch x86_64", | |
| 67600 
d515b6140381
no --enable-shared for x86_64-darwin: does not work on some test machine;
 wenzelm parents: 
67599diff
changeset | 48 | "LDFLAGS=-segprot POLY rwx rwx"), | 
| 64503 
365021be3c5b
clarified setup: avoid alternative C compiler tools, e.g. from Homebrew or MacPorts;
 wenzelm parents: 
64502diff
changeset | 49 | setup = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"), | 
| 64483 | 50 | "x86-windows" -> | 
| 51 | Platform_Info( | |
| 52 | options = | |
| 67597 | 53 |           List("--host=i686-w32-mingw32", "CPPFLAGS=-I/mingw32/include", "--disable-windows-gui"),
 | 
| 64494 | 54 | setup = | 
| 55 | """PATH=/usr/bin:/bin:/mingw32/bin | |
| 56 | export CONFIG_SITE=/etc/config.site""", | |
| 64483 | 57 | copy_files = | 
| 64504 | 58 |           List("$MSYS/mingw32/bin/libgcc_s_dw2-1.dll",
 | 
| 59 | "$MSYS/mingw32/bin/libgmp-10.dll", | |
| 60 | "$MSYS/mingw32/bin/libstdc++-6.dll")), | |
| 64483 | 61 | "x86_64-windows" -> | 
| 62 | Platform_Info( | |
| 63 | options = | |
| 67597 | 64 |           List("--host=x86_64-w64-mingw32", "CPPFLAGS=-I/mingw64/include", "--disable-windows-gui"),
 | 
| 64494 | 65 | setup = | 
| 66 | """PATH=/usr/bin:/bin:/mingw64/bin | |
| 67 | export CONFIG_SITE=/etc/config.site""", | |
| 64483 | 68 | copy_files = | 
| 64504 | 69 |           List("$MSYS/mingw64/bin/libgcc_s_seh-1.dll",
 | 
| 70 | "$MSYS/mingw64/bin/libgmp-10.dll", | |
| 71 | "$MSYS/mingw64/bin/libstdc++-6.dll"))) | |
| 64483 | 72 | |
| 73 | def build_polyml( | |
| 64489 | 74 | root: Path, | 
| 64495 | 75 | sha1_root: Option[Path] = None, | 
| 64909 | 76 | progress: Progress = No_Progress, | 
| 64493 | 77 | arch_64: Boolean = false, | 
| 64485 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 78 | options: List[String] = Nil, | 
| 65880 | 79 | msys_root: Option[Path] = None) | 
| 64483 | 80 |   {
 | 
| 64489 | 81 |     if (!((root + Path.explode("configure")).is_file && (root + Path.explode("PolyML")).is_dir))
 | 
| 82 |       error("Bad Poly/ML root directory: " + root)
 | |
| 64483 | 83 | |
| 64493 | 84 | val platform = | 
| 85 | (if (arch_64) "x86_64" else "x86") + | |
| 86 | (if (Platform.is_windows) "-windows" else if (Platform.is_macos) "-darwin" else "-linux") | |
| 87 | ||
| 64483 | 88 | val info = | 
| 89 | platform_info.get(platform) getOrElse | |
| 90 |         error("Bad platform identifier: " + quote(platform))
 | |
| 91 | ||
| 64504 | 92 | val settings = | 
| 93 |       msys_root match {
 | |
| 94 | case None if Platform.is_windows => | |
| 95 |           error("Windows requires specification of msys root directory")
 | |
| 96 | case None => Isabelle_System.settings() | |
| 97 |         case Some(msys) => Isabelle_System.settings() + ("MSYS" -> msys.expand.implode)
 | |
| 98 | } | |
| 64492 | 99 | |
| 64491 | 100 | |
| 64495 | 101 | /* bash */ | 
| 102 | ||
| 64504 | 103 | def bash( | 
| 104 | cwd: Path, script: String, redirect: Boolean = false, echo: Boolean = false): Process_Result = | |
| 105 |     {
 | |
| 106 | val script1 = | |
| 107 |         msys_root match {
 | |
| 108 | case None => script | |
| 109 | case Some(msys) => | |
| 110 |             File.bash_path(msys + Path.explode("usr/bin/bash")) + " -c " + Bash.string(script)
 | |
| 111 | } | |
| 112 | progress.bash(script1, cwd = cwd.file, redirect = redirect, echo = echo) | |
| 113 | } | |
| 64495 | 114 | |
| 115 | ||
| 64491 | 116 | /* configure and make */ | 
| 117 | ||
| 64483 | 118 | val configure_options = | 
| 67598 | 119 |       List("--enable-intinf-as-int", "--with-gmp") ::: info.platform_options(arch_64) ::: options
 | 
| 64483 | 120 | |
| 64495 | 121 | bash(root, | 
| 64487 | 122 | info.setup + "\n" + | 
| 64485 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 123 | """ | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 124 | [ -f Makefile ] && make distclean | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 125 |         {
 | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 126 | ./configure --prefix="$PWD/target" """ + Bash.strings(configure_options) + """ | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 127 | rm -rf target | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 128 | make compiler && make compiler && make install | 
| 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 129 |         } || { echo "Build failed" >&2; exit 2; }
 | 
| 64501 | 130 | """, redirect = true, echo = true).check | 
| 64485 
e996c0a5eca9
support other bash executable (notably for msys on Windows);
 wenzelm parents: 
64484diff
changeset | 131 | |
| 64495 | 132 | val ldd_files = | 
| 66998 | 133 |     {
 | 
| 134 | val ldd_pattern = | |
| 135 |         if (Platform.is_linux) Some(("ldd", """\s*libgmp.*=>\s*(\S+).*""".r))
 | |
| 67592 
66253039d5ca
enforce shared libpoly on all platforms, with File.copy before File.move;
 wenzelm parents: 
67589diff
changeset | 136 |         else if (Platform.is_macos) Some(("otool -L", """\s*(\S+lib(?:polyml|gmp).*dylib).*""".r))
 | 
| 66998 | 137 | else None | 
| 138 |       ldd_pattern match {
 | |
| 139 | case Some((ldd, pattern)) => | |
| 140 | val lines = bash(root, ldd + " target/bin/poly").check.out_lines | |
| 141 |           for { line <- lines; List(lib) <- pattern.unapplySeq(line) } yield lib
 | |
| 142 | case None => Nil | |
| 64491 | 143 | } | 
| 66998 | 144 | } | 
| 64491 | 145 | |
| 146 | ||
| 64495 | 147 | /* sha1 library */ | 
| 148 | ||
| 149 | val sha1_files = | |
| 150 |       if (sha1_root.isDefined) {
 | |
| 151 | val dir1 = sha1_root.get | |
| 64501 | 152 | bash(dir1, "./build " + platform, redirect = true, echo = true).check | 
| 64505 | 153 | |
| 64495 | 154 | val dir2 = dir1 + Path.explode(platform) | 
| 155 | File.read_dir(dir2).map(entry => dir2.implode + "/" + entry) | |
| 156 | } | |
| 157 | else Nil | |
| 158 | ||
| 159 | ||
| 64491 | 160 | /* target */ | 
| 64484 | 161 | |
| 65880 | 162 | val target = Path.explode(platform) | 
| 64488 | 163 | Isabelle_System.rm_tree(target) | 
| 64483 | 164 | Isabelle_System.mkdirs(target) | 
| 165 | ||
| 67592 
66253039d5ca
enforce shared libpoly on all platforms, with File.copy before File.move;
 wenzelm parents: 
67589diff
changeset | 166 | for (file <- info.copy_files ::: ldd_files ::: sha1_files) | 
| 
66253039d5ca
enforce shared libpoly on all platforms, with File.copy before File.move;
 wenzelm parents: 
67589diff
changeset | 167 | File.copy(Path.explode(file).expand_env(settings), target) | 
| 
66253039d5ca
enforce shared libpoly on all platforms, with File.copy before File.move;
 wenzelm parents: 
67589diff
changeset | 168 | |
| 64483 | 169 |     for {
 | 
| 64484 | 170 |       d <- List("target/bin", "target/lib")
 | 
| 64489 | 171 | dir = root + Path.explode(d) | 
| 64483 | 172 | entry <- File.read_dir(dir) | 
| 173 | } File.move(dir + Path.explode(entry), target) | |
| 174 | ||
| 67580 
eb64467e8bcf
more robust access to shared libraries for poly executable: avoid global change of LD_LIBRARY_PATH (e.g. relevant for subprocesses);
 wenzelm parents: 
66998diff
changeset | 175 | |
| 67584 | 176 | /* poly: library path */ | 
| 67580 
eb64467e8bcf
more robust access to shared libraries for poly executable: avoid global change of LD_LIBRARY_PATH (e.g. relevant for subprocesses);
 wenzelm parents: 
66998diff
changeset | 177 | |
| 67582 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 178 |     if (Platform.is_linux) {
 | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 179 | bash(target, "chrpath -r '$ORIGIN' poly", echo = true).check | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 180 | } | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 181 |     else if (Platform.is_macos) {
 | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 182 |       for (file <- ldd_files) {
 | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 183 | bash(target, | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 184 | """install_name_tool -change """ + Bash.string(file) + " " + | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 185 |             Bash.string("@executable_path/" + Path.explode(file).base_name) + " poly").check
 | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 186 | } | 
| 
bf5c69acf2be
built-in library path for (optional) libgmp on macos;
 wenzelm parents: 
67581diff
changeset | 187 | } | 
| 67584 | 188 | |
| 189 | ||
| 190 | /* polyc: directory prefix */ | |
| 191 | ||
| 192 |     {
 | |
| 193 |       val polyc_path = target + Path.explode("polyc")
 | |
| 67587 | 194 | |
| 195 | val Header = "#! */bin/sh".r | |
| 67584 | 196 | val polyc_patched = | 
| 197 |         split_lines(File.read(polyc_path)) match {
 | |
| 67587 | 198 | case Header() :: lines => | 
| 199 | val lines1 = | |
| 200 | lines.map(line => | |
| 201 |                 if (line.startsWith("prefix=")) "prefix=\"$(cd \"$(dirname \"$0\")\"; pwd)\""
 | |
| 202 |                 else if (line.startsWith("BINDIR=")) "BINDIR=\"$prefix\""
 | |
| 67584 | 203 |                 else if (line.startsWith("LIBDIR=")) "LIBDIR=\"$prefix\""
 | 
| 204 | else line) | |
| 67587 | 205 |             cat_lines("#!/usr/bin/env bash" ::lines1)
 | 
| 67584 | 206 | case lines => | 
| 67587 | 207 |             error(cat_lines("Cannot patch polyc -- undetected header:" :: lines.take(3)))
 | 
| 67584 | 208 | } | 
| 209 | File.write(polyc_path, polyc_patched) | |
| 210 | } | |
| 64483 | 211 | } | 
| 212 | ||
| 213 | ||
| 64496 | 214 | |
| 65880 | 215 | /** skeleton for component **/ | 
| 216 | ||
| 217 | def build_polyml_component(component: Path, sha1_root: Option[Path] = None) | |
| 218 |   {
 | |
| 219 |     if (component.is_dir) error("Directory already exists: " + component)
 | |
| 220 | ||
| 221 |     val etc = component + Path.explode("etc")
 | |
| 222 | Isabelle_System.mkdirs(etc) | |
| 223 |     File.copy(Path.explode("~~/Admin/polyml/settings"), etc)
 | |
| 224 |     File.copy(Path.explode("~~/Admin/polyml/README"), component)
 | |
| 64483 | 225 | |
| 65880 | 226 |     sha1_root match {
 | 
| 227 | case Some(dir) => | |
| 67599 | 228 |         Mercurial.repository(dir).archive(File.standard_path(component + Path.explode("sha1")))
 | 
| 65880 | 229 | case None => | 
| 230 | } | |
| 231 | } | |
| 232 | ||
| 233 | ||
| 234 | ||
| 235 | /** Isabelle tool wrappers **/ | |
| 236 | ||
| 237 | val isabelle_tool1 = | |
| 238 |     Isabelle_Tool("build_polyml", "build Poly/ML from sources", args =>
 | |
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 239 |     {
 | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 240 |       Command_Line.tool0 {
 | 
| 64504 | 241 | var msys_root: Option[Path] = None | 
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 242 | var arch_64 = false | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 243 | var sha1_root: Option[Path] = None | 
| 64483 | 244 | |
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 245 |         val getopts = Getopts("""
 | 
| 64489 | 246 | Usage: isabelle build_polyml [OPTIONS] ROOT [CONFIGURE_OPTIONS] | 
| 64483 | 247 | |
| 248 | Options are: | |
| 64504 | 249 | -M DIR msys root directory (for Windows) | 
| 64493 | 250 | -m ARCH processor architecture (32=x86, 64=x86_64, default: x86) | 
| 64499 | 251 | -s DIR sha1 sources, see https://bitbucket.org/isabelle_project/sha1 | 
| 64483 | 252 | |
| 64499 | 253 | Build Poly/ML in the ROOT directory of its sources, with additional | 
| 67593 | 254 | CONFIGURE_OPTIONS (e.g. --without-gmp). | 
| 64483 | 255 | """, | 
| 64504 | 256 | "M:" -> (arg => msys_root = Some(Path.explode(arg))), | 
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 257 | "m:" -> | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 258 |             {
 | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 259 | case "32" | "x86" => arch_64 = false | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 260 | case "64" | "x86_64" => arch_64 = true | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 261 |               case bad => error("Bad processor architecture: " + quote(bad))
 | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 262 | }, | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 263 | "s:" -> (arg => sha1_root = Some(Path.explode(arg)))) | 
| 64483 | 264 | |
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 265 | val more_args = getopts(args) | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 266 | val (root, options) = | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 267 |           more_args match {
 | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 268 | case root :: options => (Path.explode(root), options) | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 269 | case Nil => getopts.usage() | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 270 | } | 
| 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 271 | build_polyml(root, sha1_root = sha1_root, progress = new Console_Progress, | 
| 65880 | 272 | arch_64 = arch_64, options = options, msys_root = msys_root) | 
| 273 | } | |
| 274 | }, admin = true) | |
| 275 | ||
| 276 | val isabelle_tool2 = | |
| 277 |     Isabelle_Tool("build_polyml_component", "make skeleton for Poly/ML component", args =>
 | |
| 278 |     {
 | |
| 279 |       Command_Line.tool0 {
 | |
| 280 | var sha1_root: Option[Path] = None | |
| 281 | ||
| 282 |         val getopts = Getopts("""
 | |
| 283 | Usage: isabelle build_polyml_component [OPTIONS] TARGET | |
| 284 | ||
| 285 | Options are: | |
| 286 | -s DIR sha1 sources, see https://bitbucket.org/isabelle_project/sha1 | |
| 287 | ||
| 288 | Make skeleton for Poly/ML component in directory TARGET. | |
| 289 | """, | |
| 290 | "s:" -> (arg => sha1_root = Some(Path.explode(arg)))) | |
| 291 | ||
| 292 | val more_args = getopts(args) | |
| 293 | val component = | |
| 294 |           more_args match {
 | |
| 295 | case List(arg) => Path.explode(arg) | |
| 296 | case _ => getopts.usage() | |
| 297 | } | |
| 298 | build_polyml_component(component, sha1_root = sha1_root) | |
| 64500 
159ea1055b39
back to regular Isabelle tool (reverting abc34a149690);
 wenzelm parents: 
64499diff
changeset | 299 | } | 
| 64502 | 300 | }, admin = true) | 
| 64483 | 301 | } |