[GCC] how deep is too deep - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: July 13, 2018, 08:01:18 pm
content: 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?

author: sokoloff
author_rank: Super Contributor
timestamp: July 13, 2018, 08:04:18 pm
content: 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.

author: dmills
author_rank: Super Contributor
timestamp: July 13, 2018, 08:11:17 pm
content: Plenty!Methinks someone forgot some include guards...foo.hCode:#ifndef FOO_INCL#define FOO_INCL#include "bar.h"#endifbar.hCode:#ifndef BAR_INCL#define BAR_INCL#include"foo.h"#endifmain.cCode:#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.

author: grumpydoc
author_rank: Super Contributor
timestamp: July 13, 2018, 08:19:16 pm
content: 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 <>

author: Simon
author_rank: Unknown
timestamp: July 13, 2018, 08:35:25 pm
content: 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.

author: ajb
author_rank: Super Contributor
timestamp: July 13, 2018, 08:49:17 pm
content: 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.

author: Simon
author_rank: Unknown
timestamp: July 13, 2018, 08:52:09 pm
content: Quote from: dmills on July 13, 2018, 08:11:17 pmThat 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?

author: Simon
author_rank: Unknown
timestamp: July 13, 2018, 08:55:00 pm
content: Quote from: ajb on July 13, 2018, 08:49:17 pmThis 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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 13, 2018, 08:57:01 pm
content: Quote from: Simon on July 13, 2018, 08:52:09 pmThe 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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 13, 2018, 09:00:41 pm
content: 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.2Quote

author: MosherIV
author_rank: Super Contributor
timestamp: July 13, 2018, 10:08:06 pm
content: 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)

author: sokoloff
author_rank: Super Contributor
timestamp: July 13, 2018, 10:12:32 pm
content: 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.

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: July 13, 2018, 10:54:39 pm
content: Quote from: dmills on July 13, 2018, 08:11:17 pmIf 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.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 14, 2018, 12:18:01 am
content: Quote from: MosherIV on July 13, 2018, 10:08:06 pmDo you mean build system dependencies? I.e., where a change tofoo.hmeans 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.

author: dmills
author_rank: Super Contributor
timestamp: July 14, 2018, 12:56:10 am
content: 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.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 14, 2018, 01:08:38 am
content: Quote from: dmills on July 14, 2018, 12:56:10 amDo you work on Cray?

author: ajb
author_rank: Super Contributor
timestamp: July 14, 2018, 02:47:36 am
content: Quote from: MosherIV on July 13, 2018, 10:08:06 pmIncludes 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.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 14, 2018, 03:43:28 am
content: 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.Quote from: MosherIV on July 13, 2018, 10:08:06 pmyou 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.

author: westfw
author_rank: Super Contributor
timestamp: July 14, 2018, 04:22:38 am
content: QuoteIt'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.hQuotedependencies 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.

author: Simon
author_rank: Unknown
timestamp: July 14, 2018, 06:57:33 am
content: 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.cWhere do i declare external variables? can that go in a header file?

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 14, 2018, 07:08:27 am
content: 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.

author: Simon
author_rank: Unknown
timestamp: July 14, 2018, 07:25:46 am
content: 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

author: Ian.M
author_rank: Super Contributor
timestamp: July 14, 2018, 07:43:56 am
content: 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.Seehttp://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).

author: Simon
author_rank: Unknown
timestamp: July 14, 2018, 07:53:30 am
content: Ah so my thinking was right to have a global variables *.c and *.h file.

author: nctnico
author_rank: Super Contributor
timestamp: July 14, 2018, 08:17:19 am
content: Quote from: MosherIV on July 13, 2018, 10:08:06 pmBut 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.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 14, 2018, 08:47:30 am
content: 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.

author: andersm
author_rank: Super Contributor
timestamp: July 14, 2018, 11:34:35 am
content: Quote from: westfw on July 14, 2018, 04:22:38 amThe 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.

author: MosherIV
author_rank: Super Contributor
timestamp: July 14, 2018, 01:30:17 pm
content: QuoteQuoteThis is the starting point to say that it is OK to allow #include in header files.QuoteSort of. Yes it is to do with build dependencies but dependencies are related to module coupling. You want low coupling.QuoteThis 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.QuoteYet 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?QuoteActually 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.QuoteQuoteThis 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 dependentQuoteThis 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.

author: nctnico
author_rank: Super Contributor
timestamp: July 14, 2018, 02:04:03 pm
content: Quote from: MosherIV on July 14, 2018, 01:30:17 pmThe 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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 14, 2018, 02:14:11 pm
content: 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.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 14, 2018, 02:42:20 pm
content: Quote from: MosherIV on July 14, 2018, 01:30:17 pmI 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!)QuoteThe same statement is true when includes are nested. I.e., "include correctness" doesn't uniquely support your position.QuoteWhy do you want developers looking at include dependencies? That seems like wasted effort--something that should be done by the IDE or build system.QuoteDisallowing 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.

author: rstofer
author_rank: Super Contributor
timestamp: July 14, 2018, 03:15:45 pm
content: Quote from: Simon on July 14, 2018, 07:53:30 amI'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 -> ApplicationNo 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!

author: andersm
author_rank: Super Contributor
timestamp: July 14, 2018, 03:17:43 pm
content: Quote from: andyturk on July 14, 2018, 02:42:20 pmIf 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.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 14, 2018, 03:42:52 pm
content: 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: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.hThere may be 100+ such files generated. They're all incorporated into the build with a single line at the bottom of the Makefile:Code:-include $(OBJECTS:%.o=%.d)

author: nctnico
author_rank: Super Contributor
timestamp: July 14, 2018, 03:44:08 pm
content: Quote from: andyturk on July 14, 2018, 02:42:20 pmI know it leads to developers creating their own private version. I've seen it happen!

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 14, 2018, 03:57:37 pm
content: Quote from: MosherIV on July 14, 2018, 01:30:17 pmcoupling 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...Quotei'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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 14, 2018, 04:36:35 pm
content: Quote from: andersm on July 14, 2018, 03:17:43 pmConsider 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.

author: andersm
author_rank: Super Contributor
timestamp: July 14, 2018, 05:19:10 pm
content: Quote from: sokoloff on July 14, 2018, 04:36:35 pmI 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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 14, 2018, 08:22:52 pm
content: Quote from: andersm on July 14, 2018, 05:19:10 pmYou’re right. It was MosherIV who made that argument. My apologies to you.

author: Simon
author_rank: Unknown
timestamp: July 14, 2018, 08:25:16 pm
content: 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.

author: bson
author_rank: Unknown
timestamp: July 14, 2018, 09:30:58 pm
content: Quote from: Simon on July 13, 2018, 08:52:09 pmGcc 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.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: July 14, 2018, 09:48:01 pm
content: 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-goSo 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_guardThis is also an interesting and related read:http://gernotklingler.com/blog/care-include-dependencies-cpp-keep-minimum/

author: sokoloff
author_rank: Super Contributor
timestamp: July 14, 2018, 10:38:56 pm
content: Quote from: Doctorandus_P on July 14, 2018, 09:48:01 pmMinimum 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.

author: sokoloff
author_rank: Super Contributor
timestamp: July 14, 2018, 10:40:59 pm
content: Quote from: bson on July 14, 2018, 09:30:58 pmPreviously cited gcc docs in this thread, gcc has chosen 200 for this limit.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 15, 2018, 01:57:17 pm
content: Quote from: Doctorandus_P on July 14, 2018, 09:48:01 pmGood 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

author: mikerj
author_rank: Super Contributor
timestamp: July 15, 2018, 03:05:24 pm
content: Quote from: Simon on July 14, 2018, 08:25:16 pmIf you want to make modular code then try to avoid global variables as much as possible.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 15, 2018, 05:02:11 pm
content: Quote from: mikerj on July 15, 2018, 03:05:24 pmas 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.

author: Leiothrix
author_rank: Regular Contributor
timestamp: July 15, 2018, 10:28:42 pm
content: 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...

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 07:53:40 am
content: 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.

author: Ian.M
author_rank: Super Contributor
timestamp: July 16, 2018, 08:53:56 am
content: Are *all* the files that include "project_variables.h" in the same folder as itselfand "main.c"?

author: andersm
author_rank: Super Contributor
timestamp: July 16, 2018, 08:54:18 am
content: 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 ofthe documentation.

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 09:09:17 am
content: Quote from: Ian.M on July 16, 2018, 08:53:56 amNo,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!

author: Ian.M
author_rank: Super Contributor
timestamp: July 16, 2018, 09:20:20 am
content: You can add the project folder to the GCC include search path using the GCC -Idirectorycommand 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

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 09:45:52 am
content: OK that makes sense. So what do I call the current project folder so that it remains portable ?

author: Ian.M
author_rank: Super Contributor
timestamp: July 16, 2018, 09:52:25 am
content: You'll have to figure that out for yourself as I don't use Atmel Studio.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 16, 2018, 11:01:36 am
content: Quote from: Simon on July 16, 2018, 07:53:40 ami 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..

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 11:29:57 am
content: 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.

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 12:27:19 pm
content: 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

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 16, 2018, 01:00:49 pm
content: Menu -> Project -> Configuration Options -> Include Directories ...other than that, your project is really special...

author: newbrain
author_rank: Super Contributor
timestamp: July 16, 2018, 01:02:04 pm
content: Quote from: Simon on July 16, 2018, 11:29:57 amSee 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 describedhereQuote from: Mechatrommer on July 16, 2018, 11:01:36 amThe 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 '/'.

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 01:37:36 pm
content: Ah of course relative path will mean itself

author: Simon
author_rank: Unknown
timestamp: July 16, 2018, 01:41:08 pm
content: the result is ".."

author: ajb
author_rank: Super Contributor
timestamp: July 17, 2018, 01:38:51 am
content: Quote from: Simon on July 16, 2018, 09:09:17 amThere 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. Theexternkeyword 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 understandthe 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.

author: westfw
author_rank: Super Contributor
timestamp: July 18, 2018, 09:25:53 pm
content: QuoteThe 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