Splitting libc and libk, linker error

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
dengeltheyounger
Member
Member
Posts: 25
Joined: Wed Feb 24, 2021 8:52 pm

Splitting libc and libk, linker error

Post by dengeltheyounger »

So, I've decided that I want to split libc and libk. I went ahead and created a new branch in my Github repo, and then began altering the makefiles, in the hopes of coming up with something that successfully distinguishes between libc and libk. Overall, I have libc's stuff in the following location:
/usr/include
/usr/lib

I wasn't sure where to put libk relative to libc, and so I decided that I would put it in these locations:
/usr/src/include
/usr/src/lib

Both libc and libk compile correctly. libc.a is put in /usr/lib, and libk.a is put in /usr/src/lib. The kernel's stuff seems to be accessing the right headers, and the functions compile correctly. The issue seems to be a linking error. Basically, even when I use -L in order to specify the path to the library used in order to access libk functions (/usr/src/lib), the linker says the following:

Code: Select all

/usr/libexec/gcc/i686-elf/ld: cannot find -lk
collect2: error: ld returned 1 exit status
This happens even if I do -l:libk.a

The -lk option works in the non split version in the master branch. In the course of making the changes to the makefile, now it can't find the library, even after the path has been specified with -L.

I'll link the Github, and I'll also post as attachment several files that I specifically changed from the Meaty Skeleton template.
If there's any information (code, makefile portions) that I can specifically post in the comments in order to make things easier, let me know.

Github: https://github.com/dengeltheyounger/BlueOS
master contains the code before I tried to separate libc and libk.
separate_libc_libk is the code that results from me trying to separate the two.

UPDATE: The problems still hasn't been solved. However, I've tried one thing:
I added an echo statement to echo LIBDIR, which is included here:

Code: Select all

LIBS:=$(LIBS) -nostdlib -L$(LIBDIR) -l:libk.a -lgcc
LIBS is added to the final formula here:

Code: Select all

LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

Code: Select all

blueos.kernel: $(OBJS) $(ARCHDIR)/linker.ld
        $(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(LINK_LIST)
        grub-file --is-x86-multiboot blueos.kernel
I did an @echo in order to confirm that LIBDIR points to where it needs to. LIBDIR points to /usr/src/lib, just like it's supposed to. /usr/src/lib is actually in the sysroot path, just like it should be. libk.a is in /usr/src/lib. The -L option is part of the linker option just like it should. It's just not recognizing libk.a for some reason.

UPDATE2:
I've figured out that it is a linker issue. I don't really know why, and I don't know what's going on, but for whatever reason, the linker is not accepting the new library path. Basically, it starts out thinking that the library path is /usr/lib, and for whatever reason it looks like it's still looking in /usr/lib, even with the -L option. I don't really know why.

This is the result of verbose:

Code: Select all

COLLECT_GCC=i686-elf-gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-elf/10.2.0/lto-wrapper
Target: i686-elf
Configured with: /var/tmp/portage/cross-i686-elf/gcc-10.2.0-r5/work/gcc-10.2.0/configure --host=x86_64-pc-linux-gnu --target=i686-elf --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/i686-elf/gcc-bin/10.2.0 --includedir=/usr/lib/gcc/i686-elf/10.2.0/include --datadir=/usr/share/gcc-data/i686-elf/10.2.0 --mandir=/usr/share/gcc-data/i686-elf/10.2.0/man --infodir=/usr/share/gcc-data/i686-elf/10.2.0/info --with-gxx-include-dir=/usr/lib/gcc/i686-elf/10.2.0/include/g++-v10 --with-python-dir=/share/gcc-data/i686-elf/10.2.0/python --enable-languages=c --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 10.2.0-r5 p6' --disable-esp --disable-libstdcxx-pch --enable-poison-system-directories --disable-libstdcxx-time --disable-shared --disable-libquadmath --disable-libatomic --disable-threads --without-headers --disable-bootstrap --with-newlib --enable-multilib --disable-fixed-point --with-arch=i686 --enable-targets=all --disable-libgomp --disable-libssp --disable-libada --disable-systemtap --disable-vtable-verify --disable-libvtv --without-zstd --enable-lto --without-isl --disable-libsanitizer --enable-default-pie --enable-default-ssp
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (Gentoo 10.2.0-r5 p6) 
COMPILER_PATH=/usr/libexec/gcc/i686-elf/10.2.0/:/usr/libexec/gcc/i686-elf/10.2.0/:/usr/libexec/gcc/i686-elf/:/usr/lib/gcc/i686-elf/10.2.0/:/usr/lib/gcc/i686-elf/
LIBRARY_PATH=/usr/lib/gcc/i686-elf/10.2.0/:/usr/lib/gcc/i686-elf/10.2.0/../../../../i686-elf/lib/:/home/admin/Documents/Programs/osdev/meaty_skeleton/BlueOs/sysroot/usr/lib/
COLLECT_GCC_OPTIONS='-isystem' '=/usr/src/include' '-T' 'arch/i386/linker.ld' '-o' 'blueos.kernel' '-O2' '-g' '-ffreestanding' '-Wall' '-Wextra' '-nostdlib' '-L/usr/src/lib' '-v' '-mtune=generic' '-march=i686'
 /usr/libexec/gcc/i686-elf/10.2.0/collect2 -plugin /usr/libexec/gcc/i686-elf/10.2.0/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/i686-elf/10.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccAOwuab.res --sysroot=/home/admin/Documents/Programs/osdev/meaty_skeleton/BlueOs/sysroot -pie -o blueos.kernel -L/usr/src/lib -L/usr/lib/gcc/i686-elf/10.2.0 -L/usr/lib/gcc/i686-elf/10.2.0/../../../../i686-elf/lib -L/home/admin/Documents/Programs/osdev/meaty_skeleton/BlueOs/sysroot/usr/lib -lk -lgcc arch/i386/crti.o arch/i386/crtbegin.o arch/i386/boot.o arch/i386/prep_gdt.o arch/i386/gdt.o arch/i386/tty.o arch/i386/pic.o arch/i386/irq.o arch/i386/isr.o arch/i386/irq_handler.o arch/i386/exception.o arch/i386/exception_handler.o kernel/kernel.o kernel/memory.o arch/i386/crtend.o arch/i386/crtn.o -T arch/i386/linker.ld
/usr/libexec/gcc/i686-elf/ld: cannot find -lk
collect2: error: ld returned 1 exit status
Attachments
output.txt
This is the output that build.sh gave (in the course of running the various makefiles).
(2.24 KiB) Downloaded 30 times
dengeltheyounger
Member
Member
Posts: 25
Joined: Wed Feb 24, 2021 8:52 pm

Re: Splitting libc and libk, linker error

Post by dengeltheyounger »

So, I managed to get the error fixed. It's really really hacky, but if you're going off of the meaty skeleton and you want to split your libk and libc, you can use this as a starting point (and hopefully improve it).

Basically, instead of having kernel and libc as the only directories, you have kernel, libc, and libk. libc and libk are almost identical at this point.

This is the kernel's makefile

Code: Select all

DEFAULT_HOST!=../default-host.sh
HOST?=DEFAULT_HOST
HOSTARCH!=../target-triplet-to-arch.sh $(HOST)

CFLAGS?=-O2 -ggdb
CPPFLAGS?=
LDFLAGS?=
LIBS?=

DESTDIR?=
PREFIX?=/usr/src
EXEC_PREFIX?=$(PREFIX)
BOOTDIR?=$(EXEC_PREFIX)/boot
KINCLUDEDIR?=$(PREFIX)/include

CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra
CPPFLAGS:=$(CPPFLAGS) -isystem=$(KINCLUDEDIR) -I$(KINCLUDEDIR)
LDFLAGS:=$(LDFLAGS)
# Unfortunately, a linking error results if I don't use -L and $(SYSROOT)
LIBS:=$(LIBS) -nostdlib -L$(SYSROOT)$(KLIBDIR) -lk -lgcc

ARCHDIR=arch/$(HOSTARCH)

include $(ARCHDIR)/make.config

CFLAGS:=$(CFLAGS) $(KERNEL_ARCH_CFLAGS)
CPPFLAGS:=$(CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS)
LDFLAGS:=$(LDFLAGS) $(KERNEL_ARCH_LDFLAGS)
LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS)

KERNEL_OBJS=\
$(KERNEL_ARCH_OBJS) \
kernel/kernel.o \
kernel/memory.o \

OBJS=\
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

LINK_LIST=\
$(LDFLAGS) \
$(ARCHDIR)/crti.o \
$(ARCHDIR)/crtbegin.o \
$(KERNEL_OBJS) \
$(LIBS) \
$(ARCHDIR)/crtend.o \
$(ARCHDIR)/crtn.o \

.PHONY: all clean install install-headers install-kernel
.SUFFIXES: .o .c .S

all: blueos.kernel

blueos.kernel: $(OBJS) $(ARCHDIR)/linker.ld
	$(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(LINK_LIST)
	grub-file --is-x86-multiboot blueos.kernel

$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o:
	OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@

.c.o:
	$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)

.S.o:
	$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS)

clean:
	rm -f blueos.kernel
	rm -f $(OBJS) *.o */*.o */*/*.o
	rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d

install: install-headers install-kernel

install-headers:
	mkdir -p $(DESTDIR)$(KINCLUDEDIR)
	cp -R --preserve=timestamps include/. $(DESTDIR)$(KINCLUDEDIR)/.

install-kernel: blueos.kernel
	mkdir -p $(DESTDIR)$(BOOTDIR)
	cp blueos.kernel $(DESTDIR)$(BOOTDIR)

-include $(OBJS:.o=.d)
This is the libc's makefile:

Code: Select all

DEFAULT_HOST!=../default-host.sh
HOST?=DEFAULT_HOST
HOSTARCH!=../target-triplet-to-arch.sh $(HOST)

CFLAGS?=-O2 -g
CPPFLAGS?=
LDFLAGS?=
LIBS?=

DESTDIR?=
PREFIX?=/usr
EXEC_PREFIX?=$(PREFIX)
INCLUDEDIR?=$(PREFIX)/include
LIBDIR?=$(EXEC_PREFIX)/lib

CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra
CPPFLAGS:=$(CPPFLAGS) -Iinclude

ARCHDIR=arch/$(HOSTARCH)

include $(ARCHDIR)/make.config

CFLAGS:=$(CFLAGS) $(ARCH_CFLAGS)
CPPFLAGS:=$(CPPFLAGS) $(ARCH_CPPFLAGS)

FREEOBJS=\
$(ARCH_FREEOBJS) \
stdio/printf.o \
stdio/putchar.o \
stdio/puts.o \
stdlib/abort.o \
stdlib/int_to_ascii.o \
string/memcmp.o \
string/memcpy.o \
string/memmove.o \
string/memset.o \
string/strlen.o \
string/strcmp.o \

HOSTEDOBJS=\
$(ARCH_HOSTEDOBJS) \

OBJS=\
$(FREEOBJS) \
$(HOSTEDOBJS) \

BINARIES=libc.a

.PHONY: all clean install install-headers install-libs
.SUFFIXES: .o .c .S

all: $(BINARIES)

libc.a: $(OBJS)
	$(AR) rcs $@ $(OBJS)

.c.o:
	$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)

.S.o:
	$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS)

clean:
	rm -f $(BINARIES) *.a
	rm -f $(OBJS) *.o */*.o */*/*.o
	rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d

install: install-headers install-libs

install-headers:
	mkdir -p $(DESTDIR)$(INCLUDEDIR)
	cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/.

install-libs: $(BINARIES)
	mkdir -p $(DESTDIR)$(LIBDIR)
	cp $(BINARIES) $(DESTDIR)$(LIBDIR)

-include $(OBJS:.o=.d)
This is libk's makefile:

Code: Select all

DEFAULT_HOST!=../default-host.sh
HOST?=DEFAULT_HOST
HOSTARCH!=../target-triplet-to-arch.sh $(HOST)

CFLAGS?=-O2 -g
CPPFLAGS?= -isystem$(KINCLUDEDIR)
LDFLAGS?=
LIBS?=

DESTDIR?=
PREFIX?=/usr/src
EXEC_PREFIX?=$(PREFIX)
KINCLUDEDIR?=$(PREFIX)/include
KLIBDIR?=$(EXEC_PREFIX)/lib

CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra
CPPFLAGS:=$(CPPFLAGS) -Iinclude

ARCHDIR=arch/$(HOSTARCH)

include $(ARCHDIR)/make.config

CFLAGS:=$(CFLAGS) $(ARCH_CFLAGS)
CPPFLAGS:=$(CPPFLAGS) $(ARCH_CPPFLAGS)

FREEOBJS=\
$(ARCH_FREEOBJS) \
stdio/printf.o \
stdio/putchar.o \
stdio/puts.o \
stdlib/abort.o \
stdlib/int_to_ascii.o \
string/memcmp.o \
string/memcpy.o \
string/memmove.o \
string/memset.o \
string/strlen.o \
string/strcmp.o \

HOSTEDOBJS=\
$(ARCH_HOSTEDOBJS) \

OBJS=\
$(FREEOBJS) \
$(HOSTEDOBJS) \

BINARIES=libk.a

.PHONY: all clean install install-headers install-libs
.SUFFIXES: .o .c .S

all: $(BINARIES)

libk.a: $(OBJS)
	$(AR) rcs $@ $(OBJS)

.c.o:
	$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)

.S.o:
	$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS)

clean:
	rm -f $(BINARIES) *.a
	rm -f $(OBJS) *.o */*.o */*/*.o
	rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d

install: install-headers install-libs

install-headers:
	mkdir -p $(DESTDIR)$(KINCLUDEDIR)
	cp -R --preserve=timestamps include/. $(DESTDIR)$(KINCLUDEDIR)/.

install-libs: $(BINARIES)
	mkdir -p $(DESTDIR)$(KLIBDIR)
	cp $(BINARIES) $(DESTDIR)$(KLIBDIR)

-include $(OBJS:.o=.d)
This is config.sh

Code: Select all

SYSTEM_HEADER_PROJECTS="libk libc kernel"
PROJECTS="libk libc kernel"

export MAKE=${MAKE:-make}
export HOST=${HOST:-$(./default-host.sh)}

export AR=${HOST}-ar
export AS=${HOST}-as
export CC=${HOST}-gcc

export PREFIX=/usr
export EXEC_PREFIX=$PREFIX
export BOOTDIR=/boot
export LIBDIR=$EXEC_PREFIX/lib
export KLIBDIR=$EXEC_PREFIX/src/lib
export INCLUDEDIR=$PREFIX/include
export KINCLUDEDIR=$PREFIX/src/include

export CFLAGS='-O2 -g'
export CPPFLAGS=''

# Configure cross-compiler to use desired system root
export SYSROOT="$(pwd)/sysroot"
export CC="$CC --sysroot=$SYSROOT"

# work around that the -elf gcc targets doesn't have a system include dir
# because it was configured with --without-headers rather than --with-sysroot
# if echo "$HOST" | grep -Eq -- '-elf($|-)'; then
#	export CC="$CC -isystem=$INCLUDEDIR"
# fi
I don't think there's anything else that I changed (in build scripts).

I hope this helps someone else!
Post Reply