Let me answer your two questions in reverse order.
Or, how is the intron GFF file usually produced?
In my experience, different feature types aren't typically stored in separate files--in other words, you don't have a CDS file, a UTR file, an intron file, etc, you simply have a single file with all the features in it. That doesn't mean your approach is incorrect, it just isn't typical and doesn't provide any immediate benefit (unless of course you are running scripts that have been built to expect it).
Is there a tool to generate the intron GFF according to these two files?
Perhaps, but it shouldn't be too difficult to do with minimal scripting experience. Once you have determined the exon coordinates using the CDS and UTR data, then simply create an intron feature to fill in the space between each adjacent pair of exon features.
Haibao mentioned the very useful GenomeTools utility, but to use that you would still first have to determine the exon coordinates and provide them as input. If you can calculate the exon coordinates from a set of CDS and UTR coordinates, then surely you can calculate intron coordinates from a set of exon coordinates.
Be careful with this approach though. If exon features are not explicitly defined, then gt will not create any intron features. I've made that mistake a few times.
Pretty encouraging. I will try it. Thanks!