From 3dfc363bf140b2d385f48a53d05a8cdd72fc7033 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kim=20Nguy=E1=BB=85n?= Date: Sun, 8 Dec 2013 11:31:26 +0100 Subject: [PATCH] Update to latest master of remake. Add a workaround to silence the linker warning when building remake in the configure script. --- configure.in | 16 ++++-- remake.cpp | 143 ++++++++++++++++++++------------------------------- 2 files changed, 68 insertions(+), 91 deletions(-) diff --git a/configure.in b/configure.in index 478a416..5bcb4c0 100644 --- a/configure.in +++ b/configure.in @@ -228,16 +228,24 @@ AC_PROG_CXX() AC_SUBST([REMAKE], [./remake$EXE]) if test ! -x "$REMAKE" -o "$REMAKE" -ot remake.cpp; then AC_MSG_NOTICE([creating $REMAKE]) +REMAKE_LOG=build_remake.log case $(uname -s) in MINGW*) - $CXX -Wall -O2 -o remake.exe remake.cpp -lws2_32 - if test $? != 0; then AC_MSG_FAILURE([failed]); fi + $CXX -Wall -O2 -o remake.exe remake.cpp -lws2_32 > "$REMAKE_LOG" 2>&1 + if test $? != 0; then + cat "$REMAKE_LOG"; rm -f "$REMAKE_LOG"; + AC_MSG_FAILURE([failed]); + fi ;; *) - $CXX -Wall -O2 -o remake remake.cpp - if test $? != 0; then AC_MSG_FAILURE([failed]); fi + $CXX -Wall -O2 -o remake remake.cpp > "$REMAKE_LOG" 2>&1 + if test $? != 0; then + cat "$REMAKE_LOG"; rm -f "$REMAKE_LOG"; + AC_MSG_FAILURE([failed]); + fi ;; esac +rm -f "$REMAKE_LOG"; else AC_MSG_NOTICE([$REMAKE exists, not rebuilding]) fi diff --git a/remake.cpp b/remake.cpp index 30440a8..de68c4d 100644 --- a/remake.cpp +++ b/remake.cpp @@ -343,7 +343,7 @@ https://github.com/apenwarr/redo for an implementation and some comprehensive do \section sec-licensing Licensing @author Guillaume Melquiond -@version 0.9 +@version 0.10 @date 2012-2013 @copyright This program is free software: you can redistribute it and/or modify @@ -373,8 +373,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 - calls #run_script otherwise. In both cases, a new job is created and its - targets are put into #job_targets. + calls #run_script otherwise. In both cases, a new job is created; the + rule and the variables are stored into #jobs. - #run_script creates a shell process and stores it in #job_pids. It increases #running_jobs. - The child process possibly calls remake with a list of targets. @@ -392,7 +392,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. -- #complete_job removes the job from #job_targets 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. */ @@ -668,7 +668,7 @@ static int waiting_jobs = 0; /** * Global counter used to produce increasing job numbers. - * @see job_targets + * @see jobs */ static int job_counter = 0; @@ -720,15 +720,14 @@ static std::string working_dir; static std::string prefix_dir; /** - * Whether target-specific variables are propagated to prerequisites. + * Whether the prefix directory is different from #working_dir. */ -static bool propagate_vars = false; - +static bool changed_prefix_dir; /** - * Whether to print that we changed working directory (to be nice with emacs) + * Whether target-specific variables are propagated to prerequisites. */ -static bool print_change_working_dir = false; +static bool propagate_vars = false; #ifndef WINDOWS static volatile sig_atomic_t got_SIGCHLD = 0; @@ -871,28 +870,22 @@ static void init_working_dir() */ static void init_prefix_dir() { - std::string old_prefix_dir = prefix_dir; for (;;) { struct stat s; if (stat((prefix_dir + "/Remakefile").c_str(), &s) == 0) { - if (0 == chdir(prefix_dir.c_str())) + if (!changed_prefix_dir) return; + if (chdir(prefix_dir.c_str())) { - if (old_prefix_dir != prefix_dir) - { - std::cout << "remake: Entering directory `" - << prefix_dir << "'" - << std::endl; - print_change_working_dir = true; - } - return; + perror("Failed to change working directory"); + exit(EXIT_FAILURE); } - else + if (show_targets) { - std::cerr << "Cannot change working directory to '" << prefix_dir << "'"; - exit(EXIT_FAILURE); + std::cout << "remake: Entering directory `" << prefix_dir << '\'' << std::endl; } + return; } size_t pos = prefix_dir.find_last_of('/'); if (pos == std::string::npos) @@ -901,6 +894,7 @@ static void init_prefix_dir() exit(EXIT_FAILURE); } prefix_dir.erase(pos); + changed_prefix_dir = true; } } @@ -1097,44 +1091,44 @@ static int expect_token(std::istream &in, int mask) /** * 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; - char const *separators = " \t\r\n:$(),=+\""; + char const *separators = " \t\r\n$(),:"; 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) { - c = in.get(); + c = in.peek(); if (!in.good()) return res; if (quoted) { + in.ignore(1); if (c == '\\') res += in.get(); else if (c == '"') - return res; + quoted = false; 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; } } @@ -1239,11 +1233,11 @@ input_status input_generator::next(std::string &res) switch (expect_token(in, Word | Dollarpar)) { case Word: - res = read_word(in); + res = read_word(in, false); 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); @@ -2042,21 +2036,23 @@ static bool still_need_rebuild(std::string const &target) */ 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) { + 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); + if (show_targets) std::cout << ' ' << *j; } + if (show_targets) std::cout << std::endl; } 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) @@ -2158,25 +2154,17 @@ static std::string prepare_script(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 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; + if (show_targets) std::cout << ' ' << *i; } + if (show_targets) std::cout << std::endl; std::string script = prepare_script(job); @@ -2560,28 +2548,7 @@ static void create_server() if (sigaction(SIGINT, &sa, NULL) == -1) goto error; // Prepare a named unix socket in temporary directory. - struct stat tmpstat; - char * tmpdir; - if ((0 == stat(tmpdir = getenv("TMPDIR"), &tmpstat) - && (S_ISDIR(tmpstat.st_mode))) - || ((0 == stat(tmpdir = (char*)P_tmpdir, &tmpstat)) - && (S_ISDIR(tmpstat.st_mode))) - || ((0 == stat(tmpdir = (char*)"/tmp", &tmpstat)) - && (S_ISDIR(tmpstat.st_mode)))); - else goto error; - std::stringstream tmpname; - long int rnd = now ^ getpid(); - do - { - srandom(rnd); - rnd = random(); - tmpname << tmpdir << "/rmk-"; - tmpname.fill('0'); - tmpname.width(8); - tmpname << rnd; - } - while (access (tmpname.str().c_str(), F_OK) == 0); - socket_name = strdup(tmpname.str().c_str()); + socket_name = tempnam(NULL, "rmk-"); if (!socket_name) goto error2; struct sockaddr_un socket_addr; size_t len = strlen(socket_name); @@ -2834,9 +2801,10 @@ static void server_mode(std::string const &remakefile, string_list const &target free(socket_name); #endif save_dependencies(); - if (print_change_working_dir) - std::cout << "remake: Leaving directory `" << prefix_dir - << "'" <