]> git.donarmstrong.com Git - lilypond.git/blob - lily/main.cc
Doc: Included/compile.itexi - CG 4.2 - Updated notes on reqs for compiling
[lilypond.git] / lily / main.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "main.hh"
21 #include "lily-guile.hh"
22
23 #include <cassert>
24 #include <clocale>
25 #include <cstring>
26 #include <cerrno>
27 #include <cstdio>
28
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include "config.hh"
32
33 #if HAVE_GRP_H
34 #include <grp.h>
35 #endif
36 #if HAVE_PWD_H
37 #include <pwd.h>
38 #endif
39 #if HAVE_GETTEXT
40 #include <libintl.h>
41 #endif
42
43 #include "all-font-metrics.hh"
44 #include "file-name.hh"
45 #include "freetype.hh"
46 #include "getopt-long.hh"
47 #include "global-ctor.hh"
48 #include "international.hh"
49 #include "lily-version.hh"
50 #include "misc.hh"
51 #include "output-def.hh"
52 #include "program-option.hh"
53 #include "relocate.hh"
54 #include "string-convert.hh"
55 #include "version.hh"
56 #include "warn.hh"
57 #include "lily-imports.hh"
58
59 /*
60  * Global options that can be overridden through command line.
61  */
62
63 /* Names of header fields to be dumped to a separate file. */
64 //vector<string> dump_header_fieldnames_global; // moved to global-data.cc
65
66 /* Name of initialisation file. */
67 //string init_name_global; // moved to global-data.cc
68
69 /* Output formats to generate.  */
70 //string output_format_global = ""; // moved to global-data.cc
71
72 /* Current output name. */
73 //string output_name_global; // moved to global-data.cc
74
75 /* Run in safe mode? */
76 //bool be_safe_global = false; // moved to global-data.cc
77
78 /* Provide URI links to the original file */
79 bool point_and_click_global = true;
80
81 /* Scheme code to execute before parsing, after .scm init.
82    This is where -e arguments are appended to.  */
83 //string init_scheme_code_global; // moved to global-data.cc
84 //string init_scheme_variables_global; // moved to global-data.cc
85
86 //bool relocate_binary = true; // moved to global-data.cc
87
88 /*
89  * Miscellaneous global stuff.
90  */
91 //File_path global_path; // moved to global-data.cc
92
93 /*
94  * File globals.
95  */
96
97 static char const *AUTHORS
98   = "  Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
99     "  Jan Nieuwenhuizen <janneke@gnu.org>\n";
100
101 static char const *PROGRAM_NAME = "lilypond";
102 static char const *PROGRAM_URL = "http://lilypond.org";
103
104 static char const *NOTICE
105   = _i ("This program is free software.  It is covered by the GNU General Public\n"
106         "License and you are welcome to change it and/or distribute copies of it\n"
107         "under certain conditions.  Invoke as `%s --warranty' for more\n"
108         "information.\n");
109
110 static char const *WARRANTY
111   = _i ("    This program is free software; you can redistribute it and/or\n"
112         "modify it under the terms of the GNU General Public License as \n"
113         "published by the Free Software Foundation, either version 3 of\n"
114         "the License, or (at your option) any later version.\n"
115         "\n"
116         "    This program is distributed in the hope that it will be useful,\n"
117         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
118         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
119         "General Public License for more details.\n"
120         "\n"
121         "    You should have received a copy of the\n"
122         "GNU General Public License along with this program; if not, write to\n"
123         "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
124         "Boston, MA 02111-1307, USA.\n");
125
126 /* Where the init files live.  Typically:
127    LILYPOND_DATADIR = /usr/share/lilypond
128 */
129 //string lilypond_datadir; // moved to global-data.cc
130
131 /* The jail specification: USER, GROUP, JAIL, DIR. */
132 std::string jail_spec;
133
134 /*  The option parser */
135 static Getopt_long *option_parser = 0;
136
137 /* Internationalisation kludge in two steps:
138  * use _i () to get entry in POT file
139  * call gettext () explicitly for actual "translation"  */
140
141 /*
142   Data to be used to display when
143   -h command line option is detected.
144 */
145 static Long_option_init options_static[]
146 =
147 {
148   {
149     _i ("SYM[=VAL]"), "define-default", 'd',
150     _i ("set Scheme option SYM to VAL (default: #t).\n"
151     "Use -dhelp for help.")
152   },
153
154   {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
155   /* Bug in option parser: --output =foe is taken as an abbreviation
156      for --output-format.  */
157   {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,...  Also as separate options:")},
158   {0, "pdf", 0, _i ("generate PDF (default)")},
159   {0, "png", 0, _i ("generate PNG")},
160   {0, "ps", 0, _i ("generate PostScript")},
161   {0, "bigpdfs", 'b', _i("generate big PDF files")},
162   {0, "help", 'h', _i ("show this help and exit")},
163   {
164     _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
165     "named BASENAME.FIELD")
166   },
167   {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
168   {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
169 #if HAVE_CHROOT
170   {
171     _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
172     "and cd into DIR")
173   },
174 #endif
175   {
176     _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
177     " LOGLEVEL.  Possible values are:\n"
178     "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
179   },
180   {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
181   {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
182   {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
183   {0, "version", 'v', _i ("show version number and exit")},
184   {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
185   {0, "warranty", 'w', _i ("show warranty and copyright")},
186   {0, 0, 0, 0}
187 };
188
189 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
190
191 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
192    problems because the truncation from 80 bits to 64 bits can occur in
193    unpredictable places. To get around this, we tell the x87 FPU to use only
194    double precision. Note that this is not needed for x86_64 because that uses
195    the SSE unit by default instead of the x87 FPU. */
196 #if ((defined (__x86__) || defined (__i386__)) \
197   && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
198
199 #include <fpu_control.h>
200 static void
201 configure_fpu ()
202 {
203   fpu_control_t fpu_control = 0x027f;
204   _FPU_SETCW (fpu_control);
205 }
206
207 #else
208
209 static void
210 configure_fpu ()
211 {
212 }
213
214 #endif /* defined(__x86__) || defined(__i386__) */
215
216 using std::map;
217 using std::string;
218 using std::vector;
219
220 static void
221 env_var_info (FILE *out, char const *key)
222 /*
223  * Retrieve value of an OS environment variable.
224  * Parameter:
225  *  key, the name of an environment variable.
226  */
227 {
228   if (char const *value = getenv (key))
229     fprintf (out, "%s=\"%s\"\n", key, value);
230 }
231
232 static void
233 dir_info (FILE *out)
234 /*
235  * Print out information re directories being used by LilyPond
236  * for this session.
237  */
238 {
239   fputs ("\n", out);
240   fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
241   env_var_info (out, "LILYPONDPREFIX");
242   env_var_info (out, "LILYPOND_DATADIR");
243   fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
244
245   fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
246
247   if (relocate_binary)
248     {
249       env_var_info (out, "FONTCONFIG_FILE");
250       env_var_info (out, "FONTCONFIG_PATH");
251       env_var_info (out, "GS_FONTPATH");
252       env_var_info (out, "GS_LIB");
253       env_var_info (out, "GUILE_LOAD_PATH");
254       env_var_info (out, "PANGO_RC_FILE");
255       env_var_info (out, "PANGO_PREFIX");
256       env_var_info (out, "PATH");
257     }
258 }
259
260 static void
261 copyright ()
262 /*
263  * Print out LilyPond copyright info.
264  */
265 {
266   /* Do not update the copyright years here, run `make grand-replace'  */
267   printf ("%s", (_f ("Copyright (c) %s by\n%s  and others.", "1996--2015",
268                      AUTHORS).c_str ()));
269   printf ("\n");
270 }
271
272 static void
273 identify (FILE *out)
274 /*
275  * Print out LilyPond version string.
276  */
277 {
278   fputs (gnu_lilypond_version_string ().c_str (), out);
279   fputs ("\n", out);
280 }
281
282 static void
283 /*
284  * Print copyright and program name
285  */
286 notice ()
287 {
288   identify (stdout);
289   printf ("\n");
290   copyright ();
291   printf ("\n");
292   puts (_f (NOTICE, PROGRAM_NAME).c_str ());
293 }
294
295 LY_DEFINE (ly_usage, "ly:usage",
296            0, 0, 0, (),
297            "Print usage message.")
298 /*
299  * ly_usage: Routine to output standard information when LilyPond is run without a
300  * source file to compile.
301  * Also callable as ly:usage from Scheme.
302  */
303 {
304   /* No version number or newline here.  It confuses help2man.  */
305   printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
306   printf ("\n\n");
307   printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
308   printf ("\n\n");
309   printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
310   printf ("\n");
311   printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
312   printf ("\n\n");
313   printf ("%s", (_ ("Options:").c_str ()));
314   printf ("\n");
315   printf ("%s", Long_option_init::table_string (options_static).c_str ());
316   printf ("\n");
317   /* Translators, please translate this string as
318      "Report bugs in English via %s",
319      or if there is a LilyPond users list or forum in your language
320      "Report bugs in English via %s or in YOUR_LANG via URI"  */
321   printf ("%s", (_f ("Report bugs via %s",
322                      "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
323                     ).c_str ()));
324   printf ("\n");
325   printf ("\n");
326   return SCM_UNSPECIFIED;
327 }
328
329 static void
330 warranty ()
331 /*
332  * Prints out LilyPond warranty information
333  */
334 {
335   identify (stdout);
336   printf ("\n");
337   copyright ();
338   printf ("\n");
339   printf ("%s", (_ (WARRANTY).c_str ()));
340 }
341
342 static void
343 prepend_scheme_list (const string &dir, const string &scmlist)
344 /*
345  *  Inserts an item at the front of a Scheme list, e.g. %load-path
346  *  Parameters:
347  *    dir:     The directory to add to the front of the list
348  *    scmlist: The Scheme list onto which to prepend the directory
349  */
350 {
351   SCM var = scm_c_lookup (scmlist.c_str());
352   scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
353                                      scm_variable_ref (var)));
354   /*  string setcmd =
355              "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
356              scm_c_eval_string (setcmd.c_str());*/
357 }
358
359 void init_global_tweak_registry ();
360 void init_fontconfig ();
361
362 #if HAVE_CHROOT
363 static void
364 do_chroot_jail ()
365 {
366   /* Now we chroot, setuid/setgrp and chdir.  If something goes wrong,
367      we exit (this is a security-sensitive area).  First we split
368      jail_spec into its components, then we retrieve the user/group id
369      (necessarily *before* chroot'ing) and finally we perform the
370      actual actions.  */
371
372   enum Jail
373   {
374     USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
375   };
376
377   vector<string> components = string_split (jail_spec, ',');
378   if (components.size () != JAIL_MAX)
379     {
380       error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
381                  (unsigned) components.size ()));
382       exit (2);
383     }
384
385   /* Hmm.  */
386   errno = 0;
387
388   int uid;
389   if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
390     uid = passwd->pw_uid;
391   else
392     {
393       if (errno == 0)
394         error (_f ("no such user: %s", components[USER_NAME]));
395       else
396         error (_f ("cannot get user id from user name: %s: %s",
397                    components[USER_NAME],
398                    strerror (errno)));
399       exit (3);
400     }
401
402   /* Hmm.  */
403   errno = 0;
404
405   int gid;
406   if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
407     gid = group->gr_gid;
408   else
409     {
410       if (errno == 0)
411         error (_f ("no such group: %s", components[GROUP_NAME]));
412       else
413         error (_f ("cannot get group id from group name: %s: %s",
414                    components[GROUP_NAME],
415                    strerror (errno)));
416       exit (3);
417     }
418
419   if (chroot (components[JAIL].c_str ()))
420     {
421       error (_f ("cannot chroot to: %s: %s", components[JAIL],
422                  strerror (errno)));
423       exit (3);
424     }
425
426   if (setgid (gid))
427     {
428       error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
429       exit (3);
430     }
431
432   if (setuid (uid))
433     {
434       error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
435       exit (3);
436     }
437
438   if (chdir (components[DIR].c_str ()))
439     {
440       error (_f ("cannot change working directory to: %s: %s", components[DIR],
441                  strerror (errno)));
442       exit (3);
443     }
444 }
445 #endif
446
447 static void
448 main_with_guile (void *, int, char **)
449 /*
450  * main-with-guile is invoked as a callback via scm_boot_guile from
451  * main.
452  * scm_boot_guile will have passed its data, argc and argv parameters
453  * to main_with_guile.
454  */
455 {
456   /* Engravers use lily.scm contents, so we need to make Guile find it.
457      Prepend onto GUILE %load-path.
458       %load-path is the symbol Guile searches for .scm files
459       %load-compiled-path is the symbol Guile V2 searches for .go files
460    */
461    string scm_pct_load_path = "%load-path";
462    string scm_pct_load_compiled_path = "%load-compiled-path";
463
464    prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
465    prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
466
467 #if (GUILE2)
468    /*
469      Just as ughy - prepend "/scm/out" onto GUILE V2+ %load-compiled-path
470      and set %compile-fallback-path to our scm/out directory
471    */
472    /*
473      %load-compiled-path is the symbol Guile V2 searches for .go files
474    */
475    prepend_scheme_list (lilypond_datadir + "/scm/out",
476                           scm_pct_load_compiled_path);
477    /*
478      %compile-fallback-path is the guile cache root for auto-compiled files
479    */
480
481    string scm_pct_fallback_path = "%compile-fallback-path";
482    string ly_scm_go_dir = lilypond_datadir + "/scm/out";
483    //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
484    //  " \"" + lilypond_datadir + "/scm/out\")";
485    //scm_c_eval_string (scm_pct_set_fallback.c_str() );
486    scm_primitive_eval
487      (scm_list_3 (scm_from_latin1_symbol ("set!"),
488                   scm_from_latin1_symbol ("%compile-fallback-path"),
489                   scm_from_locale_string (ly_scm_go_dir.c_str())));
490 #endif
491
492   if (is_loglevel (LOG_DEBUG))
493     dir_info (stderr);
494
495   init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
496   init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
497
498   ly_c_init_guile ();
499   call_constructors ();
500   init_fontconfig ();
501
502   init_freetype ();
503   ly_reset_all_fonts ();
504
505   /*
506      We accept multiple independent music files on the command line to
507      reduce compile time when processing lots of small files.
508      This way we don't have to start the Guile/Scheme interpreter more than once, as
509      starting the GUILE engine is very time consuming.
510   */
511
512   SCM files = SCM_EOL;
513   SCM *tail = &files;
514   while (char const *arg = option_parser->get_next_arg ())
515     {
516       *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
517       tail = SCM_CDRLOC (*tail);
518     }
519
520   delete option_parser;
521   option_parser = 0;
522
523 #if HAVE_CHROOT
524   if (!jail_spec.empty ())
525     do_chroot_jail ();
526 #endif
527   /*
528     Now execute the Scheme entry-point declared in
529     lily.scm (lilypond-main)
530   */
531   // These commands moved to lily_guile_v2.scm
532   // SCM rep_mod = scm_c_resolve_module ("system repl repl");
533   // scm_c_use_module ("system repl repl");
534   // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
535   // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
536   // SCM result = scm_call_1 (
537   //                       scm_variable_ref (call_with_error_handling),
538   //                       scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
539
540   Lily::lilypond_main (files);
541
542   /* Unreachable.  */
543   exit (0);
544 }
545
546 static void
547 setup_localisation ()
548 /*
549  *  Set up local language text locale (if available from configure)
550  *  Implicit inputs:
551  *  HAVE_GETTEXT: Internationalization available for a local language.
552  */
553 {
554 #if HAVE_GETTEXT
555   /* Enable locales */
556   setlocale (LC_ALL, "");
557
558   /* FIXME: check if this is still true.
559      Disable localisation of float values. */
560   setlocale (LC_NUMERIC, "C");
561
562 #if GUILEV2
563   // In order not to have this porting aid backfire to GUILE1 usage,
564   // this is only compiled in the GUILEV2 version.  It should
565   // eventually be replaced with proper multibyte communication with
566   // GUILE2, but in the mean time it seems that this is the least
567   // invasive path to get comparable results between the
568   // not-really-multibyte-supporting GUILE1 and GUILE2
569
570   /* Disable character sets */
571   setlocale (LC_CTYPE, "C");
572   /* But our text domain is in UTF-8 */
573   bind_textdomain_codeset ("lilypond", "UTF-8");
574 #endif
575
576   string localedir = LOCALEDIR;
577   if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
578     localedir = env;
579
580   bindtextdomain ("lilypond", localedir.c_str ());
581   textdomain ("lilypond");
582 #endif
583 }
584
585 static void
586 add_output_format (const string &format)
587 /*
588  * Capture information internally from command-line options
589  * re output format.
590  *
591  */
592 {
593   if (output_format_global != "")
594     output_format_global += ",";
595   output_format_global += format;
596 }
597
598 static void
599 parse_argv (int argc, char **argv)
600 /*
601  *  Parse command-line options
602  *  also, if -h (help), -v (version) or  -w (warranty) is detected,
603  *  output the usage information and exit.
604  */
605 {
606   bool show_help = false;
607   option_parser = new Getopt_long (argc, argv, options_static);
608   while (Long_option_init const *opt = (*option_parser) ())
609     {
610       switch (opt->shortname_char_)
611         {
612         case 0:
613           if (string (opt->longname_str0_) == "pdf"
614               || string (opt->longname_str0_) == "png"
615               || string (opt->longname_str0_) == "ps")
616             add_output_format (opt->longname_str0_);
617           else if (string (opt->longname_str0_) == "relocate")
618             relocate_binary = true;
619           break;
620
621         case 'b':
622           bigpdfs = true;
623           break;
624
625         case 'd':
626           {
627             string arg (option_parser->optional_argument_str0_);
628             ssize eq = arg.find ('=');
629
630             string key = arg;
631             string val = "#t";
632
633             if (eq != NPOS)
634               {
635                 key = arg.substr (0, eq);
636                 val = arg.substr (eq + 1, arg.length () - 1);
637               }
638
639             init_scheme_variables_global
640             += "(cons \'" + key + " '" + val + ")\n";
641           }
642           break;
643
644         case 'v':
645           notice ();
646           exit (0);
647           break;
648         case 'o':
649           {
650             string s = option_parser->optional_argument_str0_;
651             File_name file_name (s);
652             output_name_global = file_name.to_string ();
653           }
654           break;
655         case 'j':
656           jail_spec = option_parser->optional_argument_str0_;
657           break;
658
659         case 'e':
660           init_scheme_code_global
661           += option_parser->optional_argument_str0_ + string (" ");
662           break;
663         case 'w':
664           warranty ();
665           exit (0);
666           break;
667
668         case 'f':
669           {
670             vector<string> components
671               = string_split (option_parser->optional_argument_str0_, ',');
672             for (vsize i = 0; i < components.size (); i++)
673               add_output_format (components[i]);
674           }
675           break;
676
677         case 'H':
678           dump_header_fieldnames_global
679           .push_back (option_parser->optional_argument_str0_);
680           break;
681         case 'I':
682           global_path.append (option_parser->optional_argument_str0_);
683           break;
684         case 'i':
685           init_name_global = option_parser->optional_argument_str0_;
686           break;
687         case 'h':
688           show_help = true;
689           break;
690         case 'V':
691           set_loglevel (LOGLEVEL_DEBUG);
692           break;
693         case 's':
694           set_loglevel (LOGLEVEL_ERROR);
695           break;
696         case 'l':
697           set_loglevel (option_parser->optional_argument_str0_);
698           break;
699         default:
700           programming_error (to_string ("unhandled short option: %c",
701                                         opt->shortname_char_));
702           assert (false);
703           break;
704         }
705     }
706
707   if (output_format_global == "")
708     output_format_global = "pdf";
709
710   if (show_help)
711     {
712       ly_usage ();
713       if (is_loglevel (LOG_DEBUG))
714         dir_info (stdout);
715       exit (0);
716     }
717 }
718
719 /*
720   T1686 Add two new routines called by setup_guile_env
721 */
722
723 void
724 setup_guile_gc_env ()
725 /*
726  * Set up environment variables relevant to the
727  * Garbage Collector
728  */
729 {
730   char const *yield = getenv ("LILYPOND_GC_YIELD");
731   bool overwrite = true;
732   if (!yield)
733     {
734       yield = "65";
735       overwrite = false;
736     }
737
738   sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
739   sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
740   sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
741
742   sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
743                "10485760", overwrite);
744   sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
745                "104857600", overwrite);
746 }
747
748
749 void
750 setup_guile_v2_env ()
751 /*
752  * Set up environment variables relevant to compiling
753  * Scheme files for Guile V2.
754  */
755 {
756      sane_putenv("GUILE_AUTO_COMPILE", "0", true);  // disable auto-compile
757      sane_putenv("GUILE_WARN_DEPRECATED",
758                   "detailed", "true");   // set Guile to info re deprecation
759      /*
760         Set root for Guile %compile-fallback to
761         Lilypond root for its data.
762       */
763      sane_putenv("XDG_CACHE_HOME",
764                   lilypond_datadir, true);
765 }
766
767 void
768 setup_guile_env ()
769 /*
770  * Set up environment variables relevant to Scheme
771  */
772 {
773
774   setup_guile_gc_env ();  // configure garbage collector
775 #if (GUILEV2)
776   setup_guile_v2_env ();  // configure Guile V2 behaviour
777 #endif
778 }
779
780 //vector<string> start_environment_global;
781
782 int
783 main (int argc, char **argv, char **envp)
784 /*
785  * Main entry-point for LilyPond executable image
786  * Parameters:
787  * argc:   Count of arguments on the command line
788  * argv:   Vector of string arguments on command line
789  * envp:   Point to vector of OS environment variables
790  */
791 {
792   configure_fpu ();
793   /*
794     Process environment variables
795   */
796   for (char **p = envp; *p; p++)
797     start_environment_global.push_back (*p);
798   /*
799     Handle old-style environment equivalent to
800     old-style -V or --verbose command arguments.
801     Set it to the equivalent for --loglevel-DEBUG
802    */
803   if (getenv ("LILYPOND_VERBOSE"))
804     set_loglevel (LOGLEVEL_DEBUG);
805   if (getenv ("LILYPOND_LOGLEVEL"))
806     set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
807
808   setup_localisation ();
809   parse_argv (argc, argv);
810   if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
811     identify (stderr);
812
813   setup_paths (argv[0]);
814   setup_guile_env ();  // set up environment variables to pass into Guile API
815   /*
816    * Start up Guile API using main_with_guile as a callback.
817    */
818 #if (GUILEV2)
819  /* Debugging aid.
820     Set it on by default for Guile V2
821     while migration in progress.
822  */
823   try
824     {
825       scm_boot_guile (argc, argv, main_with_guile, 0);
826     }
827   catch (exception e)
828     {
829       error (_f ("exception caught: %s", e.what ()));
830     };
831 #else
832   scm_boot_guile (argc, argv, main_with_guile, 0);
833 #endif
834
835   /* Only reachable if GUILE exits.  That is an error.  */
836   return 1;
837 }