Compiling sources is usually the first thing you want to do. Source packages for different versions are available from SourceForge.net.
Note that WinMerge uses MFC heavily. So free editions of Visual Studio cannot compile WinMerge, unless you have MFC installed separately.
Platform SDK components
With Feb 2003 Platform SDK (and VC6) following components are needed:
Project file for WinMerge executable (in /Src
) and other projects like
ShellExtension (in /ShellExtension
) have their own project files. There is no one
single project/workspace file to compile all projects.
Visual Studio project file for MSVC6 comes with WinMerge sources. Newer versions of Visual Studio can open that file too, they just ask if one wants to convert to new version. Reason we don't ship project files for all Visual Studio versions is we have no resources to keep all versions up to date. People can't test all versions themselves and easily forgot to update at least one file. So we easily end up in situation when there is no properly working project file at all...
After opening the project file you need to add HTML Help Workshop path as additional include- and library-path.
NOTE: There might be problems compiling/debugging with Visual Studio 2003 when using HTML Help WorkShop from Platform SDK in Visual Studio directory. Download and install HTML Workhop as stand-alone and include headers and libraries from standalone directory. Propable cause is that including files from Platform SDK directories breaks things.
There are several targets available for compiling different projects. Targets used
for compiling releases are:
WinMerge.exe
: ReleaseWinMergeU.exe
: UnicodeReleaseShellExtension.dll
: Release MinDependencyShellExtensionU.dll
: Unicode Release MinDependencyPlease follow these guidelines when submitting changes to WinMerge sources as patches.
Do not waste yours and ours time by submitting large feature patches before you have made sure the feature is wanted to WinMerge. Communicate with developers, either in bug/feature request(rfe) items or preferably in Developers-forum.
Post development intentions:
Before you start developing, make sure to capture a snapshot of your starting sources (presumably a pristine copy of sources from subversion, or of a source zip from a distribution).
DO NOT submit a patch against year-old version. Latest experimental/beta version is at max few weeks old. Stable releases should only get bug fixes. And even then bugfix is usually first applied to development versions. So there should be no reason to submit a patch against old version.
Review the sections on Coding conventions and Doxygen comments
Develop your new version.
Post your changes as a patch, to the SourceForge patch list. Try to give an informative patch title of course. Post to any relevant SourceForge bugs or RFEs, giving the patch number and title.
If the bug/rfe item is already assigned to you (or you submitted it), you can also attach patch into that item. Remember to add a comment so others notice the new attachment.
The active developers have often been posting entire original and modified files rather than traditional diffs, because obviously all developers have access to WinMerge to compare original and modified files, and this may be viewed as an infinite line context diff :)
HINT: If you have archive support installed in WinMerge you can do a folder
compare of your original and changed source trees. And then select Zip - Differences
from context menu and WinMerge creates a zip-file for you. Ready to be posted!
Wait for reactions from other developers (and sometimes active users).
Usually this means one of active developers approves your patch before commit.
After a reasonable amount of time has passed, and one of active developers has approved the patch, apply the patch to Subversion. (Or ask a project member to do so, if you don't have yourself developer access to the project.)
What is a reasonable amount of time? That is somewhat subjective, and we need to rely on your expertise as the patch developer, but let us suggest waiting a few days for minor patches, and at least a week for major patches.
Add a note in Src/Changes.txt
telling what files you committed,
and what bug/RFE/patch you solved. This is very important so everybody else
has a change to figure out who did what and when.
Note that Src/Changes.txt
was split from Src/readme.txt
after
2.4.0 release. So Src/readme.txt
contains older changelog entries. Also, many
subfolders have their own Changes.txt
-file. If the file exists in the folder, it must be
used instead of "global" Src/Changes.txt
.
Perry wrote a small program called MakePatchDirs, which helps in his patch process -- read the link for more information.
It is reasonable to post small snippets of code showing small changes directly in the text in bug postings, or patch postings. For example, see PATCH [ 824987 ] "Change binary-file detection (look only for zeros)", which gives the change directly in the text.
Note, however, that sourceforge trackers currently ignore tabs, so if you can convert tabs to spaces in your posting, it helps greatly.
Bugfixes may be treated less formally, especially for simple ones, or for fixes to code you know well -- eg, you caused the bug yourself with a recent patch :)
Consider still posting something to the tracker lists, even if it is simply a summary in English. If the fix is something like "misspelled variable name foo as fooz in many places", it is quite understandable that you prefer to just fix the instances rather than doing a full patch for it.
Please conform to the prevalent coding conventions. There are quite a number of files which originated elsewhere, and have their own coding conventions; please conform to the local one, in whichever files you are at work.
WinMerge itself uses Microsoft MFC style coding.
m_
.Crystal Text Editor (WinMerge/editlib/*
) and diffutils code (io.c
,
normal.c
, util.c
) use traditional Unix style coding.
analyze.c
should be in this format, but we have made a mess of it :(
We have adopted doxygen style as our desired commenting style for functions, classes, files, and so forth, in WinMerge code (this applies only to native WinMerge code, not imported files).
DiffThread.cpp
are fully doxygen commented (TODO: it would be better to give a
class example, if anyone knows a fully doxygen commented class).
docs/developers/doxygen.cfg
We have adopted the convention of using RCS id lines near the top of our source files (following the doxygen file header comments). Merely add these two lines to any new file you add to the repository, and cvs will modify the Id line by appending file version and date information at every checkin:
// RCS ID line follows -- this is updated by CVS // $Id$
Although we are now using Subversion, those lines are still useful. TortoiseSVN understands them and adds correct version number and author, as if it was checked out from CVS.
We are trying to keep a consistent numbering scheme on our file releases, so everybody can figure out what we have released by just looking at the release number. However, some of our older releases do not follow this scheme.
2.1.2.0 | | | | | | | `------- This number increases for each experimental, | | | and it is reset after each beta or major release. | | `--------- Denotes a beta release, an experimental release | | or a minor bug fix of a major release. | | even numbers means "stable" (i.e. a beta). | | odd numbers means "unstable" (i.e. an experimental). | `----------- Denotes a major release. | even numbers means "stable". | odd numbers means "unstable". `------------- Denotes a major release with major changes.
In this case:
And if we decide to rewrite most of the code, the next major release will have the number 3.0.0.0
On SourceForge there is some space to put in Release Notes and Change Notes. For experimental releases make sure to put in a note telling people that this is indeed experimental, so they should not expect everything to work perfectly. For beta builds we paste in all the changes since the last beta release, so that people can see exactly what changed. For major releases, we paste in the list of changes since the last major release, and this list can become very long.
We are using InnoSetup to make an installer for WinMerge. See readme-developers-InnoSetup.html for more information. Also zip-packages for releases are provided, zip up these files:
WinMerge.exe
and WinMergeU.exe
ShellExtension.dll
, ShellExtensionU.dll
, register.bat
and unregister.bat
to register/unregister it.filters/
directory (remember template file!)plugins/dlls/
directory. Create a MergePlugins/
directory and copy the plugins to it*.lang
files (currently we have 21 languages, counting both Chinese versions)Please remember to put the version number into both executables. You may use any of the following three methods at least.
Merge.rc
in the copy using
the MSVC6 resource editor, and compiling that (many releases have been made in this
manual, low-tech fashion).
Whatever method you use, please double-check the executable version numbers before uploading and releasing them.
Now that 2.4 release has translations for Shell Extension we must also carefully
version it. If we don't update version number installer won't install updated version.
There are no scripts or other tools to update version number, it must be done by hand
to ShellExtension.rc
file (make sure you update all four numbers!). Version numbers
follow the rule:
1.6.1.0 | | | | | | | `------- Not used - 0 (or your own build version?) | | `--------- Translation updates or other minor changes increase this by one | `----------- New features, bug fixes and other changes affecting to behavior | increase this number by one `------------- Denotes a major release with major changes.
Filenames in file releases follow this standard:
WinMerge-2.1.6.0-exe.zip
WinMerge-2.1.6.0-src.zip
WinMerge-2.1.6.0-Setup.exe
That is, dots are used only inside the version number and before the final extension.
When we make a release we always put a note in Src/Changes.txt
in SVN.
It is recommended to create a tag to repository when making a stable- or beta- releases. Although with subversion we have kind of tags for every commit (revision numbers) it is still a lot easier to handle and remeber them with human-readable names (R2_6_0) than with revision numbers (revision 3637 (not a real revision number!)). Experimental or other testing releases don't need tags since they are not intended for wide use and are usually just one-time snapshots.
The tag should follow the same numbering scheme as used above, with the dots replaced by underscores
and prefixed with an R
, so the example experimental above would have a tag named R2_1_3_0
,
the next beta would be named R2_1_4
, and the next major release would be named R2_2
.
WinMerge.exe
and WinMergeU.exe
are always compiled with the english resources.
Custom languages are in separate dll files with extension .lang
, to be placed in
Languages
subfolder in WinMerge folder. Language may be changed dynamically through the menu.
WinMerge localization is achieved through localization of resources (files with extension .rc
).
Actually there is only one rc file in the project, Merge.rc
. Localized versions for this file are
to be stored in the Languages/
directory, in the subdirectory created for that language.
Besides the resources files you could also translate things like the installer (the ISL files are just INI files) and the readme files.
The code must use resource strings for all messages, or displayed text (column title ...).
Strings ID: when applying a patch, you may define new strings (with as ID the first free ID). But probably you wrote your patch from an old version, and someone may have already inserted a patch for this ID. You need to adapt the ID in resource.h to avoid overlapping ID.
Strings order: that is really annoying with MSVC. It is important to keep the order of strings unchanged,
because merging rc files with WinMerge is then a lot easier. Strings are grouped in block according to their ID masked by 0xFFF0
.
So there are at most 16 strings in a block, but maybe less. MSVC reorders strings between and inside blocks, but never reorder blocks
(when a new blocks is created, MSVC always put it at the last position).
Typical method to merge strings in a Merge.rc
from a patch with a Merge.rc
in SVN :
resource.h
for ID, and Merge.rc
.resource.h
.Note: Blocks are not really ordered (there order comes from history), it is not a problem as MSVC never reorders blocks after creation. If you use another tool to change resources, please make sure that the blocks order is unchanged.
Localized resources must be updated regularly with new resources from Merge.rc
.
Older localized dll may crash with a recent version of WinMerge (missing dialogs). See below...
Please try to avoid changing dialog layout when translating.
The layout should be shared by all translations as much as possible, to make merging (and future translation changes) easier.
You can of course make controls wider to fit longer texts, but you should not move buttons and other controls if not really necessary.
If you want to improve dialog layout (we welcome UI improvements) you should submit it as src/Merge.rc patch so it will be merged to all translations.
CreateReviewPoFiles.vbs
With this VBScript file under the Src\Languages\
folder you can create gettext PO files to review the translations.
The script tries to collect all strings from the resource files and save the original and translated strings into PO files. For each language you will find the PO file under the language subfolder: Src\Languages\Language\LanguageReview.po
.
The script can take several minutes to finish!
If you have a PO file from your language, you could use a simple text editor or better poEdit to review the file:
#: IDD_PROPPAGE_LARGE.IDC_SINGLE_INSTANCE msgid "All&ow only one instance to run" msgstr "&Nur eine Programm-Instanz zulassen" #: IDD_PROPPAGE_LARGE.IDC_ASK_MULTIWINDOW_CLOSE #, fuzzy msgid "As&k when closing multiple windows" msgstr "As&k when closing multiple windows"
All unsure strings are marked as fuzzy (if you use a text editor search for the fuzzy
keyword).
The reference (the text after #:
) is a indication for the position in the resource file.
Search for the keywords (separated by .
) in the file MergeYourLanguage.rc
and you should find the untranslated string.
Do not edit the PO files! PO files are only for translation reviewing/checking and changes done to them are not applied to resource files.
The script should find most of the translations, but maybe not all.
So you should better search the .rc
file at the end by yourself for untranslated strings.
We have a customised tool for compiling language files. Project for it is in SVN:
/WinMerge/MakeResDll
When that project is compiled, it produces MakeResDll.exe
. Copy that executable
to /WinMerge/Src/Languages/
. In that directory there are already some batch-files
which can now be used to compile language files:
BuildAll.bat
/WinMerge/Src/Languages/
BuildDll.bat <lang>
CopyAll.bat
Compiled language files (*.lang
) are placed in /WinMerge/Build/Languages/
.
If MakeResDll does not work, and you wish to force it to use the compiler (resource compiler and linker)
of your choice, there are registry settings to accomplish this. Perry added these because he has been
unable to get MakeResDll link successfully using VS.NET 2003, due to it failing to find mspdb71.dll
at runtime. To force use of the
Visual C++ 6 binaries, assuming Visual C++ 6 is correctly installed, set
HKEY_CURRENT_USER\Software\Thingamahoochie\MakeResDll\Settings\VcVersion="6"
It is slow and tedious to update 21 languages for just one patch. But reducing the frequency of such updates does not help either: 5 small updates are tedious and frequent, but easy; 1 big update is more infrequent, but much more tedious and difficult.
Merging of layout: translator may change layout, then when developers insert new controls, moved and new controls may overlap. Visual check of 21 dialogs is definitively too long for a single patch update.
Delays in localization: translators generally need some weeks to translate, so their version is already outdated when the localization is complete, and merging with SVN must be done again.
Translators localize just betas or releases. They don't localize CVS or experimentals (they don't have to, they may if they will, then they do the merging themselves).
Patches: developers update the files : add new items, remove deleted ones, move moved items (controls going from one dialog to another one). No care of layout or visual check of dialogs. With such updates, languages dll are valid (no crash).
We may reduce this work to the languages used by experimental testers (and, for other languages, for the next beta/release, reapply together all patches since the last beta/release localization).
Good synchronization is required between developers and translators for the latest beta/release. For older versions, translators are free. The latest beta/release is the latest build which is either a beta or either a release.
Developers do not change resources for beta/release after their creation. Only localization/layout changes may be applied.
WinMerge of course, plus the plugin RCLocalizationHelper.dll
.
Most text/layout differences are ignored, so new/deleted/moved items appears clearly. Help to merge patches, and to merge a newly localized resource to its CVS version (apply the CVS changes to the newly localized resource). Contrary to a lot of (bad) localization tools, this method preserves the layout done by the translator. There are good localization tools however, and we will welcome with pleasure anyone with such a tool in the project.
Logs are a good tool for tracing errors. But logs must be first written. Its always a good habit to write error message to logfile also.
Simplest way to write errormessage to log is using
void LogErrorString(LPCTSTR sz)
defined in stdafx.h
. Another
way is to directly use gLog
which is global instance of
CLogFile
. Log is written to users temporary directory ($temp
) with name
WinMerge.log
.
Log writing is controlled by registry value:
HKEY_CURRENT_USER\Software\Thingamahoochie\WinMerge\Settings\Logging
Possible values are:
WinMerge sets executable path (WinMerge.exe
) which shellextension starts every
time when options-dialog is closed. This can cause problems when testing
several versions of WinMerge. There is registry value to overwrite path to
WinMerge executable:
HKEY_CURRENT_USER\Software\Thingamahoochie\WinMerge\PriExecutable
It does not exist by default, so create PriExecutable
as string value and type
path of WinMerge.exe
you mainly use as its value. If this value exists
ShellExtension does not care about another path value.
This is a bit tricky, and needs some patience to setup.
Needed tools
Starting Visual Studio and opening the project
We need to start Visual Studio from Platform SDK's 64-bit environment so that we get all
needed environment variables and paths correctly set. So:
devenv /USEENV (uses open environment)
ShellExtensionX64.vcproj
from ShellExtension
project
folder.Make sure you have 64-bit target selected in Project Settings. Then check that paths are OK. You MUST build to separate directory than 32-bit targets so that files don't mix up.
Compiling should now succeed. If not, check that all needed PSDK components are installed and that paths are OK. If you are compiling in 32-bit Windows you get error about registering but that is expected to happen.
64-bit ShellExtension is registered to 64-bit Windows just like counterparts in 32-bit world:
regsvr ShellExtensionX64.dll