Issue on adding werror flag - c

I am trying to add warning as error flag in my makefiles. But I am getting the following problem.
When I am compiling without adding the flag it is successful. But when I am adding Werror flag in some ".mk" files, compilation is failing with some error. But in the successful build log warning was not there for that source file(".c") which is throwing error now(Werror).
I am adding he following flags.
UN_CDEFS := -Wno-error=%
CDEFS := -Wall -Werror -Wextra
SUB_CDEFS := -Wall -Werror -Wextra
So please suggest what might be the problem.

Caveat: This isn't a complete answer because we need more information, but it would become [too] lengthy for more top comments like the ones I've already posted.
As you refine the problem and/or post more data, I can edit this answer accordingly. At a minimum, posting your actual makefiles might help, as well as, the actual final cc commands and the compiler warning/error output for the failing .c file [There may be multiple ones, but the single/first one should be sufficient].
Below are some detailed instructions on how to debug this, based on my own experience with such issues.
But, before I get to that, I'll hazard a guess. I notice that you're doing:
CDEFS := -Wall -Werror
[leaving off the -Wextra as you mentioned in a comment].
If this is done as [nearly] the first thing in the makefile, it's fine. However, if it occurs in the middle, you are replacing CDEFS with your own value. If a prior line in the makefile did (e.g.):
CDEFS = -Dwont_build_cleanly_without_this_option
then, when you add your line, that could be the issue, because this gets [effectively] removed. You might try this instead:
CDEFS += -Wall -Werror
This just appends to the existing symbol, so any prior value will be retained.
Also, the base makefile might have something like:
ifndef CDEFS
CDEFS := -Dwont_build_cleanly_without_this_option
endif
Normally, make will output the full text of commands it executes to create targets. For compilation, this is (e.g.) cc -c foo.c.
Some fancier builds wrap the command in (e.g.) #doit cc -c foo.c where doit prints a message like compiling foo.c ... and only outputs the full command if there is an error. (e.g. the linux kernel build does this, IIRC). I'm assuming you don't have this, but if you do, there is usually a command line override such as make VERBOSE=1
So, there is some .c file somewhere that builds cleanly with the normal options but generates an error when extra compile options are added. Let's call this file badnews.c
What we want to see is the compilation command that make printed for badnews.c and the warning/error output for two cases:
without the extra options
with the extra options in various combinations
In particular, examining the case (1) command against the case (2) commands might show that options other than the -W are different. This indicates a makefile issue, similar to my "guess" above. You've said that [your equivalent of] case (1) is clean with no warnings, but, given the trouble you're having, it wouldn't hurt to double check.
You can cut and paste the case (1) cc command into a shell script and manually add the -W options. Watch out for things with spaces, such as -DSTRING="foo bar" in the makefile that may need extra quotes in a shell script.
To alleviate conflicts similar to yours, in my own makefiles I separate the symbols.
DFLAGS for all -DFOO=1
COPTS for -g, -O2, -Wall, -fno-inline-functions, etc.
Then, I either do:
CFLAGS := $(COPTS) $(DFLAGS)
Or:
%.o: %.c:
cc -c $(COPTS) $(DFLAGS) $<
There are other ways to do this as well.
UPDATE:
I am using following command to build: emq PRODUCT=ASG >build_log_0508.log
I'm unfamiliar with emq. I can't find a reference to it, except as "enterprise mail queue for JIRA", which [AFAICT] may be part of cPanel?
Getting the following error on compilation: prod/libs/app/app.c:720:5: error: incompatible implicit declaration of built-in function 'free' [-Werror] free(tmp_dn);
This is the smoking gun ...
I don't know what compiler you're using, or what OS/environment, but it appears to not flag this as a warning/error by default.
However, it is a bug in the source app.c that needs to be fixed. It was correctly flagged as a warning/error by the addition of -Wall and -Werror
Note: As I mentioned in my original answer, it would be helpful to have the final cc command line that produced this error [as well as the cc command when this file is not flagged].
I created a simple test case:
void
myfree(void *ptr)
{
free(ptr);
}
Here, under gcc, I did gcc -c test.c and I get:
test.c: In function 'myfree':
test.c:5:2: warning: implicit declaration of function 'free' [-Wimplicit-function-declaration]
free(ptr);
^
test.c:5:2: warning: incompatible implicit declaration of built-in function 'free'
test.c:5:2: note: include '<stdlib.h>' or provide a declaration of 'free'
So, gcc flags this by default [even without -Wall or -Werror]. But, your compiler does not unless it is given -Wall. This could occur if your compiler were clang and you also specified -std=c89
As I implied earlier, if you just specify -Wall but not -Werror, you should get the same warnings but they just won't stop the build. In a large build, they can be easily overlooked in the log [by a human (e.g.) me :-)].
Referring to the suggestions in my original answer, assuming that the cc commands between case (1) ["good"] and case (2) ["bad"] only differed by the addition of -Wall, the correct way to fix this is to edit app.c and add #include <stdlib.h> as part of the includes.
Is there any problem with "SUB_CDEFS := -Wall -Werror"?
It will have similar problems/benefits as with CDEFS.
I am adding at the end of the makefiles
This is all the more reason to use += instead of :=. You might be "killing off" the -std=c89 if that were specified somewhere.
UPDATE #2:
It worked after doing += instead of :=.
As I mentioned, using := removed some critical compile options, that were specified elsewhere in the makefile(s).
But, once again, the source code has a bug and is broken. It was broken before you ever touched it. By adding -Wall -Werror using :=, you uncovered this bug, that previously was masked incorrectly. This is a good thing.
Using += just sweeps the bug under the rug [again], by restoring some build options that were lost with :=. But, these "lost" build options were wrong. They allowed a genuine flaw in the C code to escape detection.
This is not about getting the build to work [with a workaround], but to fix the root cause of the build problems, which is to modify the C source code. There are probably other such C source code bugs and some may be more severe.
With the workaround to "fix" the build, you've now got a piece of built software that can not be trusted to run correctly. It could fail in intermittent ways on your system(s). Or, produce incorrect results. Or, allow your system to be hacked [and potentially expose you to legal liability] if you're putting this on a publicly facing site.
If you're not comfortable doing the source modification yourself, file a bug report with the original author of the software. The source code should have a README file, or BUGS file, or whatever that should outline a procedure for doing so.
Just need one more clarification for what is the difference between SUB_CDEFS, UN_CDEFS, and CDEFS
It's completely arbitrary.
Software projects built with make, can often build multiple programs or libraries. These often are placed in subdirectories. Each such subdirectory often has its own Makefile.
To avoid needless duplication [and potential error], the parts that would be common to these makefiles are placed in a single makefile, often called a rules file [but it's just a makefile]. The individual makefiles then have a line like: include ../common/rules.mk
The rules file expects that certain symbols are defined that help guide it to build the targets for the given subdirectory.
CDEFS et. al. are an example of such symbols. Names that are descriptive of function are [should be] chosen. That is, CDEFS [probably] means "C definitions". The actual symbol names and their function depends upon the rules file. We could use the symbol SHRONK instead of CDEFS. That doesn't help much with understanding things, but if all makefiles were edited to change CDEFS to SHRONK, it would work.
For example, in other software, instead of CDEFS, a similar symbol might be named CFLAGS or COPTS. This is fairly common.
Side note: It's a bit moot at this point, but things would have gone much more smoothly and quickly if you had edited your question and posted the output cc commands and [some of] your makefiles as I had requested. You would have gotten specific answers in a matter of hours instead of general guidelines [that took several days].
So, without the rules file, it's not possible to tell. Only make a guess, based upon the names:
CDEFS -- global cc options for a subdirectories
SUB_CDEF -- cc options for this particular subdirectory
UN_CDEFS -- specify -Ufoo options
The particular software you are building may have documentation for this in a documentation file or in comments in one or more of the makefiles.
To understand this generally, there are many online guides to make. Under Linux, there are "info" files. So, try info make. Other systems have detailed manpages, so do man make

Related

autoconf configure results in C std lib header related compile errors

I am attempting to build a project that comes with an automake/autoconf build system. This is a well-used project, so I'm skeptical about a problem with the configure scripts, makefiles, or code as I received them. It is likely some kind of environment, path, flag, etc problem - something on my end with simply running the right commands with the right parameters.
The configuration step seems to complete in a satisfactory way. When I run make, I'm shown a set of errors primarily of these types:
error: ‘TRUE’ undeclared here (not in a function)
error: ‘struct work’ has no member named ‘version’
error: expected ‘)’ before ‘PRIu64’
Let's focus on the last one, which I have spent time researching - and I suspect all the errors are related to missing definitions. Apparently the print-friendly extended definitions from the C standard library header file inttypes.h is not being found. However, in the configure step everything is claimed to be in order:
configure:4930: checking for inttypes.h
configure:4930: /usr/bin/x86_64-linux-gnu-gcc -c -g -O2 conftest.c >&5
configure:4930: $? = 0
configure:4930: result: yes
All the INTTYPES flags are set correctly if I look in confdefs.h, config.h, config.log Output Variables, etc:
HAVE_INTTYPES_H='1'
#define HAVE_INTTYPES_H 1
The problem is the same whether doing a native build, or cross-compiling (for arm-linux-gnueabihf, aka armhf).
The source .c file in question does have config.h included as you'd expect, which by my understanding via the m4 macros mechanic should be adding an
#include <inttypes.h>
line. Yes, as you may be inclined to ask, if I enter this line myself into the .c file it appears to work and the PRIu64 errors go away.
I'm left with wondering how to debug this type of problem - essentially, everything I am aware of tells me I've done the configure properly, but I'm left with a bogus make process. Aside from trying every ./configure tweak and trick I can find, I've started looking at the auto-generated Makefile.in itself, but nothing so far. Also looking into how I can get the C pre-processor to tell me which header files it's actually inserting.
EDIT: I've confirmed that the -DHAVE_CONFIG_H mechanic looks good through configure, config.log, Makefile, etc.
autoconf does not automatically produce #include directives. You need to do that on your own based on the HAVE_* macros. So you'll have to add something like this:
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
If these lines show up in confdefs.h, a temporary header file used by configure scripts, this does excuse your application from performing these #includes. If configure writes them to confdefs.h, this is solely for the benefit of other configure tests, and not for application use.
First, run make -n for the target that failed. This is probably some .o file; you may need some tweaking to get its path correctly.
Now you have the command used to compile your file. If you don't find the problem by meditating on this command, try to run it, adding the -E to force preprocessor output text instead of invoking the compiler.
Note that now the .o file will be text, and you must rebuild it without -E later.
You may find some preprocessor flags useful to get more details: -dM or -dD, or others.

How can compiling the same source code generate different object files?

After a long sequence of debugging I've narrowed my problem down to one file. And the problem is that the file compiles differently in two different directories, when everything else is the same.
I'm using CodeSourcery's arm gcc compiler (gcc version 4.3.3, Sourcery G++ Lite 2009q1-161) to compile a simple file. I was using it in one module with no issues and then I copied it to another module to use there. When it compiles, the object file is significantly different. The command line to compile the two files is identical (I used the linux history to make sure), and the 3 include files are also identical copies (checked with diff).
I did a binary compare on the two object files and they have a lot of individual byte differences scattered around. I did an objdump -D of both and compared them and there are a lot of differences. Here is dump1, dump2, and the diff. The command line is "
arm-none-eabi-gcc --std=gnu99 -Wall -O3 -g3 -ggdb -Wextra -Wno-unused -c crc.c -o crc.o".
How is this possible? I've also compiled with -S instead of -c and looked at the assembler output and that's identical except for the directory path. So how can the object file be different?
My real problem is that when I try to link the object file for dump2 into my program, I get undefined reference errors, so something in the object is wrong, whereas the object for dump1 gets no such errors and links fine.
For large scale software, there are many implementations are doing hashing on pointers. This is one major reason that cause result randomization. Usually if the program logic is correct, the order of some internal data structures could be different which is not harmful in most cases.
And also, don't compare the 'objdump -D' output, since your are compiling the code from different directory, the string table, symbol table, DWARF or eh_frame should be different. You will certainly get lots of diff lines.
The only comparison that makes sense is to compare the output of 'objdump -d' which only takes care of the text section. If text section is same(similar) then it can be considered as identical.
Most likely your file picks up different include files. This this the most likely reason.
Check that your include paths are exactly the same, paths in the include statements. They may point to different directories. C and C++ has a feature that when you #include abcd.h it tries to load abcd.h from the directory of the calling file. Check this.

How to stop make (in makefile) after "No such file or directory" error?

So, most of the times I'm testing if every include is correct on a given C/C++ code, I have a makefile with a gcc/g++ call with proper -I option for searching headers on specific directories (like every program) when I'm compiling sources to headers.
However, if the included directory is not correct and an undefined header appears (e.g. foo.h has #include and was not found), the gcc/g++ will just spit a bunch of errors for every include I have of that foo.h header for all other sources I'm compiling afterwards (and I'm already using -Werror -Wfatal-errors to make gcc/g++ to stop).
So, my question is simple: how can I tell makefile stop after the first error of the type "No such file or directory" it finds? It is really annoying it continue to compile sources and sources, giving me hundreds of errors just for a repeated error I already understood.
It probably continues because you told it to. See the following two options of GNU make:
-k, --keep-going Keep going when some targets can't be made.
-S, --no-keep-going, --stop
Turns off -k.
Put the header files into a variable and use that variable as a dependency. The following snippet will not build anything until the specified headers exist.
HEADERS=test.h other.h /usr/include/special.h
all: $(HEADERS) $(BINPROGS)
[... all other rules go here as usual ...]
*.h:
echo found $#
The ".h:" simply prints out each header that is found before any building even starts. The makefile itself stops if a header cannot be found (and it will stop before trying to compile anything).
I believe that that is what you wanted?
you can write a shell script to check for error conditions before running the make script.

Unix makefile errors " 'ake: Fatal error: Don't know how to make (c file here)"

I've written the below makefile:
hw2p1: hw2p1_main.o hw2p1_getit.o hw2p1_parseit.o hw2p1_moveit.o hw2p1_showit.o
gcc hw2p1_main.o hw2p1_getit.o hw2p1_parseit.o hw2p1_moveit.o hw2p1_showit.o
hw2p1_main.o: hw2p1_main.c
gcc -c hw2p1_main.c
hw2p1_getit.o: hw2p1_getit.c
gcc -c hw2p1_getit.c
hw2p1_parseit.o: hw2p1_parseit.c
gcc -c hw2p1_parseit.c
hw2p1_moveit.o: hw2p1_moveit.c
gcc -c hw2p1_moveit.c
hw2p1_showit.o: hw2p1_showit.c
gcc -c hw2p1_showit.c
The first time I tried to call make, I got the error: "make: Fatal error: unexpected end of line seen" I deleted the blank lines between targets and called make again, but this time I got " 'ake: Fatal error: Don't know how to make hw2p1_main.c"
I've compiled all of these files separately and then linked them so I know that the errors are a result of an incorrect makefile and not a result of errors in my c files.
This is the first makefile that I've ever written so I might just be doing it completely incorrectly. Either way, any suggestions on how to get rid of these errors?
This can happen when the directory is inadvertently not the one it should be so it looks like hw2p1_main.c's absence calls for a rule to create the C source file.
It could also be a filename misspelling.
You seem to be missing the -o in the linking command, though that's probably not what's on your mind yet. The immediate complaint is that make can't find that .c file. Sure it's there in the current working directory?
As a start, try a makefile which only compiles one thing:
hw2p1_moveit.o: hw2p1_moveit.c
gcc -o moveit.o -c hw2p1_moveit.c
Also, make sure that the 2nd line uses a TAB character, rather than spaces. (I have to manually set this in my editor because spaces are the only smart way to do it :)
Your Makefile is way more complicated than it needs to be. Let Make use its implicit rules. It knows how to make foo.o from foo.c, and you don't need to tell it that. Your entire Makefile can be reduced to:
OBJS = hw2p1_main.o hw2p1_getit.o hw2p1_parseit.o hw2p1_moveit.o hw2p1_showit.o
hw2p1: $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(OBJS) -o $#
As noted by others--make sure you use an actual tab for the indentation. Make is extremely picky about that.
Just a stab in the dark, but does the filename's case match? Coming from a windows/apple world, some people are surprised that unix filenames are case sensitive.
You can check this by copying the filename exactly from the error output and trying to list it, i.e. ls -l <paste>. That should also show you whether there's some control characters embedded in the filename, which could also be your problem.
This answer is almost never available! Okay, so basically I found a solution. The makefile you've written is sound. However, you have to create it in EMACS. Wierd right? I had a submission due and had written my makefile in notepad and uploaded it onto the university server, and it never ran! I tried using different variants of the code to no luck. Then in frustration I retyped the whole thing in EMACS, and it just worked. No modifications to the code. Give it a shot!
If you have made sure
1) That all files it's saying are missing are in same directory as that of makefile or otherwise as per path indicated
2) all command lines are containing tabs and not spaces (easiest way to check is to press a left arrow key at your first character and it should return to home position (0th char of line position)
Then Most of the time the problem is file format of Makefile
If you are typing a file in an editor having a PC (CR/LF) Line format then you will have to set it to just CR file format.
So, you can type the Makefile in vi or emacs or any other editor which has default file format of UNIX and it will work or set your document file format to be of UNIX type in your editor if it allows to set one.
This must work for all errors of type
'ake: Fatal error: Don't know how to make target (OR) <BR/>
'ake: Fatal error: Don't know how to make target(lastfilename in line)
Hope this helps.

Errors while compiling Neko VM OS X

I'm trying to compile the Neko VM on Mac OS X (10.5.7) using GCC 4.01 and I'm completely stuck, because it stops while compiling saying:
vm/threads.c:202: error: conflicting types for 'neko_thread_register'
vm/neko_vm.h:37: error: previous declaration of 'neko_thread_register' was here
I've tried googling this and some say it's because of lack of a "prototype" and some say it's because of a header include being done several times, and I can't really find any of those.
The affected line in threads.c:202 looks like this:
EXTERN bool neko_thread_register( bool t ) {
And the affected line in neko_vm.h:37 looks like this:
EXTERN bool neko_thread_register( bool t );
I can't see any difference in them, besides one of them being the implementation of the other.
The compiler command I'm using is:
cc -Wall -O3 -v -fPIC -fomit-frame-pointer -I vm -D_GNU_SOURCE -arch i386 -L/usr/local/lib -L/opt/local/lib -I/opt/local/include -o vm/threads.o -c vm/threads.c
I'd appreciate some ideas on what i might be able to do here, I don't really know where to go from here.
A mirror of the code for Neko which I'm trying to compile can be found here.
Thanks!
Have you tried compiling that file alone and outputting the preprocessed version? It could be that the scope or linkage macros are being modified somewhere in between the header file and the implementation file-- the same could be true of the 'bool' type, which is usually a macro defined by a system header.
According to the GCC 4.2 docs here, you should need to add the -E flag to the compilation line above, and you ought to change -o vm/threads.o to -o vm/threads.i so a file with the correct extension is created (.i means 'preprocessed file', essentially).
First, make sure you compile this as C, not C++.
Second, without seeing the code, it's pretty much impossible to say what the problem is.
But reading the error messages is often helpful (even before you google them):
Apparently neko_thread_register is declared twice, once in threads.c:202 and once in neko_vm.h:37, and the two declarations have different (conflicting) types. So look at the two declarations. If you can't see a problem with them, show us some code.
At the very least, seeing those two lines of code would be necessary. Most likely, the types are typedefs or macros or something similar, and then we'd need to see where they are defined as well.
Without seeing the code, all we can do is repeat the compiler error. "neko_thread_register has two conflicting definitions, at the lines specified."
Did you uncomment this line:
# For OSX
#
# MACOSX = 1 <-- this one
In the makefile?

Resources