Dynamically adding gradle projects at runtime - gradle

I'm in the process of updating our build process for Android to use gradle. We have client-specific apps - i.e. a single code template which is used as the basis for all the apps which are created dynamically.
To build the apps, I loop through a CSV file to get the details for each one. I then take a copy of the source template, inserting the client's name, images, etc. before compiling the app. This works fine in the current system. In the gradle version, I've got it successfully looping through the rows and creating the app source for each one with the right details. However when I try to actually build the app, it fails with the message:
Project with path ':xxxxxx' could not be found in root project 'android-gradle'.
From reading the documentation, I understand that this is because the project doesn't exist during the configuration phase as it's not created until the execution phase. However what I haven't been able to find is a way around this. Has anyone managed to achieve something similar? Or perhaps a suggestion for a better approach?

One option is to script settings.gradle. As in any other Gradle script, you have the full power of Groovy available. Later on you can no longer change which projects the build is composed of. Note that settings.gradle will be evaluated for each and every invocation of Gradle, so evaluation needs to be fast.

While Peter's answer pointed me in the right direction, it ended up not being a workable solution. Unfortunately with nearly 200 apps to build, creating a copy of the source for each one was too big an overhead and gradle kept running out of memory.
What I have done instead is to make use of the Android plugin's product flavors functionality. It was quite straight forward dynamically adding a productFlavor for each row in the CSV (and I can do that in build.gradle rather than settings.gradle), and I just set the srcDir to point to the relevant images etc for each one.

Related

SonarQube Directory Exclusions vNext Component Issue

I've been having some difficulty with exclusions in SonarQube. I haven't really seen this particular situation posted here, and following some other solutions suggested in exclusion-related questions has not solved the issue. Any insight would be really appreciated.
I've been working with an engineer on filtering the files SonarQube is analyzing from their project during build time. Their solution is being built via a vNext build, where TFS and the build server are hosted on-prem. SonarQube is also hosted on-prem. The build is using the Sonar components included with vNext for the analysis. The project is primarily C#.
The solution consists of mostly projects exclusive to that solution, but there a few projects references that are part of another app entirely. Because of this, the workspace mapping has to get files from 2 separate parts of source control. Also, because of the way the solution is looking for the projects (based on the properties of the solution file itself), I have to map the source control files in a specific way. At a high level, the workspace on the build server looks something like this:
In the sonar settings file, the working directory is set to the Build Source Folder
The engineer wants to exclude code files from specific directories from analysis. For example, they want to exclude all cs files from folder X within B.Srvc. So, the directory would be Build Source Directory/B/Source/B.Srvc/X. Based on the exclusion instructions found on SonarQube's website, it sounded like I just needed to do something like this:
sonar.exclusions=Build Source Directory/B/Source/B.Srvc/X/**/*.cs
When I did that, it still analyzed the files within that folder. I tried various other combinations of patterns like:
sonar.exclusions=Build Source Directory/B/Source/B.Srvc/X/*.cs
sonar.exclusions=**/X/**/*.cs
sonar.exclusions=B/Source/B.Srvc/X/**/*.cs
sonar.exclusions=**/B/Source/B.Srvc/X/**/*.cs
I've even tried giving the complete directory path (so, C:/agent/_work/25/src/...) but that did not work either.
Very broad exclusions like **/* Name *.cs work perfectly fine, but if I want to start excluding files from certain directories, I can't get anything to work.
I feel like I'm missing something really basic, but I just can't figure it out. I've been trying to solve this issue for awhile when I have time, but I haven't made any progress. If anyone could provide any insight, I would really appreciate it. If you need any additional information, let me know.
In the SonarQube interface, look at one of the files you want to exclude. At the top, you will see the file path as SonarQube understands it. It is this path that you want to use when you enter your exclusions through the UI not the analysis settings.
Because of the structure of exclusion properties, they are very, very difficult to set up correctly in analysis properties. That's why doing so is not documented.
Instead, you should enter exclusions through the UI.

Build dependencies and local builds with continuous integration

Our company currently uses TFS for source control and build server. Most of our projects are written in C/C++, but we also have some .NET projects and wouldn't want to be limited if we need to use other languages in the future.
We'd like to use Git for our source control and we're trying to understand what would be the best choice for a build server. We have started looking into TeamCity, but there are some issues we're having trouble with which will probably be relevant regardless of our choice of build server:
Build dependencies - We'd like to be able to control the build dependencies for each <project, branch>. For example, have <MyProj, feature_branch> depend on <InfraProj1, feature_branch> and <InfraProj2, master>.
From what we’ve seen, to do that we might need to use Gradle or something similar to build our projects instead of plain MSBuild. Is this correct? Are there simpler ways of achieving this?
Local builds - Obviously we'd like to be able to build projects locally as well. This becomes somewhat of a problem when project dependencies are introduced, as we need a way to reference these resources or copy them locally for the build to succeed. How is this usually solved?
I'd appreciate any input, but a sample setup which covers these issues will also be a great help.
IMHO both issues you mention fall really in the config management category, thus, as you say, unrelated to the build server choice.
A workspace for a project build (doesn't matter if centralized or local) should really contain all necessary resources for the build.
How can you achieve that? Have a project "metadata" git repo with a "content" file containing all your project components and their dependencies (each with its own git/other repo) and their exact versions - effectively tying them together coherently (you may find it useful to store other metadata in this component down the road as well, like component specific SCM info if using a mix of SCMs across the workspace).
A workspace pull wrapper script would first pull this metadata git repo, parse the content file and then pull all the other project components and their dependencies according with the content file info. Any build in such workspace would have all the parts it needs.
When time comes to modify either the code in a project component or the version of one of the dependencies you'll need to also update this content file in the metadata git repo to reflect the update and commit it - this is how your project makes progress coherently, as a whole.
Of course, actually managing dependencies is another matter. Tons of opinions out there, some even conflicting.

In an Xcode 4 workspace, how do I cascade build settings & configs to subprojects

Overview
I'm using static libraries and Xcode 4 workspaces to effect modularity in iOS development, an increasingly common technique. For example, I might have a workspace which contains an App project, and a Library project, like so1:
You would then have a scheme to build these that looked something like this:
What I would like to do is have the "App build" control the "Library build" it initiates, in at least a couple of ways:
Map App configurations (e.g. Debug, AdHoc) to arbitrary Library configurations
Passing through some subset of -D defines, and/or specifying these for the library build.
I'll deal with each of these in their own section, but it's worth making a few clarifications.
Clarifications
I'm using App/Library here as an easy proxy for any Superproject/Subproject relationship you may have.
From what I've seen, Xcode 3 style embedded subprojects don't seem to work any differently in Xcode 4 than workspace "peers". I'd love to be wrong about this.
I know I could do almost anything with a "Run Build Script" build phase, and xcodebuild. But I'm trying to work within the system here, where the dependencies are specified in the scheme, and otherwise somewhat loosely coupled.
The Library exists to be used in more than just this project, and so you cannot arbitrarily load it up with junk specific to this App's build, or reference anything particular to the App or Workspace. For the general case, this rules out including static .xcconfig from the App project as a way to convey build information from the App to the Library.
Building the Library outside the workspace sacrifices too much, not an option.
Configuration Mapping
As I understand it, building a particular App configuration will:
If a configuration exists in the Library of the same name, it will build the Library using that.
Otherwise, it will build the active configuration of the Library, as specified in the Library's project file.
To my knowledge, without resorting to the aforementioned run-build-script hack, that is the extent of the control one has over subproject build configurations. Please tell me different.
Ideally, I would be able to specify (in the scheme, presumably):
AppConfigA -> LibConfig1
AppConfigB -> LibConfig2
While Debug, AdHoc, & Release may be the only configurations some ever use, complex projects often outgrow that.
Defines
I've not yet found way to pass -D defines from the App build to the Library, without resorting to xcodebuild, which can take, e.g., an .xcconfig file.
The App's build settings can be accessed in Library build run-build-script phase. However, doing that introduces a dependency in the Library on the App project, which for good reason is verboten (cf. Clarifications). But even then, I haven't found a way to use those settings to directly control the Library's build (much2).
So crazy it just might...
One scheme I came up with while writing this would be:
The Library bases it's build configurations on an empty (dummy) LibraryExternals.xcconfig file within it's own project.
A clean of Library deletes that file. A standalone build of the Library will create an empty one if it does not already exist.
That file is overwritten by an App Build run-build-script phase, and contains anything the app wants to communicate to the Library build.
Seems kind of complicated, but I'm looking for anything right now. I'll push this to an answer if nothing better comes along.
1 Apps shown are Max OS X. I find command line apps make for simpler tests. Same applies.
2 Cf. Info.plist preprocessing, which I learned about during this investigation.
If you modify your project structure to use a single project with multiple targets then each target's build settings will automatically inherit from the project. From there, you can modify ones that you want to be different, or select an individual setting and press the delete key to set it to the default specified by the project.

Any pattern for using Maven to checkout/patch/build a non-maven based open source project?

I need to have a small patch applied to the sources of an open source project before we can use the library it generates. I'd like to automate this as much as possible, and am hoping to find some pattern that will let me:
check out the sources
apply my (very small) patch
build the project using it's build system (i.e., call ant)
Is there an example anywhere of doing something like this? Right now, I'm playing with the scm and patch plugins, but it's nothing simple...
I was actually able to do this in just a couple steps, using mvn:scm:export and mvn:patch.
Essentially, you have scm:export run during the generate-sources step, exporting to your ./src/main/java/ directory, then patch runs, then the rest of your pom.xml acts as normal.
I can post a sample, but it came out pretty simple... just took a lot of referencing of the manual.

How to work on a Cocoa app and plugins in parallel?

I have a relatively simple goal: I want to create a Cocoa application which doesn't have much functionality itself, but is extendable through plugins. In addition I want to work on a few plugins to supply users with real functionality (and working examples).
As I am planning to make the application and each plugin separate open-source projects (and Git repositories), I'm now searching for the best way to organize my files and the Xcode projects. I'm not very experienced with Xcode and right now I don't see a simple way to get it working without copying files after building.
This is the simple monolithic setup I used for development up until now:
There's only one Xcode project with multiple products:
The main application
A framework for plugin development
Several plugin bundles
What I'm searching for is a comfortable way to split these into several Xcode projects (one for the application and framework) and one for each plugin. As my application is still in an early stage of development, I'm still changing lots of things in both the application and the plugins. So what I mean by "comfortable" is, that I don't want to copy files manually or similar inconvenience.
What I need is that the plugin projects know where they can find the current development framework and the application needs to know where it can find the development plugins. The best would be something like a inter-project dependency, but I couldn't find a way to setup something like that in Xcode.
One possible solution I have in mind is to copy both (the plugins and the framework) in a "Copy Files Build Phase" to a known location, e.g. /tmp/development, so production and development files aren't mixed up.
I think that my solution would be enough, but I'm curious if there's a better way to achieve what I want. So any suggestions are welcome.
First, don't use a static "known location" like you mention. I've worked in this kind of project; it's a royal pain. As soon as you get to the point of needing a couple of different copies of the project around (for fixing bugs in parallel, for testing a "clean" build versus your latest changes, for working on multiple branches), the builds start trashing each other and you find yourself having to do completely clean/builds much more often than you'd want.
You can create inter-project dependencies by adding the dependent project (Add File), right click the Target and choose "Get Info," and then add a Direct Dependency on the General pane.
In terms of structure, you can either put the main app and framework together, or put them in separate projects. In either case, I recommend a directory tree like:
/MyProject
/Framework
/Application
/Plugins
/Plugin1
/Plugin2
Projects should then refer to each other by relative paths. This means you can easily work on multiple copies of the project in parallel.
You can also look at a top-level build script that changes into each directory and runs "xcodebuild". I dislike complex build scripts (we have one; it's called Xcode), but if all it does is call "xcodebuild" with parameters if needed, then a simple build script is useful.

Resources