Missing CMAKE_ASM_NASM_COMPILER when compiling gRPC with MS visual studio - c++

I am trying to build gRPC C++ (1.48.0) with Visual Studio 2022 on Windows 10. It's a CMake build (cmake 3.22.22011901-MSVC_2)
I was able to build everything else but am stuck at BoringSSL. The relevant CMakeList is trying to enable_language(ASM_NASM). Context below:
if(NOT OPENSSL_NO_ASM)
if(UNIX)
enable_language(ASM)
# Clang's integerated assembler does not support debug symbols.
if(NOT CMAKE_ASM_COMPILER_ID MATCHES "Clang")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
endif()
# CMake does not add -isysroot and -arch flags to assembly.
if(APPLE)
if(CMAKE_OSX_SYSROOT)
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -isysroot \"${CMAKE_OSX_SYSROOT}\"")
endif()
foreach(arch ${CMAKE_OSX_ARCHITECTURES})
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch ${arch}")
endforeach()
endif()
else()
set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -gcv8")
enable_language(ASM_NASM)
endif()
endif()
It gives me CMake Error: "No CMAKE_ASM_NASM_COMPILER could be found."
I don't know enough about compilers / assemblers, and why boringSSL would need a specific one (which none of the other modules needed including gRPC).
What is the recommended way to fix this?

To answer at least some of my questions for my future self, and others who are at a similar point in the journey.
NASM is an assembly compiler (assembler). BoringSSL has some assembly language code, which is why it needs an assembly compiler (and gRPC or other modules don't). I'll let someone else opine on why NASM and not some other assembler.
To fix the issue, you have to download/install the relevant NASM executable from here. I found it easier to download the exe, place it in a folder, add that folder to the PATH and set another env variable ASM_NASM with the name of nasm.exe.
Once I did that, boringSSL and the whole gRPC compiled quite smoothly.

Related

Compile with distcc doesn't distribute to other system(s) / slave not working

I've encountered a problem with discc, a compile job distribution tool, where a (cmake) build was not distributed to other specified systems (as defined in ~/.distcc/host).
I configured the build system like so:
cmake -DCMAKE_C_COMPILER_LAUNCHER=distcc -DCMAKE_CXX_COMPILER_LAUNCHER=distcc [...]
For other (similar) builds it turned out distcc worked just fine and hence, was configured properly.
What can possibly be the issue?
It turns out that distcc refuses to work with the march=native compile option. Which certainly makes sense, since binaries with mixed optimization flags may be combined.
Just to let you know, if you have a build system using march=native, like the cmake instructions:
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
if(COMPILER_SUPPORTS_MARCH_NATIVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
You'll have to disable it, to be able to use distcc with slaves. You'll have to specifiy the architecture flags manually.
Alternatively, try to detect the use of distcc:
include(CheckCXXCompilerFlag)
STRING(FIND "${CMAKE_CXX_COMPILER_LAUNCHER}" "distcc" found)
if (${found} LESS 0)
message(STATUS "trying to use -march=native")
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
if(COMPILER_SUPPORTS_MARCH_NATIVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
else()
message(STATUS "detected 'distcc' build, hence not using -march=native")
endif()
for this to be successful, make sure you use distcc with the respective cmake compiler launcher tool:
cmake -DCMAKE_C_COMPILER_LAUNCHER=distcc -DCMAKE_CXX_COMPILER_LAUNCHER=distcc [...]

How do I make CMake play nice with a proprietary C++ compiler?

I'm building an application for which I'd like to support a certain proprietary platform. It uses a modified version of ARMCC which CMake doesn't seem to like - no matter what I do, it keeps trying to provide strange flags to armlink where it should not, ignoring attempts to override its behavior.
Is it possible to essentially provide an all-new definition of how CMake should deal with a particular compiler? i.e. specify the binary and flags used for compilation, linking, etc., the expected file extensions, etc. throughout the whole process such that CMake doesn't do anything nasty? CMake seems to make custom compiler definitions an incredibly obscure thing to accomplish.
Edit: I've made it provide most of the right flags, but now I'm realizing I can't change the CMake test program - programs for this platform will fail to build if a certain atypical set of symbols (alternative entry point, not main) don't exist.
Edit 2: I've skipped the test program, but now it's failing while trying to get compiler information (why bother? I've given it everything it needs to know for the situation...) with this error:
Error: C9912E: No --cpu selected
To make it abundantly clear, the command it presents on the line above this clearly has the --cpu flag provided to a valid value:
armcc.exe -xc++ --cpu=MPCore -fpch-preprocess -v -dD -E
Though I'm entirely unsure as to what it's trying to do with the rest of it - I can't seem to override this part.
First, you need a toolchain.cmake file. Here, you provide the paths to your armcc compiler, linker, etc.
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_VERSION 1)
# this one is important
SET( CMAKE_SYSTEM_PROCESSOR arm )
SET(MCU_ARCH Cortex-M4) #MCU architecture
SET(TOOLCHAIN_BIN_DIR "C:/Keil_v5/ARM/ARMCC/bin/")
set(LINKER_SCATTER_SCRIPT ${PROJECT_SOURCE_DIR}/Scatter_file.sct)
SET(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/armcc.exe CACHE FILEPATH "C compiler")
SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/armcc.exe CACHE FILEPATH "C++ compiler")
SET(CMAKE_LINKER ${TOOLCHAIN_BIN_DIR}/armlink.exe CACHE FILEPATH "linker")
SET(CMAKE_AR ${TOOLCHAIN_BIN_DIR}/armar.exe CACHE FILEPATH "Archiver")
SET(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/armasm.exe CACHE FILEPATH "Assembler")
SET(CMAKE_FROMELF ${TOOLCHAIN_BIN_DIR}/fromelf.exe CACHE FILEPATH "From ELF tool")
SET(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
SET(CMAKE_EXE_LINKER_FLAGS_INIT "--cpu ${MCU_ARCH} --myFlag1 --myFlag2 ${LINKER_SCATTER_SCRIPT}")
Next, within the CMakeLists.txt file, you can pass the compiler and linker flags:
cmake_minimum_required(VERSION 3.10)
SET(CMAKE_VERBOSE_MAKEFILE ON)
project (MyProject C CXX ASM)
#Source Files -> Let CMake know your source files
SET(SRC_FILES ${CMAKE_SOURCE_DIR}/Dir/main.c)
add_executable(
${PROJECT_NAME}
${SRC_FILES})
#Defining compiler preprocessor directives
target_compile_definitions(${PROJECT_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:C>: DEFINE_1;__DEBUG;>
$<$<COMPILE_LANGUAGE:CXX>:DEFINE_2;__DEBUG;>)
#Defining compiler flags
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:C>: --c99 -c -O0 --cpu ${MCU_ARCH};>
$<$<COMPILE_LANGUAGE:CXX>:--cpp11 -c -O0 --cpu ${MCU_ARCH};>
$<$<COMPILE_LANGUAGE:ASM>:--cpu ${MCU_ARCH} -g>)
SET(CMAKE_ASM_FLAGS "--pd \"DEFINE_3"")
target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/SomeLibFile.lib --flagForLibFile)
target_link_options(${PROJECT_NAME} PRIVATE --linkerFlags)
target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_SOURCE_DIR})
For the necessary flags, have a look at what Keil is using.
Then you can build your application by passing the toolchain.cmake file as -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
EDIT: Updated based on the feedback from KamilCuk

FreeType2 Cross-compiling for Android

I was able to compile Freetype2 library for arm, arm64, x86, x86_64 architectures. These are steps I done to compile it.
Created standalone toolchains for architectures mentioned above.
make_standalone_toolchain.py \
--arch arm64 \
--api 26 \
--stl=libc++ \
--install-dir=my-arm64-toolchain
Set some envirement variables
export PATH=$PATH:`pwd`/my-toolchain/bin
target_host=aarch64-linux-android
export AR=$target_host-ar
export AS=$target_host-as
export CC=$target_host-gcc
export CXX=$target_host-g++
export LD=$target_host-ld
export STRIP=$target_host-strip
export CFLAGS="-fPIE -fPIC"
export LDFLAGS="-pie"
Configure freetype for compilation
./configure --host=aarch64-linux-android --prefix=/home/freetype-arm64 --without-zlib --without-harfbuzz --with-png=no
And finally make && install
Compilation was successfull and I was able to get Static freetype library.
I added library to my android studio libs folder.
This is folder structure for library:
libs---freetype
|---${ANDROID_ABI}
|---include
|---freetype2
|---freetype
---|Bunch of header files
|---ftbuild.h
|---lib
|---libfreetype.a
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
add_definitions("-DGLM_FORCE_SIZE_T_LENGTH -DGLM_FORCE_RADIANS")
add_subdirectory(src/main/cpp/glm)
add_library(freetype STATIC IMPORTED)
set_target_properties(freetype PROPERTIES IMPORTED_LOCATION${PROJECT_SOURCE_DIR}/libs/freetype/${ANDROID_ABI}/lib/libfreetype.a)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -Wall")
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp
src/main/cpp/graph.cpp
src/main/cpp/text.cpp
src/main/cpp/graphDataWorker.cpp
)
target_include_directories(native-lib PRIVATE ${PROJECT_SOURCE_DIR}/libs/freetype/${ANDROID_ABI}/include/freetype2)
target_link_libraries(native-lib
android
freetype
GLESv2
EGL
glm
atomic
log
OpenSLES
)
The problem is that I can use library inside my code and android studio is not giving me any errors, but then i try to run application it gives me this error:
linker command failed with exit code 1 (use -v to see invocation)
PS: I Can't see freetype headers in android studio file tree aswell, but can see other libraries.
Question: Am I importing library in a wrong way or this is cross-compilation issue and if so how to do it properly?
I done a lot of research on this issue and was unable to find a solution
Any help will be appreciated.
Unless you mixed paths when installing your build of FreeType2, it seems that the compilation of the library is incorrect, since the linker complains about the library being for x86_64 architecture.
On Linux, usually you can check the architecture the library is built for with command file. Another way to check the architecture is to use the objdump tool that is shipped with Android NDK (if I remember correctly it is generated with a toolchain as well). Its name follows the same pattern than the compiler/linker/... tools, $target_host-objdump.
I would recommend to compile FreeType2 using CMake instead of autotools, at least in my case I successfully did it that way.
Here is a sample of CMake configuration I wrote to cross-compile FreeType2 for Android. It is a little complex because it is part of a project where I build several libraries.
The idea is that my CMake configuration uses ExternalProject to download and compile Freetype. My top-level CMakeLists.txt contains:
# CMakeLists.txt
set(DEVENV_CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}
-DCMAKE_C_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_C_FLAGS_${BUILD_TYPE}=${CMAKE_C_FLAGS_${BUILD_TYPE}}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_CXX_FLAGS_${BUILD_TYPE}=${CMAKE_CXX_FLAGS_${BUILD_TYPE}}
-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
-DCMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}
)
if(BUILD_SHARED_LIBS)
list(APPEND DEVENV_CMAKE_ARGS -DBUILD_STATIC_LIBS=OFF -DLIBTYPE=SHARED)
else()
list(APPEND DEVENV_CMAKE_ARGS -DBUILD_STATIC_LIBS=ON -DLIBTYPE=STATIC)
endif()
if(DEFINED ANDROID_TOOLCHAIN_DIR)
get_filename_component(_toolchain_dir ${ANDROID_TOOLCHAIN_DIR} ABSOLUTE)
list(APPEND DEVENV_CMAKE_ARGS -DANDROID_TOOLCHAIN_DIR=${_toolchain_dir})
endif()
if(DEFINED CMAKE_ANDROID_ARCH_ABI)
list(APPEND DEVENV_CMAKE_ARGS -DCMAKE_ANDROID_ARCH_ABI=${CMAKE_ANDROID_ARCH_ABI})
endif()
if(CMAKE_TOOLCHAIN_FILE)
get_filename_component(_toolchain_file ${CMAKE_TOOLCHAIN_FILE} ABSOLUTE)
list(APPEND DEVENV_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${_toolchain_file})
endif()
add_subdirectory(freetype)
So the variable DEVENV_CMAKE_ARGS contains appropriate CMake arguments for cross-compiling that reflect my current CMake configuration. Under directory freetype, the CMakeLists.txt contains:
# freetype/CMakeLists.txt
project(freetype)
include(ExternalProject)
if(NOT FREETYPE_GIT_REPOSITORY)
set(FREETYPE_GIT_REPOSITORY "https://git.savannah.gnu.org/git/freetype/freetype2.git")
endif()
set(FREETYPE_GIT_REPOSITORY "${FREETYPE_GIT_REPOSITORY}"
CACHE STRING "Git repository for library Freetype."
)
if(NOT FREETYPE_GIT_TAG)
set(FREETYPE_GIT_TAG "VER-2-9")
endif()
set(FREETYPE_GIT_TAG "${FREETYPE_GIT_TAG}"
CACHE STRING "Tag or branch of Git repository to build."
)
message(STATUS "Freetype Git repository: ${FREETYPE_GIT_REPOSITORY}")
message(STATUS "Freetype Git tag: ${FREETYPE_GIT_TAG}")
externalproject_add(freetype
GIT_REPOSITORY "${FREETYPE_GIT_REPOSITORY}"
GIT_TAG "${FREETYPE_GIT_TAG}"
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/freetype/src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/freetype/build"
CMAKE_ARGS ${DEVENV_CMAKE_ARGS}
)
Basically this CMakeLists.txt uses ExternalProject to download and compile FreeType2 in the build directory.
And I use a toolchain file for Android:
# android.cmake
set(CMAKE_SYSTEM_NAME "Android")
set(CMAKE_ANDROID_STANDALONE_TOOLCHAIN ${ANDROID_TOOLCHAIN_DIR})
Sorry if it is overly complex; it comes from a project where I was playing with cross-compiling for Android. I hope it helps anyway.

Using /usr/lib/i386-linux-gnu instead of /usr/lib/x86_64-linux-gnu to find_library in CMake

How can I make CMake look for i386 libraries instead of x86_64 ones?
I'm trying to build i386 linux executables on machine for later deployment. I've made sure I've installed the i386 version of my dependencies, and they under /usr/lib/i386-linux-gnu, while the 64bit libraries are under /usr/lib/x86_64-linux-gnu, as expected.
However, I can't seem to find a way to make CMake look under /usr/lib/i386-linux-gnu for my libraries when building 32 bit. Setting make CMAKE_CXX_FLAGS to include -m32 only causes linking to fail, since the compiler is building a 32 bit executable and trying to link 64bit libraries to it, which it obviously can't do. It does this because it somehow prefers to get /usr/lib/x86_64-linux-gnu/libsfml-system.so over /usr/lib/i386-linux-gnu/libsfml-system.so for example.
What I've tried so far:
Adding -m32 to my compile flags, caused executable not to link
Setting my CMAKE_FIND_ROOT_PATH to /usr/lib/i386-linux-gnu, hoping it would look under that directory first, though it still found the 64 bit versions of the libraries.
I don't really have any more ideas, although I'm actively researching on forums, but I can't seem to find much that is useful. Maybe someone here has an idea of what I could do next.
My CMakeLists.txt as of now:
cmake_minimum_required(VERSION 3.5)
project(Synapse)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread -O3 -m32")
set(CMAKE_SYSTEM_PROCESSOR i386)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION gnu)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules)
find_package(SFML 2.4 COMPONENTS system window graphics network audio REQUIRED)
include_directories(${SFML_INCLUDE_DIR})
message(STATUS ${SFML_LIBRARIES})
set(CLIENT_SOURCE_FILES Client/main.cpp types.h Client/Mouse.cpp Client/Mouse.h Client/Game.cpp Client/Game.h Client/Camera.cpp Client/Camera.h Client/Renderer.cpp Client/Renderer.h Networking.h)
add_executable(SynapseClient ${CLIENT_SOURCE_FILES})
set(SERVER_SOURCE_FILES Server/main.cpp types.h Server/Game.cpp Server/Game.h Server/Commander.cpp Server/Commander.h Server/Unit.cpp Server/Unit.h Server/Client.cpp Server/Client.h Networking.h Server/Log.cpp Server/Log.h Server/User.cpp Server/User.h)
add_executable(SynapseServer ${SERVER_SOURCE_FILES})
target_link_libraries(SynapseClient ${SFML_LIBRARIES})
target_link_libraries(SynapseServer ${SFML_LIBRARIES})
Let CMake know that you do not want to search the 64bit paths before calling
find_package():
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS OFF)
Documentation:
FIND_LIBRARY_USE_LIB64_PATHS
FIND_LIBRARY_USE_LIB32_PATHS

Compiling for iOS with CMake

I've compiled a C++ static library by using CMake as my building tool and I want to link it to my iOS app.
I created a simple 'Empty' application in Xcode and linked my library called libengine.a to it.
I tried to compile my iOS project and the linker gave me this warning:
ignoring file /Users/.../build/engine/libengine.a,
file was built for archive which is not the architecture being linked (i386):
/Users/.../build/engine/libengine.a
As I understand it, I need to compile my library for ARM processors. The problem is I don't know how.
I think CMake really lacks good tutorials.
Anyways, my CMake scripts are attached below.
Any help would be greatly appreciated.
Thanks, Tal.
Here is my main CMake script:
cmake_minimum_required(VERSION 2.8)
project(movie-night)
if (DEFINED PLATFORM)
include(toolchains/ios.cmake)
endif()
add_definitions(-Wall)
set(DEBUG)
if (DEFINED DEBUG)
add_definitions(-g)
endif()
if (DEFINED RELEASE)
add_definitions(-O3)
endif()
add_subdirectory(engine)
add_subdirectory(ui)
add_subdirectory(test)
Here is my toolchains/ios.cmake file:
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm)
Just use this toolchain file: http://code.google.com/p/ios-cmake/ and use it as
cmake -DCMAKE_TOOLCHAIN_FILE=path_to_your_toolchain_file
Then, in CMakeLists.txt:
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch armv7")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch armv7")
By following cmake-toolchains documentation I did like below:
cmake -G Xcode -B build \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_Swift_COMPILER_FORCED=true \
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0
Note: That assignment CMAKE_OSX_DEPLOYMENT_TARGET=11.0 is not a mistake when targeting iOS.
I've been using an updated version of the iOS CMake toolchain for quite a while: https://github.com/leetal/ios-cmake
This creates an Xcode project which you can drag into an existing iOS project if necessary.
I wrote a blog post with more details: https://blog.tomtasche.at/2019/05/how-to-include-cmake-project-in-xcode.html
There is a second version of iOS.cmake located at:
https://ceres-solver.googlesource.com
Note: You may find that both versions of iOS.cmake will only build x86 versions of your project. CMake now sets CMAKE_OSX_SYSROOT to the (latest) Mac OS X SDK available on your system. You can fix this by modifying your copy of iOS.cmake to always set CMAKE_OSX_SYSROOT. You can do this by commenting out a couple of lines your copy of iOS.cmake:
# -- Under CMake 3.4.2, CMAKE_OSX_SYSROOT is automatically defined to point to the latest Mac OS X SDK. --
# -- So, the iOS SDK is never found. Grab the correct CMAKE_OS_SYSROOT and ignore any prior setting. --
# If user did not specify the SDK root to use, then query xcodebuild for it.
# if (NOT CMAKE_OSX_SYSROOT)
execute_process(COMMAND xcodebuild -version -sdk ${XCODE_IOS_PLATFORM} Path
OUTPUT_VARIABLE CMAKE_OSX_SYSROOT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
message (STATUS "Using SDK: ${CMAKE_OSX_SYSROOT} for platform: ${IOS_PLATFORM}")
message (STATUS "be sure the previous line points to the correct SDK")
# endif ( )