Configuring cpp sources in gradle - c++

I have set up a project on top of Qt (so source is written in C++) and I wanted to try Gradle for automatic builds on that. It took me some time to get into the details of configuring a multi project build (there is an executable and two libs) and now I am trying to tell the cpp-exe and the cpp-lib plugin how my source tree is structured.
I have set up a task that should print all of the source sets (there should be at least the default ones right?) and it looks like this:
task projectinfo {
description = "Informations about the current project"
group = INFORMATIONS_GROUP
doFirst {
task -> print ("""${task.project.sourceSets.all}""")
}
If I run this task Gradle tells me that there is no property "sourceSets" for the project. The documentation of the plugin tells me that it is possible to customize the source locations, but not how.
So my question would be: How can I tell the Gradle cpp plugin which source files to use. If there is any documentation about the cpp plugin apart from its API documentation and the Gradle user guide that would be helping too.

Have a look at Adam Murdoch's usage of Gradle's 'cpp plugin'. I believe he's one of the main Gradle submitters, so he should know how to use this better than anyone:
Exert from native-platform/build.gradle
cpp {
sourceSets {
main {
source.exclude 'curses.cpp'
}
curses {
source.srcDirs = ['src/main/cpp']
source.include 'curses.cpp'
source.include 'generic.cpp'
source.include 'generic_posix.cpp'
}
}
}
Then, within the 'libraries' node, refer to all/any combination of architecture and source sets:
sourceSets << cpp.sourceSets.main
sourceSets << cpp.sourceSets.curses
I've not had too long to look over it myself, but it looks like he defines a number of OS architecture based source code include combinations and stores these in the variants variable. He then processes them into platform JARs (I haven't actually ran the build yet, maybe I should).
Also, take a look at https://github.com/rklaren/GradleJNI, it uses the cpp plugin but looks to be a little Windows-oriented.
Update - I also found https://github.com/alkemist/gradle-cpp-demo, which has an example of the 'cpp-exe' plugin building an executable.

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.

OpenLayers 3 Build from master

I've cloned the OpenLayers 3 repo and merged the latest from master. There exists a recently merged pull request that I'm interested in exploring, but I'm not sure how to create a regular old comprehensive, non-minified build.
Does anyone know how to create a non-minified, kitchen sink (everything included) build for OpenLayers?
(similar to ol-debug.js).
You can use the ol-debug.json config to concatenate all sources for the library without any minification.
node tasks/build.js config/ol-debug.json ol-debug.js
Where the ol-debug.json looks like this:
{
"exports": ["*"],
"umd": true
}
The build.js task generates builds of the library given a JSON config files. The custom build tutorial describes how this can be used to create minified profiles of the library. For a debug build, you can simply omit the compile member of the build config. This is described in the task readme:
If the compile object is not provided, the build task will generate a "debug" build of the library without any variable naming or other minification. This is suitable for development or debugging purposes, but should not be used in production.

Using AsConfigured and still be able to get UnitTest results in TFS

So I am running into an issue when I go to build my projects using tfs build controller using the Output location "AsConfigred" it will not detect my unit tests. Let me give a little info on my setup.
TFS 2013 Update 2, Default Process Template
Here is a few screenshots that can hopefully help fill in what I can't in typing. I am copying my build out to a file share on our network so that we can use other utilities use the output. I don't want to use "PerProject" or "SingleFolder" because they mess up the file structure we have configured (These both will run the tests). So i have the files copy to folder names "SingleOutputFolder" which is a child of the DropLocation. I would like to be able to run from the drop folder or run from the bin folder for each of my tests (I don't care which). However it doesn't seem to detect/run ANY of the tests. Any help would be greatly appreciated. Please let me know if you need any additional information.
I have tried using ***test*.dll, Install\SingleFolderOutput**.test.dll, and $(TF_BUILD_DROPLOCATION)\Install\SingleFolderOutput*test*.dll
But I am not sure what variables are available and understand where the scope of its execution is.
Given that you're using Build Output location set to AsConfigured you have to change the default values of the Test sources spec setting to allow build to find the test libraries in the bin folders. Here's an example.
If the full path to the unit test libraries is:
E:\Builds\7\<TFS Team Project>\<Build Definition>\src\<Unit Test Project>\bin\Release\*test*.dll
use
..\src\*UnitTest*\bin\*\*test*.dll;
This question was asked on MSDN forums here.
MSDN Forums Suggested Workaround
The suggested workaround in the accepted answer (as of 8 a.m. on June 20) is to specify the full path to the test projects' binary folders: For example:
C:\Builds\{agentId}\{teamProjectName}\{buildDefinitionName}\src\{solutionName}\{testProjectName}\bin*\Debug\*test*.dll*
which really should have been shown as
{agentWorkingFolder}\src\{relativePathToTestProjectBinariesFolder}\*test*.dll
However this approach is very brittle, for the following reasons:
Any new test projects you add to the solution will not be executed until you add them to the build definition's list of test sources:
It will break under any of the following circumstances:
the build definition is renamed
the working folder in build agent properties is modified
you have multiple build agents, and a different agent than the one you specified in {id} runs the build
Improved Workaround
My workaround mitigates the issues listed in #2 (can't do anything about #1).
In the path specified above, replace the initial part:
{agentWorkingFolder}
with
..
so you have
..\src\{relativePathToTestProjectBinariesFolder}\*test*.dll
This works because the internal working directory is apparently the \binaries\ folder that is a sibling of the \src\ folder. Navigating up to the parent folder (whatever it is named, we don't care) and back in to \src\ before specifying the path to the test projects binaries does the trick.
Note: If you have multiple test projects, you add additional entries, separated with semicolons:
..\src\{relativePathToTestProjectONEBinariesFolder}\*test*.dll;..\src\{relativePathToTestProjectTWOBinariesFolder}\*test*.dll;..\src\{relativePathToTestProjectTHREEBinariesFolder}\*test*.dll;
What I ended up doing was adding a post build event to copy all of the test.dll into the staging location folder in the specific build that is basically equivalent to where it would go on a SingleFolder build and do that on each test project.
if "$(TeamBuildOutDir)" == "" (
echo "Building Interactively not in TFS"
) else (
echo "Building in TFS"
xcopy "$(TargetDir)*.*" "$(TeamBuildBinaries)\" /Y /E /S
)
MSBUILD parameter in the build def that told it to basically drop in the folder that TFS looks for them.
/p:TeamBuildBinaries="$(TF_BUILD_BINARIESDIRECTORY)"
Kept the default Test assembly file specification:
**\*test*.dll
View this link for the information on the variable that I used and what relative path it exists at.
Another solution is to do the reverse.
Leave all of the files in the root so that all of the built in functionality works. There is more than just test execution in there. What about static code analysis, impact analysis..among others. You would have to do something custom for them all.
Instead use a pre-drop powershell script to create your Install arrangement from the root files.
If it is an application then you can use the _ApplicationFolder Nuget package to create an _PublishApplications folder same as you get for web applications.

Gradle project version property from Java source

In my application I maintain the 'user-frendly' version as a public String constant in the main class.
Is it possible to retrieve this variables in the build.gradle to set the version property of the project? Currently I have to do this manually, what of course can lead to problems.
Correct way of maintaining "user-friendly" version would be version.properties file, stored in your source tree. E.g., under src/main/resources. Then you can load this properties file in Gradle script:
def config = new ConfigSlurper().parse(new File("src/main/resources/version.properties").toURL())
println(config.versionNumber)
I've plussed Nikita's answer, which is great.
But, firstly, File.toURL() is now deprecated. Something like this would be preferable:
ConfigObject conf = new ConfigSlurper().parse( file("src/main/resources/version.properties").toURI().toURL());
Secondly, note file( ... here, not new File( ... if this line is to be included in build.gradle. The former makes a File relative to the path of the root directory of your Gradle project and is in fact a method of Gradle interface Project. It's worth knowing that every method or property in build.gradle which appears to "come from nowhere" is in fact a method or property of an underlying, "invisible" Gradle Project instance.
If you put new File( "src/main... ") in build.gradle as in Nikita's answer you would in fact not notice any problems if running your Gradle task from a console with current directory the project/root directory... but (according to my experiments) if using the GradleTasks window in Eclipse, for example, you would then be creating a File path relative to the directory where Eclipse was running from... and this would give an error message saying "system cannot find the path specified".
Using file( ..., therefore, you can then go (in build.gradle):
version = conf.versionNumber
NB version here is another property of Project... but you'll be mystified if you look at the above Javadoc for Project, because it's not there! However, you will see getVersion() and setVersion(...). With Groovy every property automatically gets given, by Groovy magic, its own getter and setter method. I took a week out to learn a bit of Groovy, which is actually a fantastic language, and familiarising yourself with it a bit is highly recommended, and makes the learning curve of Gradle substantially less painful.
You can however find the version property in the DSL (domain-specific language) API for Gradle class Project here.
The file version.properties would typically contain something like this:
versionNumber='1.0.0'
NB accessing version from your code ... if you wanted to access this version number from your app code (or test code), you would indeed use new File( ...:
ConfigObject conf = new ConfigSlurper().parse( new File("src/main/resources/version.properties").toURI().toURL());
as in Nikita's answer.

Building multiple binaries within one Eclipse project

How can I get Eclipse to build many binaries at a time within one project (without writing a Makefile by hand)?
I have a CGI project that results in multiple .cgi programs to be run by the web server, plus several libraries used by them. The hand-made Makefile used to build it slowly becomes unmaintainable. We use Eclipse's "Internal Build" to build all other projects and we'd prefer to use it here too, but for the good of me, I can't find how to get Eclipse to build multiple small programs as result instead of linking everything into one binary.
Solution for this described there: http://tinyguides.blogspot.ru/2013/04/multiple-binaries-in-single-eclipse-cdt.html.
There is an excerpt:
Create a managed project (File > New C++ Project > Executable)
Add the source code containing multiple main() functions
Go to Project > Properties > C/C++ General > Path & Symbols > Manage Configurations
Make a build configuration for each executable and name it appropriately (you can clone existing configurations like Debug and Release).
From the project explorer, right click on each source file that contains a main() function > Resource Configurations > Exclude from Build and exclude all build configurations except the one that builds the executable with this main() function
All other code is included in all build configurations by default. You may need to change this depending on your application.
You can now build an executable for each main function by going to Project > Build Configurations > Set Active , Project > Build Project
Using Eclipse as your build system for production code seems like a bad idea in general. I think it's a great IDE and have used it extensively for both Java and C++ projects, but for a build system I firmly believe that Ant, make, and other dedicated build utilities are the way to go.
There are several reasons for this:
Dedicated build utilities offer the very flexibility you are looking for in generating multiple executable targets.
Ant and make support most conceivable arbitrary build process chains (though not quite all).
A dedicated build utility is likely to offer greater stability and backward-compatibility for build description file formats than an IDE tool like Eclipse. Also, I'm pretty sure that Eclipse's internal build feature is dependent on the ".project" file description, and the latter's format is probably not as stable as the build description format for either Ant or make.
General-purpose, basic build utilities are usually command-line-based, which makes it easy to integrate them with more sophisticated, higher-level build utilities for automated build management like Pulse, CruiseControl, etc.
The need that is motivating your question is telling you that it's time to make the switch to a better build tool.
There is a way to use buildconfigurations to create one binary (or shared library, in my case) from each build config. Using the answer above, this means to manually exclude all but the effective main file from each build config.
I just used the above answers to ease up working on my eclipse project that creates 14 shared libraries through 14 build configs. However, configuring the indivdual "exclude from build" setting was quite cumbersome, so I switched to using the following code relying on a preprocessor-directive as my complete main file:
/*
*main.cpp
*/
/* Within
* Project | Properties | C/C++-Build | Settings
* | GCC C++ Compiler | Preprocessor
* set the following defined Symbol:
* _FILENAME=${ConfigName}
*/
#define __QUOT2__(x) #x
#define __QUOT1__(x) __QUOT2__(x)
#include __QUOT1__(_FILENAME.cpp)
#undef __QUOT1__
#undef __QUOT2__
/* The above include directive will include the file ${CfgName}.cpp,
* wherein ${CfgName} is the name of the build configuration currently
* active in the project.
*
* When right clicking in
* Project Tree | (Project)
* and selecting
* Build Configuration | Build all
* this file will include the corresponding .cpp file named after the
* build config and thereby effectively take that file as a main file.
*
* Remember to exclude ALL ${CfgName}.cpp files from ALL build configurations.
*/
Note that it does nothing else then include another .cpp file which's name is deduced from the preprocessor and a symbol that is set in the compiler options. The symbol is ${CfgName} and will be replaced by the current config name by eclipse automatically.
One does not need to configure, which file is included in which build config. Just exclude all ${CfgName}.cpp files in every build and include main.cpp in every build.
PS: the answer from hovercraft gave me the idea to have a main file that does not contain code on its own. If one includes shared code from the different effective main files ${CfgName}.cpp, working on their code may become infeasible because header files in main.cpp will not be visible in them.
I did this until yesterday, but maintaining the code with broken index etc. was a big pain.
PPS: this procedure currently breaks the automatic rebuild of the main file if only the included .cpp file was changed. It seems that eclipse does not recognize the changes in ${CfgName}.cpp (which is excluded from build). So a manual rebuild is required after every change. This is currently bugging me ;)