Before logging an issue, please update to the latest release of Visual Micro from the Downloads Page.

When Logging a Support Issue in the Forum, please ensure you have also:-

  • Enabled vMicro > Compiler > Show Build Properties
  • Re-Compile your program with these settings enabled
 
Save the new Output to a Text File and....
  • Click the Reply button and attach as .txt file OR
  • Click here to Email us with the file attached, and a link to your post
Support requests without the output above may be impossible to answer, so please help us to help you
 
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Including headers from subfolders and/or from VC++ Include Directories (Read 9033 times)
Mordy
Newbies
*
Offline


Posts: 4
Joined: Dec 29th, 2016
Including headers from subfolders and/or from VC++ Include Directories
Dec 29th, 2016 at 8:25am
Print Post  
Hi,

So I'm having some issues including headers in either of these ways:
  • In project subdirectories (ie. $(ProjectDir)\subfolder\header.h).  It would be included by using #include <subfolder\header.h>
  • Adding include directories to the VC++ Include Directories in the project properties

The error I get is:

Code
Select All
Sketch1.ino: 3:33: fatal error: core\include\Header.h: No such file or directory 



I have confirmed that both of the above work in a regular console application which compiles and runs correctly.

Now interestingly enough, Intellisense knows where to find them because it'll autocomplete the subfolders for me.  It'll also correctly allow me to use the classes in the headers and autocomplete those too.  The issue only crops up when actually trying to build the thing.  I've included both a console application that can build/run when using VC++ Include Directories and a Visual Micro sketch solution that uses relative paths to resolve dependencies but cannot build for the reasons above.

I've searched far and wide and the closest I can get is this post: http://www.visualmicro.com/forums/YaBB.pl?num=1381842616

And even then, the thread does not have a stated resolution; only that the item requested in the thread was going to be considered.

Which brings me to my two questions:
  • Can we use subfolders to keep headers in or must they really be directly in the project directory.
  • Can we use the project properties to define other include directories

There are a few reasons why this working would be fairly important; among them are things like being able to include git subtrees in subfolders.  For example, if I download an open source library, you would add this to the include directories:

$(ProjectDir)\AmazingLibrary\include

Additionally, if inside that library's include directory, there is a substructure, we'd be able to access them by going 

Code (C++)
Select All
#include <AmazingLibraryIncludeSubfolder\SpecificHeaderCategory\SpecificHeader.h> 



My understanding is that this is a fairly standard pattern for C/C++ development so that code bases can be well modularized and remove the issue of headers having the same name (eg. if two library code bases both have their own 'exception.h' or something, they can both be included explicitly using their relative path from $(ProjectDir)).

Thanks
- A
« Last Edit: Jan 3rd, 2017 at 1:14am by Mordy »  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12187
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #1 - Dec 29th, 2016 at 5:35pm
Print Post  
Hi,

You have good understanding of standard c++ but not of Arduino.

Notice that with Arduino we have two things that are very different.

1) Multiple .ino files are combined into a single .cpp (in tmp folder) for compilation.
2) Arduino open source shared libraries have rules. Notice that when we #include arduino libraries they are not #included with paths. Also note that there are published known locations for Arduino libraries.

These two factors should be clearly understood when working with arduino.

1) Means the build happens in a temp folder, so relative paths go out of the window. We can find all sources in the project but nothing from outside of the project.

2) Means that shared open source Arduino libraries can be easily included and shared with other people without need to change paths. 

To be able to force intellisense to find libraries and hidden cores Visual Micro has complete control of the C++ include paths. To make an arduino compatible compile we can't use VS for the build so the C++ properties are only for intellisense purposes anyway.

There are compiler switches in the visual micro project properties that would allow you to add global includes but the files in the included folder will not be compiled into .o files or linked so it's not a very useful option.

The chances are that you simply want to install open source arduino librraies in this case you should use the menu items, platform explorer or arduino ide to install them. This way you keep compatibility with the arduino ide which is always recommended.

Visual micro also allows libraries to be located below the project folder in a special known folder structure. Use the "Add code" option on the visual micro menu to create a lib and view the special structure but don't do this before understanding how arduino works normally with libraries.

You can also add short cuts to shared code into the project but bear in mind any linked sources will be treated by the compiler as if they are in the root of the project folder.

In the next release of Visual Micro (which is due over the next few days) we have enabled the Microsoft C++ Shared Projects to be used with Arduino projects. This is a powerful feature that greatly expands the capabilities for code sharing.

cross-platform-code-sharing-with-visual-c/

Quote:
Share source code across multiple C++ projects

Note: Some of you may be already familiar to the way Visual Studio 2013 enables code sharing between Windows Store and Windows Phone projects. With Visual Studio 2015, we expanded this support to all the platforms targeted by Visual C++ and we enabled more flexibility in the way code sharing can be achieved. 
 
The main building block to share code across multiple projects is the “Shared Items Project” C++ project template. These “shared items” projects don’t participate in build but they can contain any number of C++ headers and sources. When you add such a project as a reference to a regular C++ project, the files in the referenced “shared items” project will simply be treated as if they were part of the referencing project and will be built under the configuration & architecture-specific settings specified by the referencing project.


Figure 1. Create a standard Visual Studio Shared C++ Project


After creating one or more shared projects you can use the "References" node in the solution explorer to add references to the shared projects. The shared projects do not build on their own, instead the code from shared projects is treated as if part of the normal arduino projects sources. This solves the issue of includes because if you have shared project "foo\subfolder1\some_code.h" you include in arduino as #include "subfolder1\some_code.h"

Figure 2. Select “Shared Projects” tab in “Add Reference” dialog to add shared item projects as references


One last thing to bear in mind about sub folders. The Arduino IDE only allows code in an \src sub folder (and below) to be compiled. If in the future you want to combine a lot of shared code projects into an Arduino sketch for compilation outside of Visual Micro (by the Arduino IDE) then you will find the transition easier if all your shared project folders that need sub folders use an \src sub folder structure. This will allow the source codes of shared projects to be physically merged into a project without need to change existing code #includes

« Last Edit: Dec 29th, 2016 at 5:48pm by Tim@Visual Micro »  
Back to top
IP Logged
 
Mordy
Newbies
*
Offline


Posts: 4
Joined: Dec 29th, 2016
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #2 - Dec 29th, 2016 at 8:55pm
Print Post  
Ah very interesting.  I knew I had a gap in knowledge when it came to Arduino specific stuff; thanks for helping me understand that.  The fact that the build root is elsewhere explains a lot.  It also explains why Intellisense being able to find them isn't indicative of it being able to build.

I should also mention that I'm not actually using Arduino libraries here and that I'm needing to write my own libraries (regular h and cpp files) which of course work fine when directly in the project root.

To give you a bit more detail, the libraries aren't to be Arduino specific.  They involve stateless OOP interfaces that can be reused on other architectures as well.  Of course, this is embedded programming, so I'll be inlining everything, removing indirections, etc for anything that needs to be streamlined but OOP is perfect for prototyping especially when I may want to change the architecture over later (or even just to a different AVR/SAM micro).

Now for the shared projects.  Very cool that that's something that'll be coming soon.  Turns out VS2013 doesn't have that project type unfortunately.  Additionally, the git repositories for the libraries would ideally only have source and no vcxproj files given that some people that want to use them won't be using VS at all.  They might use a text editor and compile/upload everything themselves using command line.  I'd hate to tie all future usage by anyone to VS even though I really like it as an IDE (and this plugin btw Smiley).

Given the above and what I've learnt from your post, I arrive at a modified, much more specific question:
  • Is it possible somewhere for the VM plugin to expand $(ProjectDir) from the VC++ Include Directory paths and add them to the compiler include paths?  This would essentially be adding the -I compiler flags to add include paths (https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Directory-Options.html).
    • Looking through the files in the Arduino directories, I even found this: C:\Program Files (x86)\Arduino\hardware\arduino\avr\platform.txt.  It appears to have the default include locations stored in a variable called {include} though I don't know where that's populated.  There also doesn't seem to be a reason why a plugin might not be able to append more -I options to add more include directories which is a standard build system tool (those directories would basically be the expanded but unmodified directories listed in the project's VC++ Include Directories)

I attached 2 images.  One of the platform.txt file which shows the compiler args and a second one showing where one might extract the desired include directories to be added to those compiler args.  The only non-standard work the plugin would need to do is expand $(ProjectDir) or other VS specific variables into absolute paths.  ProjectDir in particular should be easy enough to expand since the plugin must know where the project lives.

I know this is getting pretty deep into things so no worries if this isn't doable.  I am hoping obviously that I'd be able to contribute good ideas on how to make the experience really really amazing with relatively low cost.  I gotta reiterate though that, regardless, this plugin is already awesome.  Thanks for all the hard work.

Thanks
-A

PS.  I'm not at this point concerned with Arduino IDE backwards compatibility since I'm just trying to put together the library's source code for device agnostic use.  In the spirit of modular code, it seems that having proper structure in the raw codebase is orthogonal to the restrictions imposed by the Arduino Library rules.  It would make sense that outputting an Arduino Library version of that codebase would essentially be a 'build variant' or a 'packaging variant'.  That way, both advanced AVR programmers and Arduino programmers would be able to use the same library, only the Arduino programmers would get a post-processed nicely packaged version of it.
« Last Edit: Jan 3rd, 2017 at 1:15am by Mordy »  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12187
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #3 - Dec 29th, 2016 at 9:59pm
Print Post  
Yes all that makes sense but for some important pointers.

Visual Micro uses the platform.txt for building, the system also uses the individual board overrides in the boards.txt of the same folder.

The visual micro project properties for compiler switches etc. allow you to add additional -I settings which are simply combined with the includes you found in the platform.txt. 

So it's the same system and doesn't matter where you add the additional -I params. The only problem is they are simply compiler search paths and do not have any bearing on which files get compiled. Both Visual Micro and the Arduino IDE have to work out what to compile through other means.

It is a consideration to allow visual micro users to register additional folders that contain files to be compiled. I think it's a different option to what the compiler search paths should be.

With this info and with users of text editors in mind I think the solution you require needs some further thought?

It's good that you have been able to understand the difference between intellisense and compile. In your considerations it will help.

It is also possible to pre-compile modules into gcc .a archive files or as .o object files. These can then be fed to the patterns of the platform.txt.

For Pro Visual Micro users, adding board.txt to the local project allows you to override any of the platform.txt properties when experimenting.

Interested to see what you think will be the simplest for all types of users then we can look at how to make VS help.
  
Back to top
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12187
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #4 - Dec 29th, 2016 at 10:06pm
Print Post  
By the way just to be clear I haven't missed the point.

$(ProjectDir)\subfolder\header.h

You can include files from sub folders of the current project. To do this in Visual Studio they must be included in the solution explorer. It's not enough for them to only physically exist on disk. 

Hopefully you have seen the solution explorer has two views. One view "shows all" the files on disk and one shows only the files included in the project. In "Show all" view you can right click and select "Include in project"

Alternatively for both Visual Micro and the Arduino make sure the sub folder structure is below the "\src" folder "project_folder\src". For normal Arduino, all project folder files and all files in or below the \src sub folder are compiled.

  
Back to top
IP Logged
 
Mordy
Newbies
*
Offline


Posts: 4
Joined: Dec 29th, 2016
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #5 - Dec 30th, 2016 at 8:32am
Print Post  
Ah yes, now we get into the deeper details Smiley.

To get the easier thing out of the way first, I do know about the 'show all' view and I have both included the header files in the on-disk folder structure as well as in the solution (where the VS filters are shown).  In the console app I attached above, it works because the headers/source are shown both present in the solution explorer as well as on disk.  The same should be true of the test sketch I also attached above except that it doesn't compile for the include path reasons.

Quote:

It is a consideration to allow visual micro users to register additional folders that contain files to be compiled. I think it's a different option to what the compiler search paths should be.

I agree.  I did verify that I am using correctly using VS solution filters to identify which source files to compile.  It is specifically the headers that cannot be found given that the compiler spits out an error for my Header.cpp file (yes, stupid file name for this test Smiley) indicating that Header.h could not be found.  This indicates that the cpp files are being added to the list of things to compile.

You mentioned that Visual Micro project properties are indeed parsed then added as -I compiler flags?  I think this means that the header should be findable if $(ProjectDir) is correctly expanded to the full path (ie. C:\folder\etc).

So given the above two points, my assumption is that VS should be able to find the cpp's that get compiled since they exist in the solution filters and the headers should be findable from the VC++ Include Directories.  Is there anything missing that Visual Micro would need to do the compilation?  It seems like all the information should be available.

I hope I'm not just doing something dumb.  I've attached the solution zip again for convenience.  I've just double checked that the header and source are in the solution as well as on disk in the right place and that Intellisense can open the file by right clicking the include and clicking "Open Document <core\include\Header.h> which means the relative path from $(ProjectDir) is valid.

Code (C++)
Select All
#include <core\include\Header.h>

// the setup function runs once when you press reset or power the board
void setup() {
}

// the loop function runs over and over again until power down or reset
void loop() {
	Stuff stuff = Stuff();
	stuff.getChar();
}
 



Quote:
Interested to see what you think will be the simplest for all types of users then we can look at how to make VS help.


If I were to think about this in a structured engineering usage scenario manner, I'd probably say that what we've been discussing can be broken down into scenarios akin to the following:

  • Basic Arduino users
    • Some libraries used but essentially only pre-built and includable using your standard Arduino (and Visual Micro) tools
  • Move advanced Arduino users
    • Using and building libraries.  Would like to share source across projects not necessarily in library form.
    • An interesting additional feature of your upcoming release, the one that lets you share source projects across Arduino solutions, is that maybe you can add the ability for a user to easily package that up as a standard Arduino library.  That'd be pretty cool for the medium advanced user that wants to share stuff but doesn't need a fully structured development process.
  • Developers looking to build and use libraries not only for Arduino, but also for custom things like other AVR projects
    • Basically using Visual Micro for it's ease of deploying to an Arduino and because it works with the other features of VS
    • If I think about it a bit more, it seems likely the core Arduino libraries aren't all written using the Arduino IDE in the first place.  I would think that instead of dogfooding, the standard libraries would be built using a well structured build process with more advanced tooling.  I can see making sure the include directory/header locating abilities of Visual Micro being extremely powerful.  Not only can Visual Micro help the consumer of Arduino libraries, it can be a great place to build code that can be used in real products as well as help be the tool that bridges production code and hobbyists easily allowing high quality code to be built for products as well as for use in tinkerer projects.

Sorry if these posts are a bit long.  There's a lot of value to be had here I think.  In this case, I think it has value for developers of all levels.  I'm always an advocate of tools that can efficiently cater to both basic and advanced users helping build one codebase suitable and easily leveraged by both groups.  On top of that, it looks like the features required to get to that level are really really close to working, or that I'm doing something dumb and they already work Wink.

Thanks
-A
« Last Edit: Jan 3rd, 2017 at 1:15am by Mordy »  
Back to top
 
IP Logged
 
Tim@Visual Micro
Administrator
*****
Offline


Posts: 12187
Location: United Kingdom
Joined: Apr 10th, 2010
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #6 - Dec 30th, 2016 at 2:13pm
Print Post  
The problem here is that you have used a sub folder name called "core" which clashes with the build of the arduino core. The core folder is renamed in the next release so this wouldn't be an issue.

However I think you are complicating things by not sticking to the arduino compatible folder structure I mentioned previously.

Rename your "core" folder to "src" then it will work in visual micro and the arduino ide

Because you are not using search paths you should use "header.h" not <header.h>

Then, in the .ino use:-

Code
Select All
#include "src\include\Header.h" 



In your .cpp I suggest a more flexible approach using "..\"

Code
Select All
#include "..\include\Header.h" 



  
Back to top
IP Logged
 
Mordy
Newbies
*
Offline


Posts: 4
Joined: Dec 29th, 2016
Re: Including headers from subfolders and/or from VC++ Include Directories
Reply #7 - Dec 30th, 2016 at 6:44pm
Print Post  
Hmm.  I've renamed 'core' to 'src'.  That does fix the include in the ino file part.

I should mention though, that I think it's generally not good practice to use path's that use ..\.  Typically, cpp files find their headers by explicitly including the header folders in the search paths for them to be found there.  Then if you move a header file from one directory to another, you don't have to go find all the cpp's it was used in and change the #include.  This post describes it nicely: http://stackoverflow.com/questions/597318/what-are-the-benefits-of-a-relative-pa....

Ideally the VC++ Include Directories would have $(ProjectDir)\src\include in it.  Then in the ino one would just have #include <Header.h> in it.  Brackets instead of quotes because it's part of the search path.

Basically, instead of having the include paths be relative to the file that's including it, for anything larger than a small codebase, teams would want to use paths relative to the search paths.  It adds code maintainability and lets team members move headers around without having to worry about modifying the source files that include them.

There any way we can make it work?  This development pattern already works for regular (non-Arduino) applications.  The console application I attached above demonstrates this by including $(ProjectDir)\core\include into the VC++ Include Directories.  It compiles and runs when I use #include <Header.h>.
« Last Edit: Dec 30th, 2016 at 6:45pm by Mordy »  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint