How to manage thrift source file in version control? - version

We are currently exploring using thrift in our project. One of my question is how to handle the thrift source files and specific language generated files in version control (git) ?
Let's say I have project server A implemented using java, and project B an mobile application using Objective-C, and project C which is the thrift files. What currently on top of my mind is having all project as different git project, and project C as submodule of project A and project B. The pro is we can have consistent thrift source, and we don't need to put generated source files into git project.
Then let's say I have another thrift file that differs with project C, and being used only with project A and project D. Should I also put those files in project C? How project B knows that some files in project C not for him in case we put those files in project C?
Another approach might be committing the generated source files into each project. Or maybe another approach that I don't know.
Thanks!

Irrespective of the musings about whether to split the projects in your highly specific case into Git submodules or not, these are the general guidelines that apply to all kinds of generated code, including Thrift, but not limited to it.
General rules
The source documents (IDL, DSL, ...) belong into the repository.
Any code that can be easily generated out of these sources does not.
Exceptions
As with nearly every rule, there are exceptions. The exceptions come in various flavours, such as
the generated artifacts are not easily producable (for whatever reason)
the generated code needs hotfixes to work around bugs 1)
etc.
Additional notes
Strive to have one source, and one source only (of course not counting branches etc.) for these files. A good idea could be to set it up as a library to be used across projects. Treat that library like you would do with any other 3rdparty module, including proper versioning and all. If you use Git, indeed Git submodules may be an approach to achieve that.
Then let's say I have another thrift file that differs with project C
If it differs, it is either a entirely different IDL, or a different version of the IDL in question.
1) In the real world, such things may happen. Unfortunately.

Related

Cross-platform Library

Basically, I want to seperate some common functionality from existing projects into a seperate library project, but also allow a project to remain cross-platform when I include this library.
I should clarify that when I say "cross-platform" I'm primarily concerned with compiling for multiple CPU architectures (x86/x86_64/ARM).
I have a few useful functions which I use across many of my software projects. So I decided that it was bad practice to keep copying these source code files between projects, and that I should create a seperate library project from them.
I decided that a static library would suit my needs better than a shared library. However, it occurred to me that the static library would be plaform dependent, and by including it with my projects that would cause these projects to also be platform dependent. This is clearly a disadvantage over including the source code itself.
Two possible solutions occur to me:
Include a static library compiled for each platform.
Continue to include the source code.
I do have reservations about both of the above options. Option 1 seems overly complex/wasteful. Option 2 seems like bad practice, as it's possible for the "library" to be modified per project and become out-of-sync; especially if the library source code is stored in the same directory as all the other project source code.
I'd be really grateful for any suggestions on how to overcome this problem, or information on how anyone else has previously overcome this problem?
You could adopt the standard approach of open source project (even if your project is not open source). There would be one central point where one can obtain the source code, presumably under revision control (subversion, git...). Anyone who wishes to use the library should check out the source code, compile it (a Makefile or something similar should be included), and then they are all set. If someone needs to change something in the library, they do so, test their changes, and send you a patch so that you can apply the change to the project (or not, depending on your opinion on the patch).

Proper workspace organization for unit testing

I'd like to know what is the best way to organize your workspace and more specifically how to setup your unit-test projects (I use google framework) when working with a small group of people so my code:
Is easily portable
Doesn't need extra setup to be compiled by others
Is not dependant of a specific IDE or compiler
Real life example for clarity, even if I'd prefer general "good practices" :
I'm working as an intern this summer and we're making a communication protocol for 1 of our product. We're 3 people developping it with different IDE, OS and compilers. Right now the project is in a SVN repository with 1 folder having the project settings for our relative IDEs and another folder containing the source code.
This allows us to link the source code with relative paths to our projects so everyone can import where he pleases with his settings but the changes happen on the same .c and .h files for everyone when we commit. Is it an acceptable practice?
Also, I'm making the unit tests and right now :
Each module Foo has a separate FooTester project
Each FooTester has access to the .h files through a compiled static library
The internals are exposed via static libs
Is it the right way to do it? Making separate projects and linking the library "manually" seems to make it dependant on my personnal settings.

Maintain a separate branch for each platform

I'm trying to port my project to another platform and I've found a few differences between this new platform and the one I started on. I've seen the autotools package and configure scripts which are supposed to help with that, but I was wondering how feasible it would be to just have a separate branch for each new platform.
The only problem I see is how to do development on the target platform and then merge in changes to other branches without getting the platform-dependent changes. If there is a way to do that, it seems to me it'd be much cleaner.
Has anyone done this who can recommend/discourage this approach?
I would definitely discourage that approach.
You're just asking for trouble if you keep the same code in branches that can't be merged. It's going to be incredibly confusing to keep track of what changes have been applied to what branches and a nightmare should you forget to apply a change to one of your platform branches.
You didn't mention the language, but use the features available in the language to separate code differences between platforms, but using one branch. For example, in C++, you should first use file-based separation. For example, if you have sound code for Mac, Linux and Windows platforms, create a sound_mac.cpp, sound_windows.cpp and sound_linux.cpp file, each containing the same classes and methods, but containing very different platform-specific implementations. Obviously, you only add the appropriate file to the IDE on the particular platform. So, your Xcode project gets sound_mac.cpp file, while your Visual Studio project uses the sound_windows.cpp file. The files which reference those classes and methods will use #ifdef's to determine which headers to include.
You'll use a similar approach for things like installer scripts. You may have a different installer on the Mac than on Windows, but the files for both will be in the branch. Your build script on the Mac will simply utilize the Mac-specific installer files and ignore the Windows-specific files.
Keeping things in one branch and just ignoring what doesn't apply to the current platform allows you merge back and forth between topic branches and the master, making your life much more sane.
Branching to work out compatibility for a target platform is doable. Just be sure to separate out changes that don't have to do with the target platform specifically into another branch.

Which dependencies can be assumed to be installed on a build machine?

We have a project that is going to require linking against libcurl and libxml2, among other libraries. We seem to have essentially two strategies for managing these depencies:
Ask each developer to install those libraries under the "usual" locations, e.g. /usr/lib, or
Include the sources to these libraries under a dedicated folder in the project's source tree.
Approach 1 requires everyone to make sure those libraries are installed on their system, but appears to be the approach used by many open source projects. On such projects, the build will detect that those libraries are missing and will fail.
Approach 2 might make the project tree unmanageably large in some instances and make the compilation time much longer. In addition, this approach can obviously be taken too far. I wouldn't put the compiler under the project tree, for instance (right?).
What are the best practices wrt external dependencies? Can/should one require of every developer to have certain libraries installed to build the project? Or is considered better to include all the dependencies in the project tree?
Don't bother about their exact location in your code. Locating them should be handled by the used compiler/linker (or the user by setting variables) if they're common. For very uncommon dependencies (or ones with customized/modified files) you might want to include them in your source (if possible due to licensing etc.).
If you'd like it more convenient, you should use some script (e.g. configure or CMake) to setup/create the build files being used. CMake for example allows you to set different packages (libcurl and libxml2 in your example) as optional and required. When building the project it will try to locate those, if that fails it will ask the user. This IS an additional step and might make building a bit more cumbersome but it will also make downloading faster (smaller source) as well as updating easier (as all you have to do is rebuild your program).
So in general I'd follow approach 1, if there's special/rare/customized stuff being used, approach 2.
The normal way is to have the respective dependencies and have the developer install them. Later, if the project is packeted into .deb or .rpm, these packets will require the respective libraries to be installed, the source packets will have the -devel packets as dependencies.
Best practice is not to include the external libraries in your source tree - instead, include a text file called INSTALL in your project root, which gives instructions on building the project and includes a list of the library dependencies, including minimum versions.

Specify makefile location to link libraries

I recently stumbled upon this in a project I'm working on. In package A, there is a required configuration option --package-B-makefile-location from which A's makefile borrows variable values.
Is this a common design pattern which has merit? It seems to me that B's package source is as important as its binary for compiling A. Might there be reasons I wouldn't want to tamper with it?
Thanks,
Andrew
It is far from unheard of for one package to need other packages pre-installed, and you have to specify those locations.
For example, building GCC (4.5.2), you need to specify the locations of the GMP, MPFR and MPC libraries if they won't be found by default.
Complex systems which are extensible - Perl, Apache, Tcl/Tk, PHP - provide configuration data to their users in various ways (Config.pm for Perl, apxs for Apache, etc), but that configuration data is crucial to dependent modules.
My suspicion is that your Package A needs some of the configuration data related to Package B, but there isn't a fully-fledged system for providing it. As a workaround, Package A needs to see the configuration data encapsulated in the makefile.
It is not common to need the makefile; it is not uncommon to need some information about other packages.
It's a common and useful design pattern as far as it goes, but it can be abused like any other.
I'm not sure I understand the second part of your question, but if the makefiles are well designed then any change you make to B's makefiles which doesn't break B won't break A either.

Resources