How do I tell CMake to specify multiple linker script files to GCC? - gcc

I"m using CMake 3.17 and the GNU ARM toolchain and I'm trying to migrate a build from Eclipse to CMake. Part of the Eclipse build specifies multiple linker script files to use at link time so I set up my CMakeLists.txt file like this:
target_link_options(${application_name} PRIVATE
-mcpu=cortex-m4
-mthumb
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-fmessage-length=0
-fsigned-char
-ffunction-sections
-fdata-sections
-flto
-Wall
-Xlinker --gc-sections
-Wl,-Map,${map_file}
-T ${CMAKE_SOURCE_DIR}/ldscripts/libs.ld
-T ${CMAKE_SOURCE_DIR}/ldscripts/mem.ld
-T ${CMAKE_SOURCE_DIR}/ldscripts/sections.ld
)
But when I run make the -T option gets swallowed for the second and third files. Here's what I get when running make VERBOSE=1 after successful compilation of all sources. The linker command line followed by a warning about missing -T options:
Linking CXX executable StartupSequence.elf
/D/gcc-arm-none-eabi-9-2019-q4/bin/arm-none-eabi-g++.exe --specs=nano.specs --specs=nosys.specs -g -Og -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -flto -Wall -Xlinker --gc-sections -Wl,-Map,StartupSequence.map -T C:/svn/startup_sequence/ldscripts/libs.ld C:/svn/startup_sequence/ldscripts/mem.ld C:/svn/startup_sequence/ldscripts/sections.ld #CMakeFiles/StartupSequence.dir/objects1.rsp -o StartupSequence.elf ../Drivers/CMSIS/DSP/Lib/libarm_cortexM4lf_math.a ../Middlewares/Third_Party/mbedTLS/library/libmbedcrypto.a
d:/gcc-arm-none-eabi-9-2019-q4/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: warning: C:/svn/startup_sequence/ldscripts/sections.ld contains output sections; did you forget -T?
Why does the -T not get sent to the command line properly for the last two files?
I've tried separating the link script specification into three separate calls to target_link_options and enclosing each script specification in double quotes but it seems to have no effect.

By default, CMake de-duplicates compile and link options. That is, multiple -T options are combined into the single one.
CMake doesn't know which options are actually bonded with the further arguments, but provides a SHELL: mechanism for define such options:
target_link_options(${application_name} PRIVATE
"SHELL:-T ${CMAKE_SOURCE_DIR}/ldscripts/libs.ld"
"SHELL:-T ${CMAKE_SOURCE_DIR}/ldscripts/mem.ld"
"SHELL:-T ${CMAKE_SOURCE_DIR}/ldscripts/sections.ld"
)
This mechanism is described in the documentation for target_link_options command.
The same mechanism works for compiler options passed to target_compile_options, see that question and my answer for it.

Because -T is interpreted as an single option. Glue -T with the path instead. Try:
-T${CMAKE_SOURCE_DIR}/ldscripts/libs.ld
-T${CMAKE_SOURCE_DIR}/ldscripts/mem.ld
-T${CMAKE_SOURCE_DIR}/ldscripts/sections.ld

Related

Problem with autoconf not making gcc with -Wall warnings

I have a simple project with a simple configure.ac script:
AC_INIT(...)
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES(...)
AC_OUTPUT
using GNU Autoconf version 2.69 (OpenSUSE Linux with gcc 9.2.1), but gcc is being called with no warning flags:
gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -MT aprog.o -MD -MP -MF .deps/aprog.Tpo -c -o aprog.o aprog.c
mv ...
gcc -g -O2 -o aprog aprog.o -lgmp
In particular, I found -Wformat not working. Shouldn't -Wall include -Wformat? And shouldn't all warnings appear on the make line? If I run gcc line directly with -Wformat the warning shows in compile but it doesn't when I run autoconf, configure and make.
What I'm doing wrong?
The -Wall flag in the AM_INIT_AUTOMAKE(...) invocation refers to warnings from automake and related tools like aclocal, not to compiler warnings. You will see these warnings when you are running autoreconf.
Note that while you can also add -Werror to AM_INIT_AUTOMAKE(...) to make your autoreconf run fail on warnings, many common macros (like those shipped with gettext or libtool) will still use deprecated macros which generates a warning, so -Werror means you cannot use this standard set of tools, so -Werror is not very useful in many cases.
If you want to add compiler options, there are a third party macros (e.g. AX_CHECK_COMPILE_FLAG) which test whether the compiler recognizes a given compile option and you can then add them to some variable and use that in places. That is a different stackoverflow question, though.

Cmake command line too long windows

From my understanding of cmake, the tool takes care of file path and command lines length to avoid reaching windows limitation of 8191 characters.
However I'm cross compiling with arm_none_eabi on windows and cmake doesn't generate a makefile using response files or any other workaround for the path length. Thus the link step fails.
Here is the generated makefile line that causes issue
XXXXX_EXTERNAL_OBJECTS =
XXXX_OBJECTS = \
"file1.c.obj" \
"file2.c.obj" \
"file3.c.obj" \
"fileXX.c.obj" \
C:/YYYY/GNU_Tools_ARM_Embedded/6-2016-q4-major/bin/arm-none-eabi-gcc.exe -mcpu=cortex-m4 -mthumb -DSTM32L4__xx -mfloat-abi=softfp -DXXXX -O0 -g -Wfatal-errors -Wall -Wno-unused-function -std=c99 -fdata-sections -ffunction-sections -mcpu=cortex-m4 -march=armv7e-m -O0 -g --specs=nano.specs -mthumb -Wl,--gc-sections -nostartfiles -Wl,-Map=$#.map -TC:SSSSSSSSS/STM32L4__RGTx_FLASH.ld $(XXXX_OBJECTS) $(XXXXX_EXTERNAL_OBJECTS) -o outHexFile_XXXX -LC:/YYYYYYYYYYYYYYYY/arm-nano-eabi/lib
The final line length is about 23000 characters (far over 8191).
Why is Cmake not generating a makefile usable by windows ?
Is this only because I am cross-compiling ?
What can I do to avoid this issue ?
EDIT
Generator is GNU Makefiles
CMake Version 3.7.2
EDIT 2
this may be automatically handled in future versions
submited bug
Turning my comment into an answer
I had the same problem with the command line length and could solve it with adding the following "use response file" settings to my toolchain file:
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_C_RESPONSE_FILE_LINK_FLAG "#")
SET(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "#")
And if you would have had used ninja you would need an additional:
SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "")

g++ linker options changes target file name

I need help it is bug or I don't understand how compilation options are working ?
I have sample main.c file and try to compile it as:
$ g++ -nostdlib -g -fno-rtti -fno-exceptions -ffreestanding -nostdinc -nostdinc++ -Wl,--build-id=none,-g,-nostdlib,-nostartfiles,-zmax-page-size=0x1000 main.c -o main
and as output I have this:
$ ls
main.c startfiles
I am trying to understand why g++ created file named "startfiles" not "main" ?
If you read the GNU ld official documentation you will see that there is no option named -nostartfiles. What you do pass for arguments to the linker with that is the options -n and -ostartfiles.
If I were you, I would check those other options you try to pass to the linker as well.
-nostartfiles is a compiler flag as far as I know, not a linker flag.
For the linker, it's the same as -n -o startfiles, which is why you're getting that output file name.

gcc -S not working?

I am trying to have a look at assembly code generated by g++. The normal way is -S. As I also want the corresponding source code, I am adding a -fverbose-asm. (I tried both with and without.)
I expect a .s file to be generated, but none is.
What am I doing wrong ?
Invoking: Cross G++ Compiler
arm-angstrom-linux-gnueabi-g++ -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp -flax-vector-conversions -S -fverbose-asm -DNAMESPACE -I/usr/local/angstrom/arm/lib/gcc/arm-angstrom-linux-gnueabi/4.3.3/include -O2 -Wall -c -fmessage-length=0 -Wl,-rpath-link,/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib,--hash-style=gnu -mthumb-interwork -mno-thumb -isystem/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/include -fexpensive-optimizations -frename-registers -fomit-frame-pointer -fpermissive -fPIC -mfpu=neon -MMD -MP -MF"Src/Kernel Filters SSEI.d" -MT"Src/Kernel\ Filters\ SSEI.d" -o "Src/Kernel Filters SSEI.o" "../Src/Kernel Filters SSEI.cpp"
Your assembly output is the file Src/Kernel Filters SSEI.o
Another issue is that -MT seems used incorrectly, it causes the target of the generated dependency to be the dependency file itself, rather than the object file.
You should not have any -o option to GCC to get the .s file. You are correct in passing -fverbose-asm -S to it. You may want some optimization, e.g. -O1
I suspect that your Src/Kernel Filters SSEI.o file may contain assembly code. I also strongly recommend avoiding spaces in your source or object file name. Name it Kernel_Filters_SSEI.cpp

gcc and linking files with CFLAGS

I am trying to run program from the Learn C Hard Way book
I need to pass the library filename 'build/liblcthw.a' as the last parameter.
For eg :
Doesnt Work on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
Works on Ubuntu :
gcc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG tests/list_tests.c -o tests/list_tests build/liblcthw.a
How do I handle this in Makefile ? CFLAGS will only add it before the source filename and it doesnt work. How do I force CFALGS to add the library filename at the end of the command ?
CFLAGS are flags for the C compiler. Libraries typically go into a variable called LDLIBS. Set LDLIBS=build/liblcthw.a and see if that works.
The first invocation doesn't succeed because the order of sources and libraries in the command line is wrong. The correct order is source files, then object files, followed by static libraries followed by dynamic libraries.

Resources