Compiling a C plus plus program using GCC compiler - c++

I am trying to compile this little program in file demo.cpp by gcc demo.cpp,
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!";
return 0;
}
It does not do so successfully. I get Undefined symbols for architecture arm64:,
This seems like pretty popular error but people are getting it on way more complicated programs. Note that it works if I comment the cout line. I am not sure exactly what am I doing wrong here. gcc -v returns,
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin22.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

This is probably because the GCC compiler, according to my experience, is supposed to compile C language codes only, not C++. G++ is used to compile C++. The specific problem with the cout line is that C uses printf(), not cout, to print to the terminal. Therefore, the C compiler outputs your line as undefined symbols.

Related

std::to_chars compile but not linking on MacOS / clang

I have problem compiling a project under MacOS with clang.
I did "pinpoint" the problem inside charconv header:
#include <charconv>
#include <array>
#include <iostream>
int main(){
std::array<char, 64> buffer;
auto[p, ec] = std::to_chars(buffer.begin(), buffer.end(), 123);
if (ec != std::errc() )
std::cout << "error" << '\n';
std::cout << (const char *) buffer.data() << '\n';
}
Here is how I am compiling it.
Nikolays-MacBook-Air:~ nmmm$ clang --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Nikolays-MacBook-Air:~ nmmm$ clang -std=c++17 x.cc -lstdc++
Undefined symbols for architecture x86_64:
"std::__1::__itoa::__u32toa(unsigned int, char*)", referenced from:
std::__1::__itoa::__traits_base<unsigned int, void>::__convert(unsigned int, char*) in x-9b1746.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Nikolays-MacBook-Air:~ nmmm$
Any help will be appreciated.
update
I tried clang++, but it gives me same error message.
The <charconv> header contains declarations and uses of std::__1::__itoa::__u32toa, a function which is not defined in that header. The function is defined in libc++.dylib. However, Apple does not ship libc++.dylib with the same frequency as it ships headers; and, possibly more important, libc++ failed to include the new symbol in its "abilist" for Apple until 2018-09-23, even though the header change landed on 2018-08-01. So there was a period of about 53 days where (this aspect of) libc++ just didn't work on OSX. Maybe Apple picked it up and shipped it during that period.
One way to make your code work is to build libc++ yourself. Instructions here, as of late 2019.
$ clang++ -std=c++17 test.cc $ROOT/llvm-project/build/lib/libc++.dylib \
-Wl,-rpath,$ROOT/llvm-project/build/lib
$ ./a.out
123
Some commenters on your question are suggesting that you could make your code work by using GNU libstdc++ instead of LLVM libc++. That's vaguely true, but I suspect that building libstdc++ for OSX will be even harder than building libc++ for OSX. (And the latter is not simple!) I am not aware of any way to install libstdc++ on OSX. There is brew install gcc#8, but I bet GCC 8 didn't have <charconv> either.
As of early 2020, no vendor (except just recently Microsoft) provides a full implementation of <charconv> — the floating-point to_chars and from_chars turn out to be difficult, so most vendors don't provide them. ("Why didn't they just copy an existing implementation?" Well, it turns out that <charconv> was standardized as part of C++17 before any implementation existed. Nobody guessed that it would be difficult!)
I wrote a nice long answer to this, to then check and see that it works for me (clang 9.0.0 on linux). You compile with clang and not clang++. The long answer below:
Clang's libc++ has not fully implemented the "Elementary string conversions, revision 5 " (as in to_chars and from_chars) for a long time and some parts are still outstanding, see here. But I think yours should work, so maybe you should update your library.
For usage of to_chars please consider, that it explicitly adds no \0 at the end of the string. Therefore you cannot just use std::cout << (const char *) buffer.data();. You have to use the pointer (named p in your code) to mark the end of your string. Either by inserting a \0, by generating a std::string_view sv(buffer.data(), static_cast<size_t>(p-buffer.data());, using std::copy(buffer.begin(), p, std::ostream_iterator<char>(std::cout, "")); or another of far too many ways.

How to compile C++ on Mac OS using TR1

I have a preexisting product that builds on Linux, and I'm trying to port it to Mac OS.
msoulier#merlin:~$ xcode-select -v
xcode-select version 2343.
msoulier#merlin:~$ g++ -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
The problem is that it uses the tr1/tuple library, and for some reason,
that is not in the default include path.
msoulier#merlin:~$ ls /usr/include/c++/4.2.1/tr1/tuple
/usr/include/c++/4.2.1/tr1/tuple
So it's there, which should be in the include path based on the
--with-gxx-include-dir option above,
And yet
msoulier#merlin:~$ cat hello.cpp
#include <iostream>
#include <tr1/tuple>
using namespace std;
int main(void) {
cout << "Hello, World!" << endl;
return 0;
}
msoulier#merlin:~$ g++ -o hello hello.cpp
hello.cpp:2:10: fatal error: 'tr1/tuple' file not found
#include <tr1/tuple>
^
1 error generated.
Why doesn't this just work?
Thanks.
Short answer: call clang++ with -stdlib=libstdc++, and the tr1 headers will be there.
Long answer:
The reason for your error and the 2 sets of C++ includes is that macOS/Xcode has two different C++ standard libraries you can build against: an old GNU libstdc++, and the new and modern LLVM libc++.
As of macOS 10.12 Sierra, the default is now libc++ and libstdc++ is deprecated. libstdc++ is quite old, v4.2.1, and predates C++11 (hence the tr1 headers). If you're going to be maintaining this code long-term, it'd be worth the time to make it C++11 compliant (i.e. #include <tuple>)
Update: Xcode 10 no longer allows building against libstdc++. Either update your codebase to use standard C++11 headers, or use Xcode 9 if that's really not an option.

std::thread works in cygwin but not in MinGw

So I decided to give c++ a try today. I downloaded MinGw and the g++ compiler that comes with it. I decided to test the following code:
#include <iostream>
#include <thread>
int foo()
{
std::cout << "foo" << std::endl;
}
int main()
{
std::thread t1(foo);
t1.join();
std::cout << "done" << std::endl;
return 0;
}
I then tried to compile it on the command line using the following line:
g++ -std=c++11 main.cpp
Which works for hello world. This time however, it gave me this error:
error: 'thread' is not a member of 'std'
I tried the exact same code using the g++ provided by cygwin, and it works. So why doesn't it work in MinGw? Is it outdated or something? I want to compile stuff using c++11 and c++14 like on the cygwin terminal, but outside of the cygwin environment.
MinGW-w64 (or rather GCC on windows) needs to be compiled with posix thread support if you want to use std::thread, presumably you downloaded a build with native windows threads.
Check out the mingw-builds folders targeting 64 bit or 32 bit and pick a version with posix threads. You'll also need to choose the exception handling method, if you don't have a reason to choose otherwise then stick with the GCC defaults of seh for 64 bit and dwarf for 32.
I tested this in linux (cross-compiling).
This compiles ok,
i686-w64-mingw32-g++-posix -std=c++11 threads.cpp -lwinpthread
this does not
i686-w64-mingw32-g++-win32 -std=c++11 threads.cpp -lwinpthread
The difference between the compilers is --enable-threads=win32 vs. --enable-threads=posix option used when the compilers were built. g++ -v should show what was used.

GCC C++11 Fails to See #if windows And #if linux (Re-ask)

When using the #if windows/#if linux compilers features in Debian GCC version 4.7.2, I have been unable to get them work when using std11.
Independently, I can get the compiler to accept the if-defines without complaint. I can also get the compiler to use the same code with c++ 11, without any if-defines (and thus not conditionally). But when I run the conditional defines through the same compiler, with the tag for c++ 11, the code is rejected.
Below I have included a simple example, with two alternate mains, and the error I get. The only difference between the two mains are the commented out lines.
Runs:
g++ main.cpp -std=c++11 -o test
The above uses the c++ 11 standard. When running commented main it works perfectly. But when running uncommented main, it fails entirely, giving the error at the far end of this post.
g++ main.cpp -o test
The above does not use the c++ 11 standard. When running either commented main or uncommented main it works perfectly.
Below are the code examples.
Commented main.cpp:
#include <iostream>
//#if windows
//#include "WindowsSolution.hpp"
//#endif
//#if linux
#include "LinuxSolution.hpp"
//#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
LinuxSolution.hpp:
class LinSolution{
public:
LinSolution(){
}
std::string out(){
std::string ret("Linux solution");
return ret;
}
};
LinSolution myGlobalSolution;
WindowsSolution.hpp:
class WinSolution{
private:
WinSolution(){
}
std::string out(){
std::string ret("Windows solution");
return ret;
}
};
WinSolution myGlobalSolution;
Uncommented main.cpp:
#include <iostream>
#if windows
#include "WindowsSolution.hpp"
#endif
#if linux
#include "LinuxSolution.hpp"
#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
Below is the error I get when compiling with the uncommented main.cpp, using the c++ 11 flag.
main.cpp: In function ‘int main()’:
main.cpp:13:15: error: ‘myGlobalSolution’ was not declared in this scope
The simple constant linux is a GCC extension and not an official OS constant. The proper constant for Debian is probably __gnu_linux__; you can find a list of them for various systems here. Usually official predefined constants follow the convention of using __ at the start.
Your code works without the standard flag because by default GCC compiles in a GNU language mode (GNU C++) rather than a standard language mode (ISO C++); the GNU language includes extensions (extra language features, and in this case, legacy OS constants). When you pass the -std=c++11 flag you are requesting ISO language mode, which means GNU extensions are disabled, including GNU-only constants. To get both GNU extensions and a specific set of ISO features, try requesting a GNU language standard version instead (e.g. -std=gnu++11 works fine).

Compiling a C++ program with GCC

How can I compile a C++ program with the GCC compiler?
File info.c
#include<iostream>
using std::cout;
using std::endl;
int main()
{
#ifdef __cplusplus
cout << "C++ compiler in use and version is " << __cplusplus << endl;
#endif
cout <<"Version is " << __STDC_VERSION__ << endl;
cout << "Hi" << __FILE__ << __LINE__ << endl;
}
And when I try to compile info.c:
gcc info.C
Undefined first referenced
symbol in file
cout /var/tmp/ccPxLN2a.o
endl(ostream &) /var/tmp/ccPxLN2a.o
ostream::operator<<(ostream &(*)(ostream &))/var/tmp/ccPxLN2a.o
ostream::operator<<(int) /var/tmp/ccPxLN2a.o
ostream::operator<<(long) /var/tmp/ccPxLN2a.o
ostream::operator<<(char const *) /var/tmp/ccPxLN2a.o
ld: fatal: Symbol referencing errors. No output written to a.out
collect2: ld returned 1 exit status
Isn't the GCC compiler capable of compiling C++ programs?
On a related note, what is the difference between gcc and g++?
gcc can actually compile C++ code just fine. The errors you received are linker errors, not compiler errors.
Odds are that if you change the compilation line to be this:
gcc info.C -lstdc++
which makes it link to the standard C++ library, then it will work just fine.
However, you should just make your life easier and use g++.
Rup says it best in his comment to another answer:
[...] gcc will
select the correct back-end compiler
based on file extension (i.e. will
compile a .c as C and a .cc as C++)
and links binaries against just the
standard C and GCC helper libraries by
default regardless of input languages;
g++ will also select the correct
back-end based on extension except
that I think it compiles all C source
as C++ instead (i.e. it compiles both
.c and .cc as C++) and it includes
libstdc++ in its link step regardless
of input languages.
If you give the code a .c extension the compiler thinks it is C code, not C++. And the C++ compiler driver is called g++, if you use the gcc driver you will have linker problems, as the standard C++ libraries will not be linked by default. So you want:
g++ myprog.cpp
And do not even consider using an uppercase .C extension, unless you never want to port your code, and are prepared to be hated by those you work with.
You should use g++ instead of gcc.
By default, gcc selects the language based on the file extension, but you can force gcc to select a different language backend with the -x option thus:
gcc -x c++
More options are detailed on the gcc man page under "Options controlling the kind of output". See e.g. gcc(1) - Linux man page (search on the page for the text -x language).
This facility is very useful in cases where gcc can't guess the language using a file extension, for example if you're generating code and feeding it to gcc via standard input.
The difference between gcc and g++ are:
gcc | g++
compiles C source | compiles C++ source
Use g++ instead of gcc to compile you C++ source.
If I recall correctly, gcc determines the filetype from the suffix. So, make it foo.cc and it should work.
And, to answer your other question, that is the difference between "gcc" and "g++". gcc is a frontend that chooses the correct compiler.
An update with my GCC version 10.3.0 on Ubuntu. Even if I add -lstdc++ or use the correct extension, cc1plus must be installed on the system. Otherwise this error shows up:
gcc: fatal error: cannot execute ‘cc1plus’: execvp: No such file or directory
One way to get this is to install g++ even if you're not going to use it directly, e.g. sudo apt install g++.
Now, if I use the extension .cc, I can just call gcc directly, however, warnings and errors still show up. To use gcc cleanly, with a .c extension I have to call it like this:
gcc -x c++ info.c -lstdc++
Shorter if I use the .cc extension, like the accepted answer:
gcc info.cc -lstdc++
Or like others have said, just use g++ info.c instead. No extra parameters are needed to indicate C++, and it works with .c, .cc and .cpp extensions.
It worked well for me. Just one line code on the Windows command line (CMD).
First, confirm that you have installed gcc (for C) or g++ (for C++) compiler.
On the command line, for gcc, type:
gcc --version
On the command line, for g++, type:
g++ --version
If it is installed then proceed.
Now, compile your .c or .cpp using the command line.
For C syntax:
gcc -o exe_filename yourfilename.c
Example:
gcc -o myfile myfile.c
Here exe_filename (myfile in example) is the name of your .exe file which you want to produce after compilation (Note: I have not put any extension here). And yourfilename.c (myfile.c in example) is the your source file which has the .c extension.
Now go to the folder containing your .c file. Here you will find a file with the .exe extension. Just open it. Hurray...
For C++ syntax:
g++ -o exe_filename yourfilename.cpp
After it, the process is the same as for the C syntax.
For a .cpp File:
g++ myprog.cpp -o myprog