What are mechanisms of selection of emulation mode for a linker? - c++

I am trying to compile arduino code under codeblocks with avr-gnu compiler. I was getting this error:
avr-ld.exe unrecognized emulation mode: mcu=atmega328p.
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
I found this page: https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html which suggests that it should be linked under avr5 sim mode, so I added -mmcu=avr5 to linker options. Now I am getting:
avr-ld.exe unrecognized emulation mode: mcu=avr5
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
How is avr5 unrecognized if it is supported?o0
I tried few different toolchains from few different years but it seems that linker cant interpret this emulation mode correctly. Newer toolchains had support for 328p but still somehow dont work. I also tried creating CodeBlocks project dedicated for Arduino but the difference is that it passes -mmcu=atmega328p itself and still doesnt work on this or newer toolchains.
Update:
There is something that I am totally missing here. I changed linker to a standard x86 32 ld.exe from Mingw and passed -mmcu=i386pe and I am getting the similar error:
ld.exe unrecognized emulation mode: mcu=i386pe
Supported emulations:i386pe
So this only leads to my lack of understanding of mechanisms how the linker emulation mode is selected/configured.

In almost any case, you do not want to call the linker (ld resp. avr-ld) by hand!
Use avr-gcc to link your programs!
Notice that avr-gcc is not a compiler by itself, it's just a driver program that calls sub-programs like compiler proper (cc1 for C, cc1plus for C++, lto1 for LTO-compiled byte-code), assembler and linker depending on command-line options and input files provided on the command line.
avr-gcc knows how to provide the respective tools with appropriate command line options like: emulation, libraries, paths for includes and libraries, startup-code, sub-options, etc.
In order to see which tools are called by avr-gcc, add the -v option. For example, for a compile command as simple as
> avr-gcc -v main.c -mmcu=atmega328p -save-temps
You'll see somethinh like (here for avr-gcc v8.5.0):
...
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-specs=device-specs/specs-atmega328p' '-mmcu=avr5'
$AVRGCC_HOME/bin/../libexec/gcc/avr/8.5.0/collect2 <many options> -plugin-opt=-pass-through=-latmega328p -mavr5 -Tdata 0x800100 $AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5/crtatmega328p.o -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0 -L$AVRGCC_HOME/bin/../lib/gcc -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib main.o --start-group -lgcc -lm -lc -latmega328p --end-group
collect2 is just some other tool that wraps the call to ld. If you want to see the real thing, use avr-gcc ... -v -Wl,-v.
The correct emulation for the linker is worked out by the device-specific spec file device-specs/specs-atmega328p located at ./lib/gcc/avr/$version in the compiler's install directory. The specs "language" is a means to describe option mappings; in particular the bits that are responsible for mapping `-mmcu=atmega328p' to the right emulation are
*link_arch:
%{mmcu=*:-m%*}
...
*self_spec:
%{!mmcu=avr*: %<mmcu=* -mmcu=avr5} %<mshort-calls %<msp8
self_spec removes -mmcu=* from the command line and sets -mmcu=avr5 which is the core family ATmega328P belongs to. Then as part of the linker invocation, link_arch maps -mmcu=avr5 to -mavr5 which is the linker emulation to be used.

Related

gperftools - profile file not dumped

I've configured and built gpreftools. however, I can't seem to find the generated profile file of my program to display it.
I took the following actions:
Adding the -lprofiler linker flag to my .pro, building the program and the flag is added correctly at the linking stage.
QMAKE_LFLAGS += -lprofiler
Running with:
$ CPUPROFILE=/tmp/prof.out /path/to/executable
Executing:
$ pprof --gv /path/to/MyExe /tmp/prof.out
Then I get the following:
Failed to get profile: curl -s --max-time 90 'http:///pprof/profile?seconds=30' > /home/eslam/pprof/.tmp.MyExe.1509005857.: No such file or directory.
Anyone has a resolve on this?
Check that your program actually links to libprofiler.so. Some OSes (e.g. AFAIK some versions of ubuntu) do not actually add .so if none of it's symbols are actually used. E.g. ldd ./yourprogram should list libprofiler.so. If this does not happen, then you should prepend something like -Wl,--no-as-needed to your linker flags.
LD_PRELOAD method without rebuild
Besides passing -Wl,--no-as-needed,-lprofiler,--as-needed at build time mentioned by Eslam, you can also get it to work without modifying the build by passing the LD_PRELOAD option at runtime as:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so CPUPROFILE=prof.out ./main.out
You can find libprofiler.so easily with locate libprofiler.so.
See also: How can I profile C++ code running on Linux?
Tested in Ubuntu 18.04.

LLVM: How to specify all link libraries as input to llvm_map_components_to_libnames()

I need an additional library given as linker input, since the linker cannot find a symbol.
llvm_map_components_to_libnames(llvm_libs support core bitreader)
target_link_libraries(SkeletonPass ${llvm_libs})
The missing library must be missing from the components.
How do I specify all components as input?
First of all, although it's outdated, I suggest you read the following
http://releases.llvm.org/2.7/docs/UsingLibraries.html
it's a nice read. In that is suggested too look up llvm-config.
LLVM comes with a tool, llvm-config
which can help you in your case.
Second, I warmly suggest you have a look at the following SO post
How do I link when building with llvm libraries?
which also mention this tool.
Looking at the documentation I linked, this is the synopsis:
llvm-config option [components...]
where if components is not specified, its default value is all which according to the doc:
Includes all LLVM libraries. The default if no components are specified.
I will explicitly add all which can be omitted in your case.
llvm-config --components all:
Print all valid component names.
while
llvm-config --libs all:
Print all the libraries needed to link against the specified LLVM components, including any dependencies.
Please check llvm-config --help for more options and info.
So to answer your question, you could print all the components with the command mentioned above and put them inside your llvm_map_components_to_libnames().
To list all the components try running this command:
llvm-config --components
For me the output was
aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo a
mdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwr
iter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo cfguard codegen core coroutines coverage debuginfocodeview debuginfodwarf debuginfogsym debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker
engine executionengine frontendopenmp fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo instcombine instrumentation interpreter ipo irreader jitlink lanai lan
aiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo libdriver lineeditor linker lto mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430
msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts object objectyaml option orcerror orcjit passes powerpc powerpcasmpars
er powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvutils runtimedyld scalaropts selectiondag sparc sparcas
mparser sparccodegen sparcdesc sparcdisassembler sparcinfo support symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target textapi transformutils vectorize weba
ssembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86utils xcore xcorecodegen xcored
esc xcoredisassembler xcoreinfo xray

linker (ld) on OS X: How to use -Wl,--start-group (and --end-group)?

I am building some projects externally which use libclang static libs.
Linking fails like this:
ld: unknown option: --start-group
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The reason I need to use this is because of circular dependencies (or as it turns out, I guess because of not knowing the correct library order).
So far I have to resort to taking the -Wl,--{start,end}-group out of the makefile, looking at the undefined symbols error list, finding the libs that have them with nm, and appending them manually to the library list (so they appear more than once in the library list).
The correct order of LLVM/Clang libs (taken from my own project that uses it) for 3.5 is:
"clangFrontend",
"clangSerialization",
"clangDriver",
"clangTooling",
"clangCodeGen",
"clangParse",
"clangSema",
"clangAnalysis",
"clangRewriteFrontend",
"clangRewrite",
"clangEdit",
"clangAST",
"clangLex",
"clangBasic",
"LLVMLTO",
"LLVMObjCARCOpts",
"LLVMLinker",
"LLVMipo",
"LLVMVectorize",
"LLVMBitWriter",
"LLVMIRReader",
"LLVMAsmParser",
"LLVMR600CodeGen",
"LLVMR600Desc",
"LLVMR600Info",
"LLVMR600AsmPrinter",
"LLVMSystemZDisassembler",
"LLVMSystemZCodeGen",
"LLVMSystemZAsmParser",
"LLVMSystemZDesc",
"LLVMSystemZInfo",
"LLVMSystemZAsmPrinter",
"LLVMHexagonCodeGen",
"LLVMHexagonAsmPrinter",
"LLVMHexagonDesc",
"LLVMHexagonInfo",
"LLVMNVPTXCodeGen",
"LLVMNVPTXDesc",
"LLVMNVPTXInfo",
"LLVMNVPTXAsmPrinter",
"LLVMCppBackendCodeGen",
"LLVMCppBackendInfo",
"LLVMMSP430CodeGen",
"LLVMMSP430Desc",
"LLVMMSP430Info",
"LLVMMSP430AsmPrinter",
"LLVMXCoreDisassembler",
"LLVMXCoreCodeGen",
"LLVMXCoreDesc",
"LLVMXCoreInfo",
"LLVMXCoreAsmPrinter",
"LLVMMipsDisassembler",
"LLVMMipsCodeGen",
"LLVMMipsAsmParser",
"LLVMMipsDesc",
"LLVMMipsInfo",
"LLVMMipsAsmPrinter",
"LLVMAArch64Disassembler",
"LLVMAArch64CodeGen",
"LLVMAArch64AsmParser",
"LLVMAArch64Desc",
"LLVMAArch64Info",
"LLVMAArch64AsmPrinter",
"LLVMAArch64Utils",
"LLVMARMDisassembler",
"LLVMARMCodeGen",
"LLVMARMAsmParser",
"LLVMARMDesc",
"LLVMARMInfo",
"LLVMARMAsmPrinter",
"LLVMPowerPCDisassembler",
"LLVMPowerPCCodeGen",
"LLVMPowerPCAsmParser",
"LLVMPowerPCDesc",
"LLVMPowerPCInfo",
"LLVMPowerPCAsmPrinter",
"LLVMSparcDisassembler",
"LLVMSparcCodeGen",
"LLVMSparcAsmParser",
"LLVMSparcDesc",
"LLVMSparcInfo",
"LLVMSparcAsmPrinter",
"LLVMTableGen",
"LLVMDebugInfo",
"LLVMOption",
"LLVMX86Disassembler",
"LLVMX86AsmParser",
"LLVMX86CodeGen",
"LLVMSelectionDAG",
"LLVMAsmPrinter",
"LLVMX86Desc",
"LLVMX86Info",
"LLVMX86AsmPrinter",
"LLVMX86Utils",
"LLVMJIT",
"LLVMLineEditor",
"LLVMMCAnalysis",
"LLVMMCDisassembler",
"LLVMInstrumentation",
"LLVMInterpreter",
"LLVMCodeGen",
"LLVMScalarOpts",
"LLVMInstCombine",
"LLVMTransformUtils",
"LLVMipa",
"LLVMAnalysis",
"LLVMProfileData",
"LLVMMCJIT",
"LLVMTarget",
"LLVMRuntimeDyld",
"LLVMObject",
"LLVMMCParser",
"LLVMBitReader",
"LLVMExecutionEngine",
"LLVMMC",
"LLVMCore",
"LLVMSupport"
You don't have to determine the order yourself- use -llvm-config to get the LLVM order. The Clang order is a bit trickier- from memory, you need to extract it from makefiles used to build Clang itself, or something like that. However, the Clang list is pretty small so determining it is pretty easy given the LLVM order and that Clang must go before LLVM. I don't know where libclang goes in this list since I don't use it, but I'm guessing that it should go first.
The accepted answer by #Puppy does answer the OP's ultimate need -- how to get the libraries in required link order.
But it does not answer the OP's actual question -- how to use --start-group and --end-group.
The clang and gcc command line options are:
-Wl,--start-group
libs-in-the-order-you-need ...
-Wl,--end-group
Your mileage may vary on other compilers.
UPDATE (2019.07.11):
David Given points out that the gcc provided by default on OSX doesn't even support these options.
That is because OSX only provides gcc 2.x compatibility.
I was using gcc 4.8 and gcc 7.0 when I started using these options in my project.
I am not sure when they were first added to gcc.

How to compile DEC UNIX v4.0 application source code in Linux?

I want to compile a source code but I have trouble in compile.
cc -O2 -Olimit 2000 -g -migrate -assume -Zp1 noaligned_objects ...
cc: error: 2000: No such file or directory
cc: error: noaligned_objects: No such file or directory
cc: error: unrecognized command line option ‘-migrate’
cc: error: unrecognized command line option ‘-assume’
cc: error: unrecognized command line option ‘-Zp1’
Start with compiling it with no system-specific flags (i.e. by using gcc possibly with -I, -L, and -l flags and nothing else). If the program in question is portable enough, then it will be a matter of getting all dependencies available for it.
Once you are able to build it, see if it runs as expected (ignore performance). If it doesn't, that would be a good time to look at the flags you used on DEC to see if it requires any special treatment when building. This is where you either make the program portable or try to get the equivalent behavior using gcc on the target architecture of your choice.
Finally, once the program builds and runs, that would be a good time to see if you want to use any optimization flags (hint: you don't have to. If it runs fine, leave it the way it is).

How to compile a C++ program as 64-bit on 64-bit machine?

Perhaps a very trivial question:
I need to compile a program as 64-bit (earlier makefile written to compile it as 32-bit).
I saw the option -m32 appearing in command line parameters with each file compilation. So, I modified the makefile to get rid of -m32 in OPTFLAG, but again when the program compiles, I still see -m32 showing up and binaries are still 32-bit. Does this m32 come from somewhere else as well?
-m32 can only be coming from somewhere in your makefiles, you'll have to track it down (use a recursive grep) and remove it.
When I am able to force -m64, I get "CPU you selected does not support x86-64 instruction set".Any clues?. uname -a gives x86_64
That error means there is an option like -march=i686 in the makefiles, which is not valid for 64-bit compilation, try removing that too.
If you can't remove it (try harder!) then adding -march=x86-64 after it on the command line will specify a generic 64-bit CPU type.
If the software you are trying to build is autotools-based, this should do the trick:
./configure "CFLAGS=-m64" "CXXFLAGS=-m64" "LDFLAGS=-m64" && make
Or, for just a plain Makefile:
env CFLAGS=-m64 CXXFLAGS=-m64 LDFLAGS=-m64 make
If you are using CMake, you can add m64 compile options by this:
add_compile_options(-m64)