I'm working on a C++ project that has some hand coded source files, as well as some source and header files that are generated by a command line tool.
The actual source and header files generated are determined by the contents of a JSON file that the tool reads, and so cannot be hardcoded into the scons script.
I would like to set up scons so that if I clean the project, then make it, it will know to run the command line tool to generate the generated source and header files as the first step, and then after that compile both my hand coded files and the generated source files and link them to make my binary.
Is this possible? I'm at a loss as to how to achieve this, so any help would be much appreciated.
Yes, this is possible. Depending on which tool you're using to create the header/source files, you want to check our ToolIndex at https://bitbucket.org/scons/scons/wiki/ToolsIndex , or read our guide https://bitbucket.org/scons/scons/wiki/ToolsForFools for writing your own Builder.
Based on your description you'll probably have to write your own Emitter, which parses the JSON input file and returns the filenames that will finally result from the call. Then, all you need to do is:
# creates foo.h/cpp and bar.h/cpp
env.YourBuilder('input.json')
env.Program(Glob('*.cpp'))
The Glob will find the created files, even if they don't physically exist on the hard drive yet, and add them to the overall dependencies.
If you have further questions or problems arise, please consider subscribing to our User mailing list at scons-users#scons.org (see also http://scons.org/lists.html ).
Thanks to Dirk Baechle I got this working - for anyone else interested here is the code I used.
import subprocess
env = Environment( MSVC_USE_SCRIPT = "c:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\vcvars32.bat")
def modify_targets(target, source, env):
#Call the code generator to generate the list of file names that will be generated.
subprocess.call(["d:/nk/temp/sconstest/codegenerator/CodeGenerator.exe", "-filelist"])
#Read the file name list and add a target for each file.
with open("GeneratedFileList.txt") as f:
content = f.readlines()
content = [x.strip('\n') for x in content]
for newTarget in content:
target.append(newTarget)
return target, source
bld = Builder(action = 'd:/nk/temp/sconstest/codegenerator/CodeGenerator.exe', emitter = modify_targets)
env.Append(BUILDERS = {'GenerateCode' : bld})
env.GenerateCode('input.txt')
# Main.exe depends on all the CPP files in the folder. Note that this
# will include the generated files, even though they may not currently
# exist in the folder.
env.Program('main.exe', Glob('*.cpp'))
There's an example at:
https://github.com/SCons/scons/wiki/UsingCodeGenerators
I'll also echo Dirk's suggestion to join the users mailing list.
I'm trying to build opencv2 as a universal framework. I am systematically removing the files/folders that I do not need. But I am running into this issue where the include files are not found. See the image below:
The following image clearly shows that the file is indeed there.
One of the contractors working with us said he had put the include files into the same directory as the source files and rename them according to their file structure but using "." instead of "/" as shown below:
But that means that I must go through all of the files that include files and change the include statement to use "." instead of "/". REALLY?
Is this true? Or do we have a configuration set wrong?
You need to setup search paths for your target in Build Settings->Search Paths->Header search paths.
My C-gcc project structure is:
\Project\wscript (only one in project)
\Project\build\
\Project\Source\Module_1\foo.c
\Project\Source\Module_1\foo.h
\Project\Source\Module_1\dummy\foo2.h
\Project\Source\Module_n\bar.c
\Project\Source\Module_n\any dept...\bar.h
How can I recursively find all *.C files in 'Source' and add to
bld.program(source=HERE)?
instead of manually listing it:
bld.program(source="foo.c bar.c...", includes='..\\Source ..\\Source\Module_1')
Also how can I find every subfolders (preferably which has *.h) and append to include path?
Should I write my own finder functions in python and just pass it?
bld.program(source=SRCs_FOUND, includes=Paths_FOUND)
Will this cause any dependency problems in building?
In any modern IDE this thinking is common, drag one file to the Source tree, and it's automatically added to the build list. Thanks!
You can use globbing to scan the directories.
bld.program(
name = ...
....
source = bld.path.ant_glob('**/Source/*.C')
)
Just search for ant_glob in the waf book.
I know that you are supposed to place any external libraries under the "libraries" folder of the arduino install directory, but I have a project that uses several libraries that I have created for the project and mainly to keep all that code self contained and out of the main pde file. However, I have tried to place the libraries in the same directory as the main PDE file so that I can more easily keep everything synced up in subversion (I work on this on multiple computers) and I don't want to have to keep going back and syncing up the libraries separately. Also, just for the sake of being able to easily zip of the sketch folder and know that it contains everything it needs.
I've tried adding the header files to the sketch as a new tab, but that doesn't seem to work at all... don't even care if they should up in the arduino IDE.
I've also tried adding the libraries to the sketch directory in subdirectories (what I would greatly prefer) and then linking to them as:
#include "mylib/mylib.h"
and
#include <mylib/mylib.h>
But both of these result in file not found errors.
Is this possible? And, if so, how do I include them in the main file for building? Preferably in their own subdirectories.
I had the same issue. Solved it for Arduino IDE > 1.8. Seems a specialty in newer IDEs (?) according to the reference (see bottom link).
You have to add a "src" Subdirectory before creating a library folder. So essentially your project should look like this:
/SketchDir (with *.ino file)
/SketchDir/src
/SketchDir/src/yourLib (with .h and .cpp file)
and finally in your sketch you reference:
#include "src/yourLib/yourLib.h"
otherwise in my case - if I am missing the "src" folder - I get the error message that it cannot find the yourLib.cpp file.
Note: I am using a windows system in case it differs and actually VS Code as wrapper for Arduino IDE. But both IDE compile it with this structure.
References:
https://forum.arduino.cc/index.php?topic=445230.0
For the sketches I have, the "*.h" and "*.cpp" library files actually reside in the same folder as the sketch, and I call them like "someheader.h". I also noticed that if I go into sketch menu and add file... that the file doesn't appear until I close and reopen the sketch.
I agree with you; this is an intolerable way to develop software: it requires every file that you need to be in the same directory as the main program!
To get around this, I use make to put together a single .h file from my .h and .cpp sources - you can see this used in this Makefile:
PREPROCESS=gcc -E -C -x c -iquote ./src
# -E : Stop after preprocessing.
# -C : Don't discard comments.
# -x c : Treat the file as C code.
# -iquote ./src : Use ./src for the non-system include path.
TARGETS=sketches/morse/morse.h
all: $(TARGETS)
clean:
rm $(TARGETS)
%.h: %.h.in
$(PREPROCESS) $< -o $#
Arduino is very picky about file endings - if you put a .cpp or .cc file in its directory it automatically uses it in the source, and you can't include anything that's not a .cpp, .cc or .h - so this is about the only way to do it.
I use a similar trick also to put together JavaScript files here.
This requires that you run make after editing your files, but since I'm using an external editor (Emacs) anyway, this is zero hassle for me.
Unfortunately the Arduino IDE is awful and shows no signs of improving. There is no real build system so it only lets you build programs that reside in a single directory.
The only real solution is to write a makefile, then you can use a real IDE. I'm hopeful that one day someone will write an Arduino plugin for QtCreator.
Here's an example makefile:
http://volker.top.geek.nz/arduino/Makefile-Arduino-v1.8
I just had this same problem (I also like to keep the code self-contained), so I'll just jot down some notes; say I have a MyPdeSketch.pde using MyLibClass.cpp; then I have it organized like this
/path/to/skdir/MyPdeSketch/MyPdeSketch.pde
/path/to/skdir/MyPdeSketch/MyLibClass/MyLibClass.cpp
/path/to/skdir/MyPdeSketch/MyLibClass/MyLibClass.h
(In principle, /path/to/skdir/ here is equivalent to ~/sketchbook/)
What worked for me is something like:
mkdir /path/to/arduino-0022/libraries/MyLibClass
ln -s /path/to/skdir/MyPdeSketch/MyLibClass/MyLibClass.* /path/to/arduino-0022/libraries/MyLibClass/
After restart of the IDE, MyLibClass should show under ''Sketch/Import Library''.
Note that the only way I can see so far for a library class file to refer to other library files is to include them relatively (from 'current location'), assuming they are all in the same main arduino-0022/libraries folder (possibly related Stack Overflow question: Is it possible to include a library from another library using the Arduino IDE?).
Otherwise, it should also be possible to symlink the MyLibClass directory directly into arduino-0022/libraries (instead of manually making a directory, and then symlinking the files). For the same reason, symlinking to the alternate location ~/sketchbook/libraries could also be problematic.
Finally, a possibly better organization could be:
/path/to/skdir/MyLibClass/MyLibClass.cpp
/path/to/skdir/MyLibClass/MyLibClass.h
/path/to/skdir/MyLibClass/MyPdeSketch/MyPdeSketch.pde
... which, after symlinking to libraries, would force MyPdeSketch to show under the examples for the MyLibClass library in Arduino IDE (however, it may not be applicable if you want to self-contain multiple class folders under a single directory).
EDIT: or just use a Makefile - which would work directly with avr-gcc, bypassing the Arduino IDE (in which case, the sketchbook file organization can be somewhat loosened)..
Think I know what do u need exactly.
you have a project folder say MYPROJ_FOLDER and you want to include a Libraries folder that contains more children folders for your custom libraries.
you need to do the following:
1- create folders as follows:
-MyProjFolder
-MyProjFolder/MyProjFolder
and then create a file with the folder name in .ino extension
-MyProjFolder/MyProjFolder/MyProjFolder.ino
2- create libraries folder:
-MyProjFolder/libraries <<<<< name is not an option should be called like that.
3- then create your own libraries
-MyProjFolder/libraries/lib1
-MyProjFolder/libraries/lib1/lib1.cpp
-MyProjFolder/libraries/lib1/examples <<<< this is a folder
-MyProjFolder/libraries/lib1/examples/example1
repeat step 3 as much as you want
also check http://arduino.cc/en/Guide/Libraries
I did it a little differently. Here is my setup.
Visually this is the directory layout
~/Arduino/Testy_app/ <- sketch dir
/Testy_app.ino <- has a #include "foo.h"
/foo <- a git repo
/foo/foo.h
/foo/foo.cpp
Here is how I build:
~/Arduino/Testy_App/$ arduino-cli compile --library "/home/davis/Arduino/Testy_app/foo/" --fqbn arduino:samd:mkrwan1310 Testy_app
If you wish to be more elaborate and specify libs and src dirs, this also works
~/Arduino/Testy_app/ <- sketch dir
/Testy_app.ino <- has a #include "foo.h"
/lib <- a git repo
/lib/foo/src/foo.h
/lib/foo/src/foo.cpp
and the build method is:
~/Arduino/Testy_App/$ arduino-cli compile --library "/home/davis/Arduino/Testy_app/lib/foo/src" --fqbn arduino:samd:mkrwan1310 Testy_app
One more bit of tweaking needs to be done to include files from the lib dirs to main dir. If you need to do that, this is the work around:
~/Arduino/Testy_app/ <- sketch dir
/Testy_app.ino <- has a #include
"foo.h"
/inc/Testy_app.h
/foo <- a git repo
/foo/foo.h
/foo/foo.cpp < has a "include testy_app.h"
Then do the compile like this
~/Arduino/Testy_App/$ arduino-cli compile \
--library "/home/davis/Arduino/Testy_app/inc" \
--library "/home/davis/Arduino/Testy_app/foo/src" \
--fqbn arduino:samd:mkrwan1310 Testy_app
What has worked for me is to create a dir, for example "src" under the sketch dir, and under that a dir for each personal library.
Example:
I have a project called ObstacleRobot, under that a folder for my sketch, named obstaclerobot (automatically created by the IDE) and there my sketch "obstacleRobot.ino"
Up to now we have:
/ObstacleRobot
/obstaclerobot
obstacleRobot.ino
Then I wanted to include a personal library that was fully related with this project and made no sense in including it in the IDE libraries, well in fact I want to do this for each part of the robot but I'm still working on it.
What in the end worked for me was:
/ObstacleRobot
/obstaclerobot
obstacleRobot.ino
/src
/Sonar
Sonar.h
Sonar.cpp
Then what you have to do in the main sketch is to write the include as follows:
#include "src/Sonar/Sonar.h"
And thats all.
Following the lines of Hefny, make your project an example for your library.
For example (Unix env), let's say the libraries are in ~arduino/libraries
Your create your project ~arduino/libraries/MyProject, your libraries go there (for example ~/arduino/libraries/MyProject/module1.h ~/arduino/libraries/MyProject/module1.cpp ~/arduino/libraries/MyProject/module2.h ~/arduino/libraries/MyProject/module2.cpp
Now:
mkdir -p ~arduino/libraries/MyProject/examples/myproj
edit ~arduino/libraries/MyProject/examples/myproj/myproj.ino
(note that this is not examples/myproj.ino but examples/myproj/myproj.ino)
Restart the IDE, you should find your project in the menu File/Example/MyProject.
Also note that you do the include with #include
Why dont we just write a script with a single copy command, copying our libs from wherever our library is located into the arduino IDE library folder?
This way we keep the file structure we want and use the IDE library requirements without fuss.
Something like this works for me:
cp -r mylibs/* ~/Documents/programs/arduino-1.5.8/libraries/.
Note that the paths are relative to my own file structure.
Hope this helps someone. This includes my future self that I bet will be reading this in a near future... as usual!
J
I'm documenting a C++ library's header files with Doxygen. In the Doxyfile, I defined
INPUT = include/
in the hopes that Doxygen would then generate documentation for all the header files in include/Foo, but it doesn't: only the index.html is generated. I can set INPUT to include/Foo, but then the documentation lists the headers with their basenames (Reader.hh), while I want clients to include the headers as Foo/Reader.hh etc.
How can I get Doxygen to look within the subdirectory?
Have you set RECURSIVE to YES?
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
it's in the Doxyfile (here line 608, might be sligthly different for you)