compiling c++ code using gnu/c getline() on mac osx? - c++

I'm trying to compile a pre-existing c++ package on my mac osx leopard machine, and get the following error:
error: no matching function for call to 'getline(char**, size_t*, FILE*&)'
This is probably because getline() is a GNU specific extension.
Can I somehow make the osx default g++ compiler recognize such GNU specific extensions?
(if not, I could always supply my own implementation or GNUs original one, but I prefer to have a "cleaner" solution if possible)

getline is defined in stdio.h in glibc version 2.10 and later, but not in earlier versions, nor (so far; added 10.5 definitely didn't have getline, and 10.7 definitely does) in the BSD derived libc.
The change in the GNU libraries came about because of a change in the POSIX 2008 standard, which now includes getline.
Presumably, this will propogate to other libc over time. In the mean time, I understand that it is causing trouble for a lot of projects.
You can download a stand alone version from GNU.

Generally, the solution is to use autoconf or some similar tool to determine whether the current platform already has getline or not, and supply your own definition only when needed.
Example:
# configure.ac
AC_CHECK_FUNCS([getline])
// compat.h
#include "config.h"
#ifndef HAVE_GETLINE
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
#endif
// getline.c
ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
/* definition */
}
# Makefile.am
program_LDADD = $(if $(HAVE_GETLINE),,getline.o)
or something along those lines, you'll have to adjust it to match your own program.

I'm not sure I've ever seen that specific definition of 'getline' here is the one I know of which uses c++ streams+strings.
http://www.cplusplus.com/reference/string/getline/

Related

Undefined Reference to `pcap_init' - Libpcap

I'm currently trying to set up a simple packet sniffer with libpcap and facing a lot of confusion over this linker error.
I cloned the most recent version from github (1.11.0-PRE-GIT) and successfully did the configure, make and make install steps outlined in the installation instructions.
My script is as follows:
#include <iostream>
#include <pcap/pcap.h>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
//Set up error buffer
char errbuf[PCAP_ERRBUF_SIZE];
// Check Libpcap version number
cout << pcap_lib_version() << endl << endl;
//Initialize the library for local charactr encoding
pcap_init(PCAP_CHAR_ENC_LOCAL, errbuf);
return 0;
}
But when I try to compile with the command below I get the error:
g++ csniff.cc -o csniff -lpcap
/usr/bin/ld: /tmp/ccAPLFoh.o: in function `main':
csniff.cc:(.text+0x79): undefined reference to `pcap_init'
collect2: error: ld returned 1 exit status
I've also checked the pcap.h files present in both usr/include and usr/local/include and they both contain a prototype for the pcap_init function that looks like this:
#define PCAP_CHAR_ENC_LOCAL 0x00000000U /* strings are in the local
character encoding */
#define PCAP_CHAR_ENC_UTF_8 0x00000001U /* strings are in UTF-8 */
PCAP_AVAILABLE_1_10
PCAP_API int pcap_init(unsigned int, char *);
One thing I have noticed though is that when I comment out the line with pcap_init and use the script to print the version number I get
libpcap version 1.9.1 (with TPACKET_V3)
Any pointers would be much appreciated!
Edit: runnning Ubuntu 20.04.3 LTS
Your operating system already comes with libpcap - version 1.9.1. Most Linux distributions do, as do the *BSDs, macOS, and some commercial UN*Xes.
You compiled and installed a newer version of libpcap, so you had two versions of the library file - the 1.9.1 that comes with the system, in the system library directory, because it comes with the OS, and the 1.11.0-PRE-GIT and you compiled and installed, probably in /usr/local/lib.
You also had one version of the libpcap header files - the 1.11.0-PRE-GIT version - in /usr/local/include/pcap, because you installed it. You did not have the 1.9.1 version of the header files, because, like many Linux distributions, a separate "development" package has to be installed in order to get the header files.
When you compiled your program, you didn't tell it where to look for header files or libraries. It found the header files in /usr/local/include/pcap - i.e., the 1.11.0-PRE-GIT header files - and found the library in the system library directory - i.e., the 1.9.1 library.
This causes problems, because the header files included a declaration of pcap_init(), so the compiler didn't print a warning about pcap_init() not being declared, but the library file doesn't include the pcap_init() function, so the linker printed an error about pcap_init() not being found in libpcap.
Removing the call to pcap_init() meant that the linker didn't try to find pcap_init(), and thus didn't fail.
If you hadn't built and installed libpcap 1.11.0-PRE-GIT, and you had installed the libpcap-dev package, your system would have the headers and library for 1.9.1, and compiling your program - without the call to pcap_init() - would find the headers for 1.9.1, so it can compile, and the library for 1.9.1, so it will link.
If, however, you want to build with 1.11.0-PRE-GIT, then you will need to tell the compiler where to find the libraries; you might also have to tell it where to find the headers.
If you don't have the libpcap-dev package installed, then you don't need to tell it where to find the headers, as it will find the 1.11.0-PRE-GIT ones you installed; however, if the libpcap-dev package is installed, you may have to add the flag -I /usr/local/include to the compiler command, to make sure it finds the headers in /usr/local/include rather than the system include directory.
To make sure it finds the 1.11.0-PRE-GIT version of the libraries, you will have to add the flag -L /usr/local/lib to the compiler command as well - or set LD_LIBRARY_PATH so that the linker finds the 1.11.0-PRE-GIT version.
If you build with 1.11.0-PRE-GIT, you can use pcap_init(). You don't need to use pcap_init() unless you want to run the program on some UN*X and on Windows and you want all strings to be in UTF-8 (on Windows, strings would, by default, be treated as being in the "local code page"). To quote the DESCRIPTION section of the pcap_init() man page:
pcap_init() is used to initialize the Packet Capture library. opts
specifies options for the library; currently, the options are:
PCAP_CHAR_ENC_LOCAL
Treat all strings supplied as arguments, and return all strings
to the caller, as being in the local character encoding.
PCAP_CHAR_ENC_UTF_8
Treat all strings supplied as arguments, and return all strings
to the caller, as being in UTF‐8.
On UNIX‐like systems, the local character encoding is assumed to be
UTF‐8, so no character encoding transformations are done.
On Windows, the local character encoding is the local ANSI code page.
If pcap_init() is not called, strings are treated as being in the local
ANSI code page on Windows, pcap_lookupdev(3PCAP) will succeed if there
is a device on which to capture, and pcap_create(3PCAP) makes an
attempt to check whether the string passed as an argument is a UTF‐16LE
string ‐ note that this attempt is unsafe, as it may run past the end
of the string ‐ to handle pcap_lookupdev() returning a UTF‐16LE string.
Programs that don’t call pcap_init() should, on Windows, call
pcap_wsockinit() to initialize Winsock; this is not necessary if
pcap_init() is called, as pcap_init() will initialize Winsock itself on
Windows.

Does clang provide an unlink implementation?

I am trying to compile a library using clang. The library makes calls to 'unlink', which is not defined by clang:
libmv/src/third_party/OpenExif/src/ExifImageFileWrite.cpp:162:17: error: use of undeclared identifier 'unlink'; did you mean 'inline'?
unlink( mTmpImageFile.c_str() ) ;
My question is, what is the clang equivalent of unlink? As I see it, the path forward would be to #define unlink somewhere with an equivalent routine.
There is no "Clang equivalent". Neither GCC nor Clang have ever been responsible for defining unlink, though they do probably distribute the POSIX headers which do (I don't recall specifically where POSIX headers come from).
Unfortunately, this appears to be a bug with the library you're using; the OpenExif developers failed to include the correct headers. Different C++ implementations may internally #include various headers for their own purposes, which has apparently masked this bug on your previous toolchain.
You can hack your copy and/or submit a patch to add:
#include <unistd.h>

ImageMagick pthread.h multiple definition

When trying to compile more recent versions of ImageMagick (v6.8.7-2 or later, v6.8.7-1 is fine), I get a bunch of:
CCLD magick/libMagickCore-6.Q16.la
magick/.libs/magick_libMagickCore_6_Q16_la-animate.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-annotate.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-artifact.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
magick/.libs/magick_libMagickCore_6_Q16_la-attribute.o: In function `__pthread_cleanup_routine':
/usr/include/pthread.h:581: multiple definition of `__pthread_cleanup_routine'
magick/.libs/magick_libMagickCore_6_Q16_la-accelerate.o:/usr/include/pthread.h:581: first defined here
... goes on for quite a bit longer, all the same.
The pertinent area of /usr/include/pthread.h (from glibc-headers 2.5-118.el5_10.2) is:
/* Function called to call the cleanup handler. As an extern inline
function the compiler is free to decide inlining the change when
needed or fall back on the copy which must exist somewhere else. */
extern __inline void
__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
{
if (__frame->__do_it) // <======= this is :581
__frame->__cancel_routine (__frame->__cancel_arg);
}
I've been posting on ImageMagick's forum without response.
Even if you can't say exactly what's happening, how do I start figuring out whether the issue is with ImageMagick or pthread.h? Where do I go from there?
grep pthread_cleanup_routine -r * only shows matches against the binary object files -- none of ImageMagick's source code has pthread_cleanup_routine in it. A few of the sources include "pthread.h" of course.
That's leading me to believe that this is a glibc issue, not an ImageMagick issue... but, again, previous versions of ImageMagick compile just fine. (I have diff'ed the svn sources between versions where it broke. Lots of configuration/makefile changes, but nothing sticks out to me as to why it would cause this.)
I'm on CentOS 5, kernel 2.6.18-308.24.1.el5, gcc v4.9.0, ld v2.24, glibc-headers 2.5-118.el5_10.2
I've seen a lot of people posting similar issues with other packages than ImageMagick. Hopefully others will find this useful.
Changing pthread.h, just before __pthread_cleanup_routine :
extern __inline void
to
if __STDC__VERSION__ < 199901L
extern
#endif
__inline void
Fixes the issue. Older versions of glibc had an issue when -fexceptions was used, and inline non-C99 conformance (see http://gcc.gnu.org/ml/gcc-patches/2006-11/msg01030.html.) More recent glibc's would fix the issue too, but this should be a temp fix for those who don't want to / shouldn't upgrade it.
ImageMagick svn 13539 (which later became v6.8.7-2) began using -fexceptions.
I faced this error with a newer gcc compiler (4.9.3)
The ImageMagick(6.8.9_7) configure script was checking if compiler supports gnu99 standard. If yes, the configure script sets standard to gnu99 and also enables openmp.
Inline semantics change with C standard gnu99 causing multiple definition of the extern inline function
https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Inline.html#Inline.
So, I added compiler flag -fgnu89-inline to use older semantics for inline and it fixed the issue.

How should I use g++'s -finput-charset compiler option correctly in order to compile a non-UTF-8 source file?

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.

How to tell if glibc is used

I am trying to implement backtrace functionality for a large framework, which is used for different platforms and OS'es. In some of them, it is linked against glibc, while in the other, something different (eg. uclibc) is used. backtrace() function exists only in the former.
Is there any way to tell whether glibc is used? Any #define? I was unable to find an answer in glibc manual. I know I can't have linking-time information during compilation, but I guess include files have to differ. At least backtrace have to be declared somewhere.
I would like to check it without being forced to pass explicit flags to the compiler.
Include features.h, it contains the macros you need, e.g.
#define __GNU_LIBRARY__ 6
/* Major and minor version number of the GNU C library package. Use
these macros to test for features in specific releases. */
#define __GLIBC__ 2
#define __GLIBC_MINOR__ 4
There are the #defines __GNU_LIBRARY__, __GLIBC__ and __GLIBC_MINOR__ (6, 2 and 11 on my system with glibc-2.11) in features.h.
Checking for preprocessor macros is not a good solution. uClibc and possibly other libc implementations define macros to mimic glibc (without providing all of its bloated functionality) for much the same reasons that all browsers include "Mozilla" in their User-Agent strings: broken programs that expect to see glibc and turn off lots of features if they don't see it.
Instead you should write a configure script to probe for backtrace and use it only if it's available.
Empirically, both of the following compile and run fine on GCC 6.4:
#include <stdio.h>
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
and:
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
but only the first produces output of course.
This must mean that __GLIBC__ comes from stdio.h which must include features.h, see also: What is the purpose of features.h header?
Therefore, strictly speaking, __GLIBC__ by itself is not a clear indication that glibc is used, since even without headers, GCC already embeds runtime objects such as crt1.o in the finale executable, and those come from glibc.
So the main missing question is: does glibc guarantee that features.h gets included by every header? I could not find a clear documentation quote. TODO.
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
This is getting a bit ugly and syntactically ambiguous, but useful.