"Unrecognised emulation mode: ain" when compiling with gcc on Ubuntu - c++

Consider the following code lying in main.cpp:
#include <iostream>
int main() {
std::cout << "Hello World!\n";
}
Compilation with g++ main.cpp -o -main fails:
/usr/bin/ld: unrecognised emulation mode: ain
Supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu elf_l1om elf_k1om i386pep i386pe
collect2: error: ld returned 1 exit status
I'm on a 64-bit Ubuntu 20.04.3 LTS running in WSL2. GCC's version is
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
How do I make this Hello World compile?

You've accidentally typed a dash before specifying your output file: it should be -o main, not -o -main, so the full command line is g++ main.cpp -o main
GCC has a -m key which allows specifying target machine architecture. For some reason, even when -main immediately follows -o, GCC still checks that the architecture (ain in case of -main) exists.
For example, if I compile with g++ main.cpp -o -melf_x86_64, I get an executable named -melf_x86_64 (to remove it, use rm ./-melf_x86_64 instead of rm -melf_x86_64). However, if I try g++ main.cpp -o -mi386, I get some compilation errors because I don't have 32-bit C++ standard library installed.
Looks like a bug to me: it simultaneously changes target architecture AND changes output file name. I've just opened GCC issue and LLVM issue (clang is affected as well).
UPD: actually looks like a bug in LD.

Related

Do I need to update g++ version? If so, then how to do that?

I am working on mac system.
g++ version is "Apple clang version 12.0.0 (clang-1200.0.32.2) Target: x86_64-apple-darwin20.6.0"(I typed g++ --version).
I need to install a c++ package with command - ' $(COMPILER) $(FLAGS) <file_name>.o output.o -lm -o <file_name> '
What should I write in the place of $(FLAGS)?
This link says there is no flag for g++-12. Then, should I update the version of g++?
P.S.
Thanks who commented.
After reading all those, I tried to reinstall the package.
I know now that g++ version is 11.
I typed - 'g++ -std=c++11 <file_name>.o -lm -o <file_name>'
It worked without any error. There is a file in that folder with the name '<file_name>.o'.
After the installation (without any error) I typed - 'g++ <file1_name>.cpp -o <file1_name>' I have got an error -
Undefined symbols for architecture x86_64:
...
...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So, what should I do now?

Link with a boost library fails when compiling with CUDA nvcc, succeeds with gcc

I'm trying to build an executable from just the following code (say it's in the file kt.cu):
#include <boost/program_options.hpp>
int main(int argc, char** argv)
{
boost::program_options::options_description options("Options");
return 0;
}
Here are 4 possible ways of building it, all should work and result in a binary with no linker errors:
Compile with CUDA nvcc, link with CUDA nvcc
Compile with CUDA nvcc, link with g++
Compile with g++, link with CUDA nvcc
Compile with g++, link with g++
The relevant compilation and linking commands:
Compile with CUDA nvcc:
nvcc -std=c++11 -c kt.cu
Compile with g++ (forcing it to be compiled as a .cpp file would):
g++ -x c++ -std=c++11 -c kt.cu
Link with CUDA nvcc:
nvcc -o kt -lboost_program_options -lcudart -L/usr/local/cuda/lib64 kt.o
Link with g++:
g++ -o kt -rdynamic -lboost_program_options -lcudart -L/usr/local/cuda/lib64 kt.o
If I compile with g++, linking works regardless of which linker I chose (i.e. options 3 and 4 work). If I compile with nvcc, linking fails, regardless of the linker I chose (i.e. options 1 and 2 fail)
Here's the error message I get:
tmpxft_00003de6_00000000-4_kt.cudafe1.cpp:(.text+0x76): undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
collect2: error: ld returned 1 exit status
Why is this failing? And what should I do to fix/work around this?
Notes:
I'm using Debian stretch with regular apt-get dist-upgrades.
I don't think there's something special about boost::program_options, i.e. it happens with other boost libs when I also use them. It's probably not boost-specific either, although I can't really say.
Versions (which shouldn't matter I think): CUDA 7.5, Boost 1.58, g++4.9.3. Also tried g++ 4.8.5 with same effect. Also tried compiling and linmking with g++ 5.2.1 only, that worked as well.
Edit: I can confirm this does not occur on Fedora 20, with g++ 4.8.3, Boost 1.54, CUDA 7.5. Can it be something with the Boost version?
This is a boost incompatibility with gcc 5 as a linker. See here. Downgrade to gcc 4 or wait for a patch.

Unrecognized Command Line Option '-stdlib=libc++' with MacPorts gcc48

Context
I'm trying to compile the package "root_numpy" which is a link between the scientific analysis software "root" and the python package "numpy". It's used as part of the root wrapper "rootpy". I get a g++ error when the following line is executed:
g++ -bundle -undefined dynamic_lookup -g -arch x86_64 -headerpad_max_install_names
-arch x86_64 build/temp.macosx-10.6-x86_64-2.7/root_numpy/src/_librootnumpy.o
-o build/lib.macosx-10.6-x86_64-2.7/root_numpy/_librootnumpy.so
-L/Users/bwells/bin/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d
-lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread
-lpthread -Wl,-rpath,/Users/bwells/bin/root/lib -stdlib=libc++ -lm -ldl
-lTreePlayer
g++: error: unrecognized command line option '-stdlib=libc++'
The same problem occurs when I compile a "hello world" program with the flag:
dhcp-130-112:helloworld bwells$ g++ -stdlib=libc++ helloworld.cpp
g++: error: unrecognized command line option '-stdlib=libc++'
Without that flag, it compiles fine:
dhcp-130-112:helloworld bwells$ g++ helloworld.cpp
dhcp-130-112:helloworld bwells$ ls
a.out helloworld.cpp
My compiler version is:
dhcp-130-112:helloworld bwells$ g++ --version
g++ (MacPorts gcc48 4.8.2_2) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AKA the result of running sudo port install gcc48. My Mac OS version is 10.9.3. The code file "helloworld.cpp" is as you'd expect
dhcp-130-112:helloworld bwells$ cat helloworld.cpp
#include <iostream>
int main(void)
{
std::cout << "Hello world!" << std::endl;
return 0;
}
dhcp-130-112:helloworld bwells$
Question: From everything I can gather on the internet, the "-stdlib=..." flag is a standard part of g++. Why do I get a g++ error when including it? How can I fix this?
Note:
While manually executing the setup.py line without the problem flag works, and allows the full package to compile, I experience linking errors when I try to import the resulting package into python. I'm concerned that the g++ problem here is a symptom of a larger issue, which is why I'm trying to solve it directly.
-stdlib=libc++ is a Clang (not GCC) option and tells clang to use LLVM libc++ standard library (which is what Clang uses) rather than GNU libstdc++ (which is what GCC uses).
Since you got linking errors, it seems likely that other packages you are using were compiled with clang and libc++, which is not ABI compatible with GCC's libstdc++ (except for some low-level stuff). So you'll need to compile the package with clang and libc++ as well. Apple's Xcode comes with clang (which is probably what you'd want to use for this), and MacPorts also supplies a number of clang distributions.

How to replace llvm-ld with clang?

Summary: llvm-ld has been removed from the LLVM 3.2 release. I am trying to figure out how to use clang in its place in my build system.
Note that I figured out the answer to my own question while writing it but I am still posting it in case it is useful to anyone else. Alternative answers are also welcome.
Details:
I have a build process which first generates bitcode using clang++ -emit-llvm. Then I take the bitcode files and link them together with llvm-link. Then I apply some standard optimization passes with opt. Then I apply another custom compiler pass with opt. Then I apply the standard optimization passes again using opt a third time. Finally I take the output from the last run of opt and use llvm-link to link with appropriate libraries to generate my executable. When I tried to replace llvm-link with clang++ in this process I get the error message: file not recognized: File format not recognized
To make this question more concrete I created a simplified example of what I am trying to do. First there are two files that I want to compile and link together
test1.cpp:
#include <stdio.h>
int getNum();
int main()
{
int value = getNum();
printf("value is %d\n", value);
return 0;
}
test2.cpp
int getNum()
{
return 5;
}
I executed the following sequence of commands:
clang++ -emit-llvm -c test1.cpp test2.cpp
llvm-link -o test.bc1 test1.o test2.o
opt test.bc1 -o test.bc2 -std-compile-opts
(Note that I am currently running llvm 3.1, but I'm trying to figure out the steps that will work for llvm 3.2. I assume that I should be able to make the LLVM 3.1 version work correctly using clang instead of llvm-ld)
Then if I run:
llvm-ld test.bc2 -o a.out -native
everything is fine and a.out prints out 5.
However, if I run:
clang++ test.bc2 -o a.out
Then I get the error message:
test.bc2: file not recognized: File format not recognized clang-3:
error: linker command failed with exit code 1 (use -v to see invocation)
Obviously I know that I can produce an executable file by running clang directly on the .cpp files. But I'm wondering what the best way to integrate clang with opt is.
The test case described in the question can be compiled using the following steps:
clang++ -emit-llvm -c test1.cpp test2.cpp
llvm-link -o test.bc1 test1.o test2.o
opt test.bc1 -o test.bc2 -std-compile-opts
llc -filetype=obj test.bc2 -o test.o
clang++ test.o
This produces a working a.out file.
It seems that llc is needed to convert from bitcode to machine code which can then be processed by clang as it normally would.
In general I've found that
llvm-ld x.bc y.bc
can be replaced with
llc x.bc
llc y.bc
clang x.s y.s

G++ compiler: option -s is obsolete and being ignored C++

I'm trying to compile and strip a very simple programm in C++ with the g++ compiler (4.6.0 on Mac OSX). But while compiling i get an warning.
source code:
#include </usr/local/Cellar/gcc/4.6.0/gcc/include/c++/4.6.0/iostream>
int main(){
std::cout << ("Hello World\n") ;
}
Terminal code:
g++ hello.cc -Wall -std=c++0x -s
/* or an alternative: */
g++ hello.cc -Wall -std=c++0x -o test -Wl,-s
Compiler warning:
ld: warning: option -s is obsolete and being ignored
Somebody any idea's about this weird warning?
Edit:
The weird thing is the size does decrease when using the -s flag, the decreases from 9,216 bytes to 9,008.
However when i use the following the size decreases to 8,896 bytes.
cp hello hello_stripped
strip hello_stripped
The error message is from ld, not from gcc or g++. (The gcc and g++ commands are a drivers that invokes the compiler, the linker, and other tools.)
gcc passes the -s option to the linker, as documented in the gcc 4.6.1 manual; apparently the MacOS port of gcc still does that.
The GNU linker (GNU ld) still accepts the -s option with its usual meaning. But the MacOS linker (also called ld) ignores it, as documented in the MacOS ld manual:
-s Completely strip the output, including removing the symbol table.
This file format variant is no longer supported. This option is
obsolete.
And the MacOS gcc manual, unlike GNU's gcc manual, doesn't mention "-s".
Apparently the -s flag is obsolete. You can use the strip program instead though.