/* Copyright (c) 2019-2024 Griefer@Work                                       *
 *                                                                            *
 * This software is provided 'as-is', without any express or implied          *
 * warranty. In no event will the authors be held liable for any damages      *
 * arising from the use of this software.                                     *
 *                                                                            *
 * Permission is granted to anyone to use this software for any purpose,      *
 * including commercial applications, and to alter it and redistribute it     *
 * freely, subject to the following restrictions:                             *
 *                                                                            *
 * 1. The origin of this software must not be misrepresented; you must not    *
 *    claim that you wrote the original software. If you use this software    *
 *    in a product, an acknowledgement (see the following) in the product     *
 *    documentation is required:                                              *
 *    Portions Copyright (c) 2019-2024 Griefer@Work                           *
 * 2. Altered source versions must be plainly marked as such, and must not be *
 *    misrepresented as being the original software.                          *
 * 3. This notice may not be removed or altered from any source distribution. *
 */

#define USELIB(name)        LIB(":" name ".so")
#define USELIBGCC()         LIB("gcc") GCC_FLAGS({ "-static-libgcc" })
#define STATIC_USELIB(name) OBJECT({ TARGET_BINPATH + DISK_LIBPATH + name ".a" })
#define STATIC_USELIBGCC()  LIB("gcc") GCC_FLAGS({ "-static-libgcc" })

#include "apps/.sources"

/* Crt0 */
BEGIN GROUP("libs.crt0") { COMPILE };
	options[OPT_COMPILE_OBJFILE] = f"{TARGET_BINPATH}{DISK_LIBPATH}crt0.o";
	SOURCE({ f"crt0/{XARCH}/crt0{SUFFIX}.S" })
	SET_LANGUAGE("assembler-with-cpp")
END
BEGIN GROUP("libs.crt0") { COMPILE };
	options[OPT_COMPILE_OBJFILE] = f"{TARGET_BINPATH}{DISK_LIBPATH}crt0S.o";
	SOURCE({ f"crt0/{XARCH}/crt0S{SUFFIX}.S" })
	SET_LANGUAGE("assembler-with-cpp")
END

/* kernel */
if (!OPT_ONLY_BUILD_LIBRARIES) {
#include "kernel/.sources"
}

/* libdl */
#include "libdl/.sources"

/* libc */
#include "libc/.sources"


BEGIN GROUP("userspace._verify") { COMPILE };
	SOURCE({
		f"_verify/arch/{XARCH}/*.c",
		"_verify/*.c",
	})
END


/* Simple utility libraries */
BEGIN
	SET_SHARED()
	SET_NOSTDLIB()
	USELIB("libc")
	STATIC_USELIBGCC()
	STATIC_USELIB("libssp")
	LD_FLAGS({ "--hash-style=gnu" })

#define DEFINE_SIMPLE_LIBRARY(name, ...)                         \
	BEGIN GROUP("libs." name) { COMPILE, LINK, ARCHIVE, MCOPY }; \
		SET_OUTPUT_LIBDLL(name)                                  \
		SOURCE({ name "/" "*.c" })                               \
		__VA_ARGS__                                              \
	END
#define DEFINE_SIMPLE_ARCH_LIBRARY(name, ...)                         \
	BEGIN GROUP("libs." name) { COMPILE };                            \
		SET_LANGUAGE("assembler-with-cpp")                            \
		SOURCE({ name "/arch/" + XARCH_ASMFILES })                    \
	END                                                               \
	BEGIN GROUP("libs." name) { COMPILE };                            \
		SOURCE({ name "/arch/" + XARCH + "/" "*.c", name "/" "*.c" }) \
	END                                                               \
	BEGIN GROUP("libs." name) { LINK, ARCHIVE, MCOPY };               \
		SET_OUTPUT_LIBDLL(name)                                       \
		SOURCE({                                                      \
			name "/arch/" + XARCH_ASMFILES,                           \
			name "/arch/" + XARCH + "/" "*.c",                        \
			name "/" "*.c",                                           \
		})                                                            \
		__VA_ARGS__                                                   \
	END
	DEFINE_SIMPLE_LIBRARY("libcmdline")
	DEFINE_SIMPLE_LIBRARY("libdebuginfo", USELIB("libunwind"))
	DEFINE_SIMPLE_LIBRARY("libdemangle")
	DEFINE_SIMPLE_LIBRARY("libdisasm")
	DEFINE_SIMPLE_LIBRARY("libinstrlen")
	DEFINE_SIMPLE_LIBRARY("libjson")
	DEFINE_SIMPLE_LIBRARY("libm")
	DEFINE_SIMPLE_LIBRARY("libansitty")
	DEFINE_SIMPLE_LIBRARY("libbuffer", USELIB("libdl"))
	DEFINE_SIMPLE_LIBRARY("libterm", USELIB("libbuffer"))
	DEFINE_SIMPLE_LIBRARY("libkeymap")
	DEFINE_SIMPLE_LIBRARY("libregex")
	DEFINE_SIMPLE_LIBRARY("libsctrace")
	DEFINE_SIMPLE_LIBRARY("libzlib")
	DEFINE_SIMPLE_LIBRARY("libvio")
	DEFINE_SIMPLE_LIBRARY("libphys", LD_FLAGS({ "-fini=libphys_fini" }))



	DEFINE_SIMPLE_LIBRARY("libiconv", LD_FLAGS({ "-fini=libiconv_fini" }))

	/* Stateful codecs have databases too large to excuse fitting them in the main library. */
	BEGIN GROUP("libs.libiconv-stateful") { COMPILE, LINK, ARCHIVE, MCOPY };
		SET_OUTPUT_LIBDLL("libiconv-stateful")
		SOURCE({ "libiconv/stateful/*.c" })
	END
	BEGIN GROUP("libs.libiconv-mbcs") { COMPILE, LINK, ARCHIVE, MCOPY };
		SET_OUTPUT_LIBDLL("libiconv-mbcs")
		SOURCE({ "libiconv/mbcs/*.c" })
	END


//	DEFINE_SIMPLE_ARCH_LIBRARY("libstdc++")
	DEFINE_SIMPLE_ARCH_LIBRARY("libunwind", USELIB("libdl") LD_FLAGS({ "-fini=libuw_fini" }))
	DEFINE_SIMPLE_ARCH_LIBRARY("libregdump", USELIB("libdl"))
	DEFINE_SIMPLE_ARCH_LIBRARY("libcpustate")
	DEFINE_SIMPLE_ARCH_LIBRARY("libviocore", USELIB("libvio") USELIB("libinstrlen"))
	if (TARGET_ARCH !in ["arm"]) { // TODO: ARM compat
		DEFINE_SIMPLE_ARCH_LIBRARY("libservice")
	}

	if (TARGET_ARCH in ["i386", "x86_64"]) {
		DEFINE_SIMPLE_LIBRARY("libvm86")
		DEFINE_SIMPLE_LIBRARY("libemu86")
		DEFINE_SIMPLE_LIBRARY("libbios86")
		DEFINE_SIMPLE_LIBRARY("libpciaccess", USELIB("libphys") LD_FLAGS({ "-fini=libpci_fini" }))
		DEFINE_SIMPLE_LIBRARY("libsvgadrv", USELIB("libphys"))

		/* DOS/NT emulation/compatiblity */
		DEFINE_SIMPLE_LIBRARY("libdl-pe", USELIB("libdl") LD_FLAGS({ "-init=libpe_init" }))
		DEFINE_SIMPLE_LIBRARY("libkernel32", USELIB("libdl") USELIB("libdl-pe"))
	}

	BEGIN GROUP("libs.libvideo-codec") { COMPILE, LINK, ARCHIVE, MCOPY };
		SET_OUTPUT_LIBDLL("libvideo-codec")
		SOURCE({ "libvideo/codec/*.c" })
	END

	BEGIN GROUP("libs.libvideo-gfx") { COMPILE, LINK, ARCHIVE, MCOPY };
		SET_OUTPUT_LIBDLL("libvideo-gfx")
		USELIB("libvideo-codec")
		SOURCE({
			"libvideo/gfx/*.c",
			"libvideo/gfx/fonts/*.c",
		})
	END
END


/* libdlmalloc */
BEGIN GROUP("libs.libdlmalloc") { COMPILE, LINK, ARCHIVE, MCOPY };
	/* Use the C compiler, so we don't have to deal with c++ meta data... */
	SET_LANGUAGE("c")
	LD_FLAGS({ "--hash-style=gnu" })
	SET_OUTPUT_LIBDLL("libdlmalloc")
	SET_SHARED()
	SET_NOSTDLIB()
	USELIB("libc")
	STATIC_USELIBGCC()
	SOURCE({ "libdlmalloc/*.c" })
END


/* Libssp */
BEGIN GROUP("libs.libssp") { COPYFILE };
	/* GCC expects a library `ssp_nonshared' in its library path... */
	options[OPT_COPYFILE_SRC] = f"{TARGET_BINPATH}{DISK_LIBPATH}libssp.a";
	options[OPT_COPYFILE_DST] = f"{TARGET_BINPATH}{DISK_LIBPATH}libssp_nonshared.a";
END

BEGIN GROUP("libs.libssp") { COMPILE, LINK, ARCHIVE, MCOPY };
	/* Use the C compiler, so we don't have to deal with c++ meta data... */
	SET_LANGUAGE("c")
	LD_FLAGS({ "--hash-style=gnu" })
	SET_OUTPUT_LIBDLL("libssp")
	SET_SHARED()
	SET_NOSTDLIB()
	USELIB("libc")
	STATIC_USELIBGCC()
	SOURCE({ "libssp/*.c" })
END


#include "misc/.sources"
