Setting the source file character encoding for Mono's xbuild - character-encoding

I'm generating C# source code which is being built by both VS2010 and Mono's xbuild (2.10.2.0). This generally works very well, I've only had a single compatibility issue so far, and in that case I was using a 'feature' that is clearly specified as undefined behaviour (so mea culpa).
Now I'm running into an issue where I have special characters in a string literal in the C# source code. I'm generating the source files in UTF-8, the character I'm testing with is a German sharp s: 0xC39F. This is written to a file in latin1 by the code, where it ends up as 0xDF when the executable is built with VS (that's the one I want) and as 0xC33F when built with xbuild.
It does not seem to matter whether I run the executable with the .NET or with the Mono CLR, as far as I can see.
My current suspicion is that xbuild is not reading the source code as UTF-8, so the compiled code already has the wrong character in the string literal. Is there a way to explicitly tell it to? I couldn't find anything on xbuild /? and the xbuild documentation isn't particularly comprehensive. If I just missed the right page where this is documented, just a link is sufficient, of course.
All experiments have been performed on Win7 x64.
EDIT 1: To clarify, I've used a hex editor to confirm that the character in the source code file is really 0xC39F, the character written when compiled with VS2010 is 0xDF and the character written when compiled with xbuild is 0xC33F.

You'll need to modify the .csproj file(s) and add a <CodePage> element to the <PropertyGroup> section.
You should be able to use Visual Studio or MonoDevelop to do this for you, as well.
In MonoDevelop, if you right-click on a project and select the "Options" menu item, you can then go to the Build/General section and there will be a "Compiler Code Page" field which you can use to select "UTF-8".
FWIW, this is what MD outputs when I select UTF-8:
<CodePage>65001</CodePage>
So you can just copy/paste that into the <PropertyGroup>

Related

Compiling projects with DCC32 as in Delphi 6 professional IDE

IDE: Delphi 6 Professional.
We have big projects.
I cannot use Project Groups to build them all, because I got OM errors, and strange file errors when I did it.
My idea was that I will use DCC32.exe
Priorly I had a fight with the command line parameters (dcc32.cfg), but it I thought I solved it...
Today I tried to compile projects with it, but at first project I got errors.
chdir c:\d\anyproject
dcc32 -b any.dpr
The error reported me that it wasn't found a unit. I tried to compile in Delphi, and it was successful.
So I checked the problem. Why the previous project buildings were successful, and why this wasn't...?
Then I realized that this dpr is using references to a subdirectory, but not all files added to the project, more of them are linked by project's "search path".
But if it's true, then this meaning that DCC32 ISN'T USING THE PROJECT'S DOF/CFG FILES!
So the problem is that Delphi merges everything to provide the result.
It merges the global search paths, the project's compiler directives, the searching paths, so everything, and using the project's conditional directives too.
If I understand it well, the DCC32 don't use, only the dcc32.cfg, and I must merge everything for the compilation, what is an impossible job, because I need to write a parser what is interprets the project's parameters, and merges with globals.
Or I misunderstand something, and the problem is caused by other thing what I missed?
I waiting for your suggestions!
Thanks for all idea, link, info, etc.
dcc32 options from the following places:
A dcc32.cfg file. This can be either in the current directory, or the same directory as dcc32.exe.
The command line.
The source code.
I have order these in order of increasing precedence. So, an option specified in source code always overrides settings made a dcc32.cfg file, or on the command line.
dcc32.exe will choose whichever dcc32.cfg file it finds first. It looks in the current directory first.
What all this means is that you are responsible for getting the settings from the .dof file, and from the IDE into your command line compilation environment.
This is one of the many reasons why you should upgrade. Modern Delphi versions use msbuild for command line compilation and make it trivially easy to be sure that your command line builds are the same as IDE builds.
When you watch an msbuild in progress you will see that it results in a call to dcc32.exe with all options specified on the command line. Transforming the project settings into a call to dcc32.exe is what you are now faced with. In Delphi 6 you have to do that yourself. In modern Delphi, the tools are part of the product.
This might help:
http://delphi.wikia.com/wiki/Compile_from_Commandline
It describes how to do commanline compiles with Delphi versions from Delphi 1 to XE3 and also links to the tool dof2cfg which you might find helpful.
IIRC the command line compiler always uses a configuration file named dcc32.cfg found either in the current folder or where dcc32.exe resides. You may try to rename or copy your .cfg file to dcc32.cfg and see if that solves your problem.

Change encoding on a per file or per extension basis

I'm using Microsoft Visual Studio Express 2012 for Web. It seems that every file which I open with it gets encoded into UTF-8. For most files which are going to be web-facing, that's fine. However, I have files in my projects that are specifically for build purposes (e.g., .bat files), which must be encoded in ANSI.
Are there any configuration settings in VS to either designate on a per file or a per extension basis the encoding? Or, if not specify the encoding, at least disable the auto-conversion to UTF-8?
Open the problematic file in Visual Studio and...
On the File menu, click Advanced Save Options.
In the Encoding dropdown, select Unicode (UTF-8 … or the encoding you require.
Click OK.
Also see:
how to change source file encoding in csharp project (visual studio / msbuild machine)?
An option to handle the encoding of all files of a given extension on a per open basis can be configured in the Options dialog. See MSDN page on Options, Text Editor, File Extension.
Navigate to Tools > Options > Text Editor > File Extension.
For the bat extension, I selected Source Code (Text) Editor with Encoding. The with Encoding part means that the user will be given options as to what encoding to use when opening the file. The default in this mode is Auto-detect, which preserves the ANSI encoding, if that is what the file already uses. Otherwise, one can explicitly designate it for the individual file.
Unfortunately, it doesn't seem to remember the setting last used when opening a file, and will thus prompt for an encoding setting every time a file is opened.
I had code conversion problems width VS studio 2012 as well. Namely, I had non ansi compliant characters in strings ind my .js files and unreadable was outputted to the browsers html page.
I figured out that accept script files (like .js) VS 2012 creates all files in UTF-8.
*The problem is with the suggestion bellow to change the defaults in the options dialog resulted in that the syntax highlighting and intelisense stopped working in all .js files.*
So my workaround solution know is that I convert my .js files with notepad++ to utf-8 without BOM.
In this way my "unusual" chars are appearing well in browsers and the intelisense is working fine as well.

Compiler Directive error in Delphi 2005

Iam using Delphi 2005 and i have included a unit to the main unit using compiler directive i.e.{$I sample.pas} whenever I try to build the main pas file I get the below error . F 1026 File not found and it shows the path where the sample.pas file is available. I tried different options like tried adding the path of the pas file in the project options- search path and also in the tools-options -library path and it doesnt work. I googled it and found a solution which says to do the following:
In the IDE from the main menu, navigate to
“Tools|Options|Environment Options|Compiling and Running”
switch “Show Commandline” ON
AND set sure you have “Verbosity” set to “Diagnostic”.
The problem is Iam using Delphi 2005 and unable to find the “Verbosity” option in Delphi 2005. It would be great if some one can help me
In Delphi 2009 it is right under the Show Commandline setting:
However, unfortunately for you the verbosity option isn't present in D2006, so I guess it was introduced in either 2007 or 2009.
Oh, and as far as the include directive goes: if your sample pas isn't in the same folder as the unit in which it is included, you could try adding the path to the $I directive:
{$I ..\..\General\sample.pas}
Put the file in the same folder as your project units, and change its extension to ".inc" ( not mandatory but I think that by convention directives files are named like this).
A possible solution could be to get the code working in a package and then have the package keep that part of things compiled. I have been able to use include files in other paths with packages, but it is quite tempermental. It can start rejecting them even with packages for reasons I don't know. This is indeed a VERY annoying problem.
You might also look into doing your builds via your own batch files where you can take full control of the command-line settings that are being used.

Delphi Compile and Build produce different binary on same project

In a fresh VCL application Compile and Build operation produce the same binary and map file (with minor differences at the end of .exe file even if "include version information in project" option is switched off - already discussed). Map file is the same byte to byte. But wen I add any third-party component the binary and map(!) file produced by Build and Compile are significantly different!
Tested on two versions of Delphi:
- Version 7.0 (Build 8.1)
- CodeGear™ RAD Studio 2007 Version 11.0.2902.10471 (+December 2007 Update)
Step to reproduce:
Create New VCL Application. Possibly add any native Delphi component (I try all components from Standart, Additional, Win32 and System tab).
Turn on Detailed Map file on Linker tab of the Project Options.
Build project.
Rename output .exe and .map file (for example: project1.exe to project1b.exe and project1.map to project1b.map).
Compile project.
Rename output .exe and .map file (for example: project1.exe to project1c.exe and project1.map to project1c.map).
Compare files from step 4 and 6. (I use WinMerge
2.12.4.0).
We have little different .exe files and fully identical .map files. Then if we repeat all steps again but use in the project third-party component (I try ODAC, DOA, DevExpress and selfmade) we get more different .exe and different .map files.
Why? Any suggestions?
UPDATE
Some information about how I found this and why it's interests me:
Project is build from simple script with MSBuild. When in the project was added translation thru ITE (dll with resources) I found that when project was Build (from script or from IDE) - translated version work wrong - some text on button, labels etc. got from wrong place (literally from another button, labels). When project Compiled from IDE - everything is ok. So I start compare Build and Compile output...
What you're seeing is simply an artifact of the built-in make logic of the compiler. When you do a build, it tells the compiler to build all available sources. So Delphi processes each source file and for each unit in the uses lists for which it finds source, it will then build that file. It does this recursively. When you do a compile, only the existing .dcu files are loaded and if they're found to be up-to-date, nothing is done. This can actually lead to a different order in which the units are discovered since each .dcu will effectively "flatten" the uses list. Since the units are discovered and loaded in a different order, they are in-turn, linked in a different order. This is why your map files look so different. Given the same sources, the map file should be the same if you do two builds in a row or two compiles in a row.
Other causes for differences are more mundane and include things like the PE header time stamp, and other bits of padding and alignments.
There is two parts to this answer I believe.
Part of the problem your seeing, IIRC, is that the compiler doesn't zero out memory before doing a compile/build. Thus anything left in uninitialized memory becomes filler in the output for alignment purposes.
I also seem to recall that there is a date time stamp included in the pe header information for the application. that will cause a difference every time.
I'm not the best person to confirm this but this is what I seem to recall from past discussions.
People like Allen Bauer or Barry Kelly would probably be able to give better/more accurate information on this.
If you use compiler defines in your project and just changed those, if you do a compile, you won't see any changes to the dcu's and the resulting module (exe or dll). If you do a full rebuild the compiler defines are used in the newly created dcu's and modules.
I have seen this in a large project group where we use modules in different projects with different defines and all dcu's are stored in the same directory.
Ergo: The compiler does not enforce the dependancies on the defines in this case.
Perhaps you did see the same issue.

delphi 2007 command line compiler dcc32.cfg problem

I'm using the command line compiler for builds. One problem I see is that the paths mentioned there seem to need to be the short versions of the filenames such that they don't contain any spaces. I don't know so much about this even though I have used it for some time.
I recently upgraded to d2009 and the problem started then.
Is there a way around shortening the path?
I should say I'm not eager to change to use the MS Build tool at this time. I just want to build an old copy of my app & get back to other work.
Here's the path used in the dcc32.cfg file for the -I, -U, -O, and -R parameters:
$(BDS)\LIB;$(BDS)\Imports;$(BDS)\Lib\Indy10;C:\PROGRA~1\Borland\BDS\4.0\RAVERE~1\Lib;c:\prj\lib\lib2002;C:\DOCUME~1\ALLUSE~1\DOCUME~1\RADSTU~1\5.0\Bpl;c:\DOCUME~1\mike\MYDOCU~1\BORLAN~1\bpl;C:\Prj\Lib\LOCKBO~1\source;C:\Prj\Lib\MyComp;C:\Prj\Lib\ABBREV~1\source;C:\Prj\Lib\ZLib;C:\Prj\Lib\MinMod;C:\Prj\Lib\HELPMA~1;C:\Prj\Lib\DXGETT~1;c:\windows\system32;c:\prj\lib\xpburn;C:\Prj\Lib\WININE~1;C:\Prj\Lib\regexpr\Source;C:\Prj\Lib\VCARDR~1;C:\PROGRA~1\Raize\RC4\Lib\BDS2006;C:\Prj\Lib\jcl\lib\d10;C:\Prj\Lib\jcl\source;C:\Prj\Lib\jvcl\lib\D10;C:\Prj\Lib\jvcl\common;C:\Prj\Lib\jvcl\RESOUR~1;C:\Prj\Lib\ProE6\Delphi;C:\Prj\Lib\FastMM4;C:\Prj\Lib\OPENOF~1;C:\Prj\Lib\DEVELO~1\Library\Delphi11;C:\Prj\Lib\DEVELO~1\EX38D9~1\Sources;C:\Prj\Lib\DEVELO~1\EXBD88~1\Sources;C:\Prj\Lib\DEVELO~1\XPTHEM~1\Sources;C:\Prj\Lib\DEVELO~1\EX2EBC~1\Sources;C:\Prj\Lib\DEVELO~1\EXC5FB~1\Sources;C:\Prj\Lib\DEVELO~1\EX7C7C~1\Sources;C:\Prj\Lib\DEVELO~1\EXPRES~3\Sources;C:\Prj\Lib\DEVELO~1\EXPRES~4\Sources;C:\Prj\Lib\DEVELO~1\EXC73B~1\Sources;C:\Prj\Lib\DEVELO~1\EX7165~1\Sources;C:\Prj\Lib\DEVELO~1\EXPRES~2\Sources;C:\Prj\Lib\DEVELO~1\EXPRES~1\Sources;C:\Prj\Lib\DEVELO~1\EX749C~1\Sources;C:\Prj\Lib\DEVELO~1\EX0A1A~1\Sources;C:\Prj\Lib\Mad\madBasic\BDS4;C:\Prj\Lib\Mad\MADDIS~1\BDS4;C:\Prj\Lib\Mad\MADEXC~1\BDS4;C:\Prj\Lib\Mad\MADKER~1\BDS4;C:\Prj\Lib\Mad\MADSEC~1\BDS4;C:\Prj\Lib\Mad\madShell\BDS4;C:\Prj\Lib\Mad\madShell\DeXter;C:\Prj\Lib\Mad\madExcept\..\Plugins;
I've copied it from the IDE's path like I have done in the path and used a program to shorten the path names.
Although there are no spaces in that path, it still can't find indy's IdCoder.dcu at C:\Program Files\CodeGear\RAD Studio\5.0\lib\Indy10
According to the d2007 environment variables, $(BDS) would apparently expand to c:\program files\codegear\rad studio\5.0
The IDE is considering this library path to be valid.
Why is this happening? I bet it's a simple mistake I haven't thought of!
Thank you for your help!
You could try to put the paths in quotes, that's the standard way of handling path-/filenames with spaces in Windows, though I never tried that in Delphi DCUs.
So, instead of
$(BDS)\Lib\Indy10
try
"$(BDS)\Lib\Indy10"
You could also try
"C:\Program Files\CodeGear\RAD Studio\5.0\lib\Indy10"
to check if the environment variable is correct.
Although .cfg files do still work in the Delphi 2007 command line compiler, you should really be using MSBuild to compile your projects. CFG files are not used by the IDE anymore. Any compiler options you set design time do not get written to the .cfg file. Using MSBuild is not harder then using .cfg. And if you want it is even more flexible since you can change the actual build processes.
msbuild YourProject.dproj
Delphi actually will give you the command line needed in the output tab when you do a compile or build.
Build your project normally in Delphi.
At the bottom there will be a tab called "Output", Look for a line that says "Target CoreCompile" (in D2007 - may be different in other versions). The line below that will be the command line used to build your project (This is what you want). Btw - you do not have to wait for your project to complete building, you can hit cancel before it finishes because all you need is that DCC32 command line call. Also, if you had done previous compiles you may want to right click and clear the output before building so you do not have a lot of "noise".
Click on that line to highlight it, then right click the line and choose copy.
Open an empty batch file and paste. (warning,the line may be very long)
Now, go to the start of that line and if your path to the DCC32 compiler includes a space, then you will need to put quotes around the DCC32 call, don't put the quotes around the parameters.
Insert a line above the DCC32 call and enter dos commands to set the directory to the directory where your dpr file is, otherwise DCC32 will say it cannot find your project. For example.
G:
then
cd \Apps\MyProject
Save the batch file and you are ready to go.
Is the $(BDS) environment variable set when you're compiling the program from the command-line? If not, that might be the problem.
Putting quotes around paths containing spaces will likely solve the problem with spaces. This has worked for me:
-U"C:\Path to libraries\First library;C:\Path to libraries\Second library;C:\Path to libraries\Third library"
Check if you have applicationname.cfg file in the current folder. Dcc32 will try to read configuration from that file first. Only if the file does not exist will it read from dcc32.cfg.

Resources