341 #define WIN32_LEAN_AND_MEAN
360 #include <sys/stat.h>
361 #include <sys/types.h>
374 #include <winsock2.h>
378 #include <sys/socket.h>
380 #include <sys/wait.h>
385 #if defined(WINDOWS) || defined(MACOSX)
386 enum { MSG_NOSIGNAL = 0 };
415 if (
ptr == p.
ptr)
return *
this;
488 typedef std::map<std::string, ref_ptr<rule_t> >
rule_map;
632 static time_t
now = time(NULL);
661 if (
open) std::cerr << std::endl;
663 std::cerr << std::string(
depth * 2,
' ');
669 if (o &&
open) std::cerr << std::endl;
672 if (o || !
open) std::cerr << std::string(
depth * 2,
' ');
693 #define DEBUG if (debug.active) debug()
694 #define DEBUG_open log_auto_close auto_close; if (debug.active) debug(true)
695 #define DEBUG_close if ((auto_close.still_open = false), debug.active) debug(false)
714 std::string
const &s = se.
input;
715 char const *quoted_char =
",: '";
716 char const *escaped_char =
"\"\\$!";
717 bool need_quotes =
false;
719 size_t len = s.length(), last = 0, j = 0;
720 for (
size_t i = 0; i < len; ++i)
722 if (strchr(escaped_char, s[i]))
725 if (!buf) buf =
new char[len * 2];
726 memcpy(&buf[j], &s[last], i - last);
732 if (!need_quotes && strchr(quoted_char, s[i]))
735 if (!need_quotes)
return out << s;
737 if (!buf)
return out << s <<
'"';
739 out.write(&s[last], len - last);
750 char *res = getcwd(buf,
sizeof(buf));
753 perror(
"Failed to get working directory");
767 size_t ll = s.length();
768 if (ll == l)
return ".";
771 size_t pos = s.rfind(
'/', l);
772 assert(pos != std::string::npos);
773 return s.substr(pos + 1);
775 if (ll == l + 1)
return ".";
776 return s.substr(l + 1);
785 char const *delim =
"/\\";
789 size_t prev = 0, len = s.length();
790 size_t pos = s.find_first_of(delim);
791 if (pos == std::string::npos)
return s;
792 bool absolute = pos == 0;
798 std::string n = s.substr(prev, pos - prev);
801 if (!l.empty()) l.pop_back();
809 if (pos >= len)
break;
811 pos = s.find_first_of(delim, prev);
812 if (pos == std::string::npos) pos = len;
814 string_list::const_iterator i = l.begin(), i_end = l.end();
815 if (i == i_end)
return absolute ?
"/" :
".";
817 if (absolute) n.push_back(
'/');
819 for (++i; i != i_end; ++i)
833 for (string_list::iterator i = l.begin(),
834 i_end = l.end(); i != i_end; ++i)
846 while (strchr(
" \t", (c = in.get()))) {}
847 if (in.good()) in.putback(c);
856 while (strchr(
"\r\n", (c = in.get()))) {}
857 if (in.good()) in.putback(c);
864 static bool skip_eol(std::istream &in,
bool multi =
false)
867 if (c ==
'\r') c = in.get();
868 if (c !=
'\n' && in.good()) in.putback(c);
869 if (c !=
'\n' && !in.eof())
return false;
904 case ':': tok =
Colon;
break;
905 case ',': tok =
Comma;
break;
906 case '=': tok =
Equal;
break;
941 if (!in.good())
return res;
942 char const *separators =
" \t\r\n:$(),=+\"";
943 bool quoted = c ==
'"';
946 if (strchr(separators, c))
956 if (!in.good())
return res;
968 if (strchr(separators, c))
988 std::cerr <<
"Failed to load rules: syntax error" << std::endl;
996 size_t fixl = fix.size();
997 if (name ==
"addprefix")
999 for (string_list::const_iterator i = names.begin(),
1000 i_end = names.end(); i != i_end; ++i)
1007 string_list::const_iterator k = fix.begin();
1008 for (
size_t j = 1; j != fixl; ++j)
1010 dest.push_back(*k++);
1012 dest.push_back(*k++ + *i);
1015 else if (name ==
"addsuffix")
1017 for (string_list::const_iterator i = names.begin(),
1018 i_end = names.end(); i != i_end; ++i)
1025 string_list::const_iterator k = fix.begin();
1026 dest.push_back(*i + *k++);
1027 for (
size_t j = 1; j != fixl; ++j)
1029 dest.push_back(*k++);
1044 std::cerr <<
"Failed to load rules: syntax error" << std::endl;
1058 if (name.empty())
goto error;
1061 variable_map::const_iterator i =
variables.find(name);
1063 res.insert(res.end(), i->second.begin(), i->second.end());
1082 if (targets.empty())
return;
1083 DEBUG <<
"reading dependencies of target " << targets.front() << std::endl;
1084 if (in.get() !=
':')
1086 std::cerr <<
"Failed to load database" << std::endl;
1092 dep->
deps.insert(d.begin(), d.end());
1093 for (string_list::const_iterator i = targets.begin(),
1094 i_end = targets.end(); i != i_end; ++i)
1108 std::ifstream in(
".remake");
1127 assert(rule.
script.empty());
1128 for (string_list::const_iterator i = rule.
targets.begin(),
1129 i_end = rule.
targets.end(); i != i_end; ++i)
1131 std::pair<rule_map::iterator, bool> j =
1142 std::cerr <<
"Failed to load rules: " << *i
1143 <<
" cannot be the target of several rules" << std::endl;
1151 for (string_list::const_iterator i = rule.
targets.begin(),
1152 i_end = rule.
targets.end(); i != i_end; ++i)
1172 for (string_list::const_iterator i = rule.
targets.begin(),
1173 i_end = rule.
targets.end(); i != i_end; ++i)
1175 std::pair<rule_map::iterator, bool> j =
1177 if (j.second)
continue;
1178 std::cerr <<
"Failed to load rules: " << *i
1179 <<
" cannot be the target of several rules" << std::endl;
1186 for (string_list::const_iterator i = rule.
targets.begin(),
1187 i_end = rule.
targets.end(); i != i_end; ++i)
1199 static void load_rule(std::istream &in, std::string
const &first)
1201 DEBUG_open <<
"Reading rule for target " << first <<
"... ";
1206 std::cerr <<
"Failed to load rules: syntax error" << std::endl;
1213 if (!first.empty()) targets.push_front(first);
1214 else if (targets.empty())
goto error;
1215 else DEBUG <<
"actual target: " << targets.front() << std::endl;
1216 bool generic =
false;
1218 for (string_list::const_iterator i = targets.begin(),
1219 i_end = targets.end(); i != i_end; ++i)
1221 if (i->empty())
goto error;
1222 if ((i->find(
'%') != std::string::npos) !=
generic)
1224 if (i == targets.begin())
generic =
true;
1228 std::swap(rule.
targets, targets);
1230 if (in.get() !=
':')
goto error;
1232 bool assignment =
false;
1263 if (!
skip_eol(in,
true))
goto error;
1266 std::ostringstream buf;
1270 if (!in.good())
break;
1271 if (c ==
'\t' || c ==
' ')
1273 in.get(*buf.rdbuf());
1274 if (in.fail() && !in.eof()) in.clear();
1276 else if (c ==
'\r' || c ==
'\n')
1289 if (assignment)
goto error;
1294 if (!rule.
script.empty())
1296 if (assignment)
goto error;
1313 std::ofstream db(
".remake");
1317 for (string_list::const_iterator i = dep->
targets.begin(),
1318 i_end = dep->
targets.end(); i != i_end; ++i)
1324 for (string_set::const_iterator i = dep->
deps.begin(),
1325 i_end = dep->
deps.end(); i != i_end; ++i)
1344 std::cerr <<
"Failed to load rules: syntax error" << std::endl;
1347 std::ifstream in(
"Remakefile");
1350 std::cerr <<
"Failed to load rules: no Remakefile found" << std::endl;
1361 while (in.get() !=
'\n') {}
1365 if (c ==
' ' || c ==
'\t')
goto error;
1369 if (name.empty())
goto error;
1372 DEBUG <<
"Assignment to variable " << name << std::endl;
1375 if (tok ==
Equal) dest.swap(value);
1376 else dest.splice(dest.end(), value);
1377 if (!
skip_eol(in,
true))
goto error;
1390 for (string_list::const_iterator i = src.begin(),
1391 i_end = src.end(); i != i_end; ++i)
1393 size_t pos = i->find(
'%');
1394 if (pos == std::string::npos)dst.push_back(*i);
1395 else dst.push_back(i->substr(0, pos) + pat + i->substr(pos + 1));
1406 size_t tlen = target.length(), plen = tlen + 1;
1411 for (string_list::const_iterator j = i->targets.begin(),
1412 j_end = i->targets.end(); j != j_end; ++j)
1414 size_t len = j->length();
1415 if (tlen < len)
continue;
1416 if (plen <= tlen - (len - 1))
continue;
1417 size_t pos = j->find(
'%');
1418 if (pos == std::string::npos)
continue;
1419 size_t len2 = len - (pos + 1);
1420 if (j->compare(0, pos, target, 0, pos) ||
1421 j->compare(pos + 1, len2, target, tlen - len2, len2))
1423 plen = tlen - (len - 1);
1424 std::string pat = target.substr(pos, plen);
1445 if (i != i_end && !i->second->script.empty())
return *i->second;
1448 if (grule.targets.empty())
1450 if (i != i_end)
return *i->second;
1454 if (grule.targets.size() == 1)
1456 if (i == i_end)
return grule;
1457 grule.
deps.insert(grule.deps.end(),
1458 i->second->deps.begin(), i->second->deps.end());
1459 grule.vars.insert(grule.vars.end(),
1460 i->second->vars.begin(), i->second->vars.end());
1465 for (string_list::const_iterator j = grule.targets.begin(),
1466 j_end = grule.targets.end(); j != j_end; ++j)
1469 if (i == i_end)
continue;
1470 if (!i->second->script.empty())
return rule_t();
1471 grule.
deps.insert(grule.deps.end(),
1472 i->second->deps.begin(), i->second->deps.end());
1473 grule.vars.insert(grule.vars.end(),
1474 i->second->vars.begin(), i->second->vars.end());
1491 std::pair<status_map::iterator,bool> i =
1494 if (!i.second)
return ts;
1495 DEBUG_open <<
"Checking status of " << target <<
"... ";
1496 dependency_map::const_iterator j =
dependencies.find(target);
1500 if (stat(target.c_str(), &s) != 0)
1509 ts.
last = s.st_mtime;
1515 for (string_list::const_iterator k = dep.
targets.begin(),
1516 k_end = dep.
targets.end(); k != k_end; ++k)
1519 if (stat(k->c_str(), &s) != 0)
1525 status[*k].last = s.st_mtime;
1526 if (s.st_mtime > latest) latest = s.st_mtime;
1528 if (st ==
Todo)
goto update;
1529 for (string_set::const_iterator k = dep.
deps.begin(),
1530 k_end = dep.
deps.end(); k != k_end; ++k)
1533 if (latest < ts_.
last)
1541 DEBUG <<
"obsolete dependency " << *k << std::endl;
1546 for (string_list::const_iterator k = dep.
targets.begin(),
1547 k_end = dep.
targets.end(); k != k_end; ++k)
1560 DEBUG_open <<
"Rechecking status of " << target <<
"... ";
1561 status_map::iterator i =
status.find(target);
1562 assert(i !=
status.end());
1571 if (stat(target.c_str(), &s) != 0)
1576 else if (s.st_mtime != ts.last)
1579 ts.last = s.st_mtime;
1593 DEBUG_open <<
"Rechecking obsoleteness of " << target <<
"... ";
1594 status_map::const_iterator i =
status.find(target);
1595 assert(i !=
status.end());
1596 if (i->second.status !=
Recheck)
return true;
1597 dependency_map::const_iterator j =
dependencies.find(target);
1600 for (string_set::const_iterator k = dep.deps.begin(),
1601 k_end = dep.deps.end(); k != k_end; ++k)
1605 for (string_list::const_iterator k = dep.targets.begin(),
1606 k_end = dep.targets.end(); k != k_end; ++k)
1619 DEBUG_open <<
"Completing job " << job_id <<
"... ";
1620 job_targets_map::iterator i =
job_targets.find(job_id);
1625 for (string_list::const_iterator j = targets.begin(),
1626 j_end = targets.end(); j != j_end; ++j)
1634 std::cerr <<
"Failed to build";
1635 for (string_list::const_iterator j = targets.begin(),
1636 j_end = targets.end(); j != j_end; ++j)
1639 std::cerr <<
' ' << *j;
1642 std::cerr << std::endl;
1654 std::cout <<
"Building";
1655 for (string_list::const_iterator i = rule.
targets.begin(),
1656 i_end = rule.
targets.end(); i != i_end; ++i)
1658 std::cout <<
' ' << *i;
1660 std::cout << std::endl;
1666 for (string_list::const_iterator i = rule.
targets.begin(),
1667 i_end = rule.
targets.end(); i != i_end; ++i)
1674 for (assign_list::const_iterator i = rule.
vars.begin(),
1675 i_end = rule.
vars.end(); i != i_end; ++i)
1678 if (!i->append) val.clear();
1679 val.insert(val.end(), i->value.begin(), i->value.end());
1683 std::ostringstream script_buf;
1684 for (variable_map::const_iterator i = vars.begin(),
1685 i_end = vars.end(); i != i_end; ++i)
1687 std::ostringstream var;
1689 for (string_list::const_iterator j = i->second.begin(),
1690 j_end = i->second.end(); j != j_end; ++j)
1692 if (first) first =
false;
1696 script_buf << i->first <<
'=' <<
escape_string(var.str()) << std::endl;
1698 script_buf << rule.
script;
1699 std::string
const &script = script_buf.str();
1701 DEBUG_open <<
"Starting script for job " << job_id <<
"... ";
1707 CloseHandle(pfd[0]);
1708 CloseHandle(pfd[1]);
1714 if (!CreatePipe(&pfd[0], &pfd[1], NULL, 0))
1716 if (!SetHandleInformation(pfd[0], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
1719 ZeroMemory(&si,
sizeof(STARTUPINFO));
1720 si.cb =
sizeof(STARTUPINFO);
1721 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
1722 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
1723 si.hStdInput = pfd[0];
1724 si.dwFlags |= STARTF_USESTDHANDLES;
1725 PROCESS_INFORMATION pi;
1726 ZeroMemory(&pi,
sizeof(PROCESS_INFORMATION));
1727 std::ostringstream buf;
1729 if (!SetEnvironmentVariable(
"REMAKE_JOB_ID", buf.str().c_str()))
1731 std::ostringstream argv;
1732 argv <<
"SH.EXE -e -s";
1734 for (string_list::const_iterator i = rule.
targets.begin(),
1735 i_end = rule.
targets.end(); i != i_end; ++i)
1739 if (!CreateProcess(NULL, (
char *)argv.str().c_str(), NULL, NULL,
1740 true, 0, NULL, NULL, &si, &pi))
1744 CloseHandle(pi.hThread);
1745 DWORD len = script.length(), wlen;
1746 if (!WriteFile(pfd[1], script.c_str(), len, &wlen, NULL) || wlen < len)
1747 std::cerr <<
"Unexpected failure while sending script to shell" << std::endl;
1748 CloseHandle(pfd[0]);
1749 CloseHandle(pfd[1]);
1765 if (pipe(pfd) == -1)
1767 if (pid_t pid = fork())
1769 if (pid == -1)
goto error2;
1770 ssize_t len = script.length();
1771 if (write(pfd[1], script.c_str(), len) < len)
1772 std::cerr <<
"Unexpected failure while sending script to shell" << std::endl;
1780 std::ostringstream buf;
1782 if (setenv(
"REMAKE_JOB_ID", buf.str().c_str(), 1))
1783 _exit(EXIT_FAILURE);
1785 char const **argv =
new char const *[num + rule.
targets.size() + 1];
1790 for (string_list::const_iterator i = rule.
targets.begin(),
1791 i_end = rule.
targets.end(); i != i_end; ++i, ++num)
1793 argv[num] = i->c_str();
1802 execv(
"/bin/sh", (
char **)argv);
1803 _exit(EXIT_FAILURE);
1813 static bool start(std::string
const &target, client_list::iterator ¤t)
1821 std::cerr <<
"No rule for building " << target << std::endl;
1824 for (string_list::const_iterator i = rule.
targets.begin(),
1825 i_end = rule.
targets.end(); i != i_end; ++i)
1831 if (!rule.
deps.empty())
1834 current->job_id = job_id;
1835 current->pending = rule.
deps;
1836 current->delayed =
new rule_t(rule);
1848 DEBUG_open <<
"Completing request from client of job " << client.
job_id <<
"... ";
1863 char res = success ? 1 : 0;
1864 send(client.
socket, &res, 1, 0);
1866 closesocket(client.
socket);
1898 DEBUG_open <<
"Handling client requests... ";
1901 for (client_list::iterator i =
clients.begin(), i_next = i,
1905 DEBUG_open <<
"Handling client from job " << i->job_id <<
"... ";
1916 for (string_set::iterator j = i->running.begin(), j_next = j,
1917 j_end = i->running.end(); j != j_end; j = j_next)
1920 status_map::const_iterator k =
status.find(*j);
1921 assert(k !=
status.end());
1922 switch (k->second.status)
1932 i->running.erase(j);
1941 while (!i->pending.empty())
1943 std::string target = i->pending.front();
1944 i->pending.pop_front();
1948 i->running.insert(target);
1960 client_list::iterator j = i;
1961 if (!
start(target, i))
goto pending_failed;
1962 j->running.insert(target);
1973 if (i->running.empty())
1975 if (i->failed)
goto failed;
1988 std::cerr <<
"Circular dependency detected" << std::endl;
1989 client_list::iterator i =
clients.begin();
2005 perror(
"Failed to create server");
2015 struct sockaddr_in socket_addr;
2016 socket_addr.sin_family = AF_INET;
2017 socket_addr.sin_addr.s_addr = inet_addr(
"127.0.0.1");
2018 socket_addr.sin_port = 0;
2021 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
2023 if (!SetHandleInformation((HANDLE)
socket_fd, HANDLE_FLAG_INHERIT, 0))
2025 if (bind(socket_fd, (
struct sockaddr *)&socket_addr,
sizeof(sockaddr_in)))
2027 int len =
sizeof(sockaddr_in);
2028 if (getsockname(socket_fd, (
struct sockaddr *)&socket_addr, &len))
2030 std::ostringstream buf;
2031 buf << socket_addr.sin_port;
2032 if (!SetEnvironmentVariable(
"REMAKE_SOCKET", buf.str().c_str()))
2034 if (listen(socket_fd, 1000))
goto error;
2039 sigemptyset(&sigmask);
2040 sigaddset(&sigmask, SIGCHLD);
2041 if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1)
goto error;
2042 struct sigaction sa;
2044 sigemptyset(&sa.sa_mask);
2046 if (sigaction(SIGCHLD, &sa, NULL) == -1)
goto error;
2048 if (sigaction(SIGINT, &sa, NULL) == -1)
goto error;
2053 struct sockaddr_un socket_addr;
2055 if (len >=
sizeof(socket_addr.sun_path) - 1)
goto error2;
2056 socket_addr.sun_family = AF_UNIX;
2058 len +=
sizeof(socket_addr.sun_family);
2059 if (setenv(
"REMAKE_SOCKET",
socket_name, 1))
goto error;
2063 socket_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
2064 if (socket_fd < 0)
goto error;
2066 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
2067 if (socket_fd < 0)
goto error;
2068 if (fcntl(socket_fd, F_SETFD, FD_CLOEXEC) < 0)
goto error;
2070 if (bind(socket_fd, (
struct sockaddr *)&socket_addr, len))
2072 if (listen(socket_fd, 1000))
goto error;
2088 if (!SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0))
2091 std::cerr <<
"Unexpected failure while setting connection with client" << std::endl;
2097 if (ioctlsocket(fd, FIONBIO, &nbio))
goto error2;
2098 #elif defined(LINUX)
2099 int fd = accept4(
socket_fd, NULL, NULL, SOCK_CLOEXEC);
2104 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
return;
2107 client_list::iterator proc =
clients.begin();
2113 std::cerr <<
"Received an ill-formed client message" << std::endl;
2124 std::vector<char> buf;
2126 while (len <
sizeof(
int) + 2 || buf[len - 1] || buf[len - 2])
2128 buf.resize(len + 1024);
2129 ssize_t l = recv(fd, &buf[0] + len, 1024, 0);
2130 if (l <= 0)
goto error;
2136 memcpy(&job_id, &buf[0],
sizeof(
int));
2138 proc->job_id = job_id;
2139 job_targets_map::const_iterator i =
job_targets.find(job_id);
2141 DEBUG <<
"receiving request from job " << job_id << std::endl;
2145 char const *p = &buf[0] +
sizeof(int);
2154 std::string target(p, p + len);
2155 DEBUG <<
"adding dependency " << target <<
" to job\n";
2156 proc->pending.push_back(target);
2157 dep.
deps.insert(target);
2167 pid_job_map::iterator i =
job_pids.find(pid);
2169 int job_id = i->second;
2189 for (pid_job_map::const_iterator i =
job_pids.begin(),
2190 i_end =
job_pids.end(); i != i_end; ++i, ++num)
2194 WSAEVENT aev = WSACreateEvent();
2196 WSAEventSelect(
socket_fd, aev, FD_ACCEPT);
2197 DWORD w = WaitForMultipleObjects(len, h,
false, INFINITE);
2200 if (w < WAIT_OBJECT_0 || WAIT_OBJECT_0 + len <= w)
2202 if (w == WAIT_OBJECT_0 + len - 1)
2207 pid_t pid = h[w - WAIT_OBJECT_0];
2209 bool res = GetExitCodeProcess(pid, &s) && s == 0;
2214 sigemptyset(&emptymask);
2218 int ret = pselect(
socket_fd + 1, &fdset, NULL, NULL, NULL, &emptymask);
2224 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
2226 bool res = WIFEXITED(status) && WEXITSTATUS(status) == 0;
2249 clients.back().pending.push_back(
"Remakefile");
2259 if (!targets.empty())
clients.back().pending = targets;
2282 perror(
"Failed to send targets to server");
2285 if (targets.empty()) exit(EXIT_SUCCESS);
2290 struct sockaddr_in socket_addr;
2291 socket_fd = socket(AF_INET, SOCK_STREAM, 0);
2293 socket_addr.sin_family = AF_INET;
2294 socket_addr.sin_addr.s_addr = inet_addr(
"127.0.0.1");
2295 socket_addr.sin_port = atoi(socket_name);
2296 if (connect(
socket_fd, (
struct sockaddr *)&socket_addr,
sizeof(sockaddr_in)))
2299 struct sockaddr_un socket_addr;
2300 size_t len = strlen(socket_name);
2301 if (len >=
sizeof(socket_addr.sun_path) - 1) exit(EXIT_FAILURE);
2302 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
2304 socket_addr.sun_family = AF_UNIX;
2305 strcpy(socket_addr.sun_path, socket_name);
2306 if (connect(
socket_fd, (
struct sockaddr *)&socket_addr,
sizeof(socket_addr.sun_family) + len))
2310 if (setsockopt(
socket_fd, SOL_SOCKET, SO_NOSIGPIPE, &set_option,
sizeof(set_option)))
2316 char *
id = getenv(
"REMAKE_JOB_ID");
2317 int job_id =
id ? atoi(
id) : -1;
2318 if (send(
socket_fd, (
char *)&job_id,
sizeof(job_id), MSG_NOSIGNAL) !=
sizeof(job_id))
2322 for (string_list::const_iterator i = targets.begin(),
2323 i_end = targets.end(); i != i_end; ++i)
2326 ssize_t len = i->length() + 1;
2327 if (send(
socket_fd, i->c_str(), len, MSG_NOSIGNAL) != len)
2333 if (send(
socket_fd, &result, 1, MSG_NOSIGNAL) != 1)
goto error;
2334 if (recv(
socket_fd, &result, 1, 0) != 1) exit(EXIT_FAILURE);
2335 exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
2343 std::cerr <<
"Usage: remake [options] [target] ...\n"
2345 " -d Echo script commands.\n"
2346 " -d -d Print lots of debugging information.\n"
2347 " -h, --help Print this message and exit.\n"
2348 " -j[N], --jobs=[N] Allow N jobs at once; infinite jobs with no arg.\n"
2349 " -k Keep going when some targets cannot be made.\n"
2350 " -r Look up targets from the dependencies on standard input.\n"
2351 " -s, --silent, --quiet Do not echo targets.\n";
2371 bool indirect_targets =
false;
2374 for (
int i = 1; i < argc; ++i)
2376 std::string arg = argv[i];
2377 if (arg.empty())
usage(EXIT_FAILURE);
2378 if (arg ==
"-h" || arg ==
"--help")
usage(EXIT_SUCCESS);
2382 else if (arg ==
"-k" || arg ==
"--keep-going")
2384 else if (arg ==
"-s" || arg ==
"--silent" || arg ==
"--quiet")
2386 else if (arg ==
"-r")
2387 indirect_targets =
true;
2388 else if (arg.compare(0, 2,
"-j") == 0)
2390 else if (arg.compare(0, 7,
"--jobs=") == 0)
2394 if (arg[0] ==
'-')
usage(1);
2396 DEBUG <<
"New target: " << arg <<
'\n';
2400 if (indirect_targets)
2407 l.push_back(
dependencies.begin()->second->targets.front());
2409 for (string_list::const_iterator i = l.begin(),
2410 i_end = l.end(); i != i_end; ++i)
2412 dependency_map::const_iterator j =
dependencies.find(*i);
2415 for (string_set::const_iterator k = dep.
deps.begin(),
2416 k_end = dep.
deps.end(); k != k_end; ++k)
2426 if (WSAStartup(MAKEWORD(2,2), &wsaData))
2428 std::cerr <<
"Unexpected failure while initializing Windows Socket" << std::endl;
2434 if (
char *sn = getenv(
"REMAKE_SOCKET"))
client_mode(sn, targets);