-
Notifications
You must be signed in to change notification settings - Fork 134
Expand file tree
/
Copy pathbuild.sh
More file actions
executable file
·8486 lines (8476 loc) · 239 KB
/
build.sh
File metadata and controls
executable file
·8486 lines (8476 loc) · 239 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/sh
# MIT License
# Autark (https://autark.dev) build system script wrapper.
# Copyright (c) 2012-2025 Softmotions Ltd <info@softmotions.com>
#
# https://github.com/Softmotions/autark
META_VERSION=0.9.0
META_REVISION=947a8ae
cd "$(cd "$(dirname "$0")"; pwd -P)"
prev_arg=""
for arg in "$@"; do
case "$prev_arg" in
-H)
AUTARK_HOME="${arg}/.autark-dist"
prev_arg="" # сброс
continue
;;
esac
case "$arg" in
-H)
prev_arg="-H"
;;
-H*)
AUTARK_HOME="${arg#-H}/.autark-dist"
;;
--cache=*)
AUTARK_HOME="${arg#--cache=}/.autark-dist"
;;
*)
prev_arg=""
;;
esac
done
export AUTARK_HOME=${AUTARK_HOME:-autark-cache/.autark-dist}
AUTARK=${AUTARK_HOME}/autark
if [ "${META_VERSION}.${META_REVISION}" = "$(${AUTARK} -v)" ]; then
${AUTARK} "$@"
exit $?
fi
set -e
echo "Building Autark executable in ${AUTARK_HOME}"
if [ -n "$CC" ] && command -v "$CC" >/dev/null 2>&1; then
COMPILER="$CC"
elif command -v clang >/dev/null 2>&1; then
COMPILER=clang
elif command -v gcc >/dev/null 2>&1; then
COMPILER=gcc
else
echo "No suitable C compiler found" >&2
exit 1
fi
mkdir -p ${AUTARK_HOME}
cat <<'a292effa503b' > ${AUTARK_HOME}/autark.c
#ifndef CONFIG_H
#define CONFIG_H
#define META_VERSION "0.9.0"
#define META_REVISION "947a8ae"
#define MACRO_MAX_RECURSIVE_CALLS 128
#endif
#define _AMALGAMATE_
#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200809L
#define _DEFAULT_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <getopt.h>
#include <glob.h>
#include <inttypes.h>
#include <libgen.h>
#include <limits.h>
#include <poll.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef BASEDEFS_H
#define BASEDEFS_H
#define QSTR(x__) #x__
#define Q(x__) QSTR(x__)
#define AK_LLEN(l__) (sizeof(l__) - 1)
#if __GNUC__ >= 4
#define AUR __attribute__((warn_unused_result))
#define AK_ALLOC __attribute__((malloc)) __attribute__((warn_unused_result))
#define AK_NORET __attribute__((noreturn))
#else
#define AUR
#define AK_ALLOC
#define AK_NORET
#endif
#define AK_CONSTRUCTOR __attribute__((constructor))
#define AK_DESTRUCTOR __attribute__((destructor))
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#define LLEN(l__) (sizeof(l__) - 1)
/* Align x_ with v_. v_ must be simple power for 2 value. */
#define ROUNDUP(x_, v_) (((x_) + (v_) - 1) & ~((v_) - 1))
/* Round down align x_ with v_. v_ must be simple power for 2 value. */
#define ROUNDOWN(x_, v_) ((x_) - ((x_) & ((v_) - 1)))
#ifdef __GNUC__
#define RCGO(rc__, label__) if (__builtin_expect((!!(rc__)), 0)) goto label__
#else
#define RCGO(rc__, label__) if (rc__) goto label__
#endif
#define RCHECK(rc__, label__, expr__) \
rc__ = expr__; \
RCGO(rc__, label__)
#define RCC(rc__, label__, expr__) RCHECK(rc__, label__, expr__)
#define RCN(label__, expr__) \
rc = (expr__); \
if (rc) { \
akerror(rc, 0, 0); \
goto label__; \
}
#ifndef MIN
#define MIN(a_, b_) ((a_) < (b_) ? (a_) : (b_))
#endif
#ifndef MAX
#define MAX(a_, b_) ((a_) > (b_) ? (a_) : (b_))
#endif
#ifndef _AMALGAMATE_
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#endif
struct value {
void *buf;
size_t len;
int error;
};
static inline int value_destroy(struct value *v) {
if (v->buf) {
free(v->buf);
v->buf = 0;
}
return v->error;
}
#endif
#ifndef LOG_H
#define LOG_H
#ifndef _AMALGAMATE_
#include "basedefs.h"
#include <stdarg.h>
#endif
enum akecode {
AK_ERROR_OK = 0,
AK_ERROR_FAIL = -1,
AK_ERROR_UNIMPLEMETED = -2,
AK_ERROR_INVALID_ARGS = -3,
AK_ERROR_ASSERTION = -4,
AK_ERROR_OVERFLOW = -5,
AK_ERROR_IO = -6,
AK_ERROR_SCRIPT_SYNTAX = -10,
AK_ERROR_SCRIPT = -11,
AK_ERROR_CYCLIC_BUILD_DEPS = -12,
AK_ERROR_SCRIPT_ERROR = -13,
AK_ERROR_NOT_IMPLEMENTED = -14,
AK_ERROR_EXTERNAL_COMMAND = -15,
AK_ERROR_DEPENDENCY_UNRESOLVED = -16,
AK_ERROR_MACRO_MAX_RECURSIVE_CALLS = -17,
};
__attribute__((noreturn))
void akfatal2(const char *msg);
__attribute__((noreturn))
void _akfatal(const char *file, int line, int code, const char *fmt, ...);
__attribute__((noreturn))
void _akfatal_va(const char *file, int line, int code, const char *fmt, va_list);
int _akerror(const char *file, int line, int code, const char *fmt, ...);
void _akerror_va(const char *file, int line, int code, const char *fmt, va_list);
void _akverbose(const char *file, int line, const char *fmt, ...);
void akinfo(const char *fmt, ...);
void akwarn(const char *fmt, ...);
#define akfatal(code__, fmt__, ...) \
_akfatal(__FILE__, __LINE__, (code__), (fmt__), __VA_ARGS__)
#define akfatal_va(code__, fmt__, va__) \
_akfatal_va(__FILE__, __LINE__, (code__), (fmt__), (va__))
#define akerror(code__, fmt__, ...) \
_akerror(__FILE__, __LINE__, (code__), (fmt__), __VA_ARGS__)
#define akerror_va(code__, fmt__, va__) \
_akerror_va(__FILE__, __LINE__, (code__), (fmt__), (va__))
#define akverbose(fmt__, ...) \
_akverbose(__FILE__, __LINE__, (fmt__), __VA_ARGS__)
#define akassert(exp__) \
do { \
if (!(exp__)) { \
akfatal(AK_ERROR_ASSERTION, Q(exp__), 0); \
} \
} while (0)
#define akcheck(exp__) \
do { \
int e = (exp__); \
if (e) akfatal(e, Q(exp__), 0); \
} while (0)
#endif
#ifndef ALLOC_H
#define ALLOC_H
#ifndef _AMALGAMATE_
#include "basedefs.h"
#include "log.h"
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#endif
AK_ALLOC static inline char* xstrdup(const char *str) {
char *ret = strdup(str);
if (!ret) {
akfatal2("Allocation failed");
}
return ret;
}
AK_ALLOC static inline void* xmalloc(size_t size) {
void *ptr = malloc(size);
if (!ptr) {
akfatal2("Allocation failed");
}
return ptr;
}
AK_ALLOC static inline void* xrealloc(void *p, size_t size) {
void *ptr = realloc(p, size);
if (!ptr) {
akfatal2("Allocation failed");
}
return ptr;
}
AK_ALLOC static inline void* xcalloc(size_t nmemb, size_t size) {
void *ptr = calloc(nmemb, size);
if (!ptr) {
akfatal2("Allocation failed");
}
return ptr;
}
#endif
#ifndef POOL_H
#define POOL_H
#ifndef _AMALGAMATE_
#include <stddef.h>
#include <stdarg.h>
#endif
struct pool_unit {
void *heap;
struct pool_unit *next;
};
struct pool {
size_t usiz; /// Used size
size_t asiz; /// Allocated size
struct pool_unit *unit; /// Current heap unit
void *user_data; /// Associated user data
char *heap; /// Current pool heap ptr
void (*on_pool_destroy)(struct pool*); /// Called when pool destroyed
};
struct pool* pool_create_empty(void);
struct pool* pool_create_preallocated(size_t);
struct pool* pool_create(void (*)(struct pool*));
void pool_destroy(struct pool*);
void* pool_alloc(struct pool*, size_t siz);
void* pool_calloc(struct pool*, size_t siz);
char* pool_strdup(struct pool*, const char*);
char* pool_strndup(struct pool*, const char*, size_t len);
char* pool_printf_va(struct pool*, const char *format, va_list va);
char* pool_printf(struct pool*, const char*, ...) __attribute__((format(__printf__, 2, 3)));
const char** pool_split_string(
struct pool *pool,
const char *haystack,
const char *split_chars,
int ignore_whitespace);
const char** pool_split(
struct pool*, const char *split_chars, int ignore_ws, const char *fmt,
...) __attribute__((format(__printf__, 4, 5)));
#endif
#ifndef XSTR_H
#define XSTR_H
#ifndef _AMALGAMATE_
#include <stdarg.h>
#include <stddef.h>
#endif
struct xstr {
char *ptr;
size_t size;
size_t asize;
};
struct xstr* xstr_create(size_t siz);
struct xstr* xstr_create_empty(void);
void xstr_cat2(struct xstr*, const void *buf, size_t size);
void xstr_cat(struct xstr*, const char *buf);
void xstr_shift(struct xstr*, size_t shift_size);
void xstr_unshift(struct xstr*, const void *buf, size_t size);
void xstr_pop(struct xstr*, size_t pop_size);
void xstr_insert(struct xstr*, size_t pos, const void *buf);
int xstr_printf_va(struct xstr*, const char *format, va_list va);
int xstr_printf(struct xstr*, const char *format, ...) __attribute__((format(__printf__, 2, 3)));
struct xstr* xstr_clear(struct xstr*);
char* xstr_ptr(struct xstr*);
size_t xstr_size(struct xstr*);
void xstr_destroy(struct xstr*);
char* xstr_destroy_keep_ptr(struct xstr*);
void xstr_cat_repeat(struct xstr*, char ch, int count);
#endif
#ifndef ULIST_H
#define ULIST_H
#ifndef _AMALGAMATE_
#include "basedefs.h"
#endif
struct ulist {
char *array;
unsigned usize;
unsigned num;
unsigned anum;
unsigned start;
};
struct ulist* ulist_create(unsigned initial_len, unsigned unit_size);
void ulist_init(struct ulist*, unsigned ini_length, unsigned unit_size);
void ulist_destroy(struct ulist**);
void ulist_destroy_keep(struct ulist*);
void ulist_clear(struct ulist*);
void ulist_reset(struct ulist*);
void* ulist_get(const struct ulist*, unsigned idx);
void* ulist_peek(const struct ulist*);
void ulist_insert(struct ulist*, unsigned idx, const void *data);
void ulist_set(struct ulist*, unsigned idx, const void *data);
void ulist_remove(struct ulist*, unsigned idx);
void ulist_push(struct ulist*, const void *data);
void ulist_pop(struct ulist*);
void ulist_unshift(struct ulist*, const void *data);
void ulist_shift(struct ulist*);
struct ulist* ulist_clone(const struct ulist*);
int ulist_find(const struct ulist*, const void *data);
int ulist_remove_by(struct ulist*, const void *data);
AK_ALLOC char* ulist_to_vlist(const struct ulist *list);
#endif
#ifndef MAP_H
#define MAP_H
#ifndef _AMALGAMATE_
#include <stdint.h>
#endif
struct map;
struct map_iter;
struct map_iter {
struct map *hm;
const void *key;
const void *val;
uint32_t bucket;
int32_t entry;
};
void map_kv_free(void *key, void *val);
void map_k_free(void *key, void *val);
struct map* map_create(
int (*cmp_fn)(const void*, const void*),
uint32_t (*hash_fn)(const void*),
void (*kv_free_fn)(void*, void*));
void map_destroy(struct map*);
struct map* map_create_u64(void (*kv_free_fn)(void*, void*));
struct map* map_create_u32(void (*kv_free_fn)(void*, void*));
struct map* map_create_str(void (*kv_free_fn)(void*, void*));
void map_put(struct map*, void *key, void *val);
void map_put_u32(struct map*, uint32_t key, void *val);
void map_put_u64(struct map*, uint64_t key, void *val);
void map_put_str(struct map*, const char *key, void *val);
void map_put_str_no_copy(struct map*, const char *key, void *val);
int map_remove(struct map*, const void *key);
int map_remove_u64(struct map*, uint64_t key);
int map_remove_u32(struct map*, uint32_t key);
void* map_get(struct map*, const void *key);
void* map_get_u64(struct map*, uint64_t key);
void* map_get_u32(struct map*, uint32_t key);
uint32_t map_count(const struct map*);
void map_clear(struct map*);
void map_iter_init(struct map*, struct map_iter*);
int map_iter_next(struct map_iter*);
#endif
#ifndef UTILS_H
#define UTILS_H
#ifndef _AMALGAMATE_
#include "basedefs.h"
#include "xstr.h"
#include <limits.h>
#include <string.h>
#include <sys/types.h>
#endif
#define Q_XSTR(s) Q_STR(s)
#define Q_STR(s) #s
static inline bool utils_char_is_space(char c) {
return c == 32 || (c >= 9 && c <= 13);
}
static inline void utils_chars_replace(char *buf, char c, char r) {
for ( ; *buf != '\0'; ++buf) {
if (*buf == c) {
*buf = r;
}
}
}
static inline long utils_lround(double x) {
if (x >= 0.0) {
x += 0.5;
} else {
x -= 0.5;
}
if (x > (double) LONG_MAX) {
return LONG_MAX;
} else if (x < (double) LONG_MIN) {
return LONG_MIN;
}
return (long) x;
}
static inline int utils_toupper_ascii(int c) {
if (c >= 'a' && c <= 'z') {
return c - ('a' - 'A'); // or: c - 32
}
return c;
}
static inline size_t utils_strnlen(const char *s, size_t maxlen) {
size_t i;
for (i = 0; i < maxlen && s[i]; ++i) ;
return i;
}
static inline char* utils_strncpy(char *dst, const char *src, size_t dst_sz) {
if (dst_sz > 1) {
size_t len = utils_strnlen(src, dst_sz - 1);
memcpy(dst, src, len);
dst[len] = '\0';
} else if (dst_sz) {
dst[0] = '\0';
}
return dst;
}
static inline char* utils_strnncpy(char *dst, const char *src, size_t src_len, size_t dst_sz) {
if (dst_sz > 1 && src_len) {
size_t len = MIN(src_len, dst_sz - 1);
memcpy(dst, src, len);
dst[len] = '\0';
} else if (dst_sz) {
dst[0] = '\0';
}
return dst;
}
static inline bool utils_startswith(const char *str, const char *prefix) {
if (!str || !prefix) {
return false;
}
size_t str_len = strlen(str);
size_t prefix_len = strlen(prefix);
if (prefix_len > str_len) {
return false;
}
return strncmp(str, prefix, prefix_len) == 0;
}
static inline bool utils_endswith(const char *str, const char *suffix) {
if (!str || !suffix) {
return false;
}
size_t str_len = strlen(str);
size_t suffix_len = strlen(suffix);
if (suffix_len > str_len) {
return false;
}
return strcmp(str + str_len - suffix_len, suffix) == 0;
}
long int utils_strtol(const char *v, int base, int *rcp);
long long utils_strtoll(const char *v, int base, int *rcp);
struct value utils_file_as_buf(const char *path, ssize_t buflen_max);
int utils_file_write_buf(const char *path, const char *buf, size_t len, bool append);
int utils_exec_path(char buf[PATH_MAX]);
int utils_copy_file(const char *src, const char *dst);
int utils_rename_file(const char *src, const char *dst);
void utils_split_values_add(const char *v, struct xstr *xstr);
int utils_fd_make_non_blocking(int fd);
//----------------------- Vlist
struct vlist_iter {
const char *item;
size_t len;
};
static inline bool is_vlist(const char *val) {
return (val && *val == '\1');
}
static inline void vlist_iter_init(const char *vlist, struct vlist_iter *iter) {
iter->item = vlist;
iter->len = 0;
}
static inline bool vlist_iter_next(struct vlist_iter *iter) {
iter->item += iter->len;
while (*iter->item == '\1') {
iter->item++;
}
if (*iter->item == '\0') {
return false;
}
const char *p = iter->item;
while (*p != '\0' && *p != '\1') {
++p;
}
iter->len = p - iter->item;
return true;
}
#endif
#ifndef SPAWN_H
#define SPAWN_H
#ifndef _AMALGAMATE_
#include <stddef.h>
#include <sys/types.h>
#include <stdbool.h>
#endif
struct spawn;
struct spawn* spawn_create(const char *exec, void *user_data);
void* spawn_user_data(struct spawn*);
pid_t spawn_pid(struct spawn*);
int spawn_exit_code(struct spawn*);
const char* spawn_arg_add(struct spawn*, const char *arg);
bool spawn_arg_exists(struct spawn*, const char *arg);
bool spawn_arg_starts_with(struct spawn*, const char *arg);
void spawn_env_set(struct spawn*, const char *key, const char *val);
void spawn_env_path_prepend(struct spawn*, const char *path);
void spawn_set_stdin_provider(struct spawn*, size_t (*provider)(char *buf, size_t buflen, struct spawn*));
void spawn_set_stdout_handler(struct spawn*, void (*handler)(char *buf, size_t buflen, struct spawn*));
void spawn_set_stderr_handler(struct spawn*, void (*handler)(char *buf, size_t buflen, struct spawn*));
void spawn_set_nowait(struct spawn*, bool nowait);
void spawn_set_wstatus(struct spawn*, int wstatus);
int spawn_do(struct spawn*);
void spawn_destroy(struct spawn*);
#endif
#ifndef PATHS_H
#define PATHS_H
#ifndef _AMALGAMATE_
#include "pool.h"
#include "basedefs.h"
#include <limits.h>
#include <stdio.h>
#endif
enum akpath_access {
AKPATH_READ = 0x01,
AKPATH_WRITE = 0x02,
AKPATH_EXEC = 0x04,
};
enum akpath_ftype {
AKPATH_NOT_EXISTS,
AKPATH_TYPE_FILE,
AKPATH_TYPE_DIR,
AKPATH_LINK,
AKPATH_OTHER,
};
struct akpath_stat {
uint64_t size;
uint64_t atime;
uint64_t ctime;
uint64_t mtime;
enum akpath_ftype ftype;
};
bool path_is_absolute(const char *path);
/// Uses stdlib `realpath` implementation.
/// NOTE: Path argument must exists on file system.
/// Foo other cases see: path_normalize()
const char* path_real(const char *path, char buf[PATH_MAX]);
const char* path_real_pool(const char *path, struct pool*);
/// Normalize a path buffer to an absolute path without resolving symlinks.
/// It operates purely on the path string, and works for non-existing paths.
char* path_normalize(const char *path, char buf[PATH_MAX]);
char* path_normalize_cwd(const char *path, const char *cwd, char buf[PATH_MAX]);
char* path_normalize_pool(const char *path, struct pool*);
char* path_normalize_cwd_pool(const char *path, const char *cwd, struct pool*);
int path_mkdirs(const char *path);
int path_mkdirs_for(const char *path);
int path_rm_cache(const char *path);
int path_stat(const char *path, struct akpath_stat *stat);
int path_stat_fd(int fd, struct akpath_stat *stat);
int path_stat_file(FILE *file, struct akpath_stat *stat);
uint64_t path_mtime(const char *path);
bool path_is_accesible(const char *path, enum akpath_access a);
bool path_is_accesible_read(const char *path);
bool path_is_accesible_write(const char *path);
bool path_is_accesible_exec(const char *path);
bool path_is_dir(const char *path);
bool path_is_file(const char *path);
bool path_is_exist(const char *path);
const char* path_is_prefix_for(const char *path, const char *haystack, const char *cwd);
AK_ALLOC char* path_relativize(const char *from, const char *to);
AK_ALLOC char* path_relativize_cwd(const char *from, const char *to, const char *cwd);
// Modifies its argument
char* path_dirname(char *path);
// Modifies its argument
char* path_basename(char *path);
#endif
#ifndef ENV_H
#define ENV_H
#ifndef _AMALGAMATE_
#include "basedefs.h"
#include "pool.h"
#include "map.h"
#include "ulist.h"
#include <stdbool.h>
#endif
#define TAG_INIT 1
#define TAG_SETUP 2
#define TAG_BUILD 3
#define AUTARK_CACHE "autark-cache"
#define AUTARK_SCRIPT "Autark"
#define AUTARK_ROOT_DIR "AUTARK_ROOT_DIR" // Project root directory
#define AUTARK_CACHE_DIR "AUTARK_CACHE_DIR" // Project cache directory
#define AUTARK_UNIT "AUTARK_UNIT" // Path relative to AUTARK_ROOT_DIR of build process unit executed
// currently.
#define AUTARK_VERBOSE "AUTARK_VERBOSE" // Autark verbose env key
#define UNIT_FLG_ROOT 0x01U // Project root unit
#define UNIT_FLG_SRC_CWD 0x02U // Set project source dir as unit CWD
#define UNIT_FLG_NO_CWD 0x04U // Do not change CWD for unit
struct unit_env_item {
const char *val;
struct node *n;
unsigned tag;
};
/// Current execution unit.
struct unit {
struct map *env; // Environment associated with unit. struct unit_env_item.
const char *rel_path; // Path to unit relative to the project root and project cache.
const char *basename; // Basename of unit path.
const char *dir; // Absolute path to unit dir.
const char *source_path; // Absolute unit source path.
const char *cache_path; // Absolute path to the unit in cache dir.
const char *cache_dir; // Absolute path to the cache directory where unit file is located.
struct pool *pool; // Pool used to allocate unit
unsigned flags; // Unit flags
struct node *n; // Node this unit associated. May be zero.
void *impl; // Arbirary implementation data
};
/// Unit context in units stack.
struct unit_ctx {
struct unit *unit;
unsigned flags;
};
/// Global env
struct env {
const char *cwd;
struct pool *pool;
int verbose;
int max_parallel_jobs; // Max number of allowed parallel jobs.
struct {
const char *root_dir; // Project root source dir.
const char *cache_dir; // Project artifacts cache dir.
bool cleanup; // Clean project cache before build
bool prepared; // Autark build prepared
struct xstr *options; // Ask option values
} project;
struct {
const char *prefix_dir; // Absolute path to install prefix dir.
const char *bin_dir; // Path to the bin dir relative to prefix.
const char *lib_dir; // Path to lib dir relative to prefix.
const char *data_dir; // Path to lib data dir relative to prefix.
const char *include_dir; // Path to include headers dir relative to prefix.
const char *pkgconf_dir; // Path to pkgconfig dir.
const char *man_dir; // Path to man pages dir.
bool enabled; // True if install operation should be performed
} install;
struct {
const char *extra_env_paths; // Extra PATH environment for any program spawn
} spawn;
struct map *map_path_to_unit; // Path to unit mapping
struct ulist stack_units; // Stack of nested unit contexts (struct unit_ctx)
struct ulist units; // All created units. (struct unit*)
struct {
struct xstr *log;
} check;
};
extern struct env g_env;
void on_unit_pool_destroy(struct pool*);
struct unit* unit_create(const char *unit_path, unsigned flags, struct pool *pool);
struct unit* unit_for_path(const char *path);
void unit_push(struct unit*, struct node*);
struct unit* unit_pop(void);
struct unit* unit_peek(void);
struct unit_ctx unit_peek_ctx(void);
struct unit* unit_root(void);
struct unit* unit_parent(struct node *n);
void unit_ch_dir(struct unit_ctx*, char *prevcwd);
void unit_ch_cache_dir(struct unit*, char *prevcwd);
void unit_ch_src_dir(struct unit*, char *prevcwd);
void unit_env_set_val(struct unit*, const char *key, const char *val);
void unit_env_set_node(struct unit*, const char *key, struct node *n, unsigned tag);
struct node* unit_env_get_node(struct unit *u, const char *key, unsigned *out_tag);
const char* unit_env_get(struct node *n, const char *key);
const char* unit_env_get_raw(struct unit *u, const char *key);
void unit_env_remove(struct unit*, const char *key);
const char* env_libdir(void);
#endif
#ifndef DEPS_H
#define DEPS_H
#ifndef _AMALGAMATE_
#include "env.h"
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
#include <stdint.h>
#endif
#define DEPS_TYPE_FILE 102 // f
#define DEPS_TYPE_FILE_OUTDATED 111 // x
#define DEPS_TYPE_NODE_VALUE 118 // v
#define DEPS_TYPE_ENV 101 // e
#define DEPS_TYPE_SYS_ENV 115 // s
#define DEPS_TYPE_ALIAS 97 // a
#define DEPS_TYPE_OUTDATED 120 // o
#define DEPS_OPEN_TRUNCATE 0x01U
#define DEPS_OPEN_READONLY 0x02U
#define DEPS_BUF_SZ 262144
struct deps {
char type;
char flags;
int num_registered; /// Number of deps registerd in the current session
int64_t serial;
const char *resource;
const char *alias;
FILE *file;
char buf[DEPS_BUF_SZ];
};
int deps_open(const char *path, int omode, struct deps *init);
bool deps_cur_next(struct deps*);
bool deps_cur_is_outdated(struct node *n, struct deps*);
int deps_add(struct deps*, char type, char flags, const char *resource, int64_t serial);
int deps_add_alias(struct deps*, char flags, const char *resource, const char *alias);
int deps_add_env(struct deps *d, char flags, const char *key, const char *value);
int deps_add_sys_env(struct deps *d, char flags, const char *key, const char *value);
void deps_close(struct deps*);
void deps_prune_all(const char *path);
#endif
#ifndef NODES_H
#define NODES_H
#ifndef _AMALGAMATE_
#include "script.h"
#endif
int node_script_setup(struct node*);
int node_meta_setup(struct node*);
int node_check_setup(struct node*);
int node_set_setup(struct node*);
int node_include_setup(struct node*);
int node_if_setup(struct node*);
int node_subst_setup(struct node*);
int node_run_setup(struct node*);
int node_echo_setup(struct node*);
int node_join_setup(struct node*);
int node_cc_setup(struct node*);
int node_configure_setup(struct node*);
int node_basename_setup(struct node*);
int node_foreach_setup(struct node*);
int node_in_sources_setup(struct node*);
int node_dir_setup(struct node*);
int node_option_setup(struct node*);
int node_error_setup(struct node*);
int node_echo_setup(struct node*);
int node_install_setup(struct node*);
int node_find_setup(struct node*);
int node_macro_setup(struct node*);
int node_call_setup(struct node*);
struct node* call_macro_node(struct node*);
struct node* call_first_node(struct node*);
void macro_register_call(struct node*);
void macro_unregister_call(struct node*);
#endif
#ifndef AUTARK_H
#define AUTARK_H
#ifndef _AMALGAMATE_
#include <stdbool.h>
#endif
void autark_init(void);
void autark_run(int argc, const char **argv);
void autark_dispose(void);
void autark_build_prepare(const char *script_path);
#endif
#ifndef SCRIPT_H
#define SCRIPT_H
#ifndef _AMALGAMATE_
#include "ulist.h"
#include "xstr.h"
#include "deps.h"
#include "map.h"
#include <stdbool.h>
#endif
// value types
#define NODE_TYPE_VALUE 0x01U
#define NODE_TYPE_SUBST 0x02U
#define NODE_TYPE_SET 0x04U
#define NODE_TYPE_JOIN 0x08U
#define NODE_TYPE_BASENAME 0x10U
#define NODE_TYPE_DIR 0x20U
#define NODE_TYPE_FIND 0x40U
// eof value types
#define NODE_TYPE_SCRIPT 0x100U
#define NODE_TYPE_BAG 0x200U
#define NODE_TYPE_META 0x400U
#define NODE_TYPE_CHECK 0x800U
#define NODE_TYPE_INCLUDE 0x1000U
#define NODE_TYPE_IF 0x2000U
#define NODE_TYPE_RUN 0x4000U
#define NODE_TYPE_CC 0x8000U
#define NODE_TYPE_CONFIGURE 0x10000U
#define NODE_TYPE_FOREACH 0x20000U
#define NODE_TYPE_IN_SOURCES 0x40000U
#define NODE_TYPE_OPTION 0x80000U
#define NODE_TYPE_ERROR 0x100000U
#define NODE_TYPE_ECHO 0x200000U
#define NODE_TYPE_INSTALL 0x400000U
#define NODE_TYPE_MACRO 0x800000U
#define NODE_TYPE_CALL 0x1000000U
#define NODE_FLG_BOUND 0x01U
#define NODE_FLG_INIT 0x02U
#define NODE_FLG_SETUP 0x04U
// Vacant: 0x08U
#define NODE_FLG_BUILT 0x10U // Node built
#define NODE_FLG_POST_BUILT 0x20U // Node post-built
#define NODE_FLG_IN_CACHE 0x40U
#define NODE_FLG_IN_SRC 0x80U
#define NODE_FLG_NO_CWD 0x100U
#define NODE_FLG_NEGATE 0x200U
#define NODE_FLG_IN_ANY (NODE_FLG_IN_SRC | NODE_FLG_IN_CACHE | NODE_FLG_NO_CWD)
#define node_is_init(n__) (((n__)->flags & NODE_FLG_INIT) != 0)
#define node_is_setup(n__) (((n__)->flags & NODE_FLG_SETUP) != 0)
#define node_is_built(n__) (((n__)->flags & NODE_FLG_BUILT) != 0)
#define node_is_post_built(n__) (((n__)->flags & NODE_FLG_POST_BUILT) != 0)
#define node_is_value(n__) ((n__)->type == NODE_TYPE_VALUE)
#define node_is_can_be_value(n__) ((n__)->type >= NODE_TYPE_VALUE && (n__)->type <= NODE_TYPE_FIND)
#define node_is_rule(n__) !node_is_value(n__)
#define NODE_PRINT_INDENT 2
struct node_foreach {
char *name;
char *value;
char *items;
unsigned access_cnt;
};
struct node {
unsigned type;
unsigned flags;
unsigned flags_owner; /// Extra flaghs set by owner node
unsigned index; /// Own index in env::nodes
unsigned lnum; /// Node line number
const char *name; /// Internal node name
const char *vfile; /// Node virtual file
const char *value; /// Key or value
struct node *child;
struct node *next;
struct node *parent;
// Recursive set
struct {
struct node *n;
bool active;
} recur_next;
struct sctx *ctx;
struct unit *unit;
const char* (*value_get)(struct node*);
void (*init)(struct node*);
void (*setup)(struct node*);
void (*build)(struct node*);
void (*post_build)(struct node*);
void (*dispose)(struct node*);
void *impl;
};
struct sctx {
struct node *root; /// Project root script node (Autark)
struct ulist nodes; /// ulist<struct node*>
struct map *products; /// Products of nodes (product name -> node)
};
int script_open(const char *file, struct sctx **out);
int script_include(struct node *parent, const char *file, struct node **out);
void script_build(struct sctx*);
void script_close(struct sctx**);
void script_dump(struct sctx*, struct xstr *out);
const char* node_env_get(struct node*, const char *key);
void node_env_set(struct node*, const char *key, const char *val);
void node_env_set_node(struct node*, const char *key, unsigned tag);
struct node* node_by_product(struct node*, const char *prod, char pathbuf[PATH_MAX]);
struct node* node_by_product_raw(struct node*, const char *prod);
void node_product_add(struct node*, const char *prod, char pathbuf[PATH_MAX]);
void node_product_add_raw(struct node*, const char *prod);
void node_reset(struct node *n);
const char* node_value(struct node *n);
#define NODE_VISIT_CHILD_SKIP INT_MAX
int node_visit(struct node *n, int lvl, void *ctx, int (*visitor)(struct node*, int, void*));
void node_module_setup(struct node *n, unsigned flags);
void node_init(struct node *n);
void node_setup(struct node *n);
void node_build(struct node *n);
void node_post_build(struct node *n);
struct node* node_find_direct_child(struct node *n, int type, const char *val);
struct node* node_find_prev_sibling(struct node *n);
struct node* node_find_parent_of_type(struct node *n, int type);
struct node_foreach* node_find_parent_foreach(struct node *n);
bool node_is_value_may_be_dep_saved(struct node *n);
struct node* node_consumes_resolve(
struct node *n,
struct node *npaths,
struct ulist *paths,
void (*on_resolved)(const char *path, void *opq),
void *opq);
void node_add_unit_deps(struct node *n, struct deps*);
struct node_resolve {
struct node *n;
const char *path;
void *user_data;
void (*on_init)(struct node_resolve*);
void (*on_env_value)(struct node_resolve*, const char *key, const char *val);
void (*on_resolve)(struct node_resolve*);
const char *deps_path_tmp;
const char *env_path_tmp;
struct ulist resolve_outdated; // struct resolve_outdated
struct ulist node_val_deps; // struct node*
struct pool *pool;
unsigned mode;
int num_deps; // Number of dependencies
bool force_outdated;
};
struct resolve_outdated {
char type;
char flags;
char *path;
};
#define NODE_RESOLVE_ENV_ALWAYS 0x01U
void node_resolve(struct node_resolve*);
__attribute__((noreturn))
void node_fatal(int rc, struct node *n, const char *fmt, ...);
void node_info(struct node *n, const char *fmt, ...);
void node_warn(struct node *n, const char *fmt, ...);
int node_error(int rc, struct node *n, const char *fmt, ...);
struct node* node_clone_and_register(struct node*);
int node_bind(struct node*);
#endif
#ifndef _AMALGAMATE_
#include "xstr.h"
#include "alloc.h"
#include <string.h>
#include <stdio.h>
#include <errno.h>
#endif
struct xstr* xstr_create(size_t siz) {
if (!siz) {
siz = 16;
}
struct xstr *xstr;
xstr = xmalloc(sizeof(*xstr));
xstr->ptr = xmalloc(siz);
xstr->size = 0;
xstr->asize = siz;
xstr->ptr[0] = '\0';
return xstr;
}
struct xstr* xstr_create_empty(void) {
return xstr_create(0);
}
void xstr_cat2(struct xstr *xstr, const void *buf, size_t size) {
size_t nsize = xstr->size + size + 1;
if (xstr->asize < nsize) {
while (xstr->asize < nsize) {
xstr->asize <<= 1;
if (xstr->asize < nsize) {
xstr->asize = nsize;
}
}
char *ptr = xrealloc(xstr->ptr, xstr->asize);
xstr->ptr = ptr;
}
memcpy(xstr->ptr + xstr->size, buf, size);
xstr->size += size;
xstr->ptr[xstr->size] = '\0';
}
void xstr_cat(struct xstr *xstr, const char *buf) {
size_t size = strlen(buf);
xstr_cat2(xstr, buf, size);
}
void xstr_shift(struct xstr *xstr, size_t shift_size) {
if (shift_size == 0) {
return;
}
if (shift_size > xstr->size) {
shift_size = xstr->size;
}
if (xstr->size > shift_size) {
memmove(xstr->ptr, xstr->ptr + shift_size, xstr->size - shift_size);
}
xstr->size -= shift_size;
xstr->ptr[xstr->size] = '\0';
}
void xstr_unshift(struct xstr *xstr, const void *buf, size_t size) {
unsigned nsize = xstr->size + size + 1;
if (xstr->asize < nsize) {
while (xstr->asize < nsize) {
xstr->asize <<= 1;
if (xstr->asize < nsize) {
xstr->asize = nsize;
}
}
char *ptr = xrealloc(xstr->ptr, xstr->asize);