Elsewhere (here on SO, for example) and even my own memory tells me that #error will cause compilation to terminate, but if I compile this:
#ifndef FOO
# error "FOO not defined."
#endif
int main() {
return "exit now!!";
}
I get:
g++ -Wall -o /dev/null main.cpp
main.cpp:2:4: error: #error "FOO not defined."
# error "FOO not defined."
^~~~~
main.cpp: In function 'int main()':
main.cpp:8:10: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
return "exit!!";
^~~~~~~~
This is for g++ versions 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4 20160609) and 7.0.0 (built myself 20161128). (There is a similar question asked here about MS Visual Studio 2015.)
According to the GNU CPP manual:
The directive ‘#error’ causes the preprocessor to report a fatal error. The tokens forming the rest of the line following ‘#error’ are used as the error message.
So, perhaps I just don't know what a "fatal error" is. The gcc option -Wfatal-errors would imply that a fatal error is one that would cause compilation to terminate, but nothing in the manuals ever defines it (unless I missed it). An answer to this question, however, is a bit more guarded and says that:
[#error] renders the translation unit ill-formed (i.e., it causes compilation to fail)
which I don't read as saying the same thing as saying compilation terminates at that point.
So, is this behaviour of gcc correct?
"Error" and "fatal error" were not separate categories in gcc until fairly recently. People would say "fatal error" just to make sure you understood that the compilation would not produce the expected object file. "warning" and "error" were always separate, but that wasn't obvious to everyone. You might think a warning is a type of error if you weren't told otherwise.
I don't know whether there was ever a version of gcc that actually terminated immediately after the #error, but I doubt it. It's possible that in the era when cpp was actually a separate program, it would have terminated at the end of the preprocessing phase without calling the compiler proper; that would have resulted in less error messages. (But not when -pipe was used to run them simultaneously!)
You could report a bug against the cpp manual. It's using "fatal error" in a way that is no longer consistent with the use of the term in the rest of the gcc manual.
Related
I am trying to build a dll in C++ in which I use a C dll with prototypes like :
int __stdcall foo();.
When linking, the compiler outputs:
Warning: resolving _foo#0 by linking to _foo
Use --enable-stdcall-fixup to disable these warnings
so I added the option when linking, the command looks like:
g++ -std=c++0x -o fooLib.dll fooObj.o -lfooClib --enable-stdcall-fixup -shared
but seems like the g++ doesn't know this option:
g++.exe: error: unrecognized option '--enable-stdcall-fixup'
when I am adding only -enable-stdcall-fixup (one hyphen), it still shows the warnings (looks like has the option has no effect), and the ouput is kind weird:
g++ -std=c++0x -o fooLib.dll fooObj.o -lfooClib -enable-stdcall-fixup -shared
Warning: resolving _foo#0 by linking to _foo
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups
ld.exe: warning: cannot find entry symbol nable-stdcall-fixup; defaulting to 679c1000
so does any body know what I am doing wrong ?
g++ --version
g++ (GCC) 4.6.1
Indeed, --enable-stdcall-fixup is not a g++ option. It's a linker option, and you can find it in the ld(1) manpage:
--enable-stdcall-fixup
--disable-stdcall-fixup
If the link finds a symbol that it cannot resolve, it will attempt
to do "fuzzy linking" by looking for another defined symbol that
differs only in the format of the symbol name (cdecl vs stdcall)
and will resolve that symbol by linking to the match. For example,
the undefined symbol "_foo" might be linked to the function
"_foo#12", or the undefined symbol "_bar#16" might be linked to the
function "_bar". When the linker does this, it prints a warning,
since it normally should have failed to link, but sometimes import
libraries generated from third-party dlls may need this feature to
be usable. If you specify --enable-stdcall-fixup, this feature is
fully enabled and warnings are not printed. If you specify
--disable-stdcall-fixup, this feature is disabled and such
mismatches are considered to be errors. [This option is specific
to the i386 PE targeted port of the linker]
gcc is able to recognize some common linker options and pass them on to ld. For example, gcc passes the -llibrary options used to link in library code directly to the linker, as well as an option -e which will be relevant below. Whenever this is the case, it's documented in the gcc(1) manpage.
As you've discovered, this is not the case with --enable-stdcall-fixup, so you'll need to explicitly pass it. In order to pass arbitrary options to the linker, gcc has -Wl. From gcc(1):
-Wl,option
Pass option as an option to the linker. [...]
So in your case, you would call
g++ -Wl,--enable-stdcall-fixup [...]
I don't have the version of the linker mentioned in the manpage, so it still comes up as an unrecognized option for me. But on your system, given that the linker is telling you to use the option, I can only assume it is the version that recognizes it.
As an aside, when you tried calling the option with only one dash, you ran into a red herring. You were actually invoking the -e gcc option that I mentioned above, with the option argument nable-stdcall-fixup. From gcc(1):
-e entry
--entry=entry
Specify that the program entry point is entry. The argument is
interpreted by the linker; the GNU linker accepts either a symbol
name or an address.
So you actually ended up passing an option to the linker saying that, when you execute your program, you want it to begin execution from a function named nable-stdcall-fixup instead of the usual main.
First of all, please read ---PS--- part. This problem is my misunderstanding.
I'm using ubuntu18.04 OS and intel fortran compiler of "parallel studio xe 2020 update 4" ifort.
I have tried to generate dependency among fortran source files using the ifort compiler with the -gen-dep option.
The following simple code was written for my test. The filename is "main.f90".
program main
use mod_a
implicit none
end program main
I executed following command to generate dependency of "main.f90".
ifort -gen-dep -syntax-only main.f90
As a result, I got following error message.
main.f90(2): エラー #7002: コンパイル済みモジュールファイルを開くときのエラーです。INCLUDE パスを確認してください。 [MOD_A]
use mod_a
--------^
The error message notifies that "mod_a.mod" file does not existed yet (while it is written in Japanese).
In the case the "mod_a.mod" has already been generated with compiling mod_a.f90, I got the following "true dependency" with executing above command.
main.o : \
main.f90 mod_a.mod
How can I generate dependency without generating mod_a.mod?
If it exist that the additional ifort options to achieve my goal, I want to know the options with priority.
Thank you for reading.
---PS---
I appologize to everyone who has read this post.
This problem is my misunderstanding.
I tried compiling my "main.f90" program again with ifort -gen-dep -syntax-only main.f90.
program main
use mod_a
implicit none
end program main
As a result, I got following error message and "true dependency".
main.f90(2): エラー #7002: コンパイル済みモジュールファイルを開くときのエラーです。INCLUDE パスを確認してください。 [MOD_A]
use mod_a
--------^
main.o : \
main.f90 mod_a.mod
I don't know why I didn't see this "true dependency", but my goal was already achieved.
However, additionally, I found a another probrem and solved it.
In the case that "main.f90" has huge code which use many subroutines, functions, variables, etc...
ifort -gen-dep -syntax-only main.f90 returned
fatal error: too many errors emitted, stopping now
and didn't return dependency.
To solve this problem, I added the -no-diag-error-limit to ifort command.
You need to supply information about mod_a.
Either compile it beforehand or supply it to the ifort -gen-dep command as such
$ ifort -gen-dep -syntax-only main.f90 mod_a.f90
main.o : \
main.f90 mod_a.mod
mod_a.mod : \
mod_a.f90
mod_a.o : \
mod_a.f90
I have used the C code from the following verbatim: https://wiki.tcl-lang.org/page/Hello+World+as+a+C+extension
/*
* hello.c -- A minimal Tcl C extension.
*/
#include <tcl.h>
static int
Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
return TCL_OK;
}
/*
* Hello_Init -- Called when Tcl loads your extension.
*/
int DLLEXPORT
Hello_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
return TCL_OK;
}
My command for compiling is nearly verbatim except for the last character, indicating Tcl version 8.6 rather than 8.4, and it compiles without error:
gcc -shared -o hello.dll -DUSE_TCL_STUBS -I$TCLINC -L$TCLLIB -ltclstub86
Then I created the following Tcl program:
load hello.dll Hello
puts "got here"
But when running it with tclsh get the following error:
cannot find symbol "Hello_Init"
while executing
"load ./hello.dll Hello"
(file "hello.tcl" line 1)
So I am essentially following a couple of suggestions from Donal Fellows answer here: cannot find symbol "Embeddedrcall_Init" The OP there however commented that, like me, the suggestion(s) hadn't resolved their issue. One thing that I didn't try from that answer was "You should have an exported (extern "C") function symbol in your library" -- could that be the difference maker? Shouldn't it have been in the example all along then?
At the suggestion of somebody on comp.lang.tcl I found "DLL Export Viewer" but when I run it against the DLL it reports 0 functions found :( What am I doing wrong?
Could it be an issue with MinGW/gcc on Windows, and I need to bite the bullet and do this with Visual Studio? That's overkill I'd like to avoid if possible.
The core of the problem is that your function Hello_Init is not ending up in the global symbol table exported by the resulting DLL. (Some linkers would put such things in as _Hello_Init instead of Hello_Init; Tcl adapts to them transparently.) The symbol must be there for Tcl's load command to work: without it, there's simply no consistent way to tell your extension code what the Tcl_Interp context handle is (which allows it to make commands, variables, etc.)
(If you'd been working with C++, one of the possible problem is a missing extern "C" whose actual meaning is to turn off name mangling. That's probably not the problem here.)
Since you are on Windows — going by the symbols in your DLL, such as EnterCriticalSection and GetLastError — the problem is probably linked to exactly how you are linking. I'm guessing that Tcl is defining your function to have __declspec(dllexport) (assuming you've not defined STATIC_BUILD, which absolutely should not be used when building a DLL) and yet that's not getting respected. Assuming you're using a modern-enough version of GCC… which you probably are.
I'm also going through the process of how to build tcl extensions in C and had exactly the same problem when working though this same example using tcl 8.6.
i.e. I was compiling using MinGW GCC (64-bit), and used the following:
gcc -shared -o hello.dll -DUSE_TCL_STUBS "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\lib" -ltclstub86
And like the OP I got no compile error, but when loading the dll at a tclsh prompt tcl complained :
'cannot find symbol "Hello_Init"'
I can't say that I understand, but I was able to find a solution that works thanks to some trial and error, and some information on the tcl wiki here
https://wiki.tcl-lang.org/page/Building+Tcl+DLL%27s+for+Windows
In my case I had to adjust the compiler statement to the following
gcc -shared -o hello.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Obviously those file paths are specific to my system, but basically
I had to add an explicit reference to the .c file
I had to include the tcl86t dll library from the tcl bin directory
I had to remove the -DUSE_TCL_STUBS flag ( meaning that the references -LC:\\ActiveTcl\\lib and -ltclstub86 could also be removed)
(attempting to use the -DUSE_TCL_STUBS flag caused the compiler to complain with C:\ActiveTcl\lib/tclstub86.lib: error adding symbols: File format not recognized )
This successfully compiled a dll that I could load, and then call the hello function to print my 'Hello World' message.
Something else I stumbled over, and which wasn't immediately obvious:
reading https://www.tcl.tk/man/tcl8.6/TclCmd/load.htm, tcl epxects to find an 'init' function based on a certain naming convention.
if the C extension does not define a package name then the name of that init function will be derived from the dll filename.
This caused a few problems for me (when compiling via Eclipse IDE), as the dll name was being automatically determined from the eclipse projet name.
For example, if I recompile the same example, but call the .dll something else, eg.
gcc -shared -o helloWorldExenstion.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Then at tclsh prompt:
% load helloWorldExtension
cannot find symbol "Helloworldextension_Init"
I'm trying to abort compilation if an unsupported fortran compiler is used. The nagfor preprocessor defines the macro NAGFOR, so I wrote the following test program:
program foo
implicit none
#ifdef NAGFOR
PRINT *, "Hello from nagfor"
#else
#error "Compiler not supported"
#endif
end program foo
When I compile with gfortran or ifort, I get the expected error message
$ gfortran foo.F90
foo.F90:8:2: error: #error "Compiler not supported"
$ ifort foo.F90
foo.F90(8): #error: "Compiler not supported"
but nagfor gives a different error
$ nagfor foo.F90
NAG Fortran Compiler Release 5.3.1(907)
"foo.F90", line 8: error: unknown fpp directive.
I can't find any mention of how to create an error in the nagfor fpp documentation so maybe #error doesn't exist. In which case, is there an alternative approach to get the same effect?
I work on the NAG Compiler. fpp is intended to be pretty lightweight in terms of operation (and functionality). It originates from Sun; we are using a version based on the netlib one from http://netlib.org/fortran/fdfpp.tgz.
The fpp manual (http://www.nag.co.uk/nagware/np/r60_doc/fpp.html) does not document #error as being supported, which you have discovered.
As francescalus suggests, the best way to acheive what you want would be with something along the lines of
program foo
implicit none
#ifdef NAGFOR
PRINT *, "Hello from nagfor"
#else
error "Compiler not supported"
#endif
end program foo
I have turned on the ld option --fatal-warning in the linux kernel. How can I generate a simple linker warning to test this feature?
#include<stdio.h>
int main()
{
printf("Run !!");
static const char warning[] __attribute__((section(".gnu.warning.printf")))="My sweet linker warning";
return 0;
}
Save this as test.c
If you build this using:
gcc -Wl,--fatal-warnings test.c -o my_exe
You should receive your linker warning and it would not prepare "my_exe"
Now try:
gcc -Wl,--no-fatal-warnings test.c -o my_exe
In this case, warning will be reported as it is but it wont be treated as error and it will prepare "my_exe" for you.
I am not sure what exactly you meant by "turned on", but if you are seeing above behavior then I guess you are good.
If you are doing something with kernel source then you will need to replace printf with any function name you already have in source( also change .gnu.warning section name )
Thank you all for your suggestions. I went through the makefile, and found some linker flags that were suppressing warnings. I just removed them to generate ld warnings.