2 Copyright 2020 René Ferdinand Rivera Morell
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)
24 char const *name_
, LIST
*(*f
)(FRAME
*, int flags
),
25 int flags
, char const **args
)
28 OBJECT
*name
= object_new(name_
);
29 func
= function_builtin(f
, flags
, args
);
30 new_rule_body(root_module(), name
, func
, 1);
36 void b2::startup::load_builtins()
39 char const *args
[] = {"dir", "?", 0};
40 bind_builtin("boost-build", builtin_boost_build
, 0, args
);
44 LIST
*b2::startup::builtin_boost_build(FRAME
*frame
, int flags
)
46 b2::jam::list dir_arg
{lol_get(frame
->args
, 0)};
48 if (!dir_arg
.empty()) dir
= b2::jam::object(*dir_arg
.begin());
50 b2::jam::variable dot_bootstrap_file
{".bootstrap-file"};
51 if (dot_bootstrap_file
)
54 "Error: Illegal attempt to re-bootstrap the build system by invoking\n"
56 " 'boost-build '%s' ;\n"
58 "Please consult the documentation at "
59 "'https://www.bfgroup.xyz/b2/'.\n\n",
64 // # Add the given directory to the path so we can find the build system. If
65 // # dir is empty, has no effect.
66 b2::jam::variable dot_boost_build_file
{".boost-build-file"};
67 b2::jam::list dot_boost_build_file_val
{static_cast<b2::jam::list
>(dot_boost_build_file
)};
68 std::string boost_build_jam
= b2::jam::object
{*dot_boost_build_file_val
.begin()};
69 std::string boost_build_dir
;
70 if (b2::paths::is_rooted(dir
))
71 boost_build_dir
= dir
;
73 boost_build_dir
= b2::paths::normalize(
74 std::string
{boost_build_jam
}+"/../"+dir
);
75 b2::jam::list search_path
{b2::jam::object
{boost_build_dir
}};
76 b2::jam::variable BOOST_BUILD_PATH
{"BOOST_BUILD_PATH"};
77 search_path
.append(BOOST_BUILD_PATH
);
79 // We set the global, and env, BOOST_BUILD_PATH so that the loading of the
80 // build system finds the initial set of modules needed for starting it up.
81 BOOST_BUILD_PATH
= search_path
;
83 // The code that loads the rest of B2, in particular the site-config.jam
84 // and user-config.jam configuration files uses os.environ, so we need to
85 // update the value there.
86 b2::jam::variable dot_ENVIRON__BOOST_BUILD_PATH
{".ENVIRON", "BOOST_BUILD_PATH"};
87 dot_ENVIRON__BOOST_BUILD_PATH
= search_path
;
89 // # Try to find the build system bootstrap file 'bootstrap.jam'.
90 std::string bootstrap_file
;
91 for (auto path
: search_path
)
93 std::string file
= b2::jam::object
{path
};
94 file
= b2::paths::normalize(file
+"/bootstrap.jam");
95 if (b2::filesys::is_file(file
))
97 bootstrap_file
= file
;
102 // # There is no bootstrap.jam we can find, exit with an error.
103 if (bootstrap_file
.empty())
106 "Unable to load B2: could not find build system.\n"
107 "-----------------------------------------------\n"
108 "%s attempted to load the build system by invoking\n"
110 " 'boost-build %s ;'\n"
112 "but we were unable to find 'bootstrap.jam' in the specified directory "
113 "or in BOOST_BUILD_PATH:\n",
114 boost_build_jam
.c_str(), dir
.c_str());
115 for (auto path
: search_path
)
117 std::string file
= b2::jam::object
{path
};
118 err_printf(" %s\n", file
.c_str());
121 "Please consult the documentation at "
122 "'https://www.bfgroup.xyz/b2/'.\n\n");
126 // Set the bootstrap=file var as it's used by the build system to refer to
127 // the rest of the build system files.
128 dot_bootstrap_file
= b2::jam::list
{b2::jam::object
{bootstrap_file
}};
130 // Show where we found it, if asked.
131 b2::jam::variable dot_OPTION__debug_configuration
{".OPTION", "debug-configration"};
132 if (dot_OPTION__debug_configuration
)
134 out_printf("notice: loading B2 from %s\n", bootstrap_file
.c_str());
137 // # Load the build system, now that we know where to start from.
138 parse_file(b2::jam::object
{bootstrap_file
}, frame
);
143 extern char const *saved_argv0
;
145 bool b2::startup::bootstrap(FRAME
*frame
)
147 b2::jam::list ARGV
= b2::jam::variable
{"ARGV"};
148 b2::jam::object opt_debug_configuration
{"--debug-configuration"};
149 b2::jam::variable dot_OPTION__debug_configuration
{".OPTION", "debug-configration"};
152 if (opt_debug_configuration
== arg
)
154 dot_OPTION__debug_configuration
= b2::jam::list
{b2::jam::object
{"true"}};
159 char *b2_exe_path_pchar
= executable_path(saved_argv0
);
160 const std::string b2_exe_path
{b2_exe_path_pchar
};
161 if (b2_exe_path_pchar
)
163 std::free(b2_exe_path_pchar
);
165 const std::string boost_build_jam
{"boost-build.jam"};
166 std::string b2_file_path
;
168 // Attempt to find the `boost-build.jam` boot file in work directory tree.
169 if (b2_file_path
.empty())
171 std::string work_dir
{b2::paths::normalize(b2::cwd_str()) + "/"};
172 while (b2_file_path
.empty() && !work_dir
.empty())
174 if (b2::filesys::is_file(work_dir
+ boost_build_jam
))
175 b2_file_path
= work_dir
+ boost_build_jam
;
176 else if (work_dir
.length() == 1 && work_dir
[0] == '/')
180 auto parent_pos
= work_dir
.rfind('/', work_dir
.length() - 2);
181 if (parent_pos
!= std::string::npos
)
182 work_dir
.erase(parent_pos
+ 1);
189 // Check relative to the executable for portable install location.
190 if (b2_file_path
.empty())
192 const std::string path
{
193 b2::paths::normalize(
194 b2_exe_path
+ "/../.b2/kernel/" + boost_build_jam
)};
195 if (b2::filesys::is_file(path
))
199 // Check relative to the executable for portable install location.
200 if (b2_file_path
.empty())
202 const std::string path
{
203 b2::paths::normalize(
204 b2_exe_path
+ "/../../share/boost-build/src/kernel/" + boost_build_jam
)};
205 if (b2::filesys::is_file(path
))
209 // Check the BOOST_BUILD_PATH (and BOOST_ROOT) paths.
210 if (b2_file_path
.empty())
212 b2::jam::list BOOST_BUILD_PATH
= b2::jam::variable
{"BOOST_BUILD_PATH"};
213 // For back-compat with Boost we also search in the BOOST_ROOT location.
214 BOOST_BUILD_PATH
.append(b2::jam::list(b2::jam::variable
{"BOOST_ROOT"}));
215 for (auto search_path
: BOOST_BUILD_PATH
)
217 std::string path
= b2::jam::object
{search_path
};
218 path
= b2::paths::normalize(path
+"/"+boost_build_jam
);
219 if (b2::filesys::is_file(path
))
227 // Indicate a load failure when we can't find the build file.
228 if (b2_file_path
.empty())
230 const char * not_found_error
=
231 "Unable to load B2: could not find 'boost-build.jam'\n"
232 "---------------------------------------------------\n"
233 "Attempted search from '%s' up to the root "
235 "Please consult the documentation at "
236 "'https://www.bfgroup.xyz/b2/'.\n\n";
237 err_printf(not_found_error
, b2::cwd_str().c_str(), b2_exe_path
.c_str());
241 // Show where we found it, if asked.
242 if (dot_OPTION__debug_configuration
)
244 out_printf("notice: found boost-build.jam at %s\n", b2_file_path
.c_str());
247 // Load the build system bootstrap file we found. But check we did that.
248 b2::jam::variable dot_boost_build_file
{".boost-build-file"};
249 dot_boost_build_file
= b2_file_path
;
250 b2::jam::object b2_file_path_sym
{b2_file_path
};
251 parse_file(b2_file_path_sym
, frame
);
252 b2::jam::list dot_dot_bootstrap_file_val
= b2::jam::variable
{".bootstrap-file"};
253 if (dot_dot_bootstrap_file_val
.empty())
256 "Unable to load B2\n"
257 "-----------------\n"
258 "'%s' was found by searching from %s up to the root.\n"
260 "However, it failed to call the 'boost-build' rule to indicate "
261 "the location of the build system.\n"
263 "Please consult the documentation at "
264 "'https://www.bfgroup.xyz/b2/'.\n\n",
265 b2_file_path
.c_str(), b2::cwd_str().c_str());