We got a large framework written in Fortran fixed format (*.f) files - where we have a lot of __FILE__ and __LINE__ to print errors, warnings etc at run time. We have so far only used ifort and there has been no problem using the -fpp flag for the macros used.
Now we are looking to use gfortran by GNU and the problem has emerged where the macros __FILE__ and __LINE__ and many line do exceed the 72 column limit for the fixed format. We think gfortran with cpp prints the entire path to the file when using __FILE__, which quite easily can make the 72 column limit easily exceeded.
The one option we have tried is to use -ffixed-line-length-none which seems to overcome the latter issue but in turn create the following problem
Error: Expected expression at (1) in PARAMETER statement
mkl_vsl.f90:711:72:
mkl_vsl is the MKL VSL library by intel and line 711 looks like this:
PARAMETER (VSL_RNG_METHOD_EXPONENTIAL_ICDF_ACCURATE= &
&IOR(VSL_RNG_METHOD_EXPONENTIAL_ICDF,VSL_RNG_METHOD_ACCURACY_FLAG))
Is there a way to truncate __FILE__ so it only prints the filename rather than the entire path?
Related
I am trying to migrate a .FOR file (for practice purposes) from ifort to gfortran. This file compiles in my Intel Visual Fortran solution with no issues. However when I compile it in gfortran using the following command:
gfortran -ffree-form -ffree-line-length-200 -Dinternal_debug -c MyFile.FOR -o MyFile.o
I get the following error message:
MyFile.FOR:4561:22:
102 format(A, I)
1
Error: Nonnegative width required in format string at (1)
Does ifort simply not require there to be a format width or are there additional ifort options that enable relaxing this requirement? How come the file runs smoothly in ifort but not in gfortran?
Your observation is correct, I have encountered this myself before. Intel Fortran does not enforce this requirement while gfortran does. The field width is actually required by the Fortran standard. I am not aware of any compiler option that could change this behaviour. The only option I am aware of is to fix the code to make it standard compliant.
How to do it can be found in Error: Nonnegative width required in format string at (1) . Note that the g0 that you asked about is not a compiler option to accept I. It is a different format descriptor to put into the code instead of I.
How can I stringify a preprocessor macro with GNU gfortran? I would like to pass a macro definition to GNU gfortran which will then be used as a string in the code.
Effectively I would like to do this:
program test
implicit none
character (len=:), allocatable :: astring
astring = MYMACRO
write (*, *) astring
end program test
and then build with:
gfortran -DMYMACRO=hello test.F90
I tried creating various macro, for example:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
...
astring = STRINGIFY(MYMACRO)
but this doesn't work with the gfortran preprocessor.
I also tried using a different style of macro:
#define STRINGIFY(x) "x"
...
astring = STRINGIFY(MYMACRO)
but this just creates a string containing the text 'MYMACRO'.
I then tried changing the macro definition to:
-DMYMACRO=\"hello\"
but this caused unrelated problem in the build process.
Thank you for your help
Your attempt to use the well-known stringification recipe of the C preprocessor,
viz:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
fails for two reasons, each sufficient by itself.
First and simplest, the source file in which you attempt to employ it apparently
has the extension .f90. What this extension signifies to gfortran (and to
the GCC compiler driver, by any other name) is: Free form Fortran source code that should not be preprocessed.
Similarly .f95, .f03 and .f08. If you want gfortran to infer that a source
file contains free form Fortran code that must be preprocessed, give it one of
the extensions .F90, .F95, .F03 or .F08. See the GCC documentation of
these points
Even if you do that simple thing, however, the second reason bites.
The use of the C preprocessor to preprocess Fortran source is as old as C
(which though old, is much younger than Fortran). gfortran is obliged not
to break ancient working code; so, when it invokes the C preprocessor,
it invokes it in traditional mode. The traditional mode of the C preprocessor
is the way in which the preprocessor behaved prior to the first standardization
of the C language (1989), insofar as that unstandardized behaviour can be pinned down. In traditional
mode, the preprocessor does not recognize the stringizing operator '#', which was
introduced by the first C Standard. You can verify this by invoking the preprocessor
directly like:
cpp -traditional test.c
where test.c contains some attempt to employ the stringification recipe. The
attempt fails.
You cannot coax gfortran on its own to work the the stringification recipe.
But there is a workaround. You can invoke cpp directly, unencumbered by traditional mode,
to preprocess the Fortran source in which you want the stringification done and relay its
output to gfortran. If you already know this and were looking for a gfortran-alone
solution you need read no further.
Doing the stringification in your test source this way would look like:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' '-DMYMACRO=STRINGIFY(hello)' test.f90
The output of that is:
# 1 "test.f90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.f90"
program test
implicit none
character (len=:), allocatable :: astring
astring = "hello"
write (*, *) astring
end program test
And that output is what you want to to compile. You could accomplish that as well by:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 > /tmp/test.f90 \
&& gfortran -o test /tmp/test.f90
Then you will find that ./test exists and that executing it outputs hello.
You can eliminate the intermediate temporary file with further refinement. Your F90 source
code will compile as F95, as the latter is conservative of the former. So you can take
advantage of the fact that GCC will compile source piped to its standard input if
you tell it what language you are piping, using its -x language option. The
Fortran dialects that you may specify in this way are f77, f77-cpp-input, f95
and f95-cpp-input, where the -cpp-input prefix denotes that
the source is to be preprocessed and its absence denotes that it is not. Thus
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' test.f90 | gfortran -x f95 -o test -
works as well as the previous solution, minus the temporary file, and emits
the innocuous warning:
Warning: Reading file '<stdin>' as free form
(Note and retain the final - on the commandline. That is what tells gfortran to
compile the standard input.). The meaning of -x f95 brings the additional
economy that the source, which is preprocessed by cpp, is not preprocessed
again by the compiler.
The use of the option -std=c89 when invoking cpp calls for a cautionary
explanation. It has the effect of making cpp conform to the earliest C Standard.
That is as close to -traditional as we can get while still availing of the
#-operator, on which the stringification recipe depends, But with it you embrace
the possibility of breaking some Fortran code if you preprocess it this way;
otherwise gfortran itself would not enforce -traditional. In the case of
your test program, you could safely omit -std=c89, allowing cpp to conform
to the default C standard when it was built. But if you permit it or direct it
to conform to -std=c99 or later, then the standard will mandate recognition
of // as the beginning of a one-line comment (as per C++), by which any line
of Fortran that contains the concatenation operator will be truncated at the
first occurrence.
Naturally, if you use are using make or another build system to build the
code in which you want the stringified macros, you will have a way of telling
the build system what actions constitute compiling a given class of compilable
files. For any Fortran source file fsrc you wanted to compile with
a stringification preamble, the actions to specify would be in the vein:
cpp -std=c89 '-DSTRINGIFY_(x)=#x' '-DSTRINGIFY(x)=STRINGIFY_(x)' \
'-DMYMACRO=STRINGIFY(hello)' fsrc.f90 | gfortran -x f95 -c -o fsrc.o -
Although this is an old and answered question, I wanted to achieve macro stringification in gfortran without changing the default preprocessor or build process. I found that the preprocessor would do what I want, as long as there was no initial quotation mark on the line, therefore the desired stringification can be achieved by breaking lines with ampersands:
astring = "&
&MYMACRO"
A caveat is that this really only works with the traditional preprocessor, and for examples breaks with intel ifort compiler, which is too smart to fall for this trick. My current solution is to define separate stringification macros for gfortran as:
#ifdef __GFORTRAN__
# define STRINGIFY_START(X) "&
# define STRINGIFY_END(X) &X"
#else /* default stringification */
# define STRINGIFY_(X) #X
# define STRINGIFY_START(X) &
# define STRINGIFY_END(X) STRINGIFY_(X)
#endif
program test
implicit none
character (len=:), allocatable :: astring
astring = STRINGIFY_START(MYMACRO)
STRINGIFY_END(MYMACRO)
write (*, *) astring
end program test
It looks really ugly, but it does get the job done.
Removing the quotes around x in STRINGIFY solved the problem for me:
#define STRINGIFY(x) x ! No quotes here
program test
implicit none
character (len=:), allocatable :: astring
astring = STRINGIFY(MYMACRO)
write(*,*), astring
end program test
Compiled with
gfortran -cpp -DMYMACRO=\"hello\" test.f90
The -cpp option enables the preprocessor for all extensions.
I am trying to compile some Fortran code that, according to the documentation, is known to compile with "Intel Fortran Compiler 11." However, when I try to compile the code using the version of ifort that comes with Intel® Fortran Composer XE 2013 for OS X (here: http://software.intel.com/en-us/fortran-compilers), I get a number of errors. I suspect that I'm either 1) using a compiler that's incompatible with the exact dialect of Fortran used and/or 2) failing to include some necessary libraries.
I'm not a Fortran programmer, so I'm hoping that someone with more experience will be able to glance at the code and recognize if it's just a simple matter of using a different compiler, setting some compiler options, including some specific libraries, or if I'm missing something else altogether.
The full source code can be found just above the Contents here: http://baydeltaoffice.water.ca.gov/modeling/deltamodeling/models/dsm2/dsm2.cfm
To start with, I'm just trying to compile groups.f in /DSM2_v8_0_6_src/dsm2_v8_0/src/common (which requires that a few other modules be compiled first), but the eventual goal is to compile DSM2_v8_0_6_src/dsm2_v8_0/src/ptm/native/fixedData.f and all of its dependencies.
The syntax I'm using follows this basic pattern:
ifort -c DSM2_v8_0_6_src/dsm2_v8_0/src/common/groups.f
To get a sense of the types of errors I'm encountering, here are a couple of types that occur repeatedly:
groups.f(225): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of:
( * ) :: , . % + - [ : . ** / // .LT. < .LE. <= .EQ. == ...
write(unit_error,*)"Error in matching text pattern:",trim(pattern)
---------------------------------------------------------------------^
groups.f(265): error #5120: Unterminated character constant
& "Error in pattern matching. Implementation count does not equal count in NumberMatches"
------^
Could be F77 or F90 depending on how you have done the formatting. Stack oveflow fomatting requires 4 spaces to start the code. On the line 225, is it indented by 6 or not indented at all. If it is indented by 6 and line 265 is indented by 5 then it is F77.
The other question is whether leading spaces have been stripped when moving from one machine to another. If that is the case then they need to be re-inserted.
On the first line with an error, check the line terminations. All lines should end with either CR LF or just LF. If there is a mix, the compiler will throw a wobbly.
If it is F77, try renaming the files with a .f extension to a .for extension. ifort will then definitely pick them up as f77.
In case this might help point somebody with a similar problem in the right direction, after doing some digging I was able to determine that the code was originally compiled using Visual Studio with the compiler option FixedFormLineLength="fixedLength132". So, using ifort from the command line, I can compile using the following basic pattern (omitting all of the include paths, etc., for clarity):
ifort -c -132 DSM2_v8_0_6_src/dsm2_v8_0/src/common/groups.f
As for the dialect, I later heard from the provider that the code was mostly written in Fortran 77, with some parts later revised to Fortran 90.
First some background - I have three VS2010 C++/OpenCL projects that compile and run fine on Windows 7 64-bit. I've been trying to compile and run each of them on Linux 64-bit (Ubuntu/Debian). The first two are compiling and running on linux and don't really use any external libraries. The third uses only Boost 1.50.0 and isn't compiling using the same method as the first two. So first let me go through what I did to get the first two to work.
I extracted only the source from the myriad of folders.
I ported windows specific code to linux specific code.
I wrote a bash script to generate the g++ command with all sources to compile them.
I ran the compile script to generate an output target file.
The bash script is as follows.
#!/bin/bash
SOURCE=""
for i in `ls *.h *.cpp *.hpp`; do
SOURCE+="${i} "
done
COMMAND="g++ -I/home/junkie/downloads/boost_1_51_0 -o out ${SOURCE} -L/opt/AMDAPP/lib/x86_64/ -I/opt/AMDAPP/include -lOpenCL -fpermissive"
echo -e "\n"
echo -e "${COMMAND}"
echo -e "\n"
$COMMAND
exit $?
And it generates and runs a command similar to following.
g++ -I/home/junkie/downloads/boost_1_51_0 -o out blah.cpp blah.h foo.hpp baz.cpp etc.cpp -L/opt/AMDAPP/lib/x86_64/ -I/opt/AMDAPP/include -lOpenCL -fpermissive
I compile using the following command.
./compile.sh &> log; echo $?; grep -ci error log; wc -l log
Now you may be wondering why I've adopted such unconventional and redundant means of getting a C++ project to compile and run on linux. Well because I'm new to the linux c and c++ toolchain and this was the quickest and simplest route I could figure out to get the job done and it did get the first two projects up and running. However, the third uses boost and this method isn't working and I need your help in figuring out what all these strange errors are.
The errors I'm getting are not actually from the project code but instead from Boost and AMD's opencl libraries code which is strange because the other projects were using opencl too and those worked fine.
Some examples of boost errors are below.
foo.hpp:2331:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
In file included from main.cpp:4:
foo2.hpp:1610:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: variable or field ‘BOOST_PP_CAT_I’ declared void /home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp: At global scope:
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: variable or field ‘BOOST_PP_CAT_I’ declared void
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘;’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘;’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected unqualified-id at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
/home/junkie/downloads/boost_1_51_0/boost/preprocessor/cat.hpp:22: error: expected ‘}’ at end of input
foo.hpp:2331:1: error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
Some examples of opencl errors are below.
In file included from /opt/AMDAPP/include/CL/cl_platform.h:35,
from /opt/AMDAPP/include/CL/cl.h:30,
from bar.h:7,
from fooGPU.hpp:6,
from main.cpp:4:
/usr/include/stdint.h:49: error: expected ‘;’ before ‘typedef’
In file included from /opt/AMDAPP/include/CL/cl.h:30,
from bar.h:7,
from fooGPU.hpp:6,
from main.cpp:4:
/opt/AMDAPP/include/CL/cl_platform.h:41: error: expected unqualified-id before string constant
main.cpp:136: error: expected ‘}’ at end of input
main.cpp:136: error: expected unqualified-id at end of input
main.cpp:136: error: expected ‘}’ at end of input
main.cpp:136: error: expected ‘}’ at end of input
The boost includes I'm Using are as follows.
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/punctuation/comma.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
So, finally, my questions are as follows.
1) What is the root cause of these errors in light of the building method I'm using and how do I resolve this problem? Does order of files or library inclusion matter? I'm using a local source download of boost as part of my g++ command as instructed by boost documentation rather than prebuilt binaries as I'm not using anything that requires prebuilt binaries.
2) I realise that my way of building things is pretty primitive. I'm learning make and I've seen some recommendations to use cmake and kdevelop which I need to look into. The primary problem with using make is that these projects weren't written with make in mind so I'm not aware of the dependency graph between source files to create the makefile (if I'm thinking correctly; I'm still fairly new to it). If you have any recommendations of how to do things better please do enlighten me.
Thanks.
I finally managed to overcome this problem and here I provide a brief account of how. To be clear I don't know what the root cause of the original problem was. In other words - I don't know why the problem occurred. All I'm saying is that my workaround allowed me to resolve the issue and move onto other problems (compile time errors).
Essentially, to reiterate, the problem was that for whatever reason a project using boost wasn't compiling on Linux because all instances of the use of the BOOST_PP_CAT() function produced the following error.
error: unterminated argument list invoking macro "BOOST_PP_CAT_I"
For whatever reason the compiler wasn't able to correctly process the use of this function but was able to process the use of other boost functions such as BOOST_PP_LPAREN(), BOOST_PP_RPAREN() and BOOST_PP_COMMA. The problem looked almost certainly related to the preprocessing stage where the combined use of the aforementioned boost functions was resulting in an unterminated argument list.
To elaborate on the nature of the relevant code (which was not written by me thankfully) the prior developers had essentially used boost preprocessor functions to create a DSL that they could then re-use multiple times to generate a list of functions. It would have seemed a lot easier to me to simply write the functions directly but anyway that's another concern.
My work around was to change the relevant section of code so that it didn't use any BOOST_PP_CAT() functions but ultimately defined the exact same functions as before. I did this by substituting the use of BOOST_PP_CAT() with the code that was being generated by it. This overcame all instances of the error quoted above but left me with hundreds of other compile time errors in my efforts to migrate this project from windows to linux.
Although this was a very specific and unusual question with an equally specific and unusual answer I wanted to feed this back to dispel the mystery behind this problem. As to why this particular function was failing to preprocess/compile on linux but passing on Windows I don't know but would very much like to know. I can only assume it is a fundamental difference in the way VC++ performs preprocessing as opposed to g++ and clang or more specifically perhaps a difference in the order of resolution of nested functions in preprocessor directives. Who knows. Anyway, thanks for your help guys.
The unterminated argument list invoking macro error suggests a lacking closing parenthesis. Use your editor's parenthesis matcher to check it. Be sure that your source files are in Unix format, not in DOS format (e.g. with \n à la Unix, not with\r\n à la MSDOS, at each end-of-line). Use dos2unix if needed.
Otherwise, don't forget that you can run g++ -Wall -C -E -H -I/home/junkie/downloads/boost_1_51_0 yoursourcecode.cc to get the preprocessed form of yoursourcecode.cc, and, by redirecting that command, you can inspect that preprocessed form with the editor of your choice (like emacs).
As I commented, learn to use Gnu make (and if in trouble debugging your Makefile, which you should edit with a good editor like emacs, use remake -x to debug it).
And the -I/home/junkie/downloads/boost_1_51_0 looks very suspicious: even if Boost is often a header only library, it has, as far as I remember, an installation procedure on Unix (and Linux distributions often package Boost libs). You should install your Boost libraries as documented (and after having configured them), and likewise for OpenCL.
I'm trying to compile a UTF-16BE C++ source file in g++ with -finput-charset compiler option but I'm always getting a bunch of errors. More details follow.
My environment(in CentOS Linux):
g++: 4.1.2
iconv: 2.5
Linux language(in Terminal): LANG="en_US.UTF-8"
My sample source file(stored in UTF-16BE encoding):
// main.cpp:
#include <iostream>
int main()
{
std::cout << "Hello, UTF-16" << std::endl;
return 0;
}
My steps:
I read the manual of g++ about the -finput-charset option. The g++ manual says:
-finput-charset=charset
Set the input character set, used for translation from the character set of the input file to the source character set used by
GCC. If the locale does not specify, or GCC cannot get this
information from the locale, the default is UTF-8. This can be
overridden by either the locale or this command line option.
Currently the command line option takes precedence if there’s a
conflict. charset can be any encoding supported by the system’s
"iconv" library routine.
Thus I entered the command as follows:
g++ -finput-charset=UTF-16BE main.cpp
and I got these errors:
In file included from main.cpp:1:
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1:
error: stray ‘\342’ in program
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1:
error: stray ‘\274’ in program
...(repeatedly, A LOT, around 4000+)...
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/iostream:1:
error: stray ‘\257’ in program
main.cpp: In function ‘int main()’:
main.cpp:5: error: ‘cout’ is not a member of ‘std’
main.cpp:5: error: ‘endl’ is not a member of ‘std’
The manual text suggests that the charset can be any encoding supported by 'iconv' routine, thus I guessed the compilation errors might be caused by my iconv library. I then tested the iconv:
iconv --from-code=UTF-16BE --to-code=UTF-8 --output=main_utf8.cpp main.cpp
A "main_utf8.cpp" file is generated as expected. I then tried to compile it:
g++ -finput-charset=UTF-8 main_utf8.cpp
Note that I specified the input-charset explicitly to see if I did anything wrong, but this time a "a.out" was generated without any errors. When I ran it, it could produce the correct output.
Finally...
I couldn't figure out where I did wrong. I searched in the web trying to find out some examples for this compiler option but I couldn't.
Please advise! Thanks!
Further edits:
Thanks, guys! Your replies are quick! Some updates:
When I said "UTF-16" I meant "UTF-16 + BOM". In fact I used UTF-16BE. I have updated the text above.
Some answers say the errors are caused by the non-UTF-16 header files. Here are my thoughts if this is the case: We'll always include some standard header files when writing a C/C++ project, right? Such as stdio.h or iostream. If the G++ compiler only deals with the encoding of the source files created by us but never with the source files in the standard library, then what does this -finput-charset option exist for??
Final edit:
At last, my solution is like this:
At the beginning, I changed the encoding of my source files to GB2312, as "Mr Lister" said below. This worked fine for a while, but later I found it not suitable for my situation because most of the other parts in the system still use UTF-8 for communication and interfaces, thus I must convert the encoding in many places... Not only an overhead of my work, it may also result in some performance decrease in my program.
Later I tried to convert all my source files to UTF-8 + BOM. In this way, Visual Studio in Windows could compile them happily but GCC in Linux would complain. I then wrote a shell script to remove the BOM, and before I want to compile my code with GCC, I run this script first.
Luckily, I don't have to build the code in Linux manually because TeamCity the continuous integration tool is used in my project to generate the build automatically. I could change the build steps in TeamCity to help me run this script before the daily build starts.
With this UTF-8 + BOM + script method, I decide not to edit my source code in Linux, because if I want to do so, I must make sure my code could build successfully before I commit it, which means I must run the script to remove the BOM before I build the code, which means SVN would report EVERY file is modified(BOM removed) thus make it very easy to mistakenly commit a wrong file. To solve this problem, I wrote another shell script to add the BOM back to the source files. Though I still don't edit my code very often in Linux, but when I really need to, I don't have to face the terribly long change list in the commit dialog.
Encoding Blues
You cannot use UTF-16 for source code files; because the header you are including, <iostream>, is not UTF-16-encoded. As #include includes the files verbatim, this means that you suddenly have an UTF-16-encoded file with a large chunk (approximately 4k, apparently) of invalid data.
There is almost no good reason to ever use UTF-16 for anything, so this is just as well.
Edit: Regarding problems with encoding support: The OSes themselves are not responsible for providing encoding support, this comes down to the compilers used.
g++ on Windows supports absolutely all of the same encodings as g++ on Linux, because it's the same program, unless whatever version of g++ you are using on Windows relies on a deeply broken iconv library.
Inspect your toolchain and ensure that all your tools are in working order.
As an alternative; don't use Chinese in the source files, but write them in English, using English-language literals, or simple TOKEN_STYLE_PLACEHOLDERs, using l10n and i18n to replace these in the running executable.
Threedit: -finput-charset is almost certainly a holdover from the days of codepages and other nonsense of the kind; however; an ISO-8859-n file will almost always be compatible with UTF-8 standard headers, however, see the reedit below.
Reedit: For next time; remember a simple mantra: "N'DUUH!"; "Never Don't Use UTF-8!"
I18N
A common solution to this kind of problem is to remove the problem entirely, by way of, for instance, gettext.
When using gettext, you usually end up with a function loc(char *) that abstracts away most of the translation tool specific code. So, instead of
#include <iostream>
int main () {
std::cout << "瓜田李下" << std::endl;
}
you would have
#include <iostream>
#include "translation.h"
int main () {
std::cout << loc("DEEPER_MEANING") << std::endl;
}
and, in zh.po:
msgid DEEPER_MEANING
msgstr "瓜田李下"
Of course, you could also then have a en.po:
msgid DEEPER_MEANING
msgstr "Still waters run deep"
This can be expanded upon, and the gettext package has tools for expansion of strings with variables and such, or you could use printf, to account for different grammars.
The Third Option
Instead of having to deal with multiple compilers with different requirements for file encodings, file endings, byte order marks, and other problems of the kind; it is possible to cross-compile using MinGW or similar tools.
This option requires some setup, but may very well reduce future overhead and headaches.
The error message says the problem is in the include files, so I presume what happens is that the include files are normal UTF-8, but the compiler wants to treat them as UTF-16 because of the compiler switch.
So I'm afraid the solution is to always convert the source to UTF-8 first; perhaps in the makefile. Or to find a solution that doesn't contain include files in other encodings...
Edit:
Maybe a GB encoding would work, if and only if none of the system source files contain any non-ASCII characters. Then you could tell the compiler they were GB encoded without problem.
This does not work because the compiler will also try to read the header files as UTF-16, which they are not.
UTF-16 is not an encoding for bytes. It's an encoding where your basic storage unit is 16 bits large.
When you want to store UTF-16 in a byte sequence you have to choose between UTF-16BE and UTF-16LE.