Noob question: using -I to organise my libraries

Go To Last Post
34 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm trying to be a bit more grown-up with how I organise my projects. My game system has a library that contains all the hardware abstractions and currently I just copy it into the folder for each game I make. This has resulted in about 6 different versions of SPIKE.h and SPIKE.c where I make small improvements with each new game.

So, to that end I have created a separate repository for my library.

In my Makefile I've added a variable that points to the path, and added that to my compiler invocation with the -I parameter, but it doesn't work. I'm still not very experienced working with C.

SPIKELIB = ../spikelib
COMPILE = avr-gcc -Wall -O3 -mmcu=$(DEVICE) $(C_FLAGS) -I$(SPIKELIB)

I get 2 different errors depending on how I modify my Makefile. If I leave everything as-is except for adding the -I param, I get the error:

make: *** No rule to make target 'SPIKE.o', needed by 'main.elf'. Stop.

If I remove SPIKE.o from the list of objects to build, I get errors complaining that there are undefined references to functions that are defined in SPIKE.

I'm only just at the point where I'm comfortable using separate files for my code, putting them in different folders is just beyond reach :(

Thank you
-Mike

This topic has a solution.
Last Edited: Sun. Mar 3, 2019 - 12:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With gcc, a ‘library’ is a compiled module that gets linked in. In Arduino parlance, a library is one or more source files that get compiled with the project.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
With gcc, a ‘library’ is a compiled module that gets linked in. In Arduino parlance, a library is one or more source files that get compiled with the project.

Right, see, this is where things always get difficult because I don't know all the words.

I have some Common Code that I want to keep in a separate folder so it can be shared by multiple projects. I think I was being silly thinking that adding -Ipathtocode would cause AVR-GCC to go find the .h and .c files it needed and compile them in.

I just copied a previously compiled .o file into my Common Code directory, and tried compiling again with the -I param set but that also didn't work. So I'm missing a step - I've heard talk and of "Linkers" before.

How to I get my Common Code object file linked into my project?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Problem is, -I tells the compiler where to find .h files, but there is no equivalent option for .c files. You have to add them individually to the gcc command line, with full path.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

.h and .c are handled differently. -I let's you tell it the "other place" for headers but for .c if using Makefiles you might want to look at VPATH.

 

But most people would not use Makefiles directly (this is 2019!) but would use an IDE and they usually have mechanisms such as "Add as link" in AS7 to set up virtual paths to sources.

 

EDIT Google gave this which seems to cover VPATH: https://www.cmcrossroads.com/art...

Last Edited: Sat. Mar 2, 2019 - 12:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

Problem is, -I tells the compiler where to find .h files, but there is no equivalent option for .c files. You have to add them individually to the gcc command line, with full path.

How about .o files?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
But most people would not use Makefiles directly (this is 2019!) but would use an IDE
.

Sadly I write my code during whatever spare 5 minutes I'm gifted with throughout the day so I'm either sat in front of a Windows machine, a Mac, my iPad or with phone in hand. A good text editor and a raspberry pi with GCC in it *should* be all I need ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can get Eclipse on all those platforms ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
[... my iPad or with phone in hand. ..] You can get Eclipse on all those platforms ;-)

I might have to call your bluff on that one. I don't think there is even a Java Virtual Machine available. Even if Eclipse IDE was available, it's use would be confined to that "special place in hell" for errant programmers.

 

Last Edited: Sat. Mar 2, 2019 - 02:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In SPIKELIB:

avr-gcc -o spike.o <flags> spike.c

avr-ar r libspke.a spike.o

 

in working dir:

avr-gcc .... -L$(SPIKELIB) -lspike

(^ flags are upper and lowercase ell -- i.e. L, l)

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Once you get this working and have a shared

spike.h and spike.c, make sure you compile all

of your old projects in addition to the one you

are currently working on.  Occasionally a change

made for your new project will break one or more

of your old ones, and the earlier you notice this

the easier it will be to reconcile the changes.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-mike wrote:
Once you get this working and have a shared spike.h and spike.c, make sure you compile all of your old projects in addition to the one you are currently working on. Occasionally a change made for your new project will break one or more of your old ones, and the earlier you notice this the easier it will be to reconcile the changes.
I keep a version archive with each project which includes copies of my libraries as they were when that version was built and deployed.

 

One of these days I'll use SVN or similar to manage all of this, but for now my efforts are on a small enough scale that a tarball is OK.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MattRW wrote:

In SPIKELIB:

avr-gcc -o spike.o <flags> spike.c

avr-ar r libspke.a spike.o

 

in working dir:

avr-gcc .... -L$(SPIKELIB) -lspike

(^ flags are upper and lowercase ell -- i.e. L, l)

 

 

Ok, so avr-ar creates an ARCHIVE? And that archive is called (in your example) libspke.a

How do the -L / -l params reference that file?

If I have other 'libraries' should I compile them all into a single archive? (I have the SPIKE.h/.c library that deals with all the hardware stuff, and I have a tilemap-engine.h/.c and then in the future I might have isometric-engine.h/.c)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MalphasWats wrote:
Ok, so avr-ar creates an ARCHIVE? And that archive is called (in your example) libspke.a How do the -L / -l params reference that file? If I have other 'libraries' should I compile them all into a single archive?
Generally, no.

 

Unless you have a very good reason (e.g. source-code confidentiality), it's better to build from source every time.  This lets the toolchain work with and optimise your project as a whole.  Many optimisations cannot be applied to .a files.

 

The rationale behind using .a files has changed over time.  On modern hardware, a complete build of an AVR app can be measured in single-digit seconds.  30 years ago, this would not have been the case, and the ability to compile and file away a variety of libraries for later linking had more appeal.  That's not really a concern today, unless you're building from millions of lines of source.

 

@barnacle recently posted about an embedded product of his with a whopping 55KLOC on an M0+.  I wonder how long it took to build...

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sat. Mar 2, 2019 - 04:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

The rationale behind using .a files has changed over time.

 

And when using C++ often a library consists only of

a .h file, no .cpp!  This is due to the way templates

work.  The compiler needs to see the implementation

of all the templates since it creates them on demand

as they are used.  Also inline functions are in the .h

and not the .cpp file.

 

--Mike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
Generally, no.

Oh, so the best way to do what I want to do is genuinely to just copy the source files I need into each project, but perhaps just add them to .gitignore so they don't get source controlled all over the place? (Or I suppose keep doing what I'm doing and then each project will always compile with its own hacker version of the 'library')?

It seems to be a lot of work to build things neatly?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,  but there was a typo in my post: libspike.a not libspke.a.

 

avr-cr generates the archive libspike.a.   You can have any number of .o files in there.  Just add to the line.   The argument "r" says (replace).   "avr-ar t libspike.a" will list the dot-o files.

 

Makefile can be set up to update new .o's in the archive.  Read the make manual.

 

The -L flags tells gcc where to look for archives.  The -l flag indicates the archive: e.g., -lspike says look for libspike.a or libspike.so (shared object).

 

You could add a rule to your makefile to rebuild if libspike has changed:

app: app.c $(LIBSPIKE)/libspike.a

    avr-gcc ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MalphasWats wrote:
Oh, so the best way
There is no one 'best' for everyone.

 

I keep all my libraries in ./lib, and my project 'foo' in ./foo.  In the makefile for 'foo' (indeed, for all my projects, I have -I ../lib

 

@avr-mike's caveat is that if you later change/rework a library, that could affect any previous projects which used that library before the rework.

 

I want to minimise the number of copies of same/similar/versioned libraries floating around, so I really only ever have one 'live' or 'current' version of each library, and it's in ./lib.  For projects that matter to me (stuff running on hardware out in the real world), I checkpoint deployed versions of the source code >>and<< my ../lib directory, so I can always rebuild that version of that project with the libraries in the state they were in at the time.

 

Not the best way.  Just a way that works for me at the moment.  I am a low-volume shop of one.  As I said, one day I'll move to SVN or something like it.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

indeed, for all my projects, I have -I ../lib

 

but that's what *I* want to do, but it won't compile?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MalphasWats wrote:
but that's what *I* want to do, but it won't compile?
I think you're going to have to show us more.

 

  • full makefile
  • full build output
  • directory structure

 

Note that -I is not sufficient.  You still need to compile the source files themselves.  The -I is only for letting the toolchain where to find #included files (i.e. .h files), so that you can #include "mylibrary.h" and it will look for it in the correct place.  You still have to have a rule in the makefile which builds mylibrary.o from mylibrary.c, and then a rule that links mylibrary.o into the final .elf

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sat. Mar 2, 2019 - 05:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MalphasWats wrote:

joeymorin wrote:

indeed, for all my projects, I have -I ../lib

 

but that's what *I* want to do, but it won't compile?

 

Say ../spike includes headers and archive (libspike.a), then you want

avr-gcc -o app -I../spike ... app.c ... -L../spike -lspike

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MattRW wrote:
Say ../spike includes headers and archive (libspike.a), then you want
I have advised not to use .a files.  I don't know what OP is doing.  His latest:

MalphasWats wrote:
joeymorin wrote: indeed, for all my projects, I have -I ../lib but that's what *I* want to do, but it won't compile?
... suggests that he is not using .a, so -L (which is for linking) is not necessary.  I expect spike.c is simply not getting built at all because there is no makefile rule for it:

make: *** No rule to make target 'SPIKE.o', needed by 'main.elf'. Stop.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sat. Mar 2, 2019 - 05:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

 I think you're going to have to show us more.

 

  • full makefile
  • full build output
  • directory structure

 

Ok, but don't come crying when your eyes are bleeding and your brain is running out of your ears!

 

home /
 - spikelib /
     SPIKE.h
     SPIKE.c
     tilemap-engine.h
     tilemap-engine.c

 - battlebeasts /
     main.h
     main.c
     beast.h
     beast.c
     makefile

 - argon /
     main.h
     main.c
     argon.h
     argon.c
     makefile

so that's my directory structure for the library, plus 2 games that use the library (although at this stage I'm just trying to get 'battle beasts' to work, 'argon' just has copies of the libraries in it which I'd like to delete if I can get this to work!)

 

my makefile looks like this:

 

#
# Makefile template for ATMega1284p
#

DEVICE     = atmega1284p
DEVDUDE    = m1284p
#CLOCK      = 16000000
PROGRAMMER = -c linuxspi -P /dev/spidev0.0
OBJECTS    = beasts.o main.o     # Add more objects for each .c file here
C_FLAGS    = -Wl,--gc-sections -Wl,--relax -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -mshort-calls

SPIKELIB = ../spikelib

# fuse settings:
# use http://www.engbedded.com/fusecalc
#FUSES      = -U lfuse:w:0x42:m -U hfuse:w:0x99:m -U efuse:w:0xff:m  # 1mhz
#FUSES      = -U lfuse:w:0xc2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m  # 8mhz
FUSES      = -U lfuse:w:0xfe:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m  # 16mhz

AVRDUDE = sudo avrdude -b 200000 $(PROGRAMMER) -p $(DEVDUDE)

COMPILE = avr-gcc -Wall -O3 -mmcu=$(DEVICE) -I$(SPIKELIB) $(C_FLAGS)

# symbolic targets:
all:	main.hex

.c.o:
	$(COMPILE) -c $< -o $@

.S.o:
	$(COMPILE) -x assembler-with-cpp -c $< -o $@

.c.s:
	$(COMPILE) -S $< -o $@

flash:	all
	$(AVRDUDE) -U flash:w:main.hex:i

fuse:
	$(AVRDUDE) $(FUSES)

install:	flash fuse

# if you use a bootloader, change the command below appropriately:
load:	all
	bootloadHID main.hex

clean:
	rm -f main.hex main.elf $(OBJECTS)

# file targets:
main.elf: $(OBJECTS)
	$(COMPILE) -o main.elf $(OBJECTS)

main.hex: main.elf
	rm -f main.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
	avr-size --format=avr --mcu=$(DEVICE) main.elf
	avr-nm -S -td --size-sort main.elf
# If you have an EEPROM section, you must also create a hex file for the
# EEPROM and add it to the "flash" target.

# Targets for code debugging and analysis:
disasm:	main.elf
	avr-objdump -d main.elf

 

The output from running make is then:

 

avr-gcc -Wall -O3 -mmcu=atmega1284p -Wl,--gc-sections -Wl,--relax -ffunction-sections -fdata-sections -fno-inline-small-functions -fpack-struct -fshort-enums -mshort-calls -I../spikelib -o main.elf beasts.o main.o
main.o: In function `main':
main.c:(.text.startup.main+0x0): undefined reference to `initialise'
main.c:(.text.startup.main+0x8): undefined reference to `millis'
main.c:(.text.startup.main+0x24): undefined reference to `draw'
beasts.o: In function `battle_beasts':
beasts.c:(.text.battle_beasts+0x0): undefined reference to `millis'
beasts.c:(.text.battle_beasts+0x4): undefined reference to `clear_buffer'
beasts.c:(.text.battle_beasts+0x8): undefined reference to `draw'
collect2: error: ld returned 1 exit status
makefile:56: recipe for target 'main.elf' failed
make: *** [main.elf] Error 1

 

Edited to mention: in argon, the makefile would have this difference:

 

OBJECTS    = SPIKE.o tilemap-engine.o argon.o main.o     # Add more objects for each .c file here

because the source files are all in the same directory

Last Edited: Sat. Mar 2, 2019 - 05:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The advantage to using an archive for your library is that you just have to reference that one item from your application Makefiles, instead of tracking all the .c or .o files you keep in ../spike.   If you use ../spike/libspike.a as a dependency in your application Makefiles, your "make" will flag that a recompile is needed.  

 

As far as optimization goes, unless gcc sees all the C code at once, it can't do global optimization (e.g., beta reductions like inlining), so I don't see any reason to stay away from archives.

 

And keeping version control straight is usually helped with a source control system.  GIT seems to be the fashion these days.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The makefile can't find SPIKE.c because it's in a different directory from the makefile itself. So when you add  SPIKE.o to the object list, it fails.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The advantage to using an archive for your library is that you just have to reference that one item from your application Makefiles, instead of tracking all the .c or .o files you keep in ../spike.  

All the .h, .c, and .a files are likely to be in the same directory anyway, so there isn't anything to keep track of, and that's not really an advantage. 

 

If you use ../spike/libspike.a as a dependency in your application Makefiles, your "make" will flag that a recompile is needed.  

If you skip the .a and just have a rule for the .c in the first place, that recompile will just happen, no need for a second step.  Unless you have that rule in your makefile already, in which case why bother with the .a in the first place.  The only advantage to using .a is speed, which isn't much of an advantage.  If my app takes 3.7 seconds to build instead of 5.1 seconds, I'm not really going to notice, let alone care.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I already told you the answer here is VPATH. After googling and reading about that which bit is still causing problems?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I already told you the answer here is VPATH. After googling and reading about that which bit is still causing problems?

When I add VPATH=../spikelib to my makefile, I get new errors:

avr-gcc: error: SPIKE.o: No such file or directory

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When the number of projects I had and the interconnectedness between those projects became unmanagable I was also in need of a way to re-use the same "source code library" in my projects.

After a few experiments I settled on simply using symbolic links on my linux box.

I've got just over 20 different of those libraries, which all have their own sub directory in ~/projects/avr/lib/

 

I have also made a makefile template from which I start new projects.

In my makefile template I have made a "link" target to make links to the libraries I want to use:

MYLIB    = /home/paul/projects/avr/lib
MKLINK    = ln -fs $(MYLIB)

link:
	$(MKLINK)/debug/debug.h
#	$(MKLINK)/keyboard/keyboard.cpp
#	$(MKLINK)/keyboard/keyboard.h
#	$(MKLINK)/lcd_hd44780/lcd_hd44780.cpp
#	$(MKLINK)/lcd_hd44780/lcd_hd44780.h
#	$(MKLINK)/lcd_pcd8544/lcd_pcd8544.cpp
#	$(MKLINK)/lcd_pcd8544/lcd_pcd8544.h
#	$(MKLINK)/lcd_pcd8544/font_5x8.cpp
#	$(MKLINK)/lcd_pcd8544/font_ubucon_11x24.cpp
	$(MKLINK)/mumarnet/mumarnet_data.cpp
	$(MKLINK)/mumarnet/mumarnet_rs485.h
#	$(MKLINK)/mumarnet/mumarnet_rf.cpp
#	$(MKLINK)/mumarnet/mumarnet_rf.h
#	$(MKLINK)/transceiver/transceiver.cpp
#	$(MKLINK)/transceiver/transceiver.h
	$(MKLINK)/timer/timer.cpp
	$(MKLINK)/timer/timer.h
####	$(MKLINK)/twi/twi.cpp
####	$(MKLINK)/twi/twi.h

 

The next step is to add the library files I need for that project to the list of link files:

LINKFILES = main.o
#LINKFILES += lcd_hd44780.o
#LINKFILES+= lcd_pcd8544.o
LINKFILES+= mumarnet.o
LINKFILES+= timer.o
#LINKFILES+= twi.o

 

After that I can use those files just as all the other files in any of my projects.

This way my libraries are compiled separately for each project, and the generated object files are also in the directory for each project.

This is a big advantage for me, because each of those library source code files has a line:

#include "main.h"

and in main.h are a bunch of #define's to adjust the behaviour of the library files.

I can reuse the HD44780 in different projects, with different pins for the LCD.

All the hardware registers get set in the object file during compile time for that specific project, which reduces code size and ram use.

 

Kartman said in #2 that a library is a compiled / archived file, and from the viewpoint of GCC he is right of course.

In the embedded world however it is not uncommon to call some source code files that deliver spicific functionality (such as a HD44780 driver) a library, even if they are distributed as source and compiled / linked into a project this way. It's not only "arduino" doing this.

 

Because of clawson I had a look into VPATH, and I glanced a bit over some pitfalls with vpath:

http://make.mad-scientist.net/papers/how-not-to-use-vpath/

but it's too much text for me to wade through. My current method seems much more straightforward and simpler.

I have no love for makfile syntax and anything to keep it simpler is a good thing in my book.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

Last Edited: Sat. Mar 2, 2019 - 09:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MalphasWats wrote:
clawson wrote:

I already told you the answer here is VPATH. After googling and reading about that which bit is still causing problems?

When I add VPATH=../spikelib to my makefile, I get new errors:

avr-gcc: error: SPIKE.o: No such file or directory

Alright, I *think* I might have cracked it. The reason it wasn't working with VPATH is because I'd copied some .o files into the ../spikelib directory in the hope that might do something and then obviously make didn't bother recompiling them but then they weren't in the build directory to be 'linked'.

I continue to learn! Thank you all for your help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This thread touches the topic of version control; something which I find very interesting. I even have a blog where I occasionally write about this. To me version control is more than just keeping source code in SVN/Git/whatever - it involves a lot more abstract principles and methods, and applies to a lot more than just source code.

 

IMHO using a version control system is fundamental to almost any kind of work of any size, including private one-man projects, because:

1) it is easy to mess up and once you do that, VCS will help you go back to a previous working state

2) file history is completely automatic  ("manual file history" like writing stuff in a file header is a terrible idea IMHO)

3) libraries can be properly handled; projects (applications) can refer other projects (libraries) and even specify a unique version OR always use latest version - this allows you to develop shared libraries without inadvertently cause changes in all projects that use them

 

IMO a VCS also has the benefit of forcing you to always consider and think in terms of reuasbility, branching and versioning. For example, when you do use a shared project (library) you realize that the more stuff that can be put in there the better since it can be reused by other projects. That process itself highlights how different modules (.h and .c files) should be structured.

 

I have seen many application projects that are badly structured. They typically contain a bunch of modules with cross-dependencies all over the place - in practice no single module can be reused because it includes other modules, that also include other modules, etc. Once you want to share code, you HAVE to organize and structure your code into reusable modules.

 

This also forces you to think about how modules can be made reusable. One trick I use quite often is to have the module include a "myModule_config.h" file. That file is not kept in the shared project. Instead it must be defined by the application in order to define the various details of that specific implementation (I/O pins, number of "things", external functions, etc).

/Jakob Selbing

Last Edited: Sun. Mar 3, 2019 - 07:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In modern Windows mklink or join do the job of ln in Linux so you can soft link the files into a project like Paul suggested too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the way, here is a link to the gcc-based avr tool chain: libc user manual.