Skip to content
This repository was archived by the owner on Feb 12, 2025. It is now read-only.

Commit bddad27

Browse files
committed
Implement GO_REBUILD_URSELF
1 parent 590cfff commit bddad27

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
nobuild
2+
*.old
23
output.txt

nobuild.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ void print_chain(const Chain *chain)
5252
});
5353
}
5454

55-
int main(void)
55+
int main(int argc, char **argv)
5656
{
57+
GO_REBUILD_URSELF(argc, argv);
58+
5759
build_tools();
5860
run_examples();
5961

nobuild.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,31 @@ void chain_echo(Chain chain);
200200
chain_run_sync(chain); \
201201
} while(0)
202202

203+
// TODO: REBUILD_URSELF does not distinguish MSVC and MinGW setups on Windows
204+
#ifndef REBUILD_URSELF
205+
# if _WIN32
206+
# define REBUILD_URSELF(binary_path, source_path) CMD("cl.exe", source_path)
207+
# else
208+
# define REBUILD_URSELF(binary_path, source_path) CMD("cc", "-o", binary_path, source_path)
209+
# endif
210+
#endif
211+
212+
#define GO_REBUILD_URSELF(argc, argv) \
213+
do { \
214+
const char *source_path = __FILE__; \
215+
assert(argc >= 1); \
216+
const char *binary_path = argv[0]; \
217+
\
218+
if (is_path1_modified_after_path2(source_path, binary_path)) { \
219+
RENAME(binary_path, CONCAT(binary_path, ".old")); \
220+
REBUILD_URSELF(binary_path, source_path); \
221+
CMD(binary_path); \
222+
exit(0); \
223+
} \
224+
} while(0)
225+
226+
void rebuild_urself(const char *binary_path, const char *source_path);
227+
203228
int path_is_dir(Cstr path);
204229
#define IS_DIR(path) path_is_dir(path)
205230

@@ -214,6 +239,13 @@ void path_mkdirs(Cstr_Array path);
214239
path_mkdirs(path); \
215240
} while (0)
216241

242+
void path_rename(Cstr old_path, Cstr new_path);
243+
#define RENAME(old_path, new_path) \
244+
do { \
245+
INFO("RENAME: %s -> %s", old_path, new_path); \
246+
path_rename(old_path, new_path); \
247+
} while (0)
248+
217249
void path_rm(Cstr path);
218250
#define RM(path) \
219251
do { \
@@ -909,6 +941,21 @@ int path_is_dir(Cstr path)
909941
#endif // _WIN32
910942
}
911943

944+
void path_rename(const char *old_path, const char *new_path)
945+
{
946+
#ifdef _WIN32
947+
if (!MoveFileEx(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) {
948+
PANIC("could not rename %s to %s: %s", old_path, new_path,
949+
GetLastErrorAsString());
950+
}
951+
#else
952+
if (rename(old_path, new_path) < 0) {
953+
PANIC("could not rename %s to %s: %s", old_path, new_path,
954+
strerror(errno));
955+
}
956+
#endif // _WIN32
957+
}
958+
912959
void path_mkdirs(Cstr_Array path)
913960
{
914961
if (path.count == 0) {
@@ -977,6 +1024,41 @@ void path_rm(Cstr path)
9771024
}
9781025
}
9791026

1027+
int is_path1_modified_after_path2(const char *path1, const char *path2)
1028+
{
1029+
#ifdef _WIN32
1030+
FILETIME path1_time, path2_time;
1031+
1032+
Fd path1_fd = fd_open_for_read(path1);
1033+
if (!GetFileTime(path1_fd, NULL, NULL, &path1_time)) {
1034+
PANIC("could not get time of %s: %s", path1, GetLastErrorAsString());
1035+
}
1036+
fd_close(path1_fd);
1037+
1038+
Fd path2_fd = fd_open_for_read(path2);
1039+
if (!GetFileTime(path2_fd, NULL, NULL, &path2_time)) {
1040+
PANIC("could not get time of %s: %s", path2, GetLastErrorAsString());
1041+
}
1042+
fd_close(path2_fd);
1043+
1044+
return CompareFileTime(&path1, &path2) == 1;
1045+
#else
1046+
struct stat statbuf = {0};
1047+
1048+
if (stat(path1, &statbuf) < 0) {
1049+
PANIC("could not stat %s: %s\n", path1, strerror(errno));
1050+
}
1051+
int path1_time = statbuf.st_mtime;
1052+
1053+
if (stat(path2, &statbuf) < 0) {
1054+
PANIC("could not stat %s: %s\n", path2, strerror(errno));
1055+
}
1056+
int path2_time = statbuf.st_mtime;
1057+
1058+
return path1_time > path2_time;
1059+
#endif
1060+
}
1061+
9801062
void VLOG(FILE *stream, Cstr tag, Cstr fmt, va_list args)
9811063
{
9821064
fprintf(stream, "[%s] ", tag);

0 commit comments

Comments
 (0)