Comment: | development milestone |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
a14ceee05626ca2753894004bbfa8747 |
User & Date: | lexi on 2019-06-27 21:39:17 |
Other Links: | manifest | tags |
2019-06-27
| ||
22:14 | fixes for shared building check-in: ec9b2b74b3 user: lexi tags: trunk | |
21:39 | development milestone check-in: a14ceee056 user: lexi tags: trunk | |
12:21 | more fixes check-in: 93014cedbc user: lexi tags: trunk | |
Modified arch/makefile from [657c34aa94] to [0ea82c6f52].
1 -linux-headers = /usr/include/asm/ 2 -calls.x86.lin.32.s: $(linux-headers)/unistd_32.h 3 - grep "#define __NR_" $< | sed "s;^#define __NR_;%define sys.;" > $@ 4 -calls.x86.lin.64.s: $(linux-headers)/unistd_64.h 5 - grep "#define __NR_" $< | sed "s;^#define __NR_;%define sys.;" > $@ 1 +lin-headers = /usr/include/asm 2 +fbsd-headers = /usr/include/sys 3 + 4 +${TMP}: 5 + mkdir -p ${TMP} 6 + 7 +${TMP}/calls.x86.lin.32.s: $(lin-headers)/unistd_32.h ${TMP} 8 + grep "#define __NR_" $< | sed 's;^#define __NR_;%define sys.;' > $@ 9 +${TMP}/calls.x86.lin.64.s: $(lin-headers)/unistd_64.h ${TMP} 10 + grep "#define __NR_" $< | sed 's;^#define __NR_;%define sys.;' > $@ 11 +${TMP}/calls.x86.fbsd.%.s: $(fbsd-headers)/syscall.h ${TMP} 12 + grep "#define SYS_" $< | sed 's;^#define SYS_;%define sys.;' > $@
Modified arch/x86.lin.64.s from [2b600a2718] to [f2e5b4d4ec].
1 1 ;; abi definition file for x86 linux 64-bit 2 2 ; vim: ft=nasm 3 3 4 4 ; syscall64 numbers - syscall table must be created first! 5 5 %include "calls.x86.lin.64.s" 6 6 7 -; syscall ops 8 -%define sys.call syscall 7 +; linux uses the common x86-64 ABI 8 +%include "x86.syscall.64.s" 9 9 10 -; register order for syscall convention 11 -%define sys.reg.n 7 12 -%define sys.reg.ret rax 13 -%define sys.reg.0 rax 14 -%define sys.reg.1 rdi 15 -%define sys.reg.2 rsi 16 -%define sys.reg.3 rdx 17 -%define sys.reg.4 r10 18 -%define sys.reg.5 r8 19 -%define sys.reg.6 r9 20 - 21 -; register order for ccall convention 22 -%define ccall.reg.ct 6 23 -%define ccall.reg.ret rdi 24 -%define ccall.reg.0 rdi 25 -%define ccall.reg.1 rsi 26 -%define ccall.reg.2 rdx 27 -%define ccall.reg.3 rcx 28 -%define ccall.reg.4 r8 29 -%define ccall.reg.5 r9 30 - 31 -%macro sys 1-8 32 -; syscall64 wrapper, ex. `sys sys.write, 1, msg, msg.len` 33 - %assign i 0 34 - %rep %0 35 - mov sys.reg. %+ i, %1 ; i'm actually shocked this worked 36 - %rotate 1 37 - %assign i i+1 38 - %endrep 39 - syscall 40 -%endmacro 41 - 42 -%macro sys.prep 1-8 43 - ; for when we need to modify parameters before we 44 - ; make the actual call. 45 - %assign i 0 46 - %rep %0 47 - mov sys.reg. %+ i, %1 48 - %rotate 1 49 - %assign i i+1 50 - %endrep 51 -%endmacro 52 - 53 -%macro ccall 1-* 54 - %if %0 > ccall.reg.ct 55 - %assign ct ccall.reg.ct 56 - %else 57 - %assign ct %0-1 58 - %endif 59 - %assign i 0 60 - %rotate 1 61 - %rep ct 62 - ; if the function is well-behaved, all its arguments fit 63 - ; in registers. if not, things get ugly. see below. 64 - mov ccall.reg. %+ i, %1 65 - %assign i i+1 66 - %rotate 1 67 - %endrep 68 - %if %0 > ccall.reg.ct 69 - ; if there are more parameters to a C function than the 70 - ; number of permitted registers, they must be pushed in 71 - ; reverse order to the stack. 72 - ; keep your function signatures under control, people. 73 - %assign ct (%0-ct)-1 74 - %rotate ct 75 - %rep ct 76 - %rotate -1 77 - push %1 78 - %endrep 79 - %rotate ct 80 - push rsp ; it's our responsibility to preserve the stack 81 - %endif 82 - call %1 83 - %if %0 > ccall.reg.ct 84 - ; the extra arguments are still on the stack; time to 85 - ; dump them back into the Garbage Zone 86 - pop rsp 87 - %endif 88 -%endmacro
Modified kcore/boot.c from [878278ef2e] to [6007ea2ce5].
1 -#include "core.h" 1 +#include <k/core.h> 2 2 extern stat entry(kenv); 3 3 4 4 stat _boot(unsigned int argc, char** argv) { 5 - kenv e = { argc, argv }; 5 + kenv e = { 6 + // todo: determine terminal class and set term vs ansi correctly! 7 + { {kiostream_term, 0}, {kiostream_term, 1} }, // chan std 8 + { {kiostream_closed}, {kiostream_term, 2} }, // chan err 9 + argc, argv, 10 + null // no environment yet 11 + }; 6 12 return entry(e); 7 13 } 8 14
Modified kcore/core.h from [bb457bb91b] to [cb5067b74b].
1 1 #ifndef KIcore 2 2 #define KIcore 3 +#include <k/type.h> 4 +#include <k/io.h> 5 +#include <k/str.h> 6 + 7 +static void* const null = (void*)0; 3 8 4 -typedef unsigned long long sz; 5 -typedef unsigned char stat; 9 +typedef struct kvar { 10 + ksraw name; 11 + ksraw val; 12 + char* platform; 13 +} kvar; 6 14 7 15 typedef struct kenv { 8 - sz argc; 9 - char** argv; 16 + kiochan std; 17 + kiochan err; 18 + sz argc; char** argv; 19 + kvar* vars; 10 20 } kenv; 11 21 12 22 #endif
Modified kcore/kcore.md from [28c0315020] to [d664110812].
1 1 # kcore 2 2 **kcore** is the foundation for the rest of libk. it defines types and structs that are needed by every program, and provides the stub that launches a program's "entry" function. 3 3 4 4 ## entry 5 5 when using libk, your program's entry point will not be the `int main(int,char**)` function that libc opens into. libk will call the function `stat entry(kenv)` instead. like libc, the value returned by `entry` will be returned to the host platform. 6 6 7 7 ## types 8 -kcore contains fixed-width integer types. note that the available of each depends on your platform; compilation will fail if e.g. you try to use a u64 or a u128 on a 32-bit platform, so where exact lengths are not required, you may wish to use the built-in C types instead. 8 +kcore contains fixed-width integer types (in <k/type.h>). note that the availability of each depends on your platform; compilation will fail if e.g. you try to use a u64 or a u128 on a 32-bit platform, so where exact lengths are not required, you may wish to use the built-in C types instead. 9 9 10 10 * `u8` - an unsigned 8-bit integer 11 11 * `s8` - a signed 8-bit integer 12 12 * `u16` - an unsigned 16-bit integer 13 13 * `s16` - a signed 16-bit integer 14 14 * `u32` - an unsigned 32-bit integer 15 15 * `s32` - a signed 32-bit integer ................................................................................ 21 21 * `sword` - a signed integer of platform word-length (e.g. 32 bits on x86.32; 64 on x86.64) 22 22 * `stat` - the type of process return values expected by the platform (usually u8 on linux) 23 23 24 24 ### struct kenv 25 25 `kenv` is a struct that encompasses the environment the program was launched in. 26 26 * `kiochan std` - a stereo IO channel for reading and writing to and from stdout. 27 27 * `kiochan err` - a mono IO channel for writing to stderr. 28 - * `kvar* env` - a pointer into the program's environment 28 + * `kvar* vars` - a pointer into the program's environment 29 29 30 30 ### struct kvar 31 31 `kvar` is a struct that abstracts over platform environment variables. 32 32 * `kstr name` - the name of an environment variable 33 33 * `kstr val` - the value of an environment variable 34 34 * `char* platform` - a pointer into the platform's underlying representation
Modified kcore/makefile from [f0df06fe05] to [a535931ecd].
1 +## kcore/makefile 2 +# kcore has to include, among other things, a replacement 3 +# for stddef.h, and that can't be written in portable C, 4 +# so we're generating it at build time. 5 +# 6 +# look, imma just be straight with you. the mechanism we're 7 +# using to generate these headers is unbelievably heinous. 8 +# it's inelegant, it's gross, and it's horrible. in the long 9 +# term this NEEDS to be replaced with a bespoke solution 10 +# instead of makefile gibberish. hopefully tho this will be 11 +# enough in the short term for libk to get going, enough that 12 +# someone more competent than me will someday be interested 13 +# in fixing this horrorshow. 14 +# 15 +# until them: i'm sorry. 16 +# very sincerely yours, lexi hale 17 + 18 +gen-headers = type.h 19 + 1 20 include ../modmake 21 + 22 +${OUT}/k/type.h: ${TMP}/type.${TARGET}.i 23 + cp $< $@ 24 + 25 +# generating C source in make… yaaay 26 +define arch = 27 +${TMP}/type.$(1).%.$(2).i: type.$(1).$(2).i def.%.i ${TMP} 28 + echo '#ifndef KItype' > $$@ 29 + echo '#define KItype' >> $$@ 30 + cat def.$$*.i >> $$@ 31 + cat $$< >> $$@ 32 + echo '#endif' >> $$@ 33 +endef 34 + 35 +$(eval $(call arch,x86,32)) 36 +$(eval $(call arch,x86,64)) 37 +
Modified kgraft/exe.attach.c from [a7ffc6f8bf] to [572a900790].
1 +#include <k/core.h> 2 +stat entry(kenv e) { 3 + return 0; 4 +}
Modified kio/io.h from [247977844e] to [824a86b217].
1 1 #ifndef KIio 2 2 #define KIio 3 +/* <k/io.h> 4 + * ~ lexi hale <lexi@hale.su> 5 + * this header declares IO primitive functions and 6 + * structures. it is the same for all platforms. 7 + * platform-specific code is found in the *.platform.h 8 + * files. 9 + */ 10 + 11 +#include <k/type.h> 12 + 13 +typedef enum kiostream_kind { 14 + kiostream_closed, 15 + // this kiostream cannot be written to 16 + kiostream_file, 17 + // this kiostream represents a file 18 + kiostream_sock, 19 + // this kiostream is attached to a socket, 20 + // UNIX, IP, or otherwise 21 + kiostream_term, 22 + // this socket is being used to communicate 23 + // directly with a human being 24 + kiostream_ansi, 25 + // like kiostream_term, but can also understand 26 + // ANSI control codes 27 + kiostream_other 28 + // no fuckin idea 29 +} kiostream_kind; 30 + 31 +typedef struct kiostream { 32 + kiostream_kind kind; 33 + #include "kiostream.platform.h" 34 +} kiostream; 35 + 36 +typedef struct kiochan { 37 + kiostream in; 38 + // text can be read from this stream 39 + kiostream out; 40 + // text can be written to this stream 41 +} kiochan; 42 + 43 +unsigned long long kiosend(kiochan); // send data to a channel 44 +unsigned long long kiorecv(kiochan); // receive data from a channel 45 + 46 +typedef enum kiocond { 47 + kiocond_ok, 48 + // success 49 + kiocond_fail, 50 + // action failed 51 +} kiocond; 3 52 4 53 #endif
Modified kio/makefile from [f0df06fe05] to [86c8f24ac7].
1 +gen-headers = kiostream.platform.h 2 + 1 3 include ../modmake 4 + 5 +ifeq (${POSIX},yes) 6 +api = posix 7 +else 8 +api = ${OS} 9 +endif 10 + 11 +${OUT}/k/kiostream.platform.h: kiostream.$(api).i 12 + cp $< $@
Modified kmem/kmem.md from [9a7772ee1a] to [9ed4178122].
50 50 51 51 the convenience function `kmstat(void*) → kmptr` wraps a pointer to a static object in a `kmptr` struct. 52 52 53 53 ### kmcell 54 54 55 55 `kmcell` is a stub struct used to disambiguate between source types.a "source" is an object that can hold an allocated object, such as the heap, a memory pool, a fixed-length array on stack, or a fixed-length global array. all values produced by a kmem allocation function point to within a `kmcell`. 56 56 57 - * `kmptr_kind kind` - kind of cell 58 - * `size_t sz` - kind of cell (data plus all fields) 57 + * `kmkind kind` - kind of cell 58 + * `size_t size` - size of cell (data plus all fields) 59 59 * `kmshred shred` - shredding flag 60 60 61 61 ### kmref 62 62 63 63 `kmref` is a struct that constitutes the in-memory representation of a reference-counted cell. 64 64 65 65 * `kmkind kind = kmkind_ref` - kind of cell
Modified kmem/mem.h from [dc631dc568] to [4d62b7403b].
1 1 #ifndef KImem 2 2 #define KImem 3 +#include <k/type.h> 4 + 5 +typedef enum kmkind { 6 + kmkind_none, 7 + kmkind_heap, 8 + kmkind_pool, 9 + kmkind_ref, 10 + kmkind_tree 11 +} kmkind; 12 + 13 +typedef enum kmshred { 14 + kmshred_yes, 15 + kmshred_no 16 +} kmshred; 17 + 18 +typedef struct kmcell { 19 + kmkind kind; 20 + sz size; 21 + kmshred shred; 22 + sz refs; 23 + struct kmcell* src; 24 + char data[]; 25 +} kmcell; 26 + 27 +typedef struct kmptr { 28 + kmkind kind; 29 + kmshred shred; 30 + void* ref; 31 + kmcell* cell; 32 +} kmptr; 3 33 4 34 #endif
Modified kstr/kstr.md from [8ba3da6088] to [b3e2b4c4d7].
2 2 3 3 **kstr** is the libk string library. it uses the **short** naming convention with the glyph `s`. **kstr** implies `#include <k/mem.h>`. 4 4 5 5 ## types 6 6 7 7 ### struct kstr 8 8 `struct kstr` is a structure for holding pascal strings (length-prefixed strings). it is the basic libk string type. **note:** if `ptr.ref` ≠ NULL and `sz` = 0, the string's length is unknown and should be calculated by any function that operates on a kstr, storing the result in the object if possible. 9 - * `size_t sz` - length of string, excluding any null terminator 9 + * `sz size` - length of string, excluding any null terminator 10 10 * `kmptr ptr` - pointer to string in memory 11 11 12 12 ### struct ksraw 13 13 `struct ksraw` is like `kstr` except it uses raw `char` pointers instead of a `kmptr`. 14 - * `size_t sz` - length of string, excluding any null terminator 14 + * `sz size` - length of string, excluding any null terminator 15 15 * `char* ptr` - pointer to string in memory 16 16 17 17 ### struct ksbuf 18 18 `struct ksbuf` is a structure used to hold buffers. 19 - * `size_t sz` - maximum size of buffer, including any null terminator 19 + * `sz size` - maximum size of buffer, including any null terminator 20 20 * `char* buf` - region of memory to store buffer in 21 21 * `ksalloc strat` - allocation strategy 22 22 * `kmkind rule` - kind of allocator to use. only needs to be set if `where` is NULL. see [kmem](../kmem/kmem.md). 23 23 * `kmcell* where` - where to allocate the object, in case of pool or tree allocation. 24 24 25 25 ### struct kschain 26 26 `struct kschain` is a structure used for string accumulators that works by aggregating pointers to strings, instead of copying the strings themselves. 27 27 * `kschain_kind kind` - kind of chain 28 28 * `kmkind rule` - kind of allocation to use if `kind` ≠ `kschain_kind_linked` 29 29 * `pstr* ptrs` - pointer to pointer list 30 - * `size_t ptrc` - number of pointers 31 - * `size_t sz` - total amount of space in `ptrs` 30 + * `sz ptrc` - number of pointers 31 + * `sz size` - total amount of space in `ptrs` 32 32 33 33 #### enum kschain_kind 34 34 * `kschain_kind_block` - occupies a single block of memory 35 35 * `kschain_kind_linked` - uses a linked list, allocated and deallocated as necessary 36 36 37 37 ### enum ksalloc 38 38 `enum ksalloc` is an enumerator that tells libk what strategy to use when filling a `ksbuf` or `kschain` struct. ................................................................................ 61 61 char* src = <...>; 62 62 kmbuf buf = { sizeof mem, &mem, kmkind_none }; 63 63 kstr chain[] = { 64 64 Kstr("<a href=\""), { 0, src }, Kstr("\">"), 65 65 ksref(text), 66 66 Kstr("</a>") 67 67 }; 68 - char* html = kscomp([Kmsz(chain)](../kmem/kmem.md), chain, &buf); 68 + char* html = kscomp(Kmsz(chain), chain, &buf); 69 69 70 70 kscomp will only calculate the length of individual strings if they are not already known. when it needs to calculate the length of a string, it will store that length in the original array so repeated calls can be made without needing to repeatedly calculate the lengths. this is not always desirable, so the variant `kscompc` exists, which is exactly the same as `kscomp` in every respect except that `chain` is not altered in any way. 71 71 72 72 ### macros 73 73 if `KFclean` is not set when <k/str.h> is included, the following macros are defined. 74 74 75 75 * `Kstr(string)` - the compile-time equivalent to `kstr()`. `Kstr` takes a literal string and inserts the text `{ sizeof (string), string }` into the document, suitable for initializing a kstr.
Modified kstr/str.h from [21d6720beb] to [f7e947c0d1].
1 1 #ifndef KIstr 2 2 #define KIstr 3 3 4 +#include <k/mem.h> 5 + 6 +typedef struct kstr { 7 + sz size; 8 + kmptr ptr; 9 +} kstr; 10 + 11 +typedef struct ksraw { 12 + sz size; 13 + char* ptr; 14 +} ksraw; 4 15 #endif
Modified libk.md from [d834bc0082] to [523e766d88].
17 17 ## goals 18 18 19 19 libk's goals are far-reaching, and suggestions are welcome. note however that libk is *not* intended to be a kitchen-sink library like libiberty. it's meant to do one thing, and to it well: to provide an easy- and pleasant-to-use foundation for modern open source projects. below is a list of some of the project's major goals. 20 20 21 21 1. **IO.** libc's basic input/output mechanisms are dreadful, built at entirely the wrong level of abstraction. libk is intended to make many more primitives available to the user, and offer a sliding scale of abstraction so libk is suitable for a wide range of needs. 22 22 2. **file manipulation.** libc's file manipulation primitives are a relic of a bygone age and in dire need of upgrading. 23 23 3. **terminal manipulation.** libc has no provision for simple output formatting, a task that requires a combination of ANSI codes and in some cases pty manipulation with POSIX APIs, both of which are somewhat dark wizardry. this situation forces many innocent coders to drag in the entire unholy bulk of the aptly named library `ncurses`, much of whose code has been utterly obsolete for the last twenty years and whose API is one of the most singularly hateful ones in existence. libk therefore should offer a simple, straightforward way to do gracefully-degrading terminal sorcery. 24 - 0. **tooling.** libk is intended as more than just a library. it's also intended to work with some basic tooling to automate tasks that current binary tooling is inadequate for -- for instance, embedding binary data into a program binary. (see module [kgraft](kgraft)) 25 - 0. **modularity.** libk is not part of the C specification and it isn't always going to be practical for developers to expect the entire library to be present on the end-user's computer. so libk is designed to be usable in many different ways -- as a traditional library, as a static library, in full form or with only components needed by the developer, to be distributed either on its own or as part of a binary. 26 - 0. **compatibility.** code that links against libk should be able to compile and run on any operating system. in the ideal case (Linux or FreeBSD) it will be able to do so without touching any other system libraries; for less ideal environments like Windows, libk will when necessary abstract over system libraries or libc itself. 24 + 4. **memory management.** the single memory management function `malloc()` provided by libc is absolutely pitiful. this is 2019. modern applications have much more exotic allocation needs, and a standard library should offer a range of allocators and management techniques, as well as abstract pointer objects so that pointers to objects of different allocation types (including static or stack allocation!) can be mixed freely and safely. 25 + 5. **intrinsic reentrancy.** because *jesus christ,* libc. 26 + 6. **interprocess communication.** libc offers no useful IPC abstractions over the paltry array of tools POSIX &co. give us to work with. we can do better. 27 + 7. **tooling.** libk is intended as more than just a library. it's also intended to work with some basic tooling to automate tasks that current binary tooling is inadequate for -- for instance, embedding binary data into a program binary. (see module [kgraft](kgraft)) 28 + 8. **modularity.** libk is not part of the C specification and it isn't always going to be practical for developers to expect the entire library to be present on the end-user's computer. so libk is designed to be usable in many different ways -- as a traditional library, as a static library, in full form or with only components needed by the developer, to be distributed either on its own or as part of a binary. 29 + 9. **compatibility.** code that links against libk should be able to compile and run on any operating system. in the ideal case (Linux or FreeBSD) it will be able to do so without touching any other system libraries; for less ideal environments like Windows, libk will when necessary abstract over system libraries or libc itself. 30 + 10. **sane error-handling.** every time you type `errno` god murders a puppy. 27 31 28 32 ## naming conventions 29 33 30 34 one of the most frustrating things about libc is its complete and total *lack* of a naming convention. in C, every function and global is injected into a single global namespace, including macros. this means that every libc header you include scatters words all over that namespace, potentially clobbering your function with a macro! 31 35 32 36 libk is designed to fix this (in hindsight) glaring error. 33 37 ................................................................................ 62 66 * FreeBSD: `fbsd` 63 67 * NetBSD: `nbsd` 64 68 * OpenBSD: `obsd` 65 69 * Darwin/Mac OS X/iOS: `dar` 66 70 * MS-DOS: `dos` 67 71 * FreeDOS: `fdos` 68 72 * Windows: `win` 73 + * Windows MinGW: `mgw` 69 74 70 75 #### file extensions 71 76 72 77 * C function implementations: `*.c` 73 78 * C module headers: `*.h` 74 79 * ancillary C headers: `*.inc.h` 75 80 * assembly code: `*.s` ................................................................................ 89 94 libk uses only three languages: C (\*.c, \*.h), yasm (\*.s), and make (makefile). 90 95 91 96 other assemblers will probably be necessary for the more exotic targets, however. 92 97 93 98 ## repository structure 94 99 95 100 libk uses a strict directory structure for code, and deviations from this structure will not be tolerated without extremely good reason. 101 + 102 +total segregation is maintained between source code, temporary files, and output objects. source is found in module directories (`k*/`). the destination for temporary files and output objects are retargetable via the `make` parameters `TMP= OUT=`, but default to `tmp/` and `out/`, which are excluded from repo with fossil's `ignore-glob` setting. 96 103 97 104 all libk code is dispersed into modules: `kcore` for internals, `kio` for I/O, `kgraft` for binary packing, etc. each module has a folder in the root directory. (libk does not have submodules.) inside each module's directory should be a header with the same name as the module (see **naming conventions** above). 98 105 99 106 each function should be kept in a separate file within its module's directory. when OS or architecture-specific code is needed, the file's name should be a list of one or more of the fields [arch, OS, bits, format] separated by a `.` -- for instance, the 32-bit x86 haiku version of a function called `write` defined in assembly would be named `write.x86.hai.32.s`. however, if a function has an extraordinarily large number of versions, they may instead be stored in a folder with the same name as the function. 100 107 101 108 each module should have a header named the same thing as the module except without the `k` prefix. (e.g. the header for `kio` is `kio/io.h`) located in its folder. this is the header that the end-user will be importing, and should handle any user-defined flags to present the API the user has selected. 102 109 ................................................................................ 154 161 155 162 **libk.so** will build the dynamically linked form of libk, according to the build variables set 156 163 157 164 **libk.a** will build the statically linked form of libk, according to the build variables set 158 165 159 166 **tool** will build the executables used for modules such as `kgraft`. 160 167 161 -there is no **clean** target. to clean the repository, simply delete the directory `out/`. 168 +**clean** will delete the `tmp` and `out` trees. 162 169 163 170 ## authors 164 171 165 172 so far, this is a one-woman show. contributions are welcome however. 166 173 167 174 * lexi hale <lexi@hale.su> 168 175
Modified makefile from [0ee3372ddd] to [2300652a5e].
1 1 export OUT = $(PWD)/out 2 2 3 3 export ARCH = x86 4 4 export OS = lin 5 5 export BITS = 64 6 +export TMP = $(PWD)/tmp 6 7 7 8 export TARGET = $(ARCH).$(OS).$(BITS) 8 9 9 10 moddirs = $(wildcard k*) 10 -modules = $(moddirs:k%=%) 11 -headers = $(moddirs:k%=$(OUT)/k/%.h) 12 -objects = $(modules:%=$(OUT)/k%.o) 13 -makefiles = $(moddirs:%=%/makefile) 14 - 15 11 binaries = $(wildcard */exe.*.c) 16 12 binmods = $(sort $(dir $(binaries))) 17 13 18 -all: obj defs tool 14 +posix-oses = lin fbsd dar and hai mgw 15 + 16 +ifeq ($(findstring $(OS),$(posix-oses)),$(OS)) 17 +export POSIX = yes 18 +else 19 +export POSIX = no 20 +endif 21 + 22 +# include libgcc.a in gcc builds, just in case 23 +ifeq ($(CC),gcc) 24 +export COMPLIB = -lgcc 25 +endif 26 + 27 +all: defs obj tool 19 28 obj: $(moddirs:%=%.obj) 20 -defs: $(headers) 21 -tool: $(binmods:%=%.tool) 29 +defs: $(moddirs:%=%.def) 30 +tool: $(OUT)/libk.a $(binmods:%=%.tool) 31 +clean: 32 + rm -rf $(TMP) $(OUT) 22 33 23 -lists = moddirs modules headers objects makefiles binaries binmods 34 +lists = moddirs objects binaries binmods POSIX 24 35 dbg: 25 36 @echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))") 26 37 27 38 %.obj: %/makefile ${TARGET}.calls $(OUT) 28 39 cd $* && $(MAKE) obj 29 40 30 41 %.tool: %/makefile $(OUT) 31 42 cd $* && $(MAKE) tool 32 43 33 44 %.dbg: %/makefile $(OUT) 34 45 cd $* && $(MAKE) dbg 46 + 47 +%.def: %/makefile $(OUT) $(OUT)/k 48 + cd $* && $(MAKE) def 35 49 36 50 %.calls: arch/makefile 37 - cd arch && make calls.$*.s 51 + cd arch && $(MAKE) $(TMP)/calls.$*.s 38 52 39 -$(OUT)/libk.so: mods $(OUT) 40 - $(CC) -shared -o $@ $(objects) 53 +$(OUT)/libk.so: obj $(OUT) 54 + $(CC) -shared -nostdlib $(COMPLIB) -o $@ $(OUT)/*.o 41 55 42 -$(OUT)/libk.a: mods $(OUT) 43 - # using `ar c` and ranlib here instead of 44 - # `ar cs` in case `ar` isn't the GNU version 45 - ar c $@ $(objects) 56 +$(OUT)/libk.a: obj $(OUT) 57 + # using `ar rc` and ranlib here instead of 58 + # `ar rcs` in case `ar` isn't the GNU version 59 + ar rc $@ $(OUT)/*.o 46 60 ranlib $@ 47 61 48 -$(OUT)/k/%.h: k%/makefile $(OUT)/k 49 - cd k$* && $(MAKE) $@ 50 - 51 62 $(OUT) $(OUT)/k: 52 63 mkdir -p $@
Modified modmake from [e72fb78502] to [adae292a57].
2 2 # this is the master makefile that controls the building of each 3 3 # libk module. it is included from each k*/makefile. 4 4 # vim: ft=make 5 5 6 6 mod = $(notdir $(PWD)) 7 7 src = $(wildcard *.c) $(wildcard *.s) 8 8 bare = $(mod:k%=%) 9 +headers = $(wildcard *.h) $(gen-headers) 9 10 10 11 tools = $(filter exe.%.c, $(src)) 11 12 nontools = $(filter-out exe.%.c, $(src)) 12 13 cobjects = $(filter %.c, $(nontools)) 13 14 sobjects = $(filter %.${TARGET}.s, $(nontools)) 14 15 16 +cflags = -isystem ${OUT} -nostdlib ${COMPLIB} -L${OUT} -lk 17 + 15 18 obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \ 16 19 $(sobjects:%.s=${OUT}/$(mod).%.o) 17 -tool: $(tools:exe.%.c=${OUT}/$(mod).%) 20 +tool: $(tools:exe.%.c=${OUT}/$(mod).%) \ 21 + ${OUT}/libk.a 22 + 23 +def: $(headers:%=${OUT}/k/%) 18 24 19 25 dbg: 20 26 @echo tools = $(tools) 21 27 @echo TARGET = ${TARGET} 22 28 @echo cobjects = $(cobjects) 23 29 @echo sobjects = $(sobjects) 30 + @echo headers = $(headers) 24 31 @echo mod = $(mod) 25 32 26 33 ${OUT}/$(mod).%.o: %.c 27 - $(CC) -c $< -o $@ 34 + $(CC) $(cflags) -c $< -o $@ 28 35 29 -${OUT}/k/$(bare).h: $(bare).h 36 +${OUT}/k/%.h: %.h 30 37 cp $< $@ 31 38 32 39 ${OUT}/$(mod).%: exe.%.c 33 - $(CC) $< -o $@ 40 + $(CC) $(cflags) $< -o $@ 41 + 42 +${TMP}: 43 + mkdir -p ${TMP} 34 44 35 45 #- assembly 36 46 # compiling the assembly code will be faster but a lot more 37 47 # complex, given the nature of assembly and the large number of 38 48 # platforms targeted. we need to add build rules for every 39 49 # arch.OS[.bits] tuple; since this is a fairly repetetive task 40 50 # that requires ugly make rules, we're just going to use a ................................................................................ 43 53 # ${OUT} = ultimate build directory 44 54 # $(mod) = module name 45 55 # % = function name 46 56 # $(1) = arch tuple 47 57 arch = ${OUT}/$(mod).%.$(1).o: %.$(1).s 48 58 # invoke with $(call arch,tuple). do not 49 59 # put spaces between either term though! 60 + 61 +ifeq ($(debug),yes) 62 +yasm-flags = -gdwarf2 63 +endif 50 64 51 65 #-- linux 52 66 # linux uses the ELF{32,64} binary format, and generating these 53 67 # from yasm is trivial. linux only supports one ABI per format, 54 68 # at least with ELF, so that's all we need to do. 55 69 56 70 #${OUT}/$(mod).%.x86.lin.32.o: %.x86.lin.32.s 57 71 $(call arch,x86.lin.32) 58 - yasm -gdwarf2 -felf32 $< -o $@ 72 + yasm $(yasm-flags) -felf32 -i${TMP} $< -o $@ 59 73 60 74 #${OUT}/$(mod).%.x86.lin.64.o: %.x86.lin.64.s 61 75 $(call arch,x86.lin.64) 62 - yasm -gdwarf2 -felf64 $< -o $@ 76 + yasm $(yasm-flags) -felf64 -i${TMP} $< -o $@ 63 77 64 78 #-- freebsd 65 79 # the freebsd ABI is different, so it will require different code 66 80 # (though there might be ways to minimize that). freebsd uses the 67 81 # same binary format as Linux (though it also supports a.out and 68 82 # COFF) but because freebsd can interpret multiple different ABIs 69 83 # the object files need to be "branded" with the correct one