Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cmake crosscompiling #60

Merged
merged 3 commits into from
Nov 18, 2019
Merged

Conversation

wtsnyder
Copy link
Contributor

This fix allows foonathan/memory to build correctly with all nodesize features when crosscompiling. It builds the nodesize_dbg tool and links it statically to avoid anoying library search paths. Then it uses the crosscompiling emulator provided by the toolchain file to run nodesize_dbg and generate container_node_sizes_impl.hpp during the build.

For this to work the toolchain file must provide the emulator executable

Example aarch64-linux-gnu.cmake toolchain file

# 64 bit ARM (aarch64)

# use it like this:
# cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake <sourcedir>

# set the name of the target system
set(CMAKE_SYSTEM_NAME "Linux" CACHE STRING "Target system")
set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "Target architecture")

# set the compiler
set(CMAKE_LIBRARY_ARCHITECTURE "aarch64-linux-gnu")
set(CMAKE_C_COMPILER   "${CMAKE_LIBRARY_ARCHITECTURE}-gcc")
set(CMAKE_CXX_COMPILER "${CMAKE_LIBRARY_ARCHITECTURE}-g++")
set(CMAKE_LINKER       "${CMAKE_LIBRARY_ARCHITECTURE}-ld")

# where is the target environment located
# this should be a chroot environment on your system with all the required native libraries
set(CMAKE_FIND_ROOT_PATH "/usr/local/targets/${CMAKE_LIBRARY_ARCHITECTURE}")
include_directories("${CMAKE_FIND_ROOT_PATH}/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}")

# adjust the default behaviour of the FIND_XXX() commands:
# search for programs in the host environment
# search for headers and libraries in the target environment 
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# crosscompiling emulator ( cmake > 3.4 )
# This variable is only used when CMAKE_CROSSCOMPILING is on.
# It should point to a command on the host system that can run
# executables built for the target system. The command will also be
# used to run try_run() generated executables, which avoids 
# manual population of the TryRunResults.cmake file.
# It is also used as the default value for the CROSSCOMPILING_EMULATOR
# target property of executables.

# not required on x86_64 systems running i386 code

set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/qemu-${CMAKE_SYSTEM_PROCESSOR})

…statically to avoid anoying library search paths then use the crosscompiling emulator to run it to generate container_node_sizes_impl during the build.
@foonathan
Copy link
Owner

So the MacOS build does not seem to work because of the -static, the windows build seems to break because it can't find the nodesize_dbg executable.

I propose you fix MacOS by adding -static only if cross compiling, I don't know how to fix Windows.

@MiguelCompany
Copy link
Contributor

@wtsnyder What if we only add -static when CMAKE_CROSSCOMPILING ?

@wtsnyder
Copy link
Contributor Author

Removed '-static' option from non cross compile builds.

The windows issues seemed to be that nodesize_dbg executable is put in '${CMAKE_BINARY_DIR}\tool\Debug\nodesize_dbg' instead of '${CMAKE_BINARY_DIR}\tool\nodesize_dbg'. Must be an MSVC thing. Was able to fix it using a generator expression to get the actual path to the executable for that build.

@alsora
Copy link

alsora commented Nov 18, 2019

+1
Tested and this fixes cross-compilation of Fast-RTPS library

@foonathan foonathan merged commit 06bf8d2 into foonathan:master Nov 18, 2019
@foonathan
Copy link
Owner

Thank you very much!

@jayhou
Copy link

jayhou commented Jun 9, 2020

Android NDK cross-compile still not work for me, my commands:
colcon build --merge-install --symlink-install --packages-up-to foonathan_memory_vendor --cmake-args -DCMAKE_CROSSCOMPILING=ON -DCMAKE_CROSSCOMPILING_EMULATOR=/usr/bin/qemu-aarch64 -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_FUNCTION_LEVEL_LINKING=OFF -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} -DANDROID_STL=c++_shared -DANDROID_ABI=${ANDROID_ABI} -DANDROID_NDK=${ANDROID_NDK} -DTHIRDPARTY=ON -DBUILD_TESTING=OFF -DCMAKE_FIND_ROOT_PATH="$ROS2_ANDROID_WORKSPACE/install"

Is there anything wrong?

@jayhou
Copy link

jayhou commented Jun 9, 2020

plus, I'm compliling Ros2 foxy

@foonathan
Copy link
Owner

Sorry, I don't know anything about cross compiling. What is your error?

@amdsobhy
Copy link

to cross compile for QNX and generate the header file manually this process can be done as following:

  • inside src/eProsima/memory/tool run:
    qcc -Vgcc_ntox86_64 -std=c++14 -stdlib=libstdc++ -I./ -static -o foonathan_memory_node_size_debugger node_size_debugger.cpp

  • copy foonathan_memory_node_size_debugger to target and run:
    foonathan_memory_node_size_debugger --code container_node_sizes_impl.hpp

  • copy back the generated file into the tool directory

  • add the following lines to src/eProsima/memory/src/CMakeLists.txt
    elseif(QNX)
    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.hpp
    COMMAND cp ${PROJECT_SOURCE_DIR}/tool/container_node_sizes_impl.hpp ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.hpp )

  • build

@amdsobhy
Copy link

One more thing I would like to add specifically for QNX is that after comparing the header file generated on my linux laptop and the one generated on a QNX system they turn out to be identical. So it can be compiled natively on linux without having to cross compile

@foonathan
Copy link
Owner

Doesn't it work out of the box with the changes from this PR?

@amdsobhy
Copy link

amdsobhy commented Jul 26, 2020

This PR solved cross compiling for linux but not for QNX as it relies on running qemu with an image of the target OS. I do actually have a qemu image for QNX but it seems that for linux qemu is started with nodesize_dbg as an argument which I could not get it to work in the same way for QNX. After Investigation on the output it seems the header file is exactly the same as the one generated on a linux laptop (host). I remodifed memory/src/CMakeLists.txt to make it more simple like so:

elseif(QNX) execute_process(COMMAND g++ -DVERSION='"0.6.2"' -o ${PROJECT_SOURCE_DIR}/tool/nodesize_dbg ${PROJECT_SOURCE_DIR}/tool/node_size_debugger.cpp ) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.hpp COMMAND ${PROJECT_SOURCE_DIR}/tool/nodesize_dbg --code ${CMAKE_CURRENT_BINARY_DIR}/container_node_sizes_impl.hpp)

No need to cross compile and generate the header file on target or emulator, it can be generated natively on Linux. I assume results will be the same on any POSIX OS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants