projects
/
tatoo.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Don't needlessly run the last bottom-up phase, when the top-down is sufficient.
[tatoo.git]
/
remake.cpp
diff --git
a/remake.cpp
b/remake.cpp
index
b8387be
..
b36a3e7
100644
(file)
--- a/
remake.cpp
+++ b/
remake.cpp
@@
-184,6
+184,10
@@
parser.c parser.h: parser.y
yacc -d -o parser.c parser.y
@endverbatim
yacc -d -o parser.c parser.y
@endverbatim
+\subsection sec-special-tgt Special targets
+
+Target <tt>.PHONY</tt> marks its prerequisites as being always obsolete.
+
\subsection sec-special-var Special variables
Variable <tt>.OPTIONS</tt> is handled specially. Its content enables some
\subsection sec-special-var Special variables
Variable <tt>.OPTIONS</tt> is handled specially. Its content enables some
@@
-343,7
+347,7
@@
https://github.com/apenwarr/redo for an implementation and some comprehensive do
\section sec-licensing Licensing
@author Guillaume Melquiond
\section sec-licensing Licensing
@author Guillaume Melquiond
-@version 0.
9
+@version 0.
11
@date 2012-2013
@copyright
This program is free software: you can redistribute it and/or modify
@date 2012-2013
@copyright
This program is free software: you can redistribute it and/or modify
@@
-373,8
+377,8
@@
When building a target, the following sequence of events happens:
- #start calls #find_rule (and #find_generic_rule) to get the rule.
- It then creates a pseudo-client if the rule has static dependencies, or
- #start calls #find_rule (and #find_generic_rule) to get the rule.
- It then creates a pseudo-client if the rule has static dependencies, or
- calls #run_script otherwise. In both cases, a new job is created
and its
-
targets are put into #job_target
s.
+ calls #run_script otherwise. In both cases, a new job is created
; the
+
rule and the variables are stored into #job
s.
- #run_script creates a shell process and stores it in #job_pids. It
increases #running_jobs.
- The child process possibly calls <b>remake</b> with a list of targets.
- #run_script creates a shell process and stores it in #job_pids. It
increases #running_jobs.
- The child process possibly calls <b>remake</b> with a list of targets.
@@
-392,7
+396,7
@@
When building a target, the following sequence of events happens:
- When a child process ends, #server_loop calls #finalize_job, which
removes the process from #job_pids, decreases #running_jobs, and calls
#complete_job.
- When a child process ends, #server_loop calls #finalize_job, which
removes the process from #job_pids, decreases #running_jobs, and calls
#complete_job.
-- #complete_job removes the job from #job
_target
s and calls #update_status
+- #complete_job removes the job from #jobs and calls #update_status
to change the status of the targets. It also removes the target files in
case of failure.
*/
to change the status of the targets. It also removes the target files in
case of failure.
*/
@@
-668,7
+672,7
@@
static int waiting_jobs = 0;
/**
* Global counter used to produce increasing job numbers.
/**
* Global counter used to produce increasing job numbers.
- * @see job
_target
s
+ * @see jobs
*/
static int job_counter = 0;
*/
static int job_counter = 0;
@@
-719,6
+723,11
@@
static std::string working_dir;
*/
static std::string prefix_dir;
*/
static std::string prefix_dir;
+/**
+ * Whether the prefix directory is different from #working_dir.
+ */
+static bool changed_prefix_dir;
+
/**
* Whether target-specific variables are propagated to prerequisites.
*/
/**
* Whether target-specific variables are propagated to prerequisites.
*/
@@
-870,7
+879,16
@@
static void init_prefix_dir()
struct stat s;
if (stat((prefix_dir + "/Remakefile").c_str(), &s) == 0)
{
struct stat s;
if (stat((prefix_dir + "/Remakefile").c_str(), &s) == 0)
{
- chdir(prefix_dir.c_str());
+ if (!changed_prefix_dir) return;
+ if (chdir(prefix_dir.c_str()))
+ {
+ perror("Failed to change working directory");
+ exit(EXIT_FAILURE);
+ }
+ if (show_targets)
+ {
+ std::cout << "remake: Entering directory `" << prefix_dir << '\'' << std::endl;
+ }
return;
}
size_t pos = prefix_dir.find_last_of('/');
return;
}
size_t pos = prefix_dir.find_last_of('/');
@@
-880,6
+898,7
@@
static void init_prefix_dir()
exit(EXIT_FAILURE);
}
prefix_dir.erase(pos);
exit(EXIT_FAILURE);
}
prefix_dir.erase(pos);
+ changed_prefix_dir = true;
}
}
}
}
@@
-1076,44
+1095,44
@@
static int expect_token(std::istream &in, int mask)
/**
* Read a (possibly quoted) word.
*/
/**
* Read a (possibly quoted) word.
*/
-static std::string read_word(std::istream &in)
+static std::string read_word(std::istream &in
, bool detect_equal = true
)
{
{
- int c = in.
get
();
+ int c = in.
peek
();
std::string res;
if (!in.good()) return res;
std::string res;
if (!in.good()) return res;
- char const *separators = " \t\r\n
:$(),=+\"
";
+ char const *separators = " \t\r\n
$(),:
";
bool quoted = c == '"';
bool quoted = c == '"';
- if (!quoted)
- {
- if (strchr(separators, c))
- {
- in.putback(c);
- return res;
- }
- res += c;
- }
+ if (quoted) in.ignore(1);
+ bool plus = false;
while (true)
{
while (true)
{
- c = in.
get
();
+ c = in.
peek
();
if (!in.good()) return res;
if (quoted)
{
if (!in.good()) return res;
if (quoted)
{
+ in.ignore(1);
if (c == '\\')
res += in.get();
else if (c == '"')
if (c == '\\')
res += in.get();
else if (c == '"')
-
return res
;
+
quoted = false
;
else
res += c;
else
res += c;
+ continue;
}
}
- else
+ if (detect_equal && c == '=')
{
{
- if (strchr(separators, c))
- {
- in.putback(c);
- return res;
- }
- res += c;
+ if (plus) in.putback('+');
+ return res;
}
}
+ if (plus)
+ {
+ res += '+';
+ plus = false;
+ }
+ if (strchr(separators, c)) return res;
+ in.ignore(1);
+ if (detect_equal && c == '+') plus = true;
+ else res += c;
}
}
}
}
@@
-1218,11
+1237,11
@@
input_status input_generator::next(std::string &res)
switch (expect_token(in, Word | Dollarpar))
{
case Word:
switch (expect_token(in, Word | Dollarpar))
{
case Word:
- res = read_word(in);
+ res = read_word(in
, false
);
return Success;
case Dollarpar:
{
return Success;
case Dollarpar:
{
- std::string name = read_word(in);
+ std::string name = read_word(in
, false
);
if (name.empty()) return SyntaxError;
if (expect_token(in, Rightpar))
nested = new variable_generator(name, local_variables);
if (name.empty()) return SyntaxError;
if (expect_token(in, Rightpar))
nested = new variable_generator(name, local_variables);
@@
-1648,6
+1667,17
@@
static void load_rule(std::istream &in, std::string const &first)
}
rule.script = buf.str();
}
rule.script = buf.str();
+ // Register phony targets.
+ if (rule.targets.front() == ".PHONY")
+ {
+ for (string_list::const_iterator i = rule.deps.begin(),
+ i_end = rule.deps.end(); i != i_end; ++i)
+ {
+ status[*i].status = Todo;
+ }
+ return;
+ }
+
// Add generic rules to the correct set.
if (generic)
{
// Add generic rules to the correct set.
if (generic)
{
@@
-2021,21
+2051,23
@@
static bool still_need_rebuild(std::string const &target)
*/
static void complete_job(int job_id, bool success)
{
*/
static void complete_job(int job_id, bool success)
{
- DEBUG
_open << "Completing job " << job_id << "... "
;
+ DEBUG
<< "Completing job " << job_id << '\n'
;
job_map::iterator i = jobs.find(job_id);
assert(i != jobs.end());
string_list const &targets = i->second.rule.targets;
if (success)
{
job_map::iterator i = jobs.find(job_id);
assert(i != jobs.end());
string_list const &targets = i->second.rule.targets;
if (success)
{
+ if (show_targets) std::cout << "Finished";
for (string_list::const_iterator j = targets.begin(),
j_end = targets.end(); j != j_end; ++j)
{
update_status(*j);
for (string_list::const_iterator j = targets.begin(),
j_end = targets.end(); j != j_end; ++j)
{
update_status(*j);
+ if (show_targets) std::cout << ' ' << *j;
}
}
+ if (show_targets) std::cout << std::endl;
}
else
{
}
else
{
- DEBUG_close << "failed\n";
std::cerr << "Failed to build";
for (string_list::const_iterator j = targets.begin(),
j_end = targets.end(); j != j_end; ++j)
std::cerr << "Failed to build";
for (string_list::const_iterator j = targets.begin(),
j_end = targets.end(); j != j_end; ++j)
@@
-2137,25
+2169,17
@@
static std::string prepare_script(job_t const &job)
*/
static status_e run_script(int job_id, job_t const &job)
{
*/
static status_e run_script(int job_id, job_t const &job)
{
- if (show_targets)
- {
- std::cout << "Building";
- for (string_list::const_iterator i = job.rule.targets.begin(),
- i_end = job.rule.targets.end(); i != i_end; ++i)
- {
- std::cout << ' ' << *i;
- }
- std::cout << std::endl;
- }
-
ref_ptr<dependency_t> dep;
dep->targets = job.rule.targets;
dep->deps.insert(job.rule.deps.begin(), job.rule.deps.end());
ref_ptr<dependency_t> dep;
dep->targets = job.rule.targets;
dep->deps.insert(job.rule.deps.begin(), job.rule.deps.end());
+ if (show_targets) std::cout << "Building";
for (string_list::const_iterator i = job.rule.targets.begin(),
i_end = job.rule.targets.end(); i != i_end; ++i)
{
dependencies[*i] = dep;
for (string_list::const_iterator i = job.rule.targets.begin(),
i_end = job.rule.targets.end(); i != i_end; ++i)
{
dependencies[*i] = dep;
+ if (show_targets) std::cout << ' ' << *i;
}
}
+ if (show_targets) std::cout << std::endl;
std::string script = prepare_script(job);
std::string script = prepare_script(job);
@@
-2792,6
+2816,10
@@
static void server_mode(std::string const &remakefile, string_list const &target
free(socket_name);
#endif
save_dependencies();
free(socket_name);
#endif
save_dependencies();
+ if (show_targets && changed_prefix_dir)
+ {
+ std::cout << "remake: Leaving directory `" << prefix_dir << '\'' << std::endl;
+ }
exit(build_failure ? EXIT_FAILURE : EXIT_SUCCESS);
}
exit(build_failure ? EXIT_FAILURE : EXIT_SUCCESS);
}
@@
-2927,8
+2955,6
@@
static void usage(int exit_status)
*/
int main(int argc, char *argv[])
{
*/
int main(int argc, char *argv[])
{
- init_working_dir();
-
std::string remakefile;
string_list targets;
bool literal_targets = false;
std::string remakefile;
string_list targets;
bool literal_targets = false;
@@
-2973,11
+2999,14
@@
int main(int argc, char *argv[])
continue;
}
new_target:
continue;
}
new_target:
- targets.push_back(
normalize(arg, working_dir, working_dir)
);
+ targets.push_back(
arg
);
DEBUG << "New target: " << arg << '\n';
}
}
DEBUG << "New target: " << arg << '\n';
}
}
+ init_working_dir();
+ normalize_list(targets, working_dir, working_dir);
+
if (indirect_targets)
{
load_dependencies(std::cin);
if (indirect_targets)
{
load_dependencies(std::cin);