gcc and AMD Open64 opencc both have a -s option to "strip symbol table and relocation information". So far I haven't been able to find the same option in Clang/LLVM. Does it exist?
You can use a strip utility from binutils.
Actually, a llvm-ld has this options http://llvm.org/cmds/llvm-ld.html
-strip-all, -s Strip all debug and symbol information from the executable
to make it smaller.
-strip-debug, -S Strip all debug information from the executable to
make it smaller.
opt have something too:
-strip-debug
This option causes opt to strip debug information from the module before applying other
optimizations. It is essentially the same as -strip but it ensures that stripping of debug
information is done first.
Related
I want to setup a custom toolchain with CMake. I've set the compiler but I don't know how to set the linker. This error is reported because CMake try to use the compiler to link:
The C compiler "xgcc.exe" is not able to compile a simple test program.
Here there is a snippet of my toolchain file
# specify the cross compiler
INCLUDE(CMakeForceCompiler)
SET(CMAKE_C_COMPILER xgcc.exe)
SET(CMAKE_CXX_COMPILER xgcc.exe)
#CMAKE_FORCE_C_COMPILER(xgcc.exe GNU)
#CMAKE_FORCE_CXX_COMPILER(xgcc.exe GNU)
I've tried to force the compiler but the linker problem will not be solved.
The link command line is set in Modules/CMake{C,CXX,Fortran}Information.cmake and defaults to using the compiler, not CMAKE_LINKER (see source code). This can be changed by replacing the rule that builds the link command line, which lives in variables CMAKE_CXX_LINK_EXECUTABLE (and friends). NB that variable does not indicate the path to the linker executable; it says how to link an executable!
One approach is to set that rule to use the linker, e.g.
cmake -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"
See also this post from CMake mailing list and this one - this also makes a natural place to prepend a linker modifier to another linker.
As Mabraham points out, CMake calls the compiler to do the linking. So, by far the simplest solution to this is to LET IT, and instead tell the compiler to run a different linker when called.
Which, as noted in this other answer — but now it's even a documented option in gcc --help=common — is as easy as:
cmake -DCMAKE_CXX_FLAGS="-fuse-ld=lld"
g++ or clang++ will get passed the -fuse-ld=lld1 flag on every call, and when they do any linking they'll use the specified command instead of the built-in default. Easy-peasy, and CMake need not concern itself with such things at all.
(BTW, the option is parsed (-f) (use-ld) (=) (lld), there's no "fuse" option to gcc.)
Notes
When using Clang, lld can be replaced with whatever other linker command you want to use, like ld.exe, ld.gold, mingw32/bin/ld.exe, etc.
GCC isn't as flexible, its -fuse-ld only accepts one of three possible arguments: lld, bfd, or gold. It will invoke the first matching ld.foo executable it finds on the PATH. (Thanks to bviktor for pointing out GCC's limitations for alternate linker selection.)
CMake only gives you direct control over the compiler for each language. To call the linker, it goes through the configured compiler. This means that there is no universal way to set the linker in CMake, you must configure your compiler to use the linker you intend.
Such flags need to be set before CMake's compiler detection routines run because it will try to compile a test binary. The best way to do this is by creating a toolchain file. The best way to set these flags in the toolchain file is like so:
# e.g. to use lld with Clang
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
These three variables control the (default) set of linker flags for executables, loadable modules, and shared libraries, respectively. There is no need to handle CMAKE_STATIC_LINKER_FLAGS_INIT (for static libraries) here because the archiver is invoked, rather than the linker.
You can then set the toolchain file when you first run CMake by setting -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake at the command line. As of CMake 3.21, you will be able to pass --toolchain /path/to/toolchain.cmake instead (which is entirely equivalent, but a little less typing).
Set the variable ${CMAKE_LINKER} either in CMakeCache.txt or after ccmake . under advanced options.
I have to use CMAKE_CXX_LINK_EXECUTABLE, CMAKE_C_LINK_EXECUTABLE variable:
SET(CMAKE_C_LINK_EXECUTABLE "c:\\MoSync\\bin\\pipe-tool.exe")
I had success with doing
add_link_options("-fuse-ld=lld")
It is a variation on the previous answers here. The difference is the CMake command I use to set the flag.
Adding it to CMAKE_CXX_FLAGS has the disadvantage of then also having to add -Wno-unused-command-line-argument as the flags get also added to compilation commands, not only to linking ones.
The disadvantage of CMAKE_SHARED_LINKER_FLAGS is that you have to add it multiple times, to _SHARED_, _EXE_, and maybe I forgot something.
Here is a CMake function which sets linker based on some predefined arbitrary rules (Clang -> lld-version or lld, GCC -> gold).
The important parts:
Search for lld-version which matches the Clang compiler version (ex. lld-13 if Clang 13.x.x is used), falls back to lld if not found
add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR}")
Use all system threads when linker is set to gold:
add_link_options("-fuse-ld=gold;LINKER:--threads,--thread-count=${HOST_PROC_COUNT}")
The example is a bit too long because of comments, logs and custom logic, but it is self-contained and could be useful staring point for beginners.
function(select_best_linker) #lld for Clang and GNU gold for GCC
if (UNIX AND NOT APPLE)
include(ProcessorCount)
ProcessorCount(HOST_PROC_COUNT)
if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
# By default LLD uses all system threads.
# This could be tweaked for versions 11+ (--threads=1), but cannot be disabled for older versions
# add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR};LINKER:--threads=${HOST_PROC_COUNT}") #LLD>=11
# add_link_options("-fuse-ld=lld;LINKER:--threads")#LLD <= 10 this is the default state
string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
list(GET VERSION_LIST 0 CLANG_VERSION_MAJOR) #extract major compiler version
find_program(LLD_PROGRAM_MATCH_VER lld-${CLANG_VERSION_MAJOR}) #search for lld-13 when clang 13.x.x is used
find_program(LLD_PROGRAM lld) #else find default lld
if (LLD_PROGRAM_MATCH_VER) #lld matching compiler version
message(STATUS "Set linker to LLD (multi-threaded): ${LLD_PROGRAM_MATCH_VER}")
add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR}")
elseif(LLD_PROGRAM) #default lld
message(STATUS "Set linker to LLD (multi-threaded): ${LLD_PROGRAM}")
add_link_options("-fuse-ld=lld")
endif(LLD_PROGRAM_MATCH_VER)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
find_program(GNU_GOLD_PROGRAM gold)
if (GNU_GOLD_PROGRAM)
message(STATUS "Set linker to GNU gold: ${GNU_GOLD_PROGRAM}, using threads: ${HOST_PROC_COUNT}")
add_link_options("-fuse-ld=gold;LINKER:--threads,--thread-count=${HOST_PROC_COUNT}")
endif(GNU_GOLD_PROGRAM)
endif(${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
endif(UNIX AND NOT APPLE)
endfunction(select_best_linker)
Tested on:
Ubuntu 20.04
CMake 3.16.3
GCC 9.4.0
Clang-12
Clang-13
GNU gold (GNU Binutils 2.37) 1.16
LLD 10.0.0 (compatible with GNU linkers)
Ubuntu LLD 13.0.1 (compatible with GNU linkers)
For completeness, another full-proof option is to just link /usr/bin/ld to ld.gold by running
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
as suggested here
There is another way to do it, gcc has a "-fuse-ld" option, you can set LINKER_FLAGS in CMakeLists.txt like these:
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
then the custom specified linker should be invoked.
Cross compiling an executable for an embedded system with CMake requires me to manually add link options to link libc, libgcc and whatnot. However using target_link_options for that results in a linker call where all those additional link options are added in front of all the object files generated from my actual code. I believe that this is the wrong linking order and it causes "duplicate symbol errors" whenever I try to overwrite weak symbols from the standard library (e.g. __cxa_pure_virtual).
Here is an exemplar of the output I get from the linking stage
"/usr/bin/ld.lld"
--gc-sections
/usr/arm-none-eabi/lib/crt0.o
/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/crti.o
/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/crtbegin.o
/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/crtn.o
/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/crtend.o
--start-group -lstdc++_nano -lm -lgcc -lc_nano --end-group
my.obj ///< Shoudln't object files and application libs be linked first?
libmylib.a
-Bstatic
-L/usr/lib/clang/10.0.0/lib/baremetal
-L/usr/arm-none-eabi/lib/thumb/v7e-m+fp/hard/
-L/usr/lib/gcc/arm-none-eabi/10.1.0/thumb/v7e-m+fp/hard/
-T ldscript.ld
-o myelf
Is there any way to solve this in CMake?
target_link_options specifies options to the linker - and typically options are specified before anything else. Use target_link_libraries to link with libraries.
I'd like to be able to view preprocessor output in order to make sure my preprocessor directives run correctly. Dev-C++ has an option in Tools > Compiler Options... > General to add commands when calling the compiler, and I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file didn't exist, but shouldn't the compiler just create the file in that case? I created the file, and now I'm getting this error: cannot specify -o with -c, -S or -E with multiple files.
Why am I using Dev-C++ instead of Visual Studio? Since I'm still learning, I'd like to be able to test just a few lines of code without having to create an entire new project.
Yes, I've seen this question and no adequate answer was given. Please don't mark this as a duplicate.
Thanks in advance for your help!
I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file
didn't exist, but shouldn't the compiler just create the file in that case?
No, because the -E option
takes no argument, filename or otherwise. It simply instructs the
compiler to do nothing but preprocessing. The preprocessed code is written to the standard output. Thus:
Thus:
g++ -E C:\Personal\preprocessed.cpp foo.cpp
tells the compiler that you want run g++ -E with the pair of input files C:\Personal\preprocessed.cpp and foo.cpp,
which as you've discovered is not allowed.
The simple thing that you want to do is absurdly difficult with your IDE of choice. Assuming
the source file you want to preprocess is C:\Personal\foo.cpp and the g++ is in your PATH,
just open a command window in C:\Personal and run:
g++ -E foo.cpp > foo.ii
I suggest the output file foo.ii - though you can call it whatever you like - because g++ recognizes the extension .ii as denoting C++ source code that has already been preprocessed. You can run:
g++ -Wall -o prog foo.ii
and foo.ii will be compiled and linked as program prog without being preprocessed again.
I have a make file that contains this code:
all: main.o Etudiant.o
gcc -lobjc -o program main.o Etudiant.o
main.o:main.m Etudiant.h
gcc -c main.m
Etudiant.o:Etudiant.m Etudiant.h
gcc -c Etudiant.m
When I write this in the shell command:
$make
I got this:
make: **** No targets specified and no makefile found. Stop.
How do I fix this?
Mmm... makefiles. Whee.
All that whitespace at the beginning of the line. That has to be tabs. Or Make will barf up a really obscure error. Make sure those are tabs and try again.
See the button on the left side of the keyboard labeled "tab". Delete the spaces and hit that once to insert a tab character.
Try make all. IIRC (been a few years since I've had to muck with makefiles) most makes will default to all, but maybe yours isn't.
Extension doesn't matter.
Holy Heck! We are all Extra Dense(#bbum mostly so)!
"no Makefile found" means... well.. that Make didn't even see the makefile. The suggestions to rename the Makefile.m to Makefile are correct. As well, the whole tab vs. whitespace thing is certainly pertinent.
and no makefile found
If you just type make with no arguments or make all, make will look for a file called Makefile in the current directory. If it's not there, you get the error you saw. make will not look in subdirectories for Makefile nor will it accept a file called Makefile.m.
In my case, the my makefile had the name MakeFile, changing it to Makefile worked
Re:
$ Make
Make: * No targets specified and no makefile found. Stop.
I just had this error and found that the Makefile extension (none) had been converted to .bat somewhere along the line.
Just spent a few insanely frustrating moments with this error. My mistake was not all that subtle: I titled the makefile MakeFile not Makefile, so even using the -f Makefile command (forcing the makefile name) still resulted in not-found, because it was MakeFile, not Makefile.
I want to setup a custom toolchain with CMake. I've set the compiler but I don't know how to set the linker. This error is reported because CMake try to use the compiler to link:
The C compiler "xgcc.exe" is not able to compile a simple test program.
Here there is a snippet of my toolchain file
# specify the cross compiler
INCLUDE(CMakeForceCompiler)
SET(CMAKE_C_COMPILER xgcc.exe)
SET(CMAKE_CXX_COMPILER xgcc.exe)
#CMAKE_FORCE_C_COMPILER(xgcc.exe GNU)
#CMAKE_FORCE_CXX_COMPILER(xgcc.exe GNU)
I've tried to force the compiler but the linker problem will not be solved.
The link command line is set in Modules/CMake{C,CXX,Fortran}Information.cmake and defaults to using the compiler, not CMAKE_LINKER (see source code). This can be changed by replacing the rule that builds the link command line, which lives in variables CMAKE_CXX_LINK_EXECUTABLE (and friends). NB that variable does not indicate the path to the linker executable; it says how to link an executable!
One approach is to set that rule to use the linker, e.g.
cmake -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"
See also this post from CMake mailing list and this one - this also makes a natural place to prepend a linker modifier to another linker.
As Mabraham points out, CMake calls the compiler to do the linking. So, by far the simplest solution to this is to LET IT, and instead tell the compiler to run a different linker when called.
Which, as noted in this other answer — but now it's even a documented option in gcc --help=common — is as easy as:
cmake -DCMAKE_CXX_FLAGS="-fuse-ld=lld"
g++ or clang++ will get passed the -fuse-ld=lld1 flag on every call, and when they do any linking they'll use the specified command instead of the built-in default. Easy-peasy, and CMake need not concern itself with such things at all.
(BTW, the option is parsed (-f) (use-ld) (=) (lld), there's no "fuse" option to gcc.)
Notes
When using Clang, lld can be replaced with whatever other linker command you want to use, like ld.exe, ld.gold, mingw32/bin/ld.exe, etc.
GCC isn't as flexible, its -fuse-ld only accepts one of three possible arguments: lld, bfd, or gold. It will invoke the first matching ld.foo executable it finds on the PATH. (Thanks to bviktor for pointing out GCC's limitations for alternate linker selection.)
CMake only gives you direct control over the compiler for each language. To call the linker, it goes through the configured compiler. This means that there is no universal way to set the linker in CMake, you must configure your compiler to use the linker you intend.
Such flags need to be set before CMake's compiler detection routines run because it will try to compile a test binary. The best way to do this is by creating a toolchain file. The best way to set these flags in the toolchain file is like so:
# e.g. to use lld with Clang
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
These three variables control the (default) set of linker flags for executables, loadable modules, and shared libraries, respectively. There is no need to handle CMAKE_STATIC_LINKER_FLAGS_INIT (for static libraries) here because the archiver is invoked, rather than the linker.
You can then set the toolchain file when you first run CMake by setting -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake at the command line. As of CMake 3.21, you will be able to pass --toolchain /path/to/toolchain.cmake instead (which is entirely equivalent, but a little less typing).
Set the variable ${CMAKE_LINKER} either in CMakeCache.txt or after ccmake . under advanced options.
I have to use CMAKE_CXX_LINK_EXECUTABLE, CMAKE_C_LINK_EXECUTABLE variable:
SET(CMAKE_C_LINK_EXECUTABLE "c:\\MoSync\\bin\\pipe-tool.exe")
I had success with doing
add_link_options("-fuse-ld=lld")
It is a variation on the previous answers here. The difference is the CMake command I use to set the flag.
Adding it to CMAKE_CXX_FLAGS has the disadvantage of then also having to add -Wno-unused-command-line-argument as the flags get also added to compilation commands, not only to linking ones.
The disadvantage of CMAKE_SHARED_LINKER_FLAGS is that you have to add it multiple times, to _SHARED_, _EXE_, and maybe I forgot something.
Here is a CMake function which sets linker based on some predefined arbitrary rules (Clang -> lld-version or lld, GCC -> gold).
The important parts:
Search for lld-version which matches the Clang compiler version (ex. lld-13 if Clang 13.x.x is used), falls back to lld if not found
add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR}")
Use all system threads when linker is set to gold:
add_link_options("-fuse-ld=gold;LINKER:--threads,--thread-count=${HOST_PROC_COUNT}")
The example is a bit too long because of comments, logs and custom logic, but it is self-contained and could be useful staring point for beginners.
function(select_best_linker) #lld for Clang and GNU gold for GCC
if (UNIX AND NOT APPLE)
include(ProcessorCount)
ProcessorCount(HOST_PROC_COUNT)
if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
# By default LLD uses all system threads.
# This could be tweaked for versions 11+ (--threads=1), but cannot be disabled for older versions
# add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR};LINKER:--threads=${HOST_PROC_COUNT}") #LLD>=11
# add_link_options("-fuse-ld=lld;LINKER:--threads")#LLD <= 10 this is the default state
string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
list(GET VERSION_LIST 0 CLANG_VERSION_MAJOR) #extract major compiler version
find_program(LLD_PROGRAM_MATCH_VER lld-${CLANG_VERSION_MAJOR}) #search for lld-13 when clang 13.x.x is used
find_program(LLD_PROGRAM lld) #else find default lld
if (LLD_PROGRAM_MATCH_VER) #lld matching compiler version
message(STATUS "Set linker to LLD (multi-threaded): ${LLD_PROGRAM_MATCH_VER}")
add_link_options("-fuse-ld=lld-${CLANG_VERSION_MAJOR}")
elseif(LLD_PROGRAM) #default lld
message(STATUS "Set linker to LLD (multi-threaded): ${LLD_PROGRAM}")
add_link_options("-fuse-ld=lld")
endif(LLD_PROGRAM_MATCH_VER)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
find_program(GNU_GOLD_PROGRAM gold)
if (GNU_GOLD_PROGRAM)
message(STATUS "Set linker to GNU gold: ${GNU_GOLD_PROGRAM}, using threads: ${HOST_PROC_COUNT}")
add_link_options("-fuse-ld=gold;LINKER:--threads,--thread-count=${HOST_PROC_COUNT}")
endif(GNU_GOLD_PROGRAM)
endif(${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
endif(UNIX AND NOT APPLE)
endfunction(select_best_linker)
Tested on:
Ubuntu 20.04
CMake 3.16.3
GCC 9.4.0
Clang-12
Clang-13
GNU gold (GNU Binutils 2.37) 1.16
LLD 10.0.0 (compatible with GNU linkers)
Ubuntu LLD 13.0.1 (compatible with GNU linkers)
For completeness, another full-proof option is to just link /usr/bin/ld to ld.gold by running
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
as suggested here
There is another way to do it, gcc has a "-fuse-ld" option, you can set LINKER_FLAGS in CMakeLists.txt like these:
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
then the custom specified linker should be invoked.