Skip to content

Latest commit

 

History

History
368 lines (313 loc) · 11.2 KB

CMake-notes.md

File metadata and controls

368 lines (313 loc) · 11.2 KB
#add subdirectory if it exists
set(SUBDIR ${CMAKE_SOURCE_DIR}/mysubdir)

if(EXISTS ${SUBDIR} AND IS_DIRECTORY ${SUBDIR})
    add_subdirectory(${SUBDIR})
else()
    message("The directory ${SUBDIR} does not exist!")
endif()
# patch diff before build
# Define the patch file and the directory to apply it to
set(PATCH_FILE ${CMAKE_SOURCE_DIR}/patches/my_patch.patch)
set(TARGET_DIR ${CMAKE_SOURCE_DIR}/third_party/my_lib)

# Use execute_process to do a dry run of the patch command
execute_process(
    COMMAND patch --dry-run -p1 -i ${PATCH_FILE}
    WORKING_DIRECTORY ${TARGET_DIR}
    RESULT_VARIABLE patch_result
    OUTPUT_QUIET
    ERROR_QUIET
)

# If the dry run succeeded, the patch has not been applied yet
if(patch_result EQUAL 0)
    # Apply the patch
    execute_process(
        COMMAND patch -p1 -i ${PATCH_FILE}
        WORKING_DIRECTORY ${TARGET_DIR}
        RESULT_VARIABLE patch_result
    )

    # Check the result of the patch command
    if(NOT patch_result EQUAL 0)
        message(FATAL_ERROR "Failed to apply patch: ${PATCH_FILE}")
    endif()
endif()
#check gcc version
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "11")
        message("GCC version is exactly 11!")
    else()
        message("GCC version is not 11!")
    endif()
endif()

use clang and libc++ if it's present

# Check if Clang is installed
find_program(CLANG clang)
if(CLANG)
    # Get the directory of Clang and Clang++
    get_filename_component(CLANG_DIR ${CLANG} DIRECTORY)
    get_filename_component(CLANGXX_DIR ${CLANGXX} DIRECTORY)

    # Set the C and C++ compilers to Clang with full path
    set(CMAKE_C_COMPILER ${CLANG_DIR}/${CLANG})
    set(CMAKE_CXX_COMPILER ${CLANGXX_DIR}/${CLANGXX})

    # Check if LLVM's libc++ is installed
    include(CheckCXXSourceCompiles)
    set(CMAKE_REQUIRED_FLAGS "-stdlib=libc++")
    CHECK_CXX_SOURCE_COMPILES("
    #include <ciso646>
    int main() {
        return 0;
    }
    " LIBCXX_FOUND)

    if(LIBCXX_FOUND)
        # Set libc++ as the standard library
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
    else()
        message(WARNING "LLVM's libc++ not found! Using default C++ standard library.")
    endif()
else()
    message(WARNING "Clang not found! Using default compiler.")
endif()
# Check if target is ARM architecture
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
    message("ARM architecture detected!")
endif()

# Check if target is x86 architecture
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86")
    message("x86 architecture detected!")
endif()

# Check if target is x86_64 architecture
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
    message("x86_64 architecture detected!")
endif()

# check target is ARM or arm64
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
    message("ARM or ARM64 architecture detected!")
endif()
# in cross-compiling, check if target is ARM architecture

if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
    message("ARM architecture detected!")
    set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
endif()
# Check if target is ARM architecture
#ifdef __arm__
    message("ARM architecture detected!")
#elif defined(__x86_64__) || defined(_M_X64)
    message("x86_64 architecture detected!")
#elif defined(__i386__) || defined(_M_IX86)
    message("x86 architecture detected!")
#else
    message("Unknown architecture detected!")
#endif
// Check if target is ARM32 architecture
#if defined(__arm__) && !defined(__aarch64__)
    message("ARM32 architecture detected!")
#endif

// Check if target is ARM64 architecture
#if defined(__aarch64__)
    message("ARM64 architecture detected!")
#endif
if(CMAKE_CXX_FLAGS MATCHES "-m32" OR CMAKE_C_FLAGS MATCHES "-m32")
    message("The -m32 option is set.")
else()
    message("The -m32 option is not set.")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
    message("Clang compiler is being used.")
    if(CMAKE_CXX_FLAGS MATCHES "-m32" OR CMAKE_C_FLAGS MATCHES "-m32")
        message("The -m32 option is set.")
    else()
        message("The -m32 option is not set.")
    endif()
else()
    message("Clang compiler is not being used.")
endif()
execute_process(COMMAND cmd ARGS arg1 arg2
                RESULT_VARIABLE cmd_result
                OUTPUT_VARIABLE cmd_output)

if(NOT ${cmd_result} EQUAL 0)
    message(WARNING "Command failed with error: ${cmd_result}")
    message(WARNING "Output: ${cmd_output}")
else()
    message("Command succeeded with output: ${cmd_output}")
endif()

#choose Nina if it's installed

#!/bin/bash

# Try to find Ninja
ninja_path=$(which ninja)

if [[ -n "$ninja_path" ]]; then
    cmake -G Ninja ..
else
    cmake -G "Unix Makefiles" ..
fi
# for cmake version since 3.29
# Attempt to find lld by checking its version
execute_process(COMMAND lld --version
                RESULT_VARIABLE lld_result
                OUTPUT_VARIABLE lld_version_output
                ERROR_QUIET
                OUTPUT_STRIP_TRAILING_WHITESPACE)

# Check if the command was successful (result variable is 0)
if(lld_result EQUAL 0)
    message(STATUS "LLD linker found: ${lld_version_output}")

    # Explicitly set lld as the linker
    set(CMAKE_LINKER "lld" CACHE FILEPATH "LLD linker" FORCE)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld" CACHE STRING "Use LLD linker" FORCE)
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld" CACHE STRING "Use LLD linker" FORCE)
    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=lld" CACHE STRING "Use LLD linker" FORCE)
else()
    message(STATUS "LLD linker not found. Using default system linker.")
endif()
# for cmake version prior to 3.29
# Attempt to find lld by checking its version
execute_process(COMMAND lld --version
                RESULT_VARIABLE lld_result
                OUTPUT_VARIABLE lld_version_output
                ERROR_QUIET
                OUTPUT_STRIP_TRAILING_WHITESPACE)

# Check if the command was successful (result variable is 0)
if(lld_result EQUAL 0)
    message(STATUS "LLD linker found: ${lld_version_output}")

    # For older CMake versions, set linker flags for C and C++ directly
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld" CACHE STRING "Use LLD linker for C" FORCE)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld" CACHE STRING "Use LLD linker for C++" FORCE)
else()
    message(STATUS "LLD linker not found. Using default system linker.")
endif()
#[[
CMake's FetchContent module does not directly support switching between HTTPS and SSH URLs if one of them isn't working. However, you can implement this functionality yourself by checking if the FetchContent_MakeAvailable command succeeds for one URL and, if not, trying again with the other URL.
]]

include(FetchContent)

set(MYLIB_HTTPS_URL https://github.com/username/mylib.git)
set(MYLIB_SSH_URL [email protected]:username/mylib.git)

FetchContent_Declare(
  mylib
  GIT_REPOSITORY ${MYLIB_HTTPS_URL}
  GIT_TAG        v1.0.0
)

# Try to fetch the content using the HTTPS URL
execute_process(
  COMMAND ${CMAKE_COMMAND} -E fetch_content mylib
  RESULT_VARIABLE result
)

# If the fetch failed, try again with the SSH URL
if(result)
  message("Failed to fetch content using HTTPS URL, trying with SSH URL...")
  FetchContent_Declare(
    mylib
    GIT_REPOSITORY ${MYLIB_SSH_URL}
    GIT_TAG        v1.0.0
  )
  FetchContent_MakeAvailable(mylib)
else()
  FetchContent_MakeAvailable(mylib)
endif()

# ---------------------------------------------------------------------------------------
# External project configuration
# ---------------------------------------------------------------------------------------
include(ExternalProject)

ExternalProject_Add(
    external_project_name
    PREFIX ${CMAKE_BINARY_DIR}/external_project_name
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/path/to/external/project
    CONFIGURE_COMMAND ""  # Skip configure step if not needed
    BUILD_COMMAND cd ${CMAKE_SOURCE_DIR}/path/to/build/directory && make  # Change directory and run make
    INSTALL_COMMAND ""    # No install command
    BUILD_IN_SOURCE 1     # Build in the source directory
    BUILD_BYPRODUCTS 
        ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/libexternal_project_name.so
        ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/libexternal_project_name.dylib
        ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/external_project_name.dll
)

# Manually specify include directories and library paths
include_directories(${CMAKE_SOURCE_DIR}/path/to/external/project/include)
link_directories(${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build)

# Create an imported library target
add_library(external_project_name_lib SHARED IMPORTED)

# Set the IMPORTED_LOCATION property based on the platform
if (UNIX AND NOT APPLE)
    set_target_properties(external_project_name_lib PROPERTIES
        IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/libexternal_project_name.so
    )
elseif (APPLE)
    set_target_properties(external_project_name_lib PROPERTIES
        IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/libexternal_project_name.dylib
    )
elseif (WIN32)
    set_target_properties(external_project_name_lib PROPERTIES
        IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/external_project_name/src/external_project_name-build/external_project_name.dll
    )
endif()

# Link the imported library to your target
target_link_libraries(your_target_name external_project_name_lib)

cmake to generate header file from xml:

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# Set the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Define the XML file and the script
set(XML_FILE ${CMAKE_SOURCE_DIR}/input.xml)
set(SCRIPT ${CMAKE_SOURCE_DIR}/generate_code.py)

# Define the output directory for generated files
set(GENERATED_DIR ${CMAKE_BINARY_DIR}/generated)
file(MAKE_DIRECTORY ${GENERATED_DIR})

# Define the generated C++ files
set(GENERATED_CPP_FILES
    ${GENERATED_DIR}/generated_code1.cpp
    ${GENERATED_DIR}/generated_code2.cpp
    ${GENERATED_DIR}/generated_code3.cpp
)
set(GENERATED_H_FILES
    ${GENERATED_DIR}/generated_code1.h
    ${GENERATED_DIR}/generated_code2.h
    ${GENERATED_DIR}/generated_code3.h
)

# Add a custom command to run the script and generate the C++ files
add_custom_command(
    OUTPUT ${GENERATED_CPP_FILES} ${GENERATED_H_FILES}
    COMMAND ${CMAKE_COMMAND} -E env python ${SCRIPT} ${XML_FILE} ${GENERATED_DIR}
    DEPENDS ${XML_FILE} ${SCRIPT}
    COMMENT "Generating C++ code from XML"
    VERBATIM
)

# Add a custom target that depends on the generated files
add_custom_target(generate_code ALL DEPENDS ${GENERATED_CPP_FILES} ${GENERATED_H_FILES})

# Add the executable and link the generated files
add_executable(MyProject main.cpp ${GENERATED_CPP_FILES})
add_dependencies(MyProject generate_code)
include_directories(${GENERATED_DIR})
# how to build compilation database with make
# python compiledb : https://github.com/nickdiego/compiledb
compiledb -n make