Author Topic: [GCC] how deep is too deep  (Read 8857 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[GCC] how deep is too deep
« on: July 13, 2018, 08:01:18 pm »
I am trying to write a modular program but I now keep getting told that header files are too deeply nested. I have a projects variable header file, this calls an atmega.h files that lists everything I am using. how many levels down am i allowed to go by this cryptic compiler?
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #1 on: July 13, 2018, 08:04:18 pm »
See if there's another atmega.h on your system (as that's a common name and it's possible that you've inadvertently caused an infinite loop of inclusion).

Alternately, rename your "atmega.h" to "atmega_target.h" or "myatmega.h" or "projatmega.h" or something and see if that makes the error go away.
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #2 on: July 13, 2018, 08:11:17 pm »
Plenty!
Methinks someone forgot some include guards...

foo.h
Code: [Select]
#ifndef FOO_INCL
#define FOO_INCL

#include "bar.h"

#endif

bar.h
Code: [Select]
#ifndef BAR_INCL
#define BAR_INCL

#include"foo.h"

#endif

main.c
Code: [Select]
#include "foo.h"

Now the first time foo.h is included in main the contents are brought in because FOO_INCL is not defined, and FOO_INCL becomes defined, foo.h then includes bar.h which when in tern includes foo.h..... But FOO_INCL is now defined so the include of foo.h evaluates to empty stopping the recursion. 

These loops can be much deeper then this if you are not paying attention.
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #3 on: July 13, 2018, 08:19:16 pm »
Agree - you have recursive inclusion - I don't know the exact limit for gcc but it is deep enough that you should not be running into it.

The compiler has several flags which control the directories searched for include files - plus remember including with "" uses a different path to files included with <>
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #4 on: July 13, 2018, 08:35:25 pm »
Oh, i have the compiler suddenly failing to find a local header file that points to atmega_user.h yet no issues with not having all of the other included files listed in it. A complete contradiction.
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2603
  • Country: us
Re: [GCC] how deep is too deep
« Reply #5 on: July 13, 2018, 08:49:17 pm »
You might still have a circular inclusion problem.  When you have interdependent code modules you need to be careful about how you structure your files so that each piece can see all of its dependencies without creating circular dependencies.  As a general rule, try to keep includes in .c files instead of in .h files as much as possible, and only include what each file actually needs.  This will reduce the complexity of your dependency tree and speed up builds, as unnecessary includes will cause unnecessary rebuilding of files when the included files change. 

It sounds like maybe you're using atmega.h as a way of getting a bunch of dependencies down to a single file you can include in most of your other files, is that right?  That's certainly tempting as it seems like it makes managing your dependencies through a complex project easier, but overconsolidation leads to headaches as you've discovered. 
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #6 on: July 13, 2018, 08:52:09 pm »
Plenty!
Methinks someone forgot some include guards...

foo.h
Code: [Select]
#ifndef FOO_INCL
#define FOO_INCL

#include "bar.h"

#endif

bar.h
Code: [Select]
#ifndef BAR_INCL
#define BAR_INCL

#include"foo.h"

#endif

main.c
Code: [Select]
#include "foo.h"

Now the first time foo.h is included in main the contents are brought in because FOO_INCL is not defined, and FOO_INCL becomes defined, foo.h then includes bar.h which when in tern includes foo.h..... But FOO_INCL is now defined so the include of foo.h evaluates to empty stopping the recursion. 

These loops can be much deeper then this if you are not paying attention.


That will not entirely solve it as standard AVR GCC headers files are too deeply nested and what you are saying involves doing this to the file itself not the file calling it. Anyone got a (soft) wall I can bang my head on?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #7 on: July 13, 2018, 08:55:00 pm »
It sounds like maybe you're using atmega.h as a way of getting a bunch of dependencies down to a single file you can include in most of your other files, is that right?  That's certainly tempting as it seems like it makes managing your dependencies through a complex project easier, but overconsolidation leads to headaches as you've discovered. 

This is precisely the problem I guess. i was trying to solve "another" problem of every time I make a new file it has a ton of stuff that needs including for me to discover one missing file at a time. I'll go back and change it.
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #8 on: July 13, 2018, 08:57:01 pm »
That will not entirely solve it as standard AVR GCC headers files are too deeply nested and what you are saying involves doing this to the file itself not the file calling it. Anyone got a (soft) wall I can bang my head on?
The chance that you're hitting the exact limit on a non-infinite chain of include files on your (maybe very first) project is vanishingly low.

I've been using GCC on and off for almost 30 years now across a dozen targets and I've literally never hit this limit without an infinite loop of includes.
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #9 on: July 13, 2018, 09:00:41 pm »
The C standard requires support for at least 15 deep include files, and the gcc limit seems to be 200.

From the GCC Preprocessor manual, section 11.2
Quote
Nesting levels of ‘#include’ files.
We impose an arbitrary limit of 200 levels, to avoid runaway recursion. The standard requires at least 15 levels.
 

Offline MosherIV

  • Super Contributor
  • ***
  • Posts: 1530
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #10 on: July 13, 2018, 10:08:06 pm »
Personally, I think it is a bad idea to do #include in header files.
It means it is difficult (impossible) to manage dependancies.
Personally, I think it is done because many coders cannot be bothered to look after coupling and dependancies, rather they prefer the ease (lazyness) of not having to type out the #includes in source files.

I have managed to develop an entire c++ based product without a single #include in header files.
(No it was not "hello world")

(Let the debate/flaming begin  :box: )
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #11 on: July 13, 2018, 10:12:32 pm »
Not even cstdint? Not including that would preclude writing functions with return types of uint16_t, etc.

On that basis alone, I disagree. I believe that a header file should #include any other header files it needs such that it can be standalone included by a .c/.cpp file.
« Last Edit: July 13, 2018, 10:15:24 pm by sokoloff »
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1670
  • Country: us
Re: [GCC] how deep is too deep
« Reply #12 on: July 13, 2018, 10:54:39 pm »
Plenty!
Methinks someone forgot some include guards...

foo.h
Code: [Select]
#ifndef FOO_INCL
#define FOO_INCL

#include "bar.h"

#endif

bar.h
Code: [Select]
#ifndef BAR_INCL
#define BAR_INCL

#include"foo.h"

#endif

main.c
Code: [Select]
#include "foo.h"

Now the first time foo.h is included in main the contents are brought in because FOO_INCL is not defined, and FOO_INCL becomes defined, foo.h then includes bar.h which when in tern includes foo.h..... But FOO_INCL is now defined so the include of foo.h evaluates to empty stopping the recursion. 

These loops can be much deeper then this if you are not paying attention.


If your compiler supports it (and most do), "#pragma once" is a cleaner solution. Put that at the top of your header files and that's all you need--that one line.
Complexity is the number-one enemy of high-quality code.
 
The following users thanked this post: andyturk, elgonzo, radar_macgyver

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] how deep is too deep
« Reply #13 on: July 14, 2018, 12:18:01 am »
Personally, I think it is a bad idea to do #include in header files.
It means it is difficult (impossible) to manage dependancies.
Do you mean build system dependencies? I.e., where a change to foo.h means you have to re-compile a bunch of implementation files?

If so, that's handled easily (with GCC and make) via the -MD command line option.
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #14 on: July 14, 2018, 12:56:10 am »
Anything following #pragma is by definition implementation defined, which is fine if you know you will only ever be targeting one known toolchain but IMHO the advantage in this case is so minimal as to make it not worth it.

Regards, Dan.
 
The following users thanked this post: jancumps

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] how deep is too deep
« Reply #15 on: July 14, 2018, 01:08:38 am »
Anything following #pragma is by definition implementation defined, which is fine if you know you will only ever be targeting one known toolchain but IMHO the advantage in this case is so minimal as to make it not worth it.

Regards, Dan.

Do you work on Cray?
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2603
  • Country: us
Re: [GCC] how deep is too deep
« Reply #16 on: July 14, 2018, 02:47:36 am »
Personally, I think it is a bad idea to do #include in header files.
It means it is difficult (impossible) to manage dependancies.

Includes in headers should definitely be limited, but providing access to data type definitions (like stdint, but also custom types used in libraries or whatever) and compile-time configuration values are two important occasions where it makes sense. 
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #17 on: July 14, 2018, 03:43:28 am »
i'm not a fan of #pragma myself. i'm not into a risk of changing them all in my many h files back into classic guard code when i move to different IDE long time after that doesnt support the pragma. there are simple rules to be used to avoid the drawbacks but "widely supported" argument is not good enough for me. ymmv.

I have managed to develop an entire c++ based product without a single #include in header files.
you must be a typing fan of many #include in source files. i have h files just to collect 5 - 10 #include in it because i hate to type 5 - 10 #include every time i create a c file. ymmv.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [GCC] how deep is too deep
« Reply #18 on: July 14, 2018, 04:22:38 am »
Quote
Personally, I think it is a bad idea to do #include in header files.
It's a common "requirement" that head files be "self-contained", which means that they should #include the files necessary to satisfy any symbols that they use.  Being able to use uint8_t and the like is an obvious example.  But if you have tcp.h that references symbols defined in ip.h to get at the pseudo-header, then tcp.h should include ip.h

Quote
It means it is difficult (impossible) to manage dependancies.
dependencies are easily managed by software.   That's what the "make depend" step is for.
I agree with everyone who says that it's extremely unlikely that you're hitting "maximum depth" via anything other than a loop of some kind.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #19 on: July 14, 2018, 06:57:33 am »
Well the circular problem is gone. I have my #include "project_variables.h" that is not finding the file, I put it in the same folder as main.c

Where do i declare external variables? can that go in a header file?
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #20 on: July 14, 2018, 07:08:27 am »
declaring external variables in h will make it visible to any c that includes the h its a common method for beginner or variables which are really "global", it may break encapsulation rule it may not depending on the complexity. it may difficult to search in the hierarchy from which source its originating, who have right and control over it and what its logical purpose. external variables can be declared as well at the beginning of each c relating to it, but ymmv.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #21 on: July 14, 2018, 07:25:46 am »
Hold on, how can I declare the variable multiple times? My variables will be global as for example the ADC interrupt routine needs to put data into variables that will be retained after it exits. I have a timer variable going that will keep track of time that everything needs access to
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: [GCC] how deep is too deep
« Reply #22 on: July 14, 2018, 07:43:56 am »
You can and should DECLARE externals in a header file but you should *never* DEFINE them in a header.  They can have multiple declarations, so they are visible in all the C files that need them, but *MUST* only be defined in a single place, so in *ONE* C file.

Rule of thumb:  If it allocates or initialises storage, (whether that be RAM or program memory or any other type of memory including MCU 'fuse' bits) it goes in a C file, not a header.  Note that device specific headers that map variables to hardware registers don't allocate storage as the registers already exist at fixed addresses.

See http://www.gamedev.net/page/resources/_/technical/general-programming/organizing-code-files-in-c-and-c-r1798 (there's a newer version of that document but its more MS/PC centric so less useful to embedded or GCC programmers).
« Last Edit: July 14, 2018, 08:12:05 am by Ian.M »
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #23 on: July 14, 2018, 07:53:30 am »
Ah so my thinking was right to have a global variables *.c and *.h file.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 26906
  • Country: nl
    • NCT Developments
Re: [GCC] how deep is too deep
« Reply #24 on: July 14, 2018, 08:17:19 am »
Personally, I think it is a bad idea to do #include in header files.
It means it is difficult (impossible) to manage dependancies.
Personally, I think it is done because many coders cannot be bothered to look after coupling and dependancies, rather they prefer the ease (lazyness) of not having to type out the #includes in source files.

I have managed to develop an entire c++ based product without a single #include in header files.
(No it was not "hello world")

(Let the debate/flaming begin  :box: )
But the problem with that is that you have to add an include to each and every file which needs it and dependancies are less clear. The latter makes it harder for someone else to work on the project. It is not hard to spend a couple of hours on figuring out which include should be included where (hence the existence of this thread).

I have a strict policy to have one include file which includes all other includes in the right order. This gets rid of the 'include hell' which quickly emerges when working on a larger project.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 
The following users thanked this post: donotdespisethesnake

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #25 on: July 14, 2018, 08:47:30 am »
you "define" variable in c where its most related. for example adc_read.c along with other related adc functions (read write etc). to make it accessible to outsiders, you "declare" them (including functions) in adc_read.h so anything using adc service will #include adc_read.h thats how logically we group things. but sometime a variable is not that too specific to a particular subject, it may related (equally) to several unit (c files) but not all units, so borderline can be obscured and it will be entirely up to you where to put (define) it, ymmv.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [GCC] how deep is too deep
« Reply #26 on: July 14, 2018, 11:34:35 am »
dependencies are easily managed by software.   That's what the "make depend" step is for.
The problem is that it's easy to end up with false dependencies, especially if you don't separate function and type declarations. I'm sure most have experienced situations where touching a header file forces completely unrelated source files to be rebuilt.

Offline MosherIV

  • Super Contributor
  • ***
  • Posts: 1530
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #27 on: July 14, 2018, 01:30:17 pm »
Quote
Not even cstdint? Not including that would preclude writing functions with return types of uint16_t, etc.
Quote
but providing access to data type definitions (like stdint, but also custom types used in libraries or whatever) and compile-time configuration values are two important occasions where it makes sense.
This is the starting point to say that it is OK to allow #include in header files.

Quote
Do you mean build system dependencies? I.e., where a change to foo.h means you have to re-compile a bunch of implementation files?
Sort of. Yes it is to do with build dependencies but dependencies are related to module coupling. You want low coupling.

Quote
It's a common "requirement" that head files be "self-contained", which means that they should #include the files necessary to satisfy any symbols that they use.
This is a complete miss-understanding of the 'coupling principle'. Achieving low coupling is not the same as saying that a module must be 'stand alone'.
This is true for binary library modules BUT NOT in house software module being developed.

Quote
dependencies are easily managed by software.   That's what the "make depend" step is for.
Yet another excuse.
How often do developer actually check the dependency tree?
How do developers know when a problem is starting when looking at the results of software to map the dependencies?

Quote
But the problem with that is that you have to add an include to each and every file which needs it and dependancies are less clear.
Actually the dependencies are absolutely clear.
By ONLY using includes in source files, the list of includes in the source file MUST be correct or it will not compile.
Therefore the list of #includes in a source file IS the list of dependent headers (assuming unnecessary includes have been removed).
It is now easy to always know what the dependencies are just by looking at the list.
You do not need to run tools to work out what the dependency is.
Let face it how often do developer actually look at the dependencies - this way they are always looking at it.

Quote
i have h files just to collect 5 - 10 #include in it because i hate to type 5 - 10 #include every time i create a c file.
Quote
I have a strict policy to have one include file which includes all other includes in the right order. This gets rid of the 'include hell' which quickly emerges when working on a larger project.
This may sound like the solution but it actually increases coupling. See the next quote and response :
By having a single file with all the includes, everything is now dependent  :palm:

Quote
The problem is that it's easy to end up with false dependencies, especially if you don't separate function and type declarations. I'm sure most have experienced situations where touching a header file forces completely unrelated source files to be rebuilt.
This is exactly one of the problems that having #include in header files cause!



By allowing #include in header files, it is inevitable that you end up with the high coupling diagram.
Dissallowing #include in header files cannot stop the high coupling problem but it will force developers to look and think about it all the time.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 26906
  • Country: nl
    • NCT Developments
Re: [GCC] how deep is too deep
« Reply #28 on: July 14, 2018, 02:04:03 pm »
By allowing #include in header files, it is inevitable that you end up with the high coupling diagram.
Dissallowing #include in header files cannot stop the high coupling problem but it will force developers to look and think about it all the time.
The latter is exactly why this approach wastes time (friggin' huge amounts!) and the root cause is lack of documentation. Having one include to include all other includes is a far better way because this also shows the dependancies immediately AND there are no circular dependancies. It also makes it easy to extend software. You only need to include one include file and add new include files in one place. I agree that excessive nesting of include files is bad but sometimes it is necessary. For example when you want to use a library. These usually have an include file which forms an API and depending on the OS, compiler, target, etc  other include files get included. You can't avoid a high level of coupling within a single program anyway.

I've seen lots of examples where programmers painted themselves into a corner due to include file cross dependancies which are easely avoided by having all include file being included in a single include file.
« Last Edit: July 14, 2018, 02:23:10 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 
The following users thanked this post: hans

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #29 on: July 14, 2018, 02:14:11 pm »
I favor the “to use this include file, you may freely include only it without compile errors” approach.
Having to include cstdint before another include file is a pointless waste of time, IMO.

I’ve worked on projects where you include “kitchen_sink.h” and didn’t especially like that on large projects. For a typical uC project, that’s fine.

For me, it’s about what wastes the least dev time and takes the least dev braincycles to work in. For me, that’s standalone includes, but not necessarily full-project includes.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] how deep is too deep
« Reply #30 on: July 14, 2018, 02:42:20 pm »
How often do developer actually check the dependency tree?
How do developers know when a problem is starting when looking at the results of software to map the dependencies?
I never check build system dependencies (any more) because the compiler generates perfect dependency info each time it produces an object file. This is a GCC specific feature though. (And a good reason to use GCC!)

Quote
By ONLY using includes in source files, the list of includes in the source file MUST be correct or it will not compile.
The same statement is true when includes are nested. I.e., "include correctness" doesn't uniquely support your position.

Quote
Therefore the list of #includes in a source file IS the list of dependent headers (assuming unnecessary includes have been removed).
It is now easy to always know what the dependencies are just by looking at the list.
You do not need to run tools to work out what the dependency is.
Let face it how often do developer actually look at the dependencies - this way they are always looking at it.
Why do you want developers looking at include dependencies? That seems like wasted effort--something that should be done by the IDE or build system.

Quote
Dissallowing #include in header files cannot stop the high coupling problem but it will force developers to look and think about it all the time.
Disallowing nested includes makes refactoring more difficult because the same information gets repeated in multiple places. I.e., if I need to use a "module" that depends on 5 others, I have to put those 5 includes directly in my implementation. Fine. But when the guy who maintains that module changes his internal dependencies, your rule says my code has to change too. That's bad.

I bet it leads to developers on your team re-implementing stuff privately specifically so they don't have to deal with this guideline. That's even worse.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: [GCC] how deep is too deep
« Reply #31 on: July 14, 2018, 03:15:45 pm »
Ah so my thinking was right to have a global variables *.c and *.h file.

I'm not much on global variables.  Ownership is a problem, contamination is a possible result.  I would rather place the ADC value in a managed container like a queue where the queue structure belongs to, and is only visible by, the queue handler.

ADC -> Queue -> Application

No global variables!

I don't have such heartburn over file static variables where the variable is only visible to functions in the same .c file.  Clearly, the queue structure and head/tail pointers would be file static variables.

It might be tempting to define the queue data structure and the queue size along with the head and tail pointers in queue.h.  But that allows other files to include queue.h and gain some knowledge about how the queue is implemented. What possible good can come from that?  Better, in my view, to define everything related to the queue implementation inside queue.c.  The only thing exposed in queue.h is the names and parameters (data types) for the insert and remove functions.

If a function doesn't have a 'need to know', it shouldn't automatically get a 'right to know'.

Keep stuff local and keep it containted!

 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [GCC] how deep is too deep
« Reply #32 on: July 14, 2018, 03:17:43 pm »
Disallowing nested includes makes refactoring more difficult because the same information gets repeated in multiple places. I.e., if I need to use a "module" that depends on 5 others, I have to put those 5 includes directly in my implementation. Fine. But when the guy who maintains that module changes his internal dependencies, your rule says my code has to change too. That's bad.
If that happens, then either the module has no separation between public and private interfaces, which is bad, or you've bypassed the interface and are directly poking around in the internals, which is also bad.

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] how deep is too deep
« Reply #33 on: July 14, 2018, 03:42:52 pm »
Just for fun, here's one of the GCC-generated dependency rules (for a Makefile) for one file. The build system produces one of these rules for every .c or .cc file in the entire project automatically.

Code: [Select]
build/debug_obj/main.o: main.cc \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/timer.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/error.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cstdint \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/c++config.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/os_defines.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/cpu_defines.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include/stdint.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/stdint.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/_default_types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/features.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/_newlib_version.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_intsup.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_stdint.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/peripheral.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/mcu_device.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52840.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/core_cm4.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/cmsis_version.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/cmsis_compiler.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/cmsis_gcc.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/mpu_armv7.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/toolchain/system_nrf52840.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52840_bitfields.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52840_peripherals.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/functional \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_function.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/move.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/concept_check.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/type_traits \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/backward/binders.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/typeinfo \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/exception \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/atomic_lockfree_defines.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/exception_ptr.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/exception_defines.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/nested_exception.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/hash_bytes.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/new \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/tuple \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/utility \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_relops.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_pair.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/initializer_list \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/array \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/stdexcept \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/string \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stringfwd.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/memoryfwd.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/char_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_algobase.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/functexcept.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/cpp_type_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/type_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/numeric_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_iterator_base_types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_iterator_base_funcs.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/debug/assertions.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/stl_iterator.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/ptr_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/debug/debug.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/predefined_ops.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/postypes.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cwchar \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/wchar.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/_ansi.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/newlib.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/config.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/ieeefp.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/reent.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include/stddef.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/_types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/lock.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/cdefs.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include/stdarg.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_locale.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/allocator.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/c++allocator.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/new_allocator.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/localefwd.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/c++locale.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/clocale \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/locale.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/_ansi.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/iosfwd \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cctype \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/ctype.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/ostream_insert.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/cxxabi_forced.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/range_access.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/basic_string.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/atomicity.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/gthr.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/gthr-default.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7e-m/fpv4-sp/hard/bits/atomic_word.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/alloc_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/alloc_traits.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/ext/string_conversions.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cstdlib \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/stdlib.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/stdlib.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/alloca.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cstdio \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/stdio.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/endian.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/_endian.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/select.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_sigset.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_timeval.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/timespec.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_timespec.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/_pthreadtypes.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/machine/types.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/stdio.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cerrno \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/errno.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/errno.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/functional_hash.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/basic_string.tcc \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/bits/uses_allocator.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/soft_device.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/error.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/nrf52/advertisement.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_gap.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_types.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_ranges.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_svc.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/flipbuffer.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cassert \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/assert.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/cstring \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/string.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/sys/string.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/common/nrf_sdh_ble.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/app_util.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/lib/gcc/arm-none-eabi/6.3.1/include/stdbool.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/compiler_abstraction.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/nordic_common.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52840.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52840_bitfields.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf51_to_nrf52840.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/nrf52_to_nrf52840.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/device/compiler_abstraction.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_gap.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_l2cap.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_err.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_error.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_gatt.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_gattc.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/ble_gatts.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/experimental_section_vars/nrf_section_iter.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/experimental_section_vars/nrf_section.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/nordic_common.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/nrf_assert.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/app_error.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/sdk_errors.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_error.h \
 sdk_config.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/app_error_weak.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/libraries/util/sdk_errors.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_sdm.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_soc.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_error_soc.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/softdevice/s132/headers/nrf_error_sdm.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/event.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/kernel.h \
 RTX_Config.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/cmsis_os2.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/rtx_os.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/include/cmsis_os2.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/rtx5/thread.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/segger/sysview.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/segger/SEGGER/SEGGER_SYSVIEW.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/segger/SEGGER/SEGGER.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/segger/Config/Global.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/panamint/the.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/boards/boards.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/drivers_nrf/hal/nrf_gpio.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/drivers_nrf/hal/nrf_peripherals.h \
 /usr/local/arm/gcc-arm-none-eabi-6-2017-q1-update/arm-none-eabi/include/c++/6.3.1/stdlib.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/boards/pca10056.h \
 /Volumes/Users/andy/code/ARM/reproducer_363/nordic_sdk_14/components/drivers_nrf/delay/nrf_delay.h


There may be 100+ such files generated. They're all incorporated into the build with a single line at the bottom of the Makefile:

Code: [Select]
-include $(OBJECTS:%.o=%.d)

 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 26906
  • Country: nl
    • NCT Developments
Re: [GCC] how deep is too deep
« Reply #34 on: July 14, 2018, 03:44:08 pm »
Dissallowing #include in header files cannot stop the high coupling problem but it will force developers to look and think about it all the time.
Disallowing nested includes makes refactoring more difficult because the same information gets repeated in multiple places. I.e., if I need to use a "module" that depends on 5 others, I have to put those 5 includes directly in my implementation. Fine. But when the guy who maintains that module changes his internal dependencies, your rule says my code has to change too. That's bad.

I bet it leads to developers on your team re-implementing stuff privately specifically so they don't have to deal with this guideline. That's even worse.
I know it leads to developers creating their own private version. I've seen it happen!
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #35 on: July 14, 2018, 03:57:37 pm »
Quote
i have h files just to collect 5 - 10 #include in it because i hate to type 5 - 10 #include every time i create a c file.
Quote
I have a strict policy to have one include file which includes all other includes in the right order. This gets rid of the 'include hell' which quickly emerges when working on a larger project.
This may sound like the solution but it actually increases coupling.
coupling is dependency, dependency is coupling yes we know that. but i dont have problem coupling (in anyway if necessary) my code with the code high above, such as standard library, or ready made library made by others that we consider complete and a blackbox. your diagram is correct, and i agree with the idea of low coupling (dependency) if we are building our own reusable library. but have you experienced having to type standard library #includes in sources of your particular application? like...
Quote
#include <stdlib.h>
#include <stdlio.h>
#include <math.h>
etc etc
i'm guessing you are a fan of those...

looking at your diagram, the structure on the right is ideal because all arrows are heading downward, but some application we cant achieve that unless we combine 2 or more small units into one bigger unit, but they are different purposes or "separable" logically so it will not be ideal to combine them frm that point of view. the other way is to rearrange the diagram so they are on the same level, like a library i did sometime ago (see attached). the green boxed are closely/heavily/highly coupled, i cannot move one of them to the bottom or up without making the arrows pointing all down. red is c standard library as you can see they can be easily brought down because they are different "group". my application will simply call #include <extlib.h> and everything (including c std library required) will be ready on silver platter.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #36 on: July 14, 2018, 04:36:35 pm »
Disallowing nested includes makes refactoring more difficult because the same information gets repeated in multiple places. I.e., if I need to use a "module" that depends on 5 others, I have to put those 5 includes directly in my implementation. Fine. But when the guy who maintains that module changes his internal dependencies, your rule says my code has to change too. That's bad.
If that happens, then either the module has no separation between public and private interfaces, which is bad, or you've bypassed the interface and are directly poking around in the internals, which is also bad.
Consider the case where a library author starts on AVR and gives you a function taking 2 ints and returning a long. On AVR, those are 16 and 32 bits. Now, they want to port to another platform and need to specify the size. Suddenly, all callers need to include cstdlib in order to include the library header? That’s a waste of time, IMO. Note that the code would likely still compile (albeit with warnings if you have strict warning settings) in the other case.

Now, a novice dev wants to use this library from GitHub. They aren’t going to know how to fix the missing include in all likelihood. Contrast with the case where the library header includes cstdlib on this change. What’s the worst case outcome? A compiler warning on implicit, lossless type conversion. Code still “works” and the warning is straightforward for anyone who is likely to be running with -Wall.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [GCC] how deep is too deep
« Reply #37 on: July 14, 2018, 05:19:10 pm »
Consider the case where a library author starts on AVR and gives you a function taking 2 ints and returning a long. On AVR, those are 16 and 32 bits. Now, they want to port to another platform and need to specify the size. Suddenly, all callers need to include cstdlib in order to include the library header? That’s a waste of time, IMO. Note that the code would likely still compile (albeit with warnings if you have strict warning settings) in the other case.
I never said you should never include headers from other headers, so that's a strawman argument. Besides, standard library headers don't change, so they're not a problem anyway. But I have worked on enough projects where out of control dependencies were real workflow impediments. Not only through longer build times, but also making testing and code reuse harder. And even if the build time increases are very small on average, it'll soon dwarf the effort required to not have such enormous dependencies in the first place.

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #38 on: July 14, 2018, 08:22:52 pm »
Consider the case where a library author starts on AVR and gives you a function taking 2 ints and returning a long. On AVR, those are 16 and 32 bits. Now, they want to port to another platform and need to specify the size. Suddenly, all callers need to include cstdlib in order to include the library header? That’s a waste of time, IMO. Note that the code would likely still compile (albeit with warnings if you have strict warning settings) in the other case.
I never said you should never include headers from other headers, so that's a strawman argument. Besides, standard library headers don't change, so they're not a problem anyway. But I have worked on enough projects where out of control dependencies were real workflow impediments. Not only through longer build times, but also making testing and code reuse harder. And even if the build time increases are very small on average, it'll soon dwarf the effort required to not have such enormous dependencies in the first place.
You’re right. It was MosherIV who made that argument. My apologies to you.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #39 on: July 14, 2018, 08:25:16 pm »
Gee calm down people. I'm still looking at how I implement this, nothing I am writing would be used in parts but yes it should be as modular as possible.
 

Offline bson

  • Supporter
  • ****
  • Posts: 2270
  • Country: us
Re: [GCC] how deep is too deep
« Reply #40 on: July 14, 2018, 09:30:58 pm »
That will not entirely solve it as standard AVR GCC headers files are too deeply nested and what you are saying involves doing this to the file itself not the file calling it. Anyone got a (soft) wall I can bang my head on?
Gcc simply adopts 256 as this is a common limit.  It may even have been adopted as a standard.  Same as MSVC etc.

It's just a sane limit to keep it from recursively including a header file indefinitely until it runs out of memory (which actually won't happen on x64 systems these days; they just fill your disk with page files and effectively never finish), and I can't imagine any SDK needs this.  That would be utterly ridiculous.
 

Online Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3358
  • Country: nl
Re: [GCC] how deep is too deep
« Reply #41 on: July 14, 2018, 09:48:01 pm »
I think the minimum required depth is 8 redirections, and the practical limit may be limited by the number of characters in the file names. those #include directives can have relative / absolute path names in them, and path names may be added by makefiles and such.

Here are some test results of a header file including itself and the results vary between 200 and 1024.
https://stackoverflow.com/questions/12125014/are-there-limits-to-how-deep-nesting-of-header-inclusion-can-go

So if this becomes a problem for you, it is very likely you have some circular reference in the header files. This is one of the reasons why there almost always is an include guard in every header file.
https://en.wikipedia.org/wiki/Include_guard

This is also an interesting and related read:
http://gernotklingler.com/blog/care-include-dependencies-cpp-keep-minimum/
« Last Edit: July 14, 2018, 09:52:37 pm by Doctorandus_P »
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #42 on: July 14, 2018, 10:38:56 pm »
I think the minimum required depth is 8 redirections, and the practical limit may be limited by the number of characters in the file names. those #include directives can have relative / absolute path names in them, and path names may be added by makefiles and such.
Minimum number is set in section §5.2.4.1 of the language spec. It is 15.
I can’t see what this limit has to do with path name length in any way.
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: [GCC] how deep is too deep
« Reply #43 on: July 14, 2018, 10:40:59 pm »
Gcc simply adopts 256 as this is a common limit.  It may even have been adopted as a standard.  Same as MSVC etc.
Previously cited gcc docs in this thread, gcc has chosen 200 for this limit.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: [GCC] how deep is too deep
« Reply #44 on: July 15, 2018, 01:57:17 pm »
This is also an interesting and related read:
http://gernotklingler.com/blog/care-include-dependencies-cpp-keep-minimum/
Good read, thanks! The blog mentions a program written at Google for maintaining the "Include what you Use" policy via tooling.

https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/WhyIWYU.md
 

Online mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: [GCC] how deep is too deep
« Reply #45 on: July 15, 2018, 03:05:24 pm »
Gee calm down people. I'm still looking at how I implement this, nothing I am writing would be used in parts but yes it should be as modular as possible.

If you want to make modular code then try to avoid global variables as much as possible.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #46 on: July 15, 2018, 05:02:11 pm »
Gee calm down people. I'm still looking at how I implement this, nothing I am writing would be used in parts but yes it should be as modular as possible.
If you want to make modular code then try to avoid global variables as much as possible.
as much as this is ideal, its not achievable in practical application, small or big. he was talking about adc and timer value. its not going to be a good idea, to call hardware adc or timer function in each modular function.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline Leiothrix

  • Regular Contributor
  • *
  • Posts: 104
  • Country: au
Re: [GCC] how deep is too deep
« Reply #47 on: July 15, 2018, 10:28:42 pm »
No, but you could have a simple inline getter function.

Then you can maintain some isolation and increase the flexibility of the ADC/timer module as well.

Sort of like a class...
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #48 on: July 16, 2018, 07:53:40 am »
Right, next problem:

#include "project_variables.h"

No such file or directory. This is included in several files but I only get one instance of the error. Um it is either there or not! what is the compiler playing at. I have the file in the same folder as the main.c file.
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: [GCC] how deep is too deep
« Reply #49 on: July 16, 2018, 08:53:56 am »
Are *all* the files that include "project_variables.h" in the same folder as itself
 and "main.c"?
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: [GCC] how deep is too deep
« Reply #50 on: July 16, 2018, 08:54:18 am »
Do you understand how the GNU C preprocessor works, and how it searches for files? If not, I suggest reading especially sections 2.1 and 2.3 of the documentation.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #51 on: July 16, 2018, 09:09:17 am »
Are *all* the files that include "project_variables.h" in the same folder as itself
 and "main.c"?

No,

so how do I write so called portable code to be used on multiple projects if I can't call one project specific file that is in the main folder of the program. So project specific files have to go into my general libraries folder or I'll have to create yet another global folder to put all project specific stuff in...... So much for an IDE!
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: [GCC] how deep is too deep
« Reply #52 on: July 16, 2018, 09:20:20 am »
You can add the project folder to the GCC include search path using the GCC -Idirectory command line option.   Use the Atmel Studio macro for the fully qualified project folder name and it will remain correct if you copy/move the project
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #53 on: July 16, 2018, 09:45:52 am »
OK that makes sense. So what do I call the current project folder so that it remains portable ?
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12860
Re: [GCC] how deep is too deep
« Reply #54 on: July 16, 2018, 09:52:25 am »
You'll have to figure that out for yourself as I don't use Atmel Studio.
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #55 on: July 16, 2018, 11:01:36 am »
Right, next problem:
#include "project_variables.h"
No such file or directory. This is included in several files but I only get one instance of the error. Um it is either there or not! what is the compiler playing at. I have the file in the same folder as the main.c file.
i tried to emulate your problem here... i have 2 c files main.c located in project folder, and another xxx.c located in "project folder\xxx".. and a project_variables.h located in project folder. both c have #include "project_variables.h". main.c doesnt report error, xxx.c does.

simple solution if you dont want to setup project configuration (include directories) is, retype in xxx.c as #include "..\project_variables.h" you use "..\" to ask compiler to use (search) relative path up one step from "project folder\xxx" where xxx.c is located which is "project folder".

two steps up you use "..\..\" and so on. one step down, say if you have yyy.h in "project folder\xxx" and you want to include it in main.c, you use #include "xxx\yyy.h" fwiw..
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #56 on: July 16, 2018, 11:29:57 am »
No the problem is that the project folder is not part of the search paths, how do I get Atmel Studio to use the current folder? The idea is that my standard header files will stay in one location while copies of the project files are made and in a different location. So I am writing a set of templates that will include some project specific files. When I make a copy of my template code the new copy will have a local project variables header that the standard files need to look at now instead.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #57 on: July 16, 2018, 12:27:19 pm »
I give up, I will do it the horrendously dumb way and put everything in one folder and copy it over and over. I searched and found no roference on how to do something so basic as make the current codes folder a default location  :palm:
 

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11634
  • Country: my
  • reassessing directives...
Re: [GCC] how deep is too deep
« Reply #58 on: July 16, 2018, 01:00:49 pm »
Menu -> Project -> Configuration Options -> Include Directories ...
other than that, your project is really special...
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: [GCC] how deep is too deep
« Reply #59 on: July 16, 2018, 01:02:04 pm »
how do I get Atmel Studio to use the current folder?

See the attached picture.
You can add include paths by right-clicking on the project (iMAC) and selecting "Properties".
In the newly opened tab, click on toolchain then "directories".
By clicking on the green "+" icon, you can add any directory.
The path can be relative (see below!), absolute or use any of the internal AS variables.
The available variables are described here



"..\project_variables.h" "..\" "project folder\xxx"  "..\..\" "project folder\xxx" "xxx\yyy.h"
The use of a backslash in the q-char-sequence (that is: "the stuff between quotes in an #include directive") is undefined behaviour in most C and C++ standards.
It might work today, but there's no guarantee it will continue to do so.
Please refrain from using it, as it is not needed: any self respecting modern compiler, and GCC is one, will allow using '/'.

Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #60 on: July 16, 2018, 01:37:36 pm »
Ah of course relative path will mean itself :)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17816
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [GCC] how deep is too deep
« Reply #61 on: July 16, 2018, 01:41:08 pm »
the result is ".."
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2603
  • Country: us
Re: [GCC] how deep is too deep
« Reply #62 on: July 17, 2018, 01:38:51 am »
so how do I write so called portable code to be used on multiple projects if I can't call one project specific file that is in the main folder of the program. So project specific files have to go into my general libraries folder or I'll have to create yet another global folder to put all project specific stuff in...... So much for an IDE!

There are a couple of ways of connecting portable library-type code to project-specific code.  Which works best depends on the nature of the project and the library.

1. Your library has no dependencies on project-specific code or data: In this case your library declares its public functions (and if necessary, variables) to the project code via a header file that the project #includes.  This is the simplest case.

2. Your library depends on a set of project-specific functions that will not change as the application runs: In this case your library can declare (but not define!) a set of functions that are defined within the project. Your library will know that those functions exist because it declared them, and as long as the linker can find their definitions (which your IDE should take care of) everything will come together properly.  Your library could optionally provide weak definitions (__attribute__((" weak")) in GCC), which allows the library to provide default functions that your project may or may not override.

3. Your library depends on a set of project-specific functions that may change depending on the application state:  In this case your library might declare a set of function pointers to which your project will assign the addresses of functions that provide the project-specific code.  This is common if the library will need to access different physical interfaces within the application, IE, fatfs, which might target both on-board flash and an SD card.  Often the function pointers are gathered in a struct type provided by the library. 

As a general rule, your application should reach into the library and not the other way around.  If the library needs to act on data 'owned' by the application, then it's often preferable for the application to pass a reference to that data into the library.  If the library and the application really need to have direct access to a shared variable, then you can define that variable in the library and expose it to the application via the library's header file.  The extern keyword is helpful here, as it allows you to declare a variable without redefining it. 

You might have a situation where you want to configure a library for your application via the preprocessor--in other words, you want to be able to #define a bunch of things in your project that influence the behavior of the library.  In this case, your library can do something like #include "lib_conf.h", where lib_conf.h is stored in one of your compiler's search paths.

It's really crucial to understand the difference between a definition and a declaration, so if that's not yet clear to you, definitely read up on the subject as it's crucial to understanding how a pile of C comes together into a working program.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [GCC] how deep is too deep
« Reply #63 on: July 18, 2018, 09:25:53 pm »
Quote
how do I get Atmel Studio to use the current folder?
The problem is probably that AS does the actual builds down in some "build" directory, so the "current directory" is not what you expect, and #include paths can get screwed up.
It looks like all of the default paths added to the compile use "..", and already include "../src" - exactly where do you have your "project_variables.h" file, anyway?  It probably should be in "projectdir/src", rather than "projectdir"(This is all in the ProjectProperties/..C Compiler/Directories panel, and you can add additional include directories.)

Studio also has some macros or environment variables that you could use in these paths:
https://www.microchip.com/webdoc/GUID-ECD8A826-B1DA-44FC-BE0B-5A53418A47BD/index.html?GUID-D42F376A-5538-4C9A-A8A3-606B3573D8C8
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf