Using CMake for multi-language project in macOS - macos

I'm working on a project that contain files from the following languages *.c, *.cpp, *.m, *.mm.
In order to provide the correct file properties to each of the types above, I set variable to store the compilation flags per file type, and apply each file it's matching flags :
set(CPP_FLAGS "-x c++ -arch x86_64 -fmessage-length=0 -std=c++11")
set(OBJCPP_FLAGS "-x objective-c++ -std=gnu++11 -stdlib=libc++ ")
set(OBJC_FLAGS "-x objective-c -fobjc-arc")
set(C_FLAGS "-x c -arch x86_64")
function(set_src_files_according_to_language in_source_files)
foreach(src_file ${in_source_files})
if(${src_file} MATCHES .cpp$)
set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${CPP_FLAGS}")
elseif(${src_file} MATCHES ".mm$")
set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${OBJCPP_FLAGS}")
elseif(${src_file} MATCHES ".m$")
set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS "${OBJC_FLAGS}")
elseif(${src_file} MATCHES ".c$")
set_source_files_properties(${src_file} PROPERTIES COMPILE_FLAGS "${C_FLAGS}")
endif()
endforeach(SRC)
endfunction()
I wanted to get some advise about whether it's the correct way to achieve this goal?
thanks

Related

How to add the -nodefaultlibs options to an add_executable() command?

I have the CMakeLists.txt for building tests using g++:
file(GLOB sources *.cpp)
foreach(src ${sources})
get_filename_component(src ${src} NAME_WE)
string(REPLACE "our_prefix" "" bin ${src})
add_executable(${bin} ${src})
target_link_libraries(${bin} our options go here)
endforeach()
What I need to do is to add the option -nodefaultlibs to each test. I've tried to do it like this:
file(GLOB sources *.cpp)
foreach(src ${sources})
get_filename_component(src ${src} NAME_WE)
string(REPLACE "our_prefix" "" bin ${src})
add_executable(${bin} ${src})
set_target_properties(${bin} PROPERTIES
INTERFACE_COMPILE_OPTIONS "-nodefaultlibs"
)
target_link_libraries(${bin} our options go here)
endforeach()
But it seems to have no effect. I've also tried to use the command target_compile_options instead of set_target_properties - and it also had no effect.
Cmake generates the link.txt file for each test - I suppose this file describes the building command used for the test. This file doesn't contain my option -nodefaultlibs.
Could you please explain me what is the right way to add the -nodefaultlibs option?
-nodefaultlibs is a linker flag so use set_target_properties(${bin} PROPERTIES LINK_OPTIONS -nodefaultlibs) or target_link_libraries(${bin} PRIVATE -nodefaultlibs) or for CMake 3.2 set_target_properties(${bin} PROPERTIES LINK_FLAGS -nodefaultlibs).
INTERFACE_COMPILE_OPTIONS is used for something else and target_compile_options won't show up on the link line.
The link.txt file isn't always generated. When using MSYS Makefiles the linker flags show up in linklibs.rsp.

What is the signification of LDFLAGS

I'm trying to compile AODV for ARM linux. I use a SabreLite as a board with kernel version 3.0.35_4.1.0. It's worth mention that i'm using openembedded to create my Linux Distribution for my board.
The AODV source code (http://sourceforge.net/projects/aodvuu/) has a README file which give some indications on how to install it on ARM as stated a bit here.
(http://w3.antd.nist.gov/wctg/aodv_kernel/kaodv_arm.html).
I was able to upgrade the makefile in order to be used with post 2.6 kernel version ( as stated above, i have the 3.0.35_4.1.0 kernel version).
So, basically, what i am trying to do is that i have to create a module (let's say file.ko) and then load it into the ARM (with insmod file.ko command).
To do that, i am using a cross compiler which some values are stated below:
echo $CC :
arm-oe-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/usr/local/oecore-x86_64/sysroots/cortexa9hf-vfp-neon-oe-linux-gnueabi
echo $ARCH=arm
echo $CFLAGS: O2 -pipe -g -feliminate-unused-debug-types
echo $LD :
arm-oe-linux-gnueabi-ld --sysroot=/usr/local/oecore-x86_64/sysroots/cortexa9hf-vfp-neon-oe-linux-gnueabi
echo $LDFLAGS :
-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,--as-needed
when i launch "make command", i get the following errors:
LD [M] /home/scof/script_emulation/AODV/aodv-uu/lnx/kaodv.o
arm-oe-linux-gnueabi-ld: unrecognized option '-Wl,-O1'
arm-oe-linux-gnueabi-ld: use the --help option for usage information
It states that there is something wrong with the linker. This linker comes from the cross compilation tools and i normally shouldn't touch it.
Anyway, to get this above errors fixed, i try to withdraw the LDFLAGS like this:
export LDFLAGS='',
and after this, the make command works and i get the module kaodv.ko. But when i insert it into my ARM to check, it does not work. It actually freeze my terminal
So my question is, do i have to specify the LDFLAGS when compiling ? Does withdrawing LDFLAGS can have impact on the generated kernel module.
Actually, i try to understand where might be the problem and the only thing that come to me is that may be i should not change manually the LDFLAGS. But if i don't change de LDFLAGS, i get the unrecognized option error.
My second question related to that is, what are the possibly value of LDFLAGS
in ARM compilation
Thanks !!
echo $LDFLAGS : -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,--as-needed
There are two common methods of invoking the linker in a GCC-based toolchain. One is to do it directly, but another is to use GCC as a front end to invoke the linker, rather than invoke it directly. When doing this, options intended for the linker are prefixed with -Wl, so that GCC knows to pass them through rather than interpret them itself.
In your case the error message from LD itself
arm-oe-linux-gnueabi-ld: unrecognized option '-Wl,-O1'
Indicates that your build system is passing LDFLAGS directly to the linker, and not by way of GCC.
Therefore, you should remove the -Wl, prefix and your LDFLAGS would instead be
-O1 --hash-style=gnu --as-needed --as-needed
(the duplication of the last argument is probably pointless but benign)
-O1 is an option that tells the linker to optimize. I believe it something new, and your linker may be slightly out of date. Try removing -Wl,-O1, it should still work.

GNU LD: How to override a symbol value (an address) defined by the linker script specified using -T

My usecase is as follows:
I am using a typical SDK that comes with Makefile based projects
I belive the linker is patched gcc. gcc --version gives me 4.3.4
SDK defines the linker script (lets call it Linker.ld)
Linker.ld includes LinkerMemMap.cfg, which defines the absolute addresses for various sections in the linked ELF image
SDK provides application templates based on Makefiles (GNU Make 3.81) and make itself
In the SDK provided Makefile template, when gcc is invoked the Linker.ld is provided with -T command line option, as follows:
gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf
My requirement is as follows:
I would like to use the sections as defined in Linker.ld and use the memory map as per LinkerMemMap.cfg however tweak a particular symbol(lets call it SYMBOL_RAM_START) defined in LinkerMemMap.cfg
What works:
I have tried in the makefile, prior to linking the final ELF image, copy the LinkerMemMap.cfg (which is included by Linker.ld) to the build directory and patch it to redefine SYMBOL_RAM_START. This does work as the linker searches for the linker scripts and the files included by the linker scripts in the current folder first.
What doesn't:
Unfortunately our stakeholders think the above method is too risky and complex to understand. I would like to override the symbol value on the linker command line with something like below:
gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections,--defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf
gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf
gcc $(OBJS) -l$(Lib1) -l$(Lib2) --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf
None of these seem to have any effect on the linked image created by the linker.
Can --defsym override the symbols defined by linkerscript specified using -T?
Could any of you please see what am I doing wrong here?
While waiting for someone to respond, I did resolve the issue. There are few issues with the problem here and I thought of explaining my findings for someone who might do the same mistake.
First of all Any options to be passed to the linker must be specified with -Xlinker or with -Wl. Hence both 2 and 3 won't work in the above case. The corrected 2 and 3 would be as follows:
Is correct already
gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -Xlinker --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf
gcc $(OBJS) -l$(Lib1) -l$(Lib2) -Xlinker --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf
Now for the case of options 1 & 2 above, --defsym comes after linker script and SYMBOL_RAM_START was already defined by the linker script. It does override it. But the overriden value will not be used, because the sections have already been defined as the linker script has already been used.
For the case of option 3 above, the SYMBOL_RAM_START was defined before the linker script was read by the linker. Hence when linker script is parsed, the value specified in the script overrides it.
Solution:
In order for this to work, the linker script will need to conditionally initialize the symbol SYMBOL_RAM_START, something like below:
SYMBOL_RAM_START = DEFINED( SYMBOL_RAM_START ) ? SYMBOL_RAM_START : DEFAULT_VALUE ;
Given the above in the linker script, when the SYMBOL_RAM_START was defined before the linker script is included (as shows in option 3 above) it did work. But in the end I had to patch the linker script.
This solution doesn't really override the symbol, but provides a way in which a symbol can be defined so that it can be overridden.

what's the difference between DLDFLAGS and LDFLAGS

A quick question. I found both "DLDFLAGS" and "LDFLAGS" in a sample Makefile. The compiler used is gcc. It looks like they are both used for linkers. I'm wondering what's the difference between them.
LDFLAGS is normally set to contain options that are passed through to the linker (so may include required libraries). Together with CFLAGS, these are often set as part of a developers environment variables and make will know about them so will actively look to see if they're set and pass them through to the compiler.
For example, if I set CFLAGS in my environment to -O2 -Wall, then if I type make hello with no Makefile, make will automatically invoke the compiler as gcc -O2 -Wall hello.c -o hello.o. Then it'll invoke the linker in a similar way, adding the flags in LDFLAGS to the command line.
Makefiles can explicitly override both LDFLAGS and CFLAGS.
DLDFLAGS on the other hand is not a well known/defined variable, so it's likely to be specific to that particular Makefile. You'd have to read the Makefile to find out how it's used. It may, for example, define linker flags to use if LDFLAGS is set - read the Makefile to find out for sure.
Isn't DLDFLAGS just a precompiler flag that defines macro named "LDFLAGS"?
From gcc manual:
-D name
Predefine name as a macro, with definition 1

gcc compiling linking .a file

in my homework i must use this command to compile my program:
gcc -o mtm_rentals -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG mtm_ex2.c rentals.c list.c -L -lmtm
what i can change in that line are the files im writing after -DNDEBUG. when i do this the gcc says that there are undefined references to specific functions. now those functions are declared in an .h file and are implemented in a given file called libmtm.a
i concluded that it doesnt recognize libmtm.a, but our homework task says that the -lmtm flag(which is not declared anywhere) is supposed to link libmtm.a to the program.
what am i missing here? am i supposed to implement somehow the -lmtm flag?
thank you!
You are missing a . (single dot) behind the -L.
-lmtm will link against a libmtm library, this is correct. It's not an -lmtm flag, it's a -l flag concatenated with mtm, the library you want to link against. This library is searched in some predefined paths (like /usr/lib/) and additionally in the paths given by -L. Assuming libmtm lives in your current directory, you need to add that to -L, which is done with a ..

Resources