Making libraries in cc65
Making libraries in cc65
I've done some tinkering and it appears that the cc65 linker pulls in code at the library module level - so any code contained in "module.o" gets linked in regardless of whether it's actually used in the program.
So let's say fubar.c contains functions foo() and bar(), and yolo.c contains functions yo() and lo().
These compile to fubar.o and yolo.o
Archive them as mylib.lib <--- fubar.o yolo.o
If your program uses function foo() but not bar - the object code for bar() will be linked in anyway as a component of module fubar.o
If the library were to have foo.c and bar.c ---> %.o ----> mylib.lib then only the one actually used gets included by the linker.
Further tinkering has revealed that the names of the object libraries in an archive do not clash with the names of object files in the program using the library.
e.g.: if your program has fubar.o and mylib.lib contains a module fubar.o - these do not get confused by the linker.
Identical symbols, however, do cause issues, even if not exported in mylib.h - so if I were to make a function foo() in my program, and foo() wasn't published in mylib.h - the compiler won't bark, and the project will build, but you may be surprised to see strange things happening. When library code tries to call foo(), it will be linked to the program's version of foo() and not the one in the library.
So that's one good reason why libraries often have some universal prefix e.g. sdl_XXXX
-
- Posts: 952
- Joined: Fri Mar 19, 2021 9:06 pm
Making libraries in cc65
38 minutes ago, ZeroByte said:
I've done some tinkering and it appears that the cc65 linker pulls in code at the library module level - so any code contained in "module.o" gets linked in regardless of whether it's actually used in the program.
So let's say fubar.c contains functions foo() and bar(), and yolo.c contains functions yo() and lo().
These compile to fubar.o and yolo.o
Archive them as mylib.lib <--- fubar.o yolo.o
If your program uses function foo() but not bar - the object code for bar() will be linked in anyway as a component of module fubar.o
If the library were to have foo.c and bar.c ---> %.o ----> mylib.lib then only the one actually used gets included by the linker.
Further tinkering has revealed that the names of the object libraries in an archive do not clash with the names of object files in the program using the library.
e.g.: if your program has fubar.o and mylib.lib contains a module fubar.o - these do not get confused by the linker.
Identical symbols, however, do cause issues, even if not exported in mylib.h - so if I were to make a function foo() in my program, and foo() wasn't published in mylib.h - the compiler won't bark, and the project will build, but you may be surprised to see strange things happening. When library code tries to call foo(), it will be linked to the program's version of foo() and not the one in the library.
So that's one good reason why libraries often have some universal prefix e.g. sdl_XXXX
This is how I suspected it. And the fact that you can create conflicting symbols in your program is sometimes / often used to good effect. malloc & free in particular are often replaced because memory access patterns can vary a lot between programs. A special purpose allocator tailored to the needs of a program can greatly increase overall performance, and replacing malloc and free is often a "cheap" way to do it.
Making libraries in cc65
13 hours ago, Scott Robison said:
And the fact that you can create conflicting symbols in your program is sometimes / often used to good effect.
This fact is not lost on me. I've been pondering whether it might make sense for my zwidgits library- instead of using function pointers, just override the code entirely with routines specific to the project. I'm thinking no, as each type of widgit you define will potentially need its own unique version of the routine e.g. draw_widgit(id).. but that application certainly sprung right to mind. (Poor man's inheritance/subclassing)
Making libraries in cc65
I settled on a Makefile format that works for me, and now I copy it with every new project. All I have to change is the SOURCES and PROGRAM.
At one time I knew what each bit did. Now I'm kinda murky on the CFLAGS.
Mind the mangled whitespace and lost tabs... Make is finicky... I'll attach it too.
SOURCES = main.c petscii-panel.c
PROGRAM = BLINKENLIGHTS
CC65_TARGET = cx16
CC = cl65
CFLAGS = --cpu 65c02 -t $(CC65_TARGET) --create-dep $(<:.c=.d) -Ors
LDFLAGS = -t $(CC65_TARGET) -m $(PROGRAM).map
OBJDIR = .obj
#############################################
OBJECTS = $(SOURCES:%.c=$(OBJDIR)/%.o)
.SUFFIXES:
all: $(PROGRAM)
ifneq (($MAKECMDGOALS),clean)
-include $(SOURCES:.c=.d)
endif
clean:
$(RM) $(OBJECTS) $(SOURCES:.c=.d) $(PROGRAM) $(PROGRAM).map
.PHONY: all clean
$(PROGRAM): $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $^
$(OBJECTS): $(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
Makefile
Making libraries in cc65
One thing I've had issues with in my adventures with Makefiles is the .h files. If I make changes to an .h file, most of the time it doesn't cause Make to realize that the c files which include it should be rebuilt.
In Makefiles where I went through and defined each and every dependency myself, I can make that happen, but these self-directing Makefiles tend to miss that. Is that what the --create-dep option helps with?
-
- Posts: 952
- Joined: Fri Mar 19, 2021 9:06 pm
Making libraries in cc65
35 minutes ago, ZeroByte said:
One thing I've had issues with in my adventures with Makefiles is the .h files. If I make changes to an .h file, most of the time it doesn't cause Make to realize that the c files which include it should be rebuilt.
In Makefiles where I went through and defined each and every dependency myself, I can make that happen, but these self-directing Makefiles tend to miss that. Is that what the --create-dep option helps with?
I think so. Every tool chain has its own way of dealing with dependencies if they are designed to be used in a makefile. Back when I first started with C (Turbo C 2.0), the IDE (if I recall correctly) had dark magic to make things "Just Work(TM)". Such has been true with every IDE I've ever used where the IDE and toolchain was provided by the same company (Turbo C, Turbo C++, Borland C++, all the various Visual C++ versions I've used).
When it comes to make files though, they can't just know how every language does "internal" dependencies. I've seen projects create their makefiles to include explicit listings of header files along with dependent c files. I've seen things like create-dep. I think CMake has some dark arts in it to know how certain languages do it and ensure they include that information, since not every toolchain will do it the same way.
Making libraries in cc65
Yeah, H files aren't as straightforward as .s and .o files are.
Making libraries in cc65
"-t" sets the CPU. Therefore, if you want a different one, then you must put "--cpu" on the right side of "-t".
Making libraries in cc65
So back to Zero's talking about library files. Looks like the rule is:
1. If the very-common pattern is to USE all of the functions, then gang them together.
2. If someone might just want to use ONE function, then split them apart.
3. And make the common data its own library as well!
This could make for a very leggy set of libraries!