I'm making a card game engine on top of libGDX for many similar games I plan to make. Here's how I plan to structure this: each game is a separate project and the engine is a dependency added to the core module. The engine itself will have a lot of assets like card sprites and other UI elements, and they need to be included too.
How can I make that structure work? Is there any way to make a dependency include its assets? The alternative is to duplicate all assets for each game which I don't think is very efficient. Also the assets are in the android module by default, which the engine dependency doesn't have (the engine is a single module). Where do I put the assets in the engine module?
We have a setup that seems similar to what you've outlined above with a "many to one" relationship of projects to assets. Here's a potential way to go about it.
The basic idea is:
Have a single, authoritative assets folder
Have individual projects copy this folder to their build output at build time
Accomplish this by having a project's compile task dependsOn or be finalizedBy a copy task.
Ensure that the Android and other projects are happy by copying the assets to the place that libgdx's internal File APIs look for that particular type of project. (For example, android projects automatically get an assets/ prepended to the URI provided to Gdx.files.internal(). This step is more dependent on your personal file structure, so it may take a little tweaking to get the pathing right for all projects, but don't get discouraged!
Side-note: Gradle should automatically track whether or not the assets dir actually changed. If nothing's been updated, then the copy tasks will effectively become no-ops, which speeds up the build quite a bit for non-first runs. Obviously if you do a cleanAssets like I mention below, then this won't apply.
The advantage of this approach (to me anyway) is that it no longer relies on cross-project links or funky classpath manipulation. It's just real files in real directories. The downside is that it increases the disk space used because there can be multiple physical copies of the assets in the various projects.
The following is not a complete example, but should hopefully give you enough to go by.
Example of a copy task in action. This particular one takes an assets dir from a "core" project and copies it into an android project.
android/build.gradle
task copyAssets(type: Copy) {
from "../core/assets"
into "./assets"
}
Example of how to make the android project's build depend on this task:
android/build.gradle
afterEvaluate { project ->
project.tasks.preDebugBuild {
dependsOn copyAssets
}
project.tasks.preReleaseBuild {
dependsOn cleanAssets
finalizedBy copyAssets
}
}
You'll notice in the preReleaseBuild I added a cleanAssets task as well. It's always a good idea to clean up any junk and do a fresh copy during a production build. cleanAssets is just a basic Delete task.
Example of a copy task dependency for a non-android project:
build {
finalizedBy copyAssets
}
If you're still stuck, let me know where and I'll try to help.
Do it like libgdx does itself. There are assets included in the classpath, like arial-15.fnt which is located in the core project at gdx/src/com/badlogic/gdx/utils/. Take a look at BitmapFont's no-param constructor how it is referenced.
Related
In gradle, what is the purpose of using a buildSrc file as a top level, as opposed to just a typical java project layout (src/main/java)?
If I have a layout of
src
main
java
or
buildSrc
src
main
java
What would be the difference (or the reason for doing this)? Is it more useful in multi module projects? Even for a multi module project, couldn't I do something like
proj1
src
proj2
src
And then just have a top level build.gradle (at the same level as proj1 and proj2) that defines common settings across the projects?
buildSrc is a separate build whose purpose is to build any tasks, plugins, or other classes which are intended to be used in build scripts of the main build, but don't have to be shared across builds.(*) It wouldn't be possible to build such classes as part of the main build, because they have to exist before the main build's build scripts can even be compiled/evaluated, and Gradle compiles/evaluates all build scripts before it does any work (configuration vs. execution phase).
Compared to putting all build code into build scripts, buildSrc gives you a way to develop build code more like regular code, as classes that you can test, import into your IDE, etc. It is one way to keep build scripts simple and DRY even for more complicated builds.
buildSrc is more often seen in multi-project builds simply because larger builds are more likely to implement their own custom tasks and plugins.
Over time, buildSrc will grow into a more general capability of executing multiple dependent builds in a single Gradle invocation.
(*) Sharing classes across builds is possible but more involved. In particular, you'll need to publish the classes to a repository, and consuming builds have to explicitly import them from there, similar to when sharing production libraries between builds.
In gradle, what is the purpose of using a buildSrc file as a top
level, as opposed to just a typical java project layout
(src/main/java)?
You can definitely do this. It is known as a composite build in gradle, but you have to tell Gradle to include any builds from that folder. A unique property of a top-level buildSrc folder is that gradle automatically treats it as an included build.
Note that even though buildSrc is treated as a composite build, it is not visible in the list of included builds when you run gradle.getIncludedBuilds(). I believe the reason is because the list is reserved for builds which you manually included in your settings.gradle.
For you to also include src/main/java as a composite build, you have to run your gradle script using the --include-build flag, followed by the path to src/main/java. This is an unusual place for an included build, but gradle won't complain.
And then just have a top level build.gradle (at the same level as
proj1 and proj2) that defines common settings across the projects?
You CAN have a top-level build.gradle at the same level as your proj1, and proj2 sub-projects. This is typically how most multi-project projects are structured.
As another answer already highlighted, the purpose of the buildSrc project is to create custom plugins or tasks which is meant to be shared locally among the different projects in your build. This is not to imply that you cannot create those custom tasks and plugins in your top-level build.gradle. You can do it this way, but the problem is that you will not be able to use it in any of your sub-projects.
Remember that being able to import something in java/groovy requires that thing to exist in a proper java/groovy file (or module for java 9+). Seeing as your build.gradle is simply a script, it is not arbitrary to simply import a plugin or task from it.
As I have already pointed out and this is from the Gradle docs, one of the reasons for having a buildSrc directory is:
Upon discovery of the directory, Gradle automatically compiles and
tests this code and puts it in the classpath of your build script.
As you can see, the buildSrc acts as an extension of your build process in that it can add additional functionality to all your project's build scripts.
A few more points:
Any dependencies declared in your buildSrc/build.gradle is visible to the rest of the build scripts in your project.
The buildscript block in your buildSrc/build.gradle is only visible to buildSrc/build.gradle and nothing else.
Any plugin class defined in buildSrc can be used in any build script in your project, and does not need to be declared in a META-INF/gradle-plugins.
Any dependencies defined in your main build.gradle or any of your subprojects is not visible in buildSrc. If you remember that this folder is treated as an included build (i.e. external), it should make sense why it cannot see the classpath of the project that includes it.
We are currently using the RazorGenerator library to generate pre-compiled views for a project. Up until now we have been using the Visual Studio Extension to handle the generation, with these generated files also being committed to our repository.
This is causing bit of a pain point as we constantly have to resolve merge defects in a generated file. With that in mind I've set about to try and integrate the RazorGenerator.MsBuild target library into our build process so we can get away from storing the code-genned files in our repository.
So far I've disabled the VS Extension, and got the build target working as required however I've now lost intellisense and resharper support for the generated files as they are no longer part of the Solution.
I'm wondering if anyone else has come down this path before, Ideally what I'm trying to achieve is using the Build target to generate the cs files, removing the need to include these cs files in the repository, and still having Intellisense/Resharper coverage for the generated files.
Any thoughts?
I've resolved this problem by creating a an empty partial class for each of the cshtml templates which implements our own base class, which in-turn implements RazorGenerator.Templating.RazorTemplateBase.
By doing it this way we have access to all the publicly accessible properties and methods exposed on those classes which makes intellisense/resharper happy and at build time the templates .cs files are generated which do the heavy lifting for outputting the layout etc.
I'm working on a project with two other developers that's built on FireBreath. So far, I've been able to get things working perfectly on my machine, but we need to coordinate our development via Mercurial. So I pushed my files to the repository and thought all was well.
Unfortunately, that doesn't work.
The various .vcproj files that make up the solution all contain hard-coded references to my local file system. This works fine for me, because I'm not moving the project around. But when you try to build the solution on another machine with a different file structure (different drive letter, different folder location, etc.) everything breaks.
I used FireBreath's standard project generation script (Python) and then the Visual Studio CMake script (prep2008.cmd) to generate the solution files. What can I do to tweak things so that other developers can use the same code base?
If your developers are not using the same build/make/project files, this could quickly become a maintenance nightmare. So you should definitively all use the same .vcproj files. (An exception to this would be if the project files were generated from some other files. In that case treat those other files in the way described above.)
there's two ways to deal with the problem of differing setups on different machines. One is to make all paths relative to the project's path. The other is to use environment variables to refer to files/tools/libraries/whatever. IME it's best to use relative paths for everything that can be checked out with the project, and use environment variables for the rest. Add a script that checks for the existence of all necessary environment variable, pointing out the meaning of any missing ones, and run this as a build prerequisite, so whoever tries to get a new build machine up and running gets hints at what to do.
To make sure that everyone caught the updated comments from sbi's answer, let me give you the "definitive" answer from the FireBreath devs.
Your build directory is disposable; you should never share .vcproj files. Instead, you should regenerate your build/ directory any time you change the project and on each new computer, just like any project that uses CMake.
For more information, see http://colonelpanic.net/2010/11/firebreath-tips-working-with-source-control/
For reference, I am the primary author of FireBreath and I wrote the article.
I'm not familiar with FireBreath, but you need to make the references relative, and then recreate that relative structure on every machine. That is, if your project sits in "c:\myprojects\thisproject" and has an additional include directory "c:\mydir\mylib\include", then the latter path needs to be replaced with "....\mydir\mylib\include".
EDIT: I rewrote my anyswer to make it clearer. When I got you correctly, your problem is that FireBreath generates those .vcproj files with absolute paths in it, and you want to use this .vcproj files on a different developer machine.
I see 3 options:
Live with it. That means, make sure, every team member has the same file structure / view to the file system, tools installed in the same place.
Ask the authors of FireBreath to change their .vcproj generator to allow relative paths, use of environment variables etc.
If 1 or 2 does not work, write a program or script for changing the absolute path to relatives in those .vcproj files. Run this script whenever you have to regenerate your FireBreath project.
What you should not do due to the FireBreath FAQ: don't change the .vcproj manually, those changes will be lost next time the project is regenerated.
EDIT: seems that "option 4." turned out to be the best solution: generating those .vcproj files for each developer individually. Hope my suggestions were helpful, either.
I'm currently looking at structuring my teams projects into a consistent manner that properly utilises packages and is easily version-controlled (via SVN).
I'm interested in any 'best practise' with regards to project structuring and how to use consistent packaging without lumping everything into a gigantic com.domainname.projects folder structure whilst maintaining that package structure. I'm also keen to use the src/bin/lib folder structure within each project.
I guess I'm asking 'how do you do it?' and 'why?'. Sorry if this is a bit abstract for Stack Overflow but you guys give the best answers I've found.
You might need to provide more information for a "complete" answer, like your shop size, number of active projects, how you build them, and how you reuse code.
Here are some insights anyway... hope I understood the direction of you question :)
If your projects are coupled and you release new versions of each reusable artifact frequently, a single svn repo keeping a folder for each should do it. Tag/branches should remain at the project level.
Having separate repos for code that is linked may become a maintainability headache.
Package1
src\com\domainname\Package1
source files
Package2
src\com\domainname\Package2
source files
Package3
src\com\domainname\Package3
source files
Lib
All packages export swcs into this folder
Problem with re-usability is going backwards -- sometimes changing something in the corelib will break all sorts of stuff going backwards, so I suggest doing running builds against it to create one large swc with all the packages in it.
I don't know why you're keen to use the bin\lib folder -- it makes more sense to have them point at things explicity rather than having parent projects export into children ...
I want to give credit to all open source libraries we use in our (commercial) application. I thought of showing a HTML page in our about dialog. Our build process uses ant and the third party libs are committed in svn.
What do you think is the best way of generating the HTML-Page?
Hard code the HTML-Page?
Switch dependency-management to apache-ivy and write some ant task to generate the html
Use maven-ant-tasks and write some ant task to generate the HTML
Use maven only to handle the dependencies and the HTML once, download them and commit them. The rest is done by the unchanged ant-scripts
Switch to maven2 (Hey boss, I want to switch to maven, in 1 month the build maybe work again...)
...
What elements should the about-dialog show?
Library name
Version
License
Author
Homepage
Changes made with link to source archive
...
Is there some best-practise-advice? Some good examples (applications having a nice about-dialog showing the dependencies)?
There are two different things you need to consider.
First, you may need to identify the licenses of the third-party code. This is often down with a THIRDPARTYLICENSE file. Sun Microsystems does this a lot. Look in the install directory for OpenOffice.org, for example. There are examples of .txt and .html versions of such files around.
Secondly, you may want to identify your dependencies in the About box in a brief way (and also refer to the file of license information). I would make sure the versions appear in the About box. One thing people want to quickly check for is an indication of whether the copy of your code they have needs to be replaced or updated because one of your library dependencies has a recently-disclosed bug or security vulnerability.
So I guess the other thing you want to include in the about box is a way for people to find your support site and any notices of importance to users of the particular version (whether or not you have a provision in your app for checking on-line for updates).
Ant task seems to be the best way. We do a similar thing in one of our projects. All the open source libraries are present in a specified folder. An Ant task reads the manifest of these libraries, versions and so on and generates an HTML, copies into another specified folder from where it is picked up by the web container.
Generating the page with each build would be wasteful if the libraries are not going to change often. Library versions may change, but the actual libraries don't. Easier to just create a HTML page would be the easiest way out, but that's one more maintenance head ache. Generate it once and include it with the package. The script can always be run again in case some changes are being made to the libraries (updating versions, adding new libraries).