2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2005--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
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.
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.
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/>.
20 #include "relocate.hh"
25 /* TODO: autoconf support */
27 #include <sys/types.h>
34 #include "file-name.hh"
35 #include "file-path.hh"
36 #include "international.hh"
37 #include "lily-guile.hh"
38 #include "lily-version.hh"
43 #define FRAMEWORKDIR ".."
46 sane_putenv (char const *key
, string value
, bool overwrite
)
48 if (overwrite
|| !getenv (key
))
50 string combine
= string (key
) + "=" + value
;
51 char *s
= strdup (combine
.c_str ());
53 if (be_verbose_global
)
54 progress_indication (_f ("Setting %s to %s" , key
, value
.c_str ())
57 int retval
= putenv (s
);
59 unfortunately, we can't portably free S here,
60 due to various bugs in glibc prior to 2.1.1
69 set_env_file (char const *key
, string value
, bool overwrite
= false)
72 return sane_putenv (key
, value
, overwrite
);
73 else if (be_verbose_global
)
74 warning (_f ("no such file: %s for %s", value
, key
));
79 set_env_dir (char const *key
, string value
)
82 return sane_putenv (key
, value
, false);
83 else if (be_verbose_global
)
84 warning (_f ("no such directory: %s for %s", value
, key
));
89 prepend_env_path (char const *key
, string value
)
93 if (be_verbose_global
)
94 progress_indication (_f ("%s=%s (prepend)\n", key
, value
.c_str ()));
96 if (char const *cur
= getenv (key
))
97 value
+= to_string (PATHSEP
) + cur
;
99 return sane_putenv (key
, value
.c_str (), true);
101 else if (be_verbose_global
)
102 warning (_f ("no such directory: %s for %s", value
, key
));
111 prefix_relocation (string prefix
)
113 string bindir
= prefix
+ "/bin";
114 string datadir
= prefix
+ "/share";
115 string localedir
= datadir
+ "/locale";
116 string package_datadir
= datadir
+ "/lilypond/";
117 string old_lilypond_datadir
= lilypond_datadir
;
119 if (is_dir (package_datadir
+ "/" + TOPLEVEL_VERSION
))
120 lilypond_datadir
= package_datadir
+ "/" + TOPLEVEL_VERSION
;
121 else if (is_dir (package_datadir
+ "/current"))
122 lilypond_datadir
= package_datadir
+ "/current";
124 warning (_f ("not relocating, no %s/ or current/ found under %s",
125 TOPLEVEL_VERSION
, package_datadir
.c_str ()));
128 if (is_dir (localedir
))
129 bindtextdomain ("lilypond", localedir
.c_str ());
132 prepend_env_path ("PATH", bindir
);
134 if (be_verbose_global
)
135 warning (_f ("Relocation: compile datadir=%s, new datadir=%s",
136 old_lilypond_datadir
.c_str (),
137 lilypond_datadir
.c_str ()));
141 UGH : this is a complete mess.
145 framework_relocation (string prefix
)
147 if (be_verbose_global
)
148 warning (_f ("Relocation: framework_prefix=%s", prefix
));
150 sane_putenv ("INSTALLER_PREFIX", prefix
, true);
152 read_relocation_dir (prefix
+ "/etc/relocate/");
154 string bindir
= prefix
+ "/bin";
156 prepend_env_path ("PATH", bindir
);
160 UGH : this is a complete mess.
163 setup_paths (char const *argv0_ptr
)
165 File_name
argv0_filename (argv0_ptr
);
169 string prefix_directory
;
170 if (getenv ("LILYPOND_RELOCATE_PREFIX"))
172 prefix_directory
= getenv ("LILYPOND_RELOCATE_PREFIX");
174 /* Normalize file name. */
175 prefix_directory
= File_name (prefix_directory
).to_string ();
176 #endif /* __MINGW32__ */
178 prefix_relocation (prefix_directory
);
179 string bindir
= prefix_directory
+ "/bin";
180 framework_relocation (bindir
);
182 else if (relocate_binary
)
185 if (argv0_filename
.is_absolute ())
187 argv0_abs
= argv0_filename
.to_string ();
188 if (be_verbose_global
)
189 warning (_f ("Relocation: is absolute: argv0=%s", argv0_ptr
));
191 else if (argv0_filename
.dir_
.length ())
193 argv0_abs
= get_working_directory ()
194 + "/" + string (argv0_filename
.to_string ());
195 if (be_verbose_global
)
196 warning (_f ("Relocation: from cwd: argv0=%s", argv0_ptr
));
200 /* Find absolute ARGV0 name, using PATH. */
202 path
.parse_path (getenv ("PATH"));
205 argv0_abs
= path
.find (argv0_filename
.to_string ());
206 #else /* __MINGW32__ */
207 path
.prepend (get_working_directory ());
208 char const *ext
[] = {"exe", "", 0 };
209 argv0_abs
= path
.find (argv0_filename
.to_string (), ext
);
210 #endif /* __MINGW32__ */
212 if (be_verbose_global
)
213 warning (_f ("Relocation: from PATH=%s\nargv0=%s",
214 path
.to_string ().c_str (), argv0_ptr
));
216 if (argv0_abs
.empty ())
217 programming_error ("cannot find absolute argv0");
220 string bindir
= dir_name (argv0_abs
);
221 string argv0_prefix
= dir_name (bindir
);
222 string compile_prefix
= dir_name (dir_name (dir_name (lilypond_datadir
)));
223 if (argv0_prefix
!= compile_prefix
)
225 prefix_relocation (argv0_prefix
);
226 prefix_directory
= argv0_prefix
;
228 if (argv0_prefix
!= compile_prefix
|| string (FRAMEWORKDIR
) != "..")
230 framework_relocation (bindir
+ "/" + FRAMEWORKDIR
);
231 prefix_directory
= bindir
+ "/" + FRAMEWORKDIR
;
235 lilypond_datadir
= prefix_directory
236 + "/share/lilypond/" TOPLEVEL_VERSION
;
239 if (getenv ("LILYPONDPREFIX"))
240 error (_ ("LILYPONDPREFIX is obsolete, use LILYPOND_DATADIR"));
242 if (char const *env
= getenv ("LILYPOND_DATADIR"))
244 /* Normalize file name. */
245 lilypond_datadir
= File_name (env
).to_string ();
248 /* When running from build dir, a full LILYPOND_DATADIR is set-up at
249 $(OUTBASE)/{share, lib}/lilypond/current. Configure lily using
250 ./configure --prefix=$(pwd)/out */
251 string build_datadir_current
= dir_name (lilypond_datadir
) + "/current";
252 if (!is_dir (lilypond_datadir
.c_str ())
253 && is_dir (build_datadir_current
.c_str ()))
254 lilypond_datadir
= build_datadir_current
;
257 lilypond_datadir
= File_name (lilypond_datadir
).canonicalized().to_string();
259 global_path
.append ("");
261 /* Adding mf/out make lilypond unchanged source directory, when setting
262 LILYPONDPREFIX to lilypond-x.y.z */
263 char const *suffixes
[] = {"ly", "ps", "scm", 0 };
266 for (char const **s
= suffixes
; *s
; s
++)
268 string path
= lilypond_datadir
+ to_string ('/') + string (*s
);
269 dirs
.push_back (path
);
272 dirs
.push_back (lilypond_datadir
+ "/fonts/otf/");
273 dirs
.push_back (lilypond_datadir
+ "/fonts/type1/");
274 dirs
.push_back (lilypond_datadir
+ "/fonts/svg/");
276 for (vsize i
= 0; i
< dirs
.size (); i
++)
277 global_path
.prepend (dirs
[i
]);
281 expand_environment_variables (string orig
)
283 char const *start_ptr
= orig
.c_str ();
284 char const *ptr
= orig
.c_str ();
285 size_t len
= orig
.length ();
288 while (ptr
< start_ptr
+ len
)
290 char const *dollar
= strchr (ptr
, '$');
294 char const *start_var
= dollar
+ 1;
295 char const *end_var
= start_var
;
296 char const *start_next
= end_var
;
298 out
+= string (ptr
, dollar
- ptr
);
301 if (*start_var
== '{')
305 end_var
= strchr (start_var
, '}');
309 end_var
= start_var
+ len
;
310 start_next
= end_var
;
314 start_next
= end_var
+ 1;
320 Hmm. what to do for $1 , $~ etc.?
326 while (isalnum (*end_var
) || *end_var
== '_');
327 start_next
= end_var
;
330 if (start_var
< end_var
)
332 string
var_name (start_var
, end_var
- start_var
);
333 char const *value
= getenv (var_name
.c_str ());
335 out
+= string (value
);
350 // Ugh - very inefficient, but safer than fgets.
357 while ((c
= fgetc (f
)) != EOF
&& c
!= '\n')
364 read_relocation_file (string filename
)
366 if (be_verbose_global
)
367 progress_indication (_f ("Relocation file: %s", filename
.c_str ())
370 char const *cname
= filename
.c_str ();
371 FILE *f
= fopen (cname
, "r");
373 error (_f ("cannot open file: `%s'", cname
));
377 string line
= read_line (f
);
378 size_t idx
= line
.find (' ');
382 string command
= line
.substr (0, idx
);
383 line
= line
.substr (idx
+ 1);
387 idx
= line
.find ('=');
389 string variable
= line
.substr (0, idx
);
390 string value
= line
.substr (idx
+ 1);
392 value
= expand_environment_variables (value
);
394 if (command
== "set")
395 sane_putenv (variable
.c_str (), value
, true);
396 else if (command
== "setdir")
397 set_env_dir (variable
.c_str (), value
);
398 else if (command
== "setfile")
399 set_env_file (variable
.c_str (), value
);
400 else if (command
== "prependdir")
401 prepend_env_path (variable
.c_str (), value
);
403 error (_f ("Unknown relocation command %s", command
));
410 read_relocation_dir (string dirname
)
412 if (DIR *dir
= opendir (dirname
.c_str ()))
413 while (struct dirent
*ent
= readdir (dir
))
415 File_name
name (ent
->d_name
);
416 if (name
.ext_
== "reloc")
417 read_relocation_file (dirname
+ "/" + name
.to_string ());