Gradle include all files under a directory ('recursively') - c++

So I've been making a Java project using Gradle (GitHub), but it uses/needs JNI (natives).
I was first using Makefiles to compile and link the C++ code, but then I found out how to compile and link C++ natives using Gradle, so I got all of that working. But now I am stuck, because I can't find a way to include all natives, on the same level (base) inside of the JAR file. NOTE: I don't need help with compiling the natives, only with including/packaging them.
EDIT: I just commited the changes to GitHub.
This is my directory structure:
[Project Directory]
- build.gradle
- src/
- win32/ (the only native library that i currently have)
- cpp/
- main/
- java/
- build/
- libs/ (here is the JAR and the natives)
- win32/ (the natives)
- shared/ (the dynamic link libraries, i only want these)
- x64/ (i want to include both x64 and x86)
- mylibrary.dll (just the DLLs should be included)
- mylibrary.ext
- mylibrary.lib
- x86/
So there are a few criteria:
I only want the DLL files, none of the .ext and .lib stuff.
I want to be able to dynamically change the amount of libraries and the names of the natives.
What I have tried:
My first attempt was just looping through all folders. I didn't have to use recursion because the depth of the file structure is fixed, so it will never be further from or closer to the build/libs directory. This is how I tried coding it:
sourceSets {
main {
resources {
srcDirs "src/main/resources"
// include natives
String libfp = "${buildDir}/libs/"
File libf = new File(libfp);
if (!libf.exists())
libf.mkdir();
FileFilter isDir = f -> f.isDirectory();
FileFilter isDll = f -> f.getAbsolutePath().endsWith(".dll");
for (File file : libf.listFiles(isDir)) { // iterate "libs" to find all libraries
// enter "shared"
File filen = new File(file.getAbsolutePath() + "/shared/");
for (File file1 : filen.listFiles(isDir)) { // iterate over "shared" to find all platforms
for (File file2 : file1.listFiles(isDll)) { // get all dlls
include(file2.getAbsolutePath())
}
}
}
}
}
}
This worked, except from the including itself. I don't know if I understand how this works correctly, but the include function didn't seem to add anything to the resources.
Then, I checked the documentation and found it was a pattern based function, so I tried making a simple include call with the pattern I thought would work:
include "/build/libs/**/*.dll"
// I also tried the following:
include "/build/libs/**.dll"
include "/build/libs/*.dll"
But that didn't seem to work too. So I think I am just misunderstanding how the include function works.

Just use
include '/build/libs/**'
will work. Thanks.

Related

Gradle native c++ non source files resources or assets folder location?

Context: I am primarily a Java developer and I use gradle for all my builds. As a hobby I've been playing around with C/C++ and found that gradle has the ability to build these as well. So instead of learning cmake/make just for some small hobby projects I thought I'd use gradle since I am familiar with it.
Question: How do I define locations for non-source files?
With Java there is a resources folder that you can put things like images, text files, etc... in and gradle will put these in the jar so in your code you can load them with relative paths pretty easily.
src > main > java for source files.
src > main > resources for assets.
Is there an equivalent way to do this for c++ projects?
Also if there is a default folder that would be good to know, but also how to define it in the build.gradle file to a different location would also be appreciated.
For reference here is my simple build file right now:
apply plugin: "cpp"
model {
components {
main(NativeExecutableSpec) {
sources {
cpp {
source {
srcDir "src"
}
}
}
}
}
}
In my code I'd like to be able to load an image, for example, with something like:
HoweverYouLoadAnImageInCpp("imageName.png");
While having a simple structure like:
root
--src
--images
If there is no way to currently do this, is there a workaround or a more standard way people do this in C/C++?
As mentioned in the comments, unlike jars in java, c/c++ does not seem to have a standard way of including assets in the executable. There do seem to be platform specific ways and gradle does seem to have support for Windows resource files, so if that is what you are looking for see the gradle docs.
I prefer not to do any platform specific things though so I thought I'd answer this with what I decided to do in case someone else finds this question with a similar need. If another, better, answer pops up and I notice I will change the selection.
In the end the executable will look for paths relative to where it is executed (from what I can tell at least.) So I just made a copy task to put the assets in a parallel folder.
task copyAssets {
copy {
from "."
into "build/exe/main"
include "images/**" // This will take the whole images folder from project root
}
}
build.dependsOn copyAssets
So when I gradle build now it will copy my images folder to the same folder that it builds my 'main' cpp source executable. And in my code I can access those images with:
HoweverYouGetImages("images/imagename.png");
You could of course get more fancy with your task and zip it up or compress your images and decompress on loading in your code.

How to add all .pri files inside a directory

I've searched quite thoroughly, but couldn't find a way to get all the folders inside a directory. I have the following qt project structure
first/
second/
- second.pri
third/
- third.pri
...
first.pri
I want to include all the pri files inside the first.pri file. I can do
include($$PWD/second/second.pri)
include($$PWD/third/third.pri)
...
But the problem is there could be many sub directories added in the future and I want to automatically include all the pri files. I've tried
FILES = $$files($$PWD/*/*.pri)
for(FILE, FILES) {
include($$FILE)
}
But this does not find the folders inside 'first' folder. $$files documentation allows specification of recursive, but it does not descend into subdirectories. How do I achieve it?
The following QMAKE function lists recursively all the files below a directory:
# - Function that list all files below a directory
defineReplace(list_recursively) {
FILES = $$files($$1)
RESULT =
for(var, $$list($$FILES)) {
exists($$var)
{
RESULT *= $$find(var, .*\.pri)
RESULT *= $$list_recursively($$var/*)
}
}
return($$RESULT)
}
# - Define the base directory
DIR = $$PWD/*
# - Test the function
temp_dir = $$list_recursively($$DIR)
# - Output the result
for(var, $$list($$temp_dir)) {
message($$var)
}
In the list_recursively function, it is possible to filter only those files with a specific extension, for example .pri. This is not even required if your project structure contain only .pri file.
Note: QMake does not work correctly with white spaces, it is usually a good idea to avoid them.
EDITED:
Added a filter for .pri files.

Create c++ NuGet package with nested include folders

I'm trying to package a toolkit for C++ where the include files are spread over several folders, like so:
Includes - cen_dcm -dcmnet
-ofstd
-dcmdata
Inside the nuspec is: include: { ${SDK_Base}\cen_dcm\**\*.h };
With this package deployed I get the include files in the following location:
..\packages\DCMTK.3.42.0.0\build\native\include including subfolders.
When I use the including the IntelliSense has no problems finding it, but if that include file includes something from a different folder it fails to find it.
So I use: #include"dcmnet/assoc.h" which works just fine, but when compiling assoc.h it reports it cannot find osconfig.h
That file is in the package but in the ofstd folder.
Normally I'd solve that by adding additional includes, but since this is a package I don't want that.
What am I missing? I can't imagine that support for something so basic is lacking?
To answer my own question. You can add {targets} to your autopkg file.
It looks like this:
targets {
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm";
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm\config";
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm\dcmtls";
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm\dcmdata";
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm\dcmnet";
Includes += "$(MSBuildThisFileDirectory)..\..${d_include}cen_dcm\ofstd";
}
This additional include folders will show up in the of your package.targets file.
There are more possibilities using {targets}. See http://coapp.org/reference/autopackage-ref.html

Difficulty in using SDL_LoadBMP with relative path in Xcode

Firstly, I know this question has been asked many, many times; I have read at least five or ten variations, but none of the answers given worked in my case. I have the line:
helloWorld = SDL_LoadBMP("helloworld.bmp");
in the main.cpp file of my Xcode 5 project. The directory structure is as follows:
TestProject1
main.cpp
Resources
helloworld.bmp
TestProject1.1
TestProject1.xcodeproj
Of course, I have tried different paths, i.e. Resources/helloworld.bmp, and yes, the Resources folder is imported into the project. However, the statement returns NULL because (according to SDL_Error) it cannot find the file. Now, the line:
helloWorld = SDL_LoadBMP("/fully/qualified/path/to/helloworld.bmp");
works fine, so it is not a problem with my code. What is the generally accepted way to get Xcode to work with relative paths for resources? I am looking for a method that will be portable (to the platforms that SDL supports, ofc on different computers/devices) when I make a larger project, and am open to using a different IDE if Xcode cannot make portable C++ projects. Miscellaneous other things I have tried after reading other questions:
Adding helloworld.bmp to Build Phases > Copy Files.
Adding the code:
// ----------------------------------------------------------------------------
// This makes relative paths work in C++ in Xcode by changing directory to the Resources folder inside the .app bundle
#ifdef __APPLE__
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
char path[PATH_MAX];
if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
{
// error!
}
CFRelease(resourcesURL);
chdir(path);
std::cout << "Current Path: " << path << std::endl;
#endif
// ----------------------------------------------------------------------------
to the beginning of main.cpp (returns "Expected unqualified-id" compiler error on the if (!CFURL...) line).
Using an absolute path - as I said, this works, but I want portability.
Calling getcwd: this is C++ code. Is there something I am missing here? It doesn't seem like getcwd is a C++ function.
In your Build Phases you need to create a new build phase of type Copy Files.
Set Destination to be 'Resources' and leave Subpath blank unless you want to have a subfolder in your resources (can be useful when you have a lot and want to separate eg fonts, textures, sounds etc)
Leave Copy only when installing unticked
Then just add the resources to that build phase, in your case helloworld.bmp
You should then be able to load by doing:
helloWorld = SDL_LoadBMP("helloworld.bmp");
or if you used a Subpath:
helloWorld = SDL_LoadBMP("textures/helloworld.bmp");
This is the same sort of way you could bundle the SDL2.framework with your application. There is a tutorial here - http://zamma.co.uk/setup-sdl2-in-xcode-osx/ and in Part 3 it describes how to bundle the frameworks if you are interested.
Overal though the best way to do fully portable builds is going to be something like CMake or Gradle.

Keeping all libraries in the Arduino sketch directory

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