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.
Related
In my C++ application, I have a text file (dataFile.txt) that is installed on the Linux target machine in the following path:
/SoftwareHomeDir/Configuration/Application/dataFile.txt
This file exists on my Rational ClearCase source code environment under the path:
/ProjectName/config/Application/dataFile.txt
I am developping a unitTest in gtest that does following:
Read a specific data from dataFile.txt , if the data does not exist than write it into the file.
1) I am avoiding to create an environment variable to check whether I am in the compilation environment or the target machine. Then add additional test code in the final release. I really want to separate test code from final code.
2) I am not using any IDE (no visual studio, no qt, etc.), just notepad++
3) The compilatio. server is shared (access with a username, however the root folder "/" is shared. Which means that if I create the path "/SoftwareHomeDir/Confiugration/Application/dataFile.txt", it will be visible by all users, and if another user is running his gtest unitTest, he may overwrite my file.
4) In the final code, the path to the dataFile is hard coded, and it is very costly (will take few seconds to run) to implement a filesearch(filename) method to look for the file in the entire hard drive before reading the file.
Question:
I am looking for a solution to unit-test my code in the compilation environment that is using /ProjectName/config/Application/dataFile.txt
The solution to my problem was to combine gmock with gtest as described by the link
https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#delegating-calls-to-a-fake
The only modification I made to my code is that instead of defining the path to the configuration data using #define, I created a function getConfigFilePath() that returns the hardcoded path of the configuration file in the installed application. From here, I mocked the class and in my mock, I call a fake getConfigFilePath() that returns, when the real code is executing, the hardcoded path of the config file in the project tree in ClearCase. This is precisely what I was looking for.
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.
I have a java-project that is developed with help of maven. Part of the project is unit-testing. I plan to put all temporary files that are produced by unittests into maven's target directory. This might be a good idea, because if for whatever reason temporary files are not removed by unittests, target directory may be cleaned and with it all temporary files still lying around in the file-system. So i found filtering function of the maven resources plugin and was wondering if it possible to instantiate it for my usecase. My plan is to have an entry in the properties file like this
targetdir = ${project.build.directory}
which should offer me a property that reveals the location of mavens target-directory. Now, caveeat is, the filtered property file is stored in the target directory by the maven resource plugin. How can i find it there? I need the properties file to tell me where the target-directory is, but the properties-file is in the target directory?
Is my approach still worth beeing done? Or is it not possible this way?
I have got two ways:
1. Use a Java Magic
Here, I just ran a trick
#Test
public void testpath(){
//gets me surefire report dir, lies just below /target
File testDir = new File(TestTargetPath.class.getResource("/").getPath());
//Get its parent! location of target
System.out.println("target? " + testDir.getParent());
//modify your properties object to set this as targetDir
}
this prints
target? /home/naishe/workspace/in/naishe/homeapp/target
2. Read the config file as resource using relative path
There are two places to put a resource file such as configuration properties in Maven layout.
/src/main/resources -- the files under this goes as a part of artifact. You can access them using getResource() from any class under /src/main/java
/src/test/resources -- files under this, does not go as a part of artifact, but they are available from any class /src/test/java.
So, based on what your need is, you can keep your config.properties under one or both the places and read the config files using:
Properties props = new Properties();
InputStream stream = AppConfig.class.getResourceAsStream("/config.properties");
props.load(stream);
System.out.println(">> " + props.getProperty("targetDir"));
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.
I am trying out lua script with C++ in Mac OS X. I was finding a way to make the program returning the current working directory. That's no problem with getcwd, but then I came one thing:
My foo.lua stays at its initial path only. When I compile program, it is not being copied over to the build/Debug directory. Sure, I can grab my script there, but that's just impractical. XCode or any IDE should carry resources to the build zone. XCode does this automatically with iPhone app, but this seems to be a different case. For this case, how to command XCode to put the respective resources in the build directories?
int main (int argc, char * const argv[]) {
...
...
luaL_dofile(luaVM,"/Users/yourNameHere/Desktop/LuaSandbox/LetsTryLua/foo.lua");
//typing the whole absolute path here is just ugly and impractical.
...
...
printf("working directory: %s", buffer);
//output is: working directory: /Users/yourNameHere/Desktop/LuaSandbox/LetsTryLua/build/Debug
...
...
Rather than hard code the path to your Lua script you may want to use the NSBundle API's to find it:
NSBundle * mainNSBundle = [NSBundle mainBundle];
NSString * luaFilePath = [mainNSBundle pathForResource:#"foo"
ofType:#"lua"
inDirectory:NULL
forLocalization:NULL];
luaL_dofile(luaVM,[luaFilePath UTF8String]);
This will find it in the bundle's folder (if you added the "Copy Bundle Resources" build step to your target as the above poster suggested.
Because you're using a .lua file as a resource, I suspect that isn't recognised as a standard resource type and hence it hasn't been automatically copied. You should be able to do this though by adding an extra Copy Bundle Resources build step to your target and then add your file to it in the project view.
If you're creating a command line tool that is not a bundle, then there's never going to be a good solution. If you're creating a regular app then the aforementioned solution will work, but you're going to have to stop assuming that your working directory is set to anything even remotely meaningful at any point in time and use the appropriate methods for finding resources stored within your bundle.