I failed to find out what do C, M, and P stand for in CMake in the official documents. For example, why not POLICY0077 instead of CMP0077.
My understanding was always that it is an abbreviation from "C Make Policy".
Related
I am learning CMake with CMake Tutorial and found something which is not clear for me:
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
So what is the CheckSymbolExists? Is it a function or a lib?
What's meaning of the "m"? Does it mean a lib name or some flag?
I had tried to read through cmake documents, but I just don't understand.
Please somebody help me to understand these.
First, set(CMAKE_REQUIRED_LIBRARIES "m") includes the math library. You do the same on the command-line like this: gcc test.c -lm which includes the library libm.so/.dll
CheckSymbolExists is a CMake Module which provides more functionality. You can include it with include(CheckSymbolExists)
After this you can use the function check_symbol_exists(...) in CMake to check the availability of symbols in header files.
The exact example from the tutorial:
check_symbol_exists(log "math.h" HAVE_LOG) checks if the header file math.h has a symbol (can be a function, constant or whatever) which is called log. If there is one, the CMake Variable HAVE_LOG is set to 1, otherwise set to 0.
The document said, if my understanding is correct, this module will check if a symbol can be correctly linked when it saw a symbol that is not a enum, type or intrinsic.
So in that snippet, when the first runs of check_symbol_exists didn't define the two cache variable, it will check if it had missed an required lib, and retry.
I need to adapt a series of codes and scripts written for raspberry Pi (1st gen) (that was running a ARM11 cpu) to run on a Allwinner H6-based board cpu (an ARM Cortex-A53).
I already substituted CMAKE_SYSTEM_PROCESSOR from ARCH armv7l to ARCH aarch64.
But, to launch the cmake compiling command string I had
cmake -D CMAKE_CXX_FLAGS="-march=armv7-a" /..path
and I thought to substitute the -march=armv7-a with -march=armv8-a.
Now my doubt is: could be this correct to compile for the Allwinner H6 64bit? Why I can't put directly aarch64 instead of armv8-a? And, finally: what the difference between "armv8" and "armv8-a"?.
Sorry, I am a little bit confused here.
1) Yes, -march=armv8-a would be correct but less specific than,
say, -mtune=cortex-a53, since the Allwinner H6 is a cortex-a53.
My guess is that you cannot put -march=aarch64 instead of -march=arm-v8-a because this would be too generic: after all, you can already specify ‘armv8-a’, ‘armv8.1-a’, ‘armv8.2-a’, ‘armv8.3-a’, ‘armv8.4-a’ and ‘armv8.5-a’, as documented here.
armv8 is the umbrella name for ARMv8-A, ARMv8-M and ARMv8-R. A, R and M are 'profiles' according to arm terminology, and target different types of applications:
See here, here and here for more details.
I have cross compiled a software for an HummingBoard-Pro (arm processor).
The software just receives some data using the lcm protocol.
If I use the cross compiled software, the data received by the application are invalid, while if I use on-board compiled software everything works fine.
-The software is exactly the same!
-I cross compiled using cmake and a specific arm toolchain.
Output example of cross compiled sw:
first value 5.73599e+107
second value 5.73599e+107
third value 5.73599e+107
Output example of on board compiled sw:
first value 1
second value 2
third value 3
Note: It's my first cross compilation attempt so probably something goes wrong but I haven't really idea about what.
CMakelists file
cmake_minimum_required(VERSION 3.1)
set(main_project_dir ${CMAKE_CURRENT_SOURCE_DIR})
set(external_dir ${main_project_dir}/external)
set(external_lcm_dir ${external_dir}/lcm_dir)
set(external_lcm ${external_lcm_dir}/lcm)
set(external_lcm_build ${external_lcm}/build)
set(external_lcm_gen_exe /usr/local/bin/lcm-gen)
set(lcm_input_file ${main_project_dir}/lcm_format_files/lcm_input_files/indrive.sensors.vanet.lcm)
set(lcm_libraries ${main_project_dir}/external/lcm_dir/lcm/build/lcm)
set(lmc_libraries_header ${main_project_dir}/external/lcm_dir/lcm/)
set(lcm_autogenerated_dir ${main_project_dir}/build/lcm_autogenerated_classes)
add_custom_target(
generate-lcm
COMMAND ${external_lcm_gen_exe} -x ${lcm_input_file} --cpp-hpath ${lcm_autogenerated_dir}
COMMENT "=================== Generating lcm files..."
)
add_subdirectory(testSender)
add_subdirectory(testReceiver)
TOOLCHAIN FILE
SET (CMAKE_SYSTEM_NAME Linux)
SET (CMAKE_SYSTEM_VERSION 1)
SET (CMAKE_SYSTEM_PROCESSOR arm)
INCLUDE_DIRECTORIES(/usr/hummingboard/usr/include /usr/hummingboard/include /usr/hummingboard/usr/include/arm-linux-gnueabihf/)
LINK_DIRECTORIES(/usr/hummingboard/usr/lib /usr/hummingboard/lib /usr/hummingboard/lib/arm-linux-gnueabihf )
SET(CMAKE_PREFIX_PATH /usr/arm-linux-gnueabihf/lib/
/usr/hummingboard/
/usr/hummingboard/lib/arm-linux-gnueabihf/
/usr/hummingboard/usr
/usr/hummingboard/usr/lib/arm-linux-gnueabihf/
)
SET (CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabi-gcc)
SET (CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabi-g++)
SET (CMAKE_FIND_ROOT_PATH /usr/hummingboard/ /usr/hummingboard/usr)
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Turning my comments into an answer
Your toolchain file looks like a mixture of two GNU toolchains, which is not allowed and could explain strange behavior of your software.
I would e.g. expect there to be a /usr/hummingboard/bin directory. And shouldn't there be a arm-linux-gnueabihf-gcc to match with /usr/arm-linux-gnueabihf/lib/.
My guess would be that you are mixing hard-float (hf) with soft-float libraries and native- with cross-compilers.
It gets visible with the value 5.73599e+107 = 0x7f800000 which means infinite.
To find the root-cause I would recommend to check your floating point settings. Please compare the compiler command lines between both builds (working vs. non-working) using verbose makefiles.
References
Assign infinity to float
Using CMake with GNU Make: How can I see the exact commands?
I'd need to find how to best use CMake to build multiple different versions of the same library.
Let's assume that I have software A, B and C. All of these use the same external library, let's call that D. Let's assume that D is huge compared to A, B & C. So just using svn:external to checkout it multiple times is a bad option.
What crossed my mind is to have a folder where I have the subfolders for A, B, C & D and just calling add_subdir(../D). But to make things complicated, I don't want to enforce this folder structure on other developers, so I ended up with the thought of making this work with find_package, somehow.
What I'd like to see is that you are able to get C and D from subversion to any folders and have C compile it's own version of D for itself and use it, with no effort from the custom folders.
This might seem like a silly dream, but not being the smartest man on the planet, maybe someone has an idea of how to achieve this.
EDIT:
note that A B & C cannot use the same binaries for D since they would use different compiler flags to build the library.
add_subdirectory works with directories located outside the main project dir, you just have to give a binary_dir.
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
Add a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.txt and code files are located. If it is a relative path it will be evaluated with respect to the current directory (the typical usage), but it may also be an absolute path. The binary_dir specifies the directory in which to place the output files. If it is a relative path it will be evaluated with respect to the current output directory, but it may also be an absolute path.
In A, B and C you could have something like that:
set(MYPROJECT_D_PATH "" CACHE PATH "Path to D")
if("${test}" STREQUAL "")
message(FATAL_ERROR "You must set MYPROJECT_D_PATH")
endif()
add_subdirectory(${MYPROJECT_D_PATH} D)
When you compile A, B or C for the first time, you provides the path to D like that:
cmake <src_dir> -DMYPROJECT_D_PATH=<path_to_D>
I want to access some subroutines from a third party DLL. The functions use STDCALL as the calling convention.
Running dumpbin /export foo.dll gives me something like:
...
7 6 00004B40 Foo#16
...
I compile my code using:
gfortran test.f90 -o test.exe -Wl,foo.dll
I get an error: undefined reference to '_foo_' (note the underscores).
I have tried adding the -mrtd compilation flag, as well as other flags I googled, all to no avail.
How can I tell fortran to not add the underscores?
edit: A bit of clarification is in order.
I have an existing DLL to which I do not have the source to.
This DLL is written in Visual Basic, if it helps.
I want to call this DLL from fortran.
When I write in test.f90: Foo(1.0d0) I get an undefined reference to '_foo_' linkage error
Did you try -fno-underscoring ?
I found a post by Tobias Burnus (a gfortran developer) at http://www.rhinocerus.net/forum/lang-fortran/604847-fortran-dll-call-excel-2.html (near the end) -- he recommends the use of compiler directives instead of -mrtd.
You need to combine the use of ISO_C_BINDING with compiler attributes. You should really read the Mixed-Language Programming section of the gfortran manual. It gives good advice that can be used with other compilers as well. In particular, in your case you need the stdcall attribute:
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
!GCC$ ATTRIBUTES stdcall :: foo
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs
Notice the line with stdcall, it's what should make it work.
Just wanted to expand on M.S.B's -fno-underscoring answer: You may run into issues if using f2c & g77. From the gfortran documentation:
With -funderscoring in effect, GNU
Fortran appends one underscore to
external names with no underscores.
This is done to ensure compatibility
with code produced by many UNIX
Fortran compilers.
Caution: The default behavior of GNU
Fortran is incompatible with f2c and
g77, please use the -ff2c option if
you want object files compiled with
GNU Fortran to be compatible with
object code created with these tools.
Use of -fno-underscoring is not
recommended unless you are
experimenting with issues such as
integration of GNU Fortran into
existing system environments
(vis-à-vis existing libraries, tools,
and so on).
You might need to recompile the DLL with something like -fno-underscoring to remove the underscores from the DLL.
I've run into portability issues related to underscore prefix/suffix by certain Fortran compilers: Some compilers _prefix or suffix_ by default, while others don't! My solution has been preprocessor directives:
#ifdef LC_UNSC
#define GET_DIP_MOMENT get_dip_moment_
#elif LC_NOUNSC
#define GET_DIP_MOMENT get_dip_moment
#endif
...
call GET_DIP_MOMENT()
A different approach is to use the ISO C Binding of Fortran 2003, which is supported by gfortran >= 4.3. This will automatically use the underscoring conventions of C (i.e., probably none), rather those of the Fortran compiler. It will also give you control over the case (capitalization) of the subroutine names, if the Windows linker cares about that. Fortran is case insensitive, and so you can call Fortran subroutines by any case -- probably the linker is converting to lower case.
Including the following "interface" in the declarations of the Fortran routine that calls "Foo" describes Foo to be a C subroutine (void function) with a single argument of double type -- Fortran input/output, or a pointer in C. If Foo has other properties, the interface needs to be changed. The "bind" clause specifies the case-sensitive name to provide to the linker. If you call Foo from several Fortran routines, then it is best to put the interface into a module and "use" it from each Fortran routine.
This is intended for C -- maybe it will work for Visual Basic. The ISO C Binding gives a lot of control, so if this doesn't work, maybe some variation will.
interface VisBasSubs
subroutine foo (DoubleArg) bind (C, name="Foo")
use iso_c_binding, only: c_double
real (kind=c_double), intent (inout) :: DoubleArg
end subroutine foo
end interface VisBasSubs