How does gcc make use of __builtin_<target>_func functions during compilation - gcc

When compiling gcc for a aarch64 target, I see several __builtin_aarch64_##func## functions in the include/arm_neon.h file in the build directory.
For example,
__extension__ extern __inline float64_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vmulxd_f64 (float64_t __a, float64_t __b)
{
return __builtin_aarch64_fmulxdf (__a, __b);
}
Where is the definition of __builtin_aarch64_fmulxdf() ? I cannot figure out how these builtins connect to the target specific md files.
Does the above mean the only way to generate this instruction is via an explicit call to this GCC extension ?

These __builtin_aarch64_* functions are AArch64-specific GCC builtins. They are primarily used to implement the intrinsics in arm_neon.h.
GCC defines them internally in its code, not in some header file. They are not documented anywhere as they can be changed from release to release and users should not be relying on their behaviour.
The Advanced SIMD intrinsics in arm_neon.h are documented and defined in ACLE (https://developer.arm.com/technologies/neon/intrinsics for example) so you should be using those.
The target-specific builtins themselves are just an implementation detail in this context.

Related

Link a static library to object in cmake

I am trying to compile a project using cmake. I need to use an external static library in src1.c so I utilized target_link_libraries to link it to the object file. However, I am getting some complains about missing functions in src1.c which should be in the external library.
add_library(input_output OBJECT
src/src1.c
src/src2.c
src/src3.c)
find_library(EXTERNAL_LIB NAMES libexternallib.a PATHS ~/lib)
target_link_libraries(input_output PRIVATE
"${EXTERNAL_LIB}")
So I am not sure what I should do at this point. the logic sounds right at least
UPDATE1: I also added the external library directly into the linker command
add_compile_options(-Wall -Wextra --std=c99 -L~/lib -lexternallib)
add_link_options(-L~/lib -lexternallib)
but this added the library flags before the object file for the linker command, which leads to some other problem with ordering the linker arguments
It's hard to say what is really the reason for your error here, but I'll give it a try.
First of all, you don't need to link manually with add_compile_options or add_link_options. The cmake command target_link_libraries is doing that for you.
What I could imagine, because of the missing functions, that you need to add a header include directory from the dependency.
e.g.:
target_include_directories(input_output PRIVATE /path/to/external_library_header)

Why does cmake always use `-isystem` on imported interface target?

I'm trying to write a CMakeLists.txt to compile my Arduino-Projects to get to know cmake better.
I defined the Arduino-Core library as an imported interface and try to link my own target against it. The problem is, that, when calling make the avr-gcc is provided with the specified include-paths via -isystem instead of -I. This results in several errors.
CMakeLists.txt (minimal-version to reproduce the problem)
cmake_minimum_required(VERSION 3.1)
set(ARDUINO_DIR "/opt/arduino/arduino-1.8.13")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-gcc)
set(CMAKE_CXX_COMPILER ${ARDUINO_DIR}/hardware/tools/avr/bin/avr-g++)
set(CMAKE_SYSTEM_NAME NONE)
set(CMAKE_SYSTEM_PROCESSOR NONE)
add_library(Arduino::Core INTERFACE IMPORTED)
target_include_directories(Arduino::Core INTERFACE
"${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/"
"${ARDUINO_DIR}/hardware/arduino/avr/variants/eightanaloginputs/"
)
file(GLOB_RECURSE ARDUINO_CORE_SRC "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.c[p]*")
file(GLOB_RECURSE ARDUINO_CORE_ASM "${ARDUINO_DIR}/hardware/arduino/avr/cores/arduino/*.S")
target_sources(Arduino::Core INTERFACE ${ARDUINO_CORE_SRC} ${ARDUINO_CORE_ASM})
project(Blinky)
set(${PROJECT_NAME}_SRC
src/Blink.cpp
)
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SRC})
target_link_libraries(${PROJECT_NAME} Arduino::Core)
Here is my Blink.cpp:
#include <Arduino.h>
void setup()
{
pinMode(13,OUTPUT);
}
void loop()
{
digitalWrite(13,HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
make --trace gives me the following output:
[ 5%] Building CXX object CMakeFiles/Blinky.dir/src/Blink.cpp.obj
/opt/arduino/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/cores/arduino -isystem /opt/arduino/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs -std=gnu++11 -o CMakeFiles/Blinky.dir/src/Blink.cpp.obj -c /tmp/so/src/Blink.cpp
As you can see, linking against the imported target includes the dependencies with -isystem even though I haven't declared SYSTEM anywhere? How can I prevent that?!
Is it, because it is an INTERFACE IMPORTED target?
I tried taget_include_directories(Arduino::Core PRIVATE ${my_include_dirs}) but obviously that is not allowed for INTERFACE-Targets.
Thanks in advance for every hint.
P.S. please note, that I'm aware, that this would not compile my arduino-code. This is just a mcve to show you my problem.
edit
I'm using Arduino-SDK 1.8.13 and cmake 3.18.2
It is because it is an imported target.
From the CMake docs on buildsystems at the section for "include directories and usage requirements" (one of the last paragraphs in the section):
When the INTERFACE_INCLUDE_DIRECTORIES of an imported target is consumed, the entries in the property are treated as SYSTEM include directories, as if they were listed in the INTERFACE_SYSTEM_INCLUDE_DIRECTORIES of the dependency. This can result in omission of compiler warnings for headers found in those directories. This behavior for Imported Targets may be controlled by setting the NO_SYSTEM_FROM_IMPORTED target property on the consumers of imported targets, or by setting the IMPORTED_NO_SYSTEM target property on the imported targets themselves.
See the docs for include_directories and target_include_directories for other documentation on SYSTEM.
As stated in the docs, you can solve this by modifying consumers of the imported target like set_target_property(${PROJECT_NAME} PROPERTIES NO_SYSTEM_FROM_IMPORTED TRUE) or set_property(TARGET ${PROJECT_NAME} PROPERTY NO_SYSTEM_FROM_IMPORTED TRUE).
But there's another option not mentioned in the docs I quoted that I think may be better: In the docs for NO_SYSTEM_FROM_IMPORTED, it says:
See the IMPORTED_NO_SYSTEM target property to set this behavior on the target providing the include directories rather than consuming them.
I think it's better because NO_SYSTEM_FROM_IMPORTED will change the "system-ness" of all imported targets that the consumer links to, which may not be desirable. Perhaps a similar argument could be made against IMPORTED_NO_SYSTEM, but I personally can't think of a good backing for such an argument at the moment.

How to add compile flags in cmake on windows?

I wrote a project using CMake (with ninja and Visual Studio 2017 C++ compiler), with two modules lib_A and lib_B
lib_B depends one lib_A.
Both lib_B and lib_A define std::vector < size_t >.
Finally, the compiler told me: LNK2005 lib_A: std::vector < size_t > already defined in lib_B
I searched answers, and they gave the solution to add link flag /FORCE:MULTIPLE, page1 and page2.
I tried all these, but none of them work.
Use target_link_libraries
with target_link_libraries(lib_B lib_A INTERFACE "/FORCE:MULTIPLE")
compiler tells me The INTERFACE, PUBLIC or PRIVATE option must appear as the second argument, just after the target name.
with target_link_libraries(lib_B INTERFACE "/FORCE:MULTIPLE" lib_A )
compiler tells me ninja: error: '/FORCE:MULTIPLE', needed by 'lib_B', missing and no known rule to make it
Use CMAKE_EXE_LINKER_FLAGS
withset(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "/FORCE:MULTIPLE")
compile tells me LINK : warning LNK4012: value “x64;/FORCE:MULTIPLE” is invalid, must be one of "ARM, EBC, HYBRID_X86_ARM64X64, or X86" omit this option"
Use set_target_properties
with CMake code
get_target_property(TEMP lib_B COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP} /FORCE:MULTIPLE" )
set_target_properties(lib_B PROPERTIES COMPILE_FLAGS ${TEMP} )
The compiler tells me cl: command line error D8021 : invalid parameter "/FORCE:MULTIPLE"
If I change /FORCE:MULTIPLE to -Wl,--allow-multiple-definition, compiler tells me similar result.
Could anyone help me?
Does add link flag with any error?
You can use target_link_options in CMake ≥ 3.13 or set_target_properties with the LINK_FLAGS property before.
i.e. target_link_options(${PROJECT_NAME} PUBLIC $<$<CXX_COMPILER_ID:MSVC>:/FORCE:MULTIPLE>)
This also uses generator expressions to only apply the flag for MSVC.
But it seems like both your libraries are shared (DLL), but you are statically linking the runtime to both.
I don’t think that that’s a good idea.
Try either linking to the runtime dynamically for both libs if you want to dynamically link to them, or use the static runtime but build both libraries as static library too.
Adding the following line worked for me:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE")

Error: no member named 'to_string' in namespace 'std'; did you mean 'toString'? Gradle+Cmake

<string> is included. What is wrong in std::to_sting(intVar)?
cppreference. Does it mean CLang does not meet STandarD?
Another question helped, but the answers are not good (for me) because:
write own std::to_string() is bad idea. Standard is standard. If i write own implementation. I need to wrap it with defines to prevent errors from another compilers/toolchains which does not leak std features. And this impl still leaks full-featured STD.
Application.mk - is bad idea too since lastest studio offers Gradle+CMake. Makefile is too ugly and hard for manual using.
My solution is better.
Does it mean CLang does not meet STandarD?
No, it is because minimal std library set in Android NDK by default.
I use gradle build system:
android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake build script.
externalNativeBuild {
cmake {
...
// Use the following syntax when passing arguments to variables:
// arguments "-DVAR_NAME=VALUE"
// ------------------- ANSWER -------------------
arguments "-DANDROID_STL=c++_shared"
}
}
}
buildTypes {...}
// Use this block to link Gradle to your CMake build script.
externalNativeBuild {
cmake {...}
}
}
Read these:
https://developer.android.com/ndk/guides/cmake.html#variables
https://developer.android.com/ndk/guides/cpp-support.htm

conditional include of sources in kbuild

Say there is a source file a.c with some function func_a. I would like to call func_a based on some feature define and would also like a.c to be included in the module based on ideally same feature define.
so in my module source that is always present (say main.c) I could have something like
#ifdef FEATURE_A
func_a();
#endif
and in the kbuild for the module something like
obj-$(CONFIG_SAMPLE) += sample.o
sample-objs := main.o utils.o
only if FEATURE_A is defined, include a.c into the sample module
???
But this may not make sense since one is a pre-processor directive and the other a compiler/linker/build directive. Maybe the other way where the pre-processor directive uses some flag defined by the kbuild makes more sense? Is there some way to accomplish this?
Thanks.
I will answer your question by pointing out how sysctl support is conditionally included in the NFS module (I'm sure there are other examples, but this is what I'm familiar with):
include/linux/nfs_fs.h
fs/nfs/Makefile
fs/nfs/super.c
The kernel config system maintains a file "include/linux/autoconf.h" that exposes your configuration options as C preprocessor macros. So the files listed above compile differently depending on whether you configured sysctl support.
If sysctl support is enabled: The header "include/linux/nfs_fs.h" checks the macro CONFIG_SYSCTL and declares the C function nfs_register_sysctl(). This function is called in "fs/nfs/super.c". The Makefile (seeing nfs-y += sysctl.o) directs the build system to compile in the file "fs/nfs/sysctl.c" into the module, which defines the function nfs_register_sysctl().
If sysctl support is disabled: The header "include/linux/nfs_fs.h" checks the macro CONFIG_SYSCTL and declares the preprocessor macro nfs_register_sysctl() to be 0. This macro is used in "fs/nfs/super.c" to bypass some (dead) error-handling code. The Makefile (seeing nfs-n += sysctl.o) does not compile or link "fs/nfs/sysctl.c".
Please read 3.7 Compilation flags.
As I understand it, there's loosless reletionship between Kconfig option and preprocessed macros, passed while compiling. It's up to kernel developer to define which preprocessor flags to use during compilation.
For example in net/rds/Makefile:
ccflags-$(CONFIG_RDS_DEBUG) := -DDEBUG
Here preprocessor flag DEBUG will be passed if you kernel is configured with Kconfig option CONFIG_RDS_DEBUG.

Resources