From bddad27087113001954cb06864fc4a092c5bf0c4 Mon Sep 17 00:00:00 2001 From: rexim Date: Mon, 12 Jul 2021 23:54:25 +0700 Subject: [PATCH 1/8] Implement GO_REBUILD_URSELF --- .gitignore | 1 + nobuild.c | 4 ++- nobuild.h | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b053582..092269a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ nobuild +*.old output.txt \ No newline at end of file diff --git a/nobuild.c b/nobuild.c index 9821140..a9cbd9c 100644 --- a/nobuild.c +++ b/nobuild.c @@ -52,8 +52,10 @@ void print_chain(const Chain *chain) }); } -int main(void) +int main(int argc, char **argv) { + GO_REBUILD_URSELF(argc, argv); + build_tools(); run_examples(); diff --git a/nobuild.h b/nobuild.h index 9f57fab..3c16310 100644 --- a/nobuild.h +++ b/nobuild.h @@ -200,6 +200,31 @@ void chain_echo(Chain chain); chain_run_sync(chain); \ } while(0) +// TODO: REBUILD_URSELF does not distinguish MSVC and MinGW setups on Windows +#ifndef REBUILD_URSELF +# if _WIN32 +# define REBUILD_URSELF(binary_path, source_path) CMD("cl.exe", source_path) +# else +# define REBUILD_URSELF(binary_path, source_path) CMD("cc", "-o", binary_path, source_path) +# endif +#endif + +#define GO_REBUILD_URSELF(argc, argv) \ + do { \ + const char *source_path = __FILE__; \ + assert(argc >= 1); \ + const char *binary_path = argv[0]; \ + \ + if (is_path1_modified_after_path2(source_path, binary_path)) { \ + RENAME(binary_path, CONCAT(binary_path, ".old")); \ + REBUILD_URSELF(binary_path, source_path); \ + CMD(binary_path); \ + exit(0); \ + } \ + } while(0) + +void rebuild_urself(const char *binary_path, const char *source_path); + int path_is_dir(Cstr path); #define IS_DIR(path) path_is_dir(path) @@ -214,6 +239,13 @@ void path_mkdirs(Cstr_Array path); path_mkdirs(path); \ } while (0) +void path_rename(Cstr old_path, Cstr new_path); +#define RENAME(old_path, new_path) \ + do { \ + INFO("RENAME: %s -> %s", old_path, new_path); \ + path_rename(old_path, new_path); \ + } while (0) + void path_rm(Cstr path); #define RM(path) \ do { \ @@ -909,6 +941,21 @@ int path_is_dir(Cstr path) #endif // _WIN32 } +void path_rename(const char *old_path, const char *new_path) +{ +#ifdef _WIN32 + if (!MoveFileEx(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) { + PANIC("could not rename %s to %s: %s", old_path, new_path, + GetLastErrorAsString()); + } +#else + if (rename(old_path, new_path) < 0) { + PANIC("could not rename %s to %s: %s", old_path, new_path, + strerror(errno)); + } +#endif // _WIN32 +} + void path_mkdirs(Cstr_Array path) { if (path.count == 0) { @@ -977,6 +1024,41 @@ void path_rm(Cstr path) } } +int is_path1_modified_after_path2(const char *path1, const char *path2) +{ +#ifdef _WIN32 + FILETIME path1_time, path2_time; + + Fd path1_fd = fd_open_for_read(path1); + if (!GetFileTime(path1_fd, NULL, NULL, &path1_time)) { + PANIC("could not get time of %s: %s", path1, GetLastErrorAsString()); + } + fd_close(path1_fd); + + Fd path2_fd = fd_open_for_read(path2); + if (!GetFileTime(path2_fd, NULL, NULL, &path2_time)) { + PANIC("could not get time of %s: %s", path2, GetLastErrorAsString()); + } + fd_close(path2_fd); + + return CompareFileTime(&path1, &path2) == 1; +#else + struct stat statbuf = {0}; + + if (stat(path1, &statbuf) < 0) { + PANIC("could not stat %s: %s\n", path1, strerror(errno)); + } + int path1_time = statbuf.st_mtime; + + if (stat(path2, &statbuf) < 0) { + PANIC("could not stat %s: %s\n", path2, strerror(errno)); + } + int path2_time = statbuf.st_mtime; + + return path1_time > path2_time; +#endif +} + void VLOG(FILE *stream, Cstr tag, Cstr fmt, va_list args) { fprintf(stream, "[%s] ", tag); From 7638841b1bbe529bbb310572e38b5d99fcee3923 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:01:03 +0700 Subject: [PATCH 2/8] Try to change is_path1_modified_after_path2 Because I probably do not understand how CompareFileTime works --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index 3c16310..c62beca 100644 --- a/nobuild.h +++ b/nobuild.h @@ -1041,7 +1041,7 @@ int is_path1_modified_after_path2(const char *path1, const char *path2) } fd_close(path2_fd); - return CompareFileTime(&path1, &path2) == 1; + return CompareFileTime(&path1, &path2) == -1; #else struct stat statbuf = {0}; From fff3242d0989d9d8a0976f6af9225111792b5c5d Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:55 +0700 Subject: [PATCH 3/8] Add TODO(#28) --- nobuild.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index c62beca..2549f59 100644 --- a/nobuild.h +++ b/nobuild.h @@ -72,7 +72,7 @@ int closedir(DIR *dirp); #endif // MINIRENT_H_ // minirent.h HEADER END //////////////////////////////////////// -// TODO: use GetLastErrorAsString everywhere on Windows error reporting +// TODO(#28): use GetLastErrorAsString everywhere on Windows error reporting LPSTR GetLastErrorAsString(void); #endif // _WIN32 @@ -209,6 +209,7 @@ void chain_echo(Chain chain); # endif #endif +// TODO: we need to test GO_REBUILD_URSELF on a real Windows machine #define GO_REBUILD_URSELF(argc, argv) \ do { \ const char *source_path = __FILE__; \ From 68cf423351eb538c6de46080cc5b275dc68018f1 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:56 +0700 Subject: [PATCH 4/8] Add TODO(#29) --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index 2549f59..50d3369 100644 --- a/nobuild.h +++ b/nobuild.h @@ -200,7 +200,7 @@ void chain_echo(Chain chain); chain_run_sync(chain); \ } while(0) -// TODO: REBUILD_URSELF does not distinguish MSVC and MinGW setups on Windows +// TODO(#29): REBUILD_URSELF does not distinguish MSVC and MinGW setups on Windows #ifndef REBUILD_URSELF # if _WIN32 # define REBUILD_URSELF(binary_path, source_path) CMD("cl.exe", source_path) From b8b1b84502fa2ab78f38d101b3eb3f2bacf68762 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:56 +0700 Subject: [PATCH 5/8] Add TODO(#30) --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index 50d3369..528953b 100644 --- a/nobuild.h +++ b/nobuild.h @@ -209,7 +209,7 @@ void chain_echo(Chain chain); # endif #endif -// TODO: we need to test GO_REBUILD_URSELF on a real Windows machine +// TODO(#30): we need to test GO_REBUILD_URSELF on a real Windows machine #define GO_REBUILD_URSELF(argc, argv) \ do { \ const char *source_path = __FILE__; \ From 7d4dfeee214decdcc11ba6fbbd4220e20b809f7c Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:57 +0700 Subject: [PATCH 6/8] Add TODO(#31) --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index 528953b..50299d8 100644 --- a/nobuild.h +++ b/nobuild.h @@ -655,7 +655,7 @@ void pid_wait(Pid pid) Cstr cmd_show(Cmd cmd) { - // TODO: cmd_show does not render the command line properly + // TODO(#31): cmd_show does not render the command line properly // - No string literals when arguments contains space // - No escaping of special characters // - Etc. From 558a11054aa18f93166d7eb71c963e7e832fa599 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:58 +0700 Subject: [PATCH 7/8] Add TODO(#32) --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index 50299d8..d3d6844 100644 --- a/nobuild.h +++ b/nobuild.h @@ -673,7 +673,7 @@ Pid cmd_run_async(Cmd cmd, Fd *fdin, Fd *fdout) // NOTE: theoretically setting NULL to std handles should not be a problem // https://docs.microsoft.com/en-us/windows/console/getstdhandle?redirectedfrom=MSDN#attachdetach-behavior siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); - // TODO: check for errors in GetStdHandle + // TODO(#32): check for errors in GetStdHandle siStartInfo.hStdOutput = fdout ? *fdout : GetStdHandle(STD_OUTPUT_HANDLE); siStartInfo.hStdInput = fdin ? *fdin : GetStdHandle(STD_INPUT_HANDLE); siStartInfo.dwFlags |= STARTF_USESTDHANDLES; From c1ca9c4649faf8b66999ce5666855b6c98d732d2 Mon Sep 17 00:00:00 2001 From: rexim Date: Tue, 13 Jul 2021 00:05:58 +0700 Subject: [PATCH 8/8] Add TODO(#33) --- nobuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nobuild.h b/nobuild.h index d3d6844..9a8a347 100644 --- a/nobuild.h +++ b/nobuild.h @@ -684,7 +684,7 @@ Pid cmd_run_async(Cmd cmd, Fd *fdin, Fd *fdout) BOOL bSuccess = CreateProcess( NULL, - // TODO: cmd_run_async on Windows does not render command line properly + // TODO(#33): cmd_run_async on Windows does not render command line properly // It may require wrapping some arguments with double-quotes if they contains spaces, etc. cstr_array_join(" ", cmd.line), NULL,