diff --git a/README.md b/README.md index 7576d0e..dddd39a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # abcmake - Simple CMake for Simple Projects -![version](https://img.shields.io/badge/version-5.1.2-green) +![version](https://img.shields.io/badge/version-5.2.0-green) [![Build Test](https://github.com/an-dr/abcmake/actions/workflows/test.yml/badge.svg)](https://github.com/an-dr/abcmake/actions/workflows/test.yml) `abcmake` or **Andrei's Build CMake subsystem** is a CMake module to work with C/C++ project of a predefined standard structure in order to simplify the build process. @@ -73,7 +73,7 @@ If you want to use the module in your project, you can use the badge: - `add_component(TARGETNAME [INCLUDE_DIR SOURCE_DIR SHARED])` - Add a component as a library. It will scan the same default directories as *add_main_component*. - `target_link_component (TARGETNAME COMPONENTPATH)` - Add a component to the target. Can be used for linking components between each other. - `target_sources_directory(TARGETNAME SOURCE_DIR)` - Add all sources from the directory - +- `set_abcmake_project_structure([COMPONENTS_DIR] [INCLUDE_DIR] [SOURCE_DIR] [INSTALL_DIR])` - Set the project structure. Must be called before any other extension function. The values are distributed to all subprojects automatically if not overwritten my other commands. Default values are **components**, **include**, **src**, and **../install**. ## Real Life Example (abcmake v5.1.1) diff --git a/abcmake.code-workspace b/abcmake.code-workspace index 9c16bef..48900fb 100644 --- a/abcmake.code-workspace +++ b/abcmake.code-workspace @@ -36,72 +36,8 @@ "problemMatcher": [] }, - // Cmake build - { - "label": "project: Configure", - "type": "shell", - "command": "cmake", - "args": [ - "-G", - "Ninja", - "-B", - "build", - "-S ." - ], - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/tests/project", - "env": { - "ABCMAKE_PATH": "${workspaceFolder}/src" - } - }, - "problemMatcher": [] - }, - // Cmake build - { - "label": "project: Build", - "type": "shell", - "command": "cmake", - "args": [ - "--build", - "build", - "--target", - "all", - "--config", - "Release" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/tests/project" - }, - "problemMatcher": [], - }, - // Install to workspace/install - { - "label": "project: Install", - "type": "shell", - "command": "cmake", - "args": [ - "--install", - "build", - ], - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/tests/project", - }, - "problemMatcher": [], - }, { - "label": "test_interdep: Configure", + "label": "project_custom: Configure", "type": "shell", "command": "cmake", "args": [ @@ -116,7 +52,7 @@ "isDefault": true }, "options": { - "cwd": "${workspaceFolder}/tests/test_interdep", + "cwd": "${workspaceFolder}/tests/project_custom", "env": { "ABCMAKE_PATH": "${workspaceFolder}/src" } @@ -125,7 +61,7 @@ }, // Cmake build { - "label": "test_interdep: Build", + "label": "project_custom: Build", "type": "shell", "command": "cmake", "args": [ @@ -141,13 +77,13 @@ "isDefault": true }, "options": { - "cwd": "${workspaceFolder}/tests/test_interdep" + "cwd": "${workspaceFolder}/tests/project_custom" }, "problemMatcher": [], }, // Install to workspace/install { - "label": "test_interdep: Install", + "label": "project_custom: Install", "type": "shell", "command": "cmake", "args": [ @@ -159,7 +95,7 @@ "isDefault": true }, "options": { - "cwd": "${workspaceFolder}/tests/test_interdep", + "cwd": "${workspaceFolder}/tests/project_custom", }, "problemMatcher": [], } diff --git a/release/ab.cmake b/release/ab.cmake index 93c2897..fbeb02a 100644 --- a/release/ab.cmake +++ b/release/ab.cmake @@ -16,29 +16,200 @@ # ************************************************************************* set(ABCMAKE_VERSION_MAJOR 5) -set(ABCMAKE_VERSION_MINOR 1) -set(ABCMAKE_VERSION_PATCH 2) +set(ABCMAKE_VERSION_MINOR 2) +set(ABCMAKE_VERSION_PATCH 0) set(ABCMAKE_VERSION "${ABCMAKE_VERSION_MAJOR}.${ABCMAKE_VERSION_MINOR}.${ABCMAKE_VERSION_PATCH}") # Configure CMake set(CMAKE_EXPORT_COMPILE_COMMANDS 1) +# ---------------------------------------------------------------------------- +# Internal CMake modules +# ---------------------------------------------------------------------------- + +# ============================================================================== +# abcmake_property.cmake ======================================================= + +# List of the global abcmake properties: +# - ABCMAKE_COMPONENTS_DIR +# - ABCMAKE_SRC_DIR +# - ABCMAKE_INCLUDE_DIR +# - ABCMAKE_INSTALL_DIR + +# Default prop values +# =================== + +# A change in any of these variables will cause a breaking change in the API +set(ABCMAKE_PROPERTY_PREFIX "ABCMAKE_") +set(ABCMAKE_DEFAULT_COMPONENTS_DIR "components") +set(ABCMAKE_DEFAULT_SRC_DIR "src") +set(ABCMAKE_DEFAULT_INCLUDE_DIR "include") +set(ABCMAKE_DEFAULT_INSTALL_DIR "${CMAKE_BINARY_DIR}/../install") + + +# Setters +# ======= + +function(_set_abcprop PROPERTY_NAME PROPERTY_VALUE) + set_property(GLOBAL PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_append_abcprop PROPERTY_NAME PROPERTY_VALUE) + set_property(GLOBAL APPEND PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_set_abcprop_curdir PROPERTY_NAME PROPERTY_VALUE) + set_directory_properties(PROPERTIES + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_append_abcprop_curdir PROPERTY_NAME PROPERTY_VALUE) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + APPEND PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + + +# Getters +# ======= + +# Get a global property of ABCMAKE (with the ABCMAKE_PROPERTY_PREFIX) +# @param PROPERTY_NAME - The name of the property to get +# @param OUT_VAR_NAME - The name of the variable to set with the result +# @param FALLBACK - Optional argument, if the property is not found, the value of FALLBACK will be used +function(_get_abcprop PROPERTY_NAME OUT_VAR_NAME) + # optional argument FALLBACK + set(flags) + set(args) + set(listArgs FALLBACK) + cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) + + # Getting the property + get_property(tmp_result GLOBAL PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME}) + + # If not found, try to use the fallback + if(NOT tmp_result AND arg_FALLBACK) + set(tmp_result ${arg_FALLBACK}) + endif() + + # Setting the result + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abcprop_dir DIRECTORY PROPERTY_NAME OUT_VAR_NAME) + get_directory_property(tmp_result DIRECTORY ${DIRECTORY} + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +# Specific Getters +# ================= + +function(_get_abc_components OUT_VAR_NAME) + _get_abcprop("COMPONENTS_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_COMPONENTS_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_src OUT_VAR_NAME) + _get_abcprop("SRC_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_SRC_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_include OUT_VAR_NAME) + _get_abcprop("INCLUDE_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_INCLUDE_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_install OUT_VAR_NAME) + _get_abcprop("INSTALL_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_INSTALL_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +# abcmake_property.cmake ======================================================= +# ============================================================================== + + + +# ---------------------------------------------------------------------------- +# Public Functions +# ---------------------------------------------------------------------------- +# ============================================================================== +# set_abcmake_project_structure.cmake ========================================== + +# Configures the project structure for the project and subprojects. +# @param COMPONENTS_DIR: Optional. The directory where the components are stored. +# @param SRC_DIR: Optional. The directory where the source files are stored. +# @param INCLUDE_DIR: Optional. The directory where the include files are stored. +# @param INSTALL_DIR: Optional. The directory where the project is installed. +function (set_abcmake_project_structure) + set(flags SHARED) + set(args) + set(listArgs COMPONENTS_DIR + SRC_DIR + INCLUDE_DIR + INSTALL_DIR) + cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) + + if (arg_COMPONENTS_DIR) + _set_abcprop(COMPONENTS_DIR ${arg_COMPONENTS_DIR}) + endif() + + if (arg_SRC_DIR) + _set_abcprop(SRC_DIR ${arg_SRC_DIR}) + endif() + + if (arg_INCLUDE_DIR) + _set_abcprop(INCLUDE_DIR ${arg_INCLUDE_DIR}) + endif() + + if (arg_INSTALL_DIR) + _set_abcprop(INSTALL_DIR ${arg_INSTALL_DIR}) + endif() + + _get_abc_components("current_components") + _get_abc_src("current_src") + _get_abc_include("current_include") + _get_abc_install("current_install") + message(STATUS "🔤 New project structure applied") + message(STATUS " 📁 Components: ${current_components}") + message(STATUS " 📁 Sources: ${current_src}") + message(STATUS " 📁 Include: ${current_include}") + message(STATUS " 📁 Install: ${current_install}") + +endfunction() + +# set_abcmake_project_structure.cmake ========================================== +# ============================================================================== + # ============================================================================== # add_component.cmake ========================================================== include(CMakeParseArguments) +set(ABC_INSTALL_LIB_SUBDIR "lib") +set(ABC_INSTALL_EXE_SUBDIR ".") # Add all projects from the components subdirectory # @param TARGETNAME - name of the target to add components function(_abc_AddComponents TARGETNAME) + + # Get component directory + _get_abc_components(components) + # List of possible subprojects - file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/components ${CMAKE_CURRENT_SOURCE_DIR}/components/*) + file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/${components} ${CMAKE_CURRENT_SOURCE_DIR}/${components}/*) # Link all subprojects to the ${TARGETNAME} foreach(child ${children}) - if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/components/${child}) - target_link_component(${TARGETNAME} ${CMAKE_CURRENT_SOURCE_DIR}/components/${child}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${components}/${child}) + target_link_component(${TARGETNAME} ${CMAKE_CURRENT_SOURCE_DIR}/${components}/${child}) endif() endforeach() @@ -48,9 +219,10 @@ endfunction() # Install the target near the build directory # @param TARGETNAME - name of the target to install # @param DESTINATION - path to the destination directory inside the install dir -function(_target_install_near_build TARGETNAME DESTINATION) +function(_target_install TARGETNAME DESTINATION) # install directory - set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/../install" + _get_abc_install(install_dir) + set (CMAKE_INSTALL_PREFIX ${install_dir} CACHE PATH "default install path" FORCE) install(TARGETS ${TARGETNAME} DESTINATION ${DESTINATION}) endfunction() @@ -69,12 +241,10 @@ function(_target_init_abcmake TARGETNAME INCLUDE_DIR SOURCE_DIR) endif () # Report version - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY - ABCMAKE_VERSION ${ABCMAKE_VERSION}) + _set_abcprop_curdir("VERSION" ${ABCMAKE_VERSION}) # Add target to the target list - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} APPEND PROPERTY - ABCMAKE_TARGETS ${TARGETNAME}) + _append_abcprop_curdir("TARGETS" ${TARGETNAME}) target_sources_directory(${TARGETNAME} ${SOURCE_DIR}) target_include_directories(${TARGETNAME} PUBLIC ${INCLUDE_DIR}) @@ -93,16 +263,16 @@ function(add_main_component TARGETNAME) cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) if (NOT arg_SOURCE_DIR) - set(arg_SOURCE_DIR "src") + _get_abc_src(arg_SOURCE_DIR) endif() if (NOT arg_INCLUDE_DIR) - set(arg_INCLUDE_DIR "include") + _get_abc_include(arg_INCLUDE_DIR) endif() add_executable(${TARGETNAME}) _target_init_abcmake(${TARGETNAME} ${arg_INCLUDE_DIR} ${arg_SOURCE_DIR}) - _target_install_near_build(${TARGETNAME} ".") + _target_install(${TARGETNAME} ${ABC_INSTALL_EXE_SUBDIR}) endfunction() # Add a shared or static library component to the project @@ -117,11 +287,11 @@ function(add_component TARGETNAME) cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) if (NOT arg_SOURCE_DIR) - set(arg_SOURCE_DIR "src") + _get_abc_src(arg_SOURCE_DIR) endif() if (NOT arg_INCLUDE_DIR) - set(arg_INCLUDE_DIR "include") + _get_abc_include(arg_INCLUDE_DIR) endif() if (arg_SHARED) @@ -131,14 +301,13 @@ function(add_component TARGETNAME) endif() _target_init_abcmake(${TARGETNAME} ${arg_INCLUDE_DIR} ${arg_SOURCE_DIR}) - _target_install_near_build(${TARGETNAME} "lib") + _target_install(${TARGETNAME} ${ABC_INSTALL_LIB_SUBDIR}) endfunction() # add_component.cmake ========================================================== # ============================================================================== - # ============================================================================== # target_sources_directory.cmake =============================================== @@ -160,14 +329,14 @@ endfunction() function(_add_subdirectory PATH) # ABCMAKE_ADDED_PROJECTS is an interface, it may break compatibility if changed! - get_property(projects GLOBAL PROPERTY ABCMAKE_ADDED_PROJECTS) + _get_abcprop("ADDED_PROJECTS" projects) # Resolve relative path get_filename_component(PATH "${PATH}" ABSOLUTE) if (NOT PATH IN_LIST projects) # Add PATH to the global list - set_property(GLOBAL APPEND PROPERTY ABCMAKE_ADDED_PROJECTS ${PATH}) + _set_abcprop("ADDED_PROJECTS" ${PATH}) # Use the last directory name for a binary directory name get_filename_component(last_dir "${PATH}" NAME) @@ -181,7 +350,7 @@ function(_abc_AddProject PATH OUT_ABCMAKE_VER) message(DEBUG "Adding project ${PATH}") _add_subdirectory(${PATH}) - get_directory_property(version DIRECTORY ${PATH} ABCMAKE_VERSION) + _get_abcprop_dir(${PATH} "VERSION" version) set(${OUT_ABCMAKE_VER} ${version} PARENT_SCOPE) if (NOT version) message (STATUS " 🔶 ${PATH} is not an ABCMAKE project. Link it manually.") @@ -198,7 +367,7 @@ endfunction() function (target_link_component TARGETNAME COMPONENTPATH) _abc_AddProject(${COMPONENTPATH} ver) if (ver) - get_directory_property(to_link DIRECTORY ${COMPONENTPATH} ABCMAKE_TARGETS) + _get_abcprop_dir(${COMPONENTPATH} "TARGETS" to_link) message (STATUS " ✅ Linking ${to_link} to ${TARGETNAME}") target_link_libraries(${TARGETNAME} PRIVATE ${to_link}) endif() diff --git a/src/ab.cmake b/src/ab.cmake index 11edd67..79270c5 100644 --- a/src/ab.cmake +++ b/src/ab.cmake @@ -20,6 +20,16 @@ include(${CMAKE_CURRENT_LIST_DIR}/version.cmake) # Configure CMake set(CMAKE_EXPORT_COMPILE_COMMANDS 1) +# ---------------------------------------------------------------------------- +# Internal CMake modules +# ---------------------------------------------------------------------------- +include(${CMAKE_CURRENT_LIST_DIR}/abcmake/constants.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/abcmake/abcmake_property.cmake) + +# ---------------------------------------------------------------------------- +# Public Functions +# ---------------------------------------------------------------------------- +include(${CMAKE_CURRENT_LIST_DIR}/abcmake/set_abcmake_config.cmake) include(${CMAKE_CURRENT_LIST_DIR}/abcmake/add_component.cmake) include(${CMAKE_CURRENT_LIST_DIR}/abcmake/target_sources_directory.cmake) include(${CMAKE_CURRENT_LIST_DIR}/abcmake/target_link_component.cmake) diff --git a/src/abcmake/abcmake_property.cmake b/src/abcmake/abcmake_property.cmake new file mode 100644 index 0000000..a86ae35 --- /dev/null +++ b/src/abcmake/abcmake_property.cmake @@ -0,0 +1,108 @@ +# ============================================================================== +# abcmake_property.cmake ======================================================= + +# List of the global abcmake properties: +# - ABCMAKE_COMPONENTS_DIR +# - ABCMAKE_SRC_DIR +# - ABCMAKE_INCLUDE_DIR +# - ABCMAKE_INSTALL_DIR + +# Default prop values +# =================== + +# A change in any of these variables will cause a breaking change in the API +set(ABCMAKE_PROPERTY_PREFIX "ABCMAKE_") +set(ABCMAKE_DEFAULT_COMPONENTS_DIR "components") +set(ABCMAKE_DEFAULT_SRC_DIR "src") +set(ABCMAKE_DEFAULT_INCLUDE_DIR "include") +set(ABCMAKE_DEFAULT_INSTALL_DIR "${CMAKE_BINARY_DIR}/../install") + + +# Setters +# ======= + +function(_set_abcprop PROPERTY_NAME PROPERTY_VALUE) + set_property(GLOBAL PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_append_abcprop PROPERTY_NAME PROPERTY_VALUE) + set_property(GLOBAL APPEND PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_set_abcprop_curdir PROPERTY_NAME PROPERTY_VALUE) + set_directory_properties(PROPERTIES + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + +function(_append_abcprop_curdir PROPERTY_NAME PROPERTY_VALUE) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + APPEND PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME} ${PROPERTY_VALUE}) +endfunction() + + +# Getters +# ======= + +# Get a global property of ABCMAKE (with the ABCMAKE_PROPERTY_PREFIX) +# @param PROPERTY_NAME - The name of the property to get +# @param OUT_VAR_NAME - The name of the variable to set with the result +# @param FALLBACK - Optional argument, if the property is not found, the value of FALLBACK will be used +function(_get_abcprop PROPERTY_NAME OUT_VAR_NAME) + # optional argument FALLBACK + set(flags) + set(args) + set(listArgs FALLBACK) + cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) + + # Getting the property + get_property(tmp_result GLOBAL PROPERTY + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME}) + + # If not found, try to use the fallback + if(NOT tmp_result AND arg_FALLBACK) + set(tmp_result ${arg_FALLBACK}) + endif() + + # Setting the result + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abcprop_dir DIRECTORY PROPERTY_NAME OUT_VAR_NAME) + get_directory_property(tmp_result DIRECTORY ${DIRECTORY} + ${ABCMAKE_PROPERTY_PREFIX}${PROPERTY_NAME}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +# Specific Getters +# ================= + +function(_get_abc_components OUT_VAR_NAME) + _get_abcprop("COMPONENTS_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_COMPONENTS_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_src OUT_VAR_NAME) + _get_abcprop("SRC_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_SRC_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_include OUT_VAR_NAME) + _get_abcprop("INCLUDE_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_INCLUDE_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +function(_get_abc_install OUT_VAR_NAME) + _get_abcprop("INSTALL_DIR" tmp_result + FALLBACK ${ABCMAKE_DEFAULT_INSTALL_DIR}) + set(${OUT_VAR_NAME} ${tmp_result} PARENT_SCOPE) +endfunction() + +# abcmake_property.cmake ======================================================= +# ============================================================================== + diff --git a/src/abcmake/add_component.cmake b/src/abcmake/add_component.cmake index a45654a..f4609b3 100644 --- a/src/abcmake/add_component.cmake +++ b/src/abcmake/add_component.cmake @@ -2,17 +2,23 @@ # add_component.cmake ========================================================== include(CMakeParseArguments) +set(ABC_INSTALL_LIB_SUBDIR "lib") +set(ABC_INSTALL_EXE_SUBDIR ".") # Add all projects from the components subdirectory # @param TARGETNAME - name of the target to add components function(_abc_AddComponents TARGETNAME) + + # Get component directory + _get_abc_components(components) + # List of possible subprojects - file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/components ${CMAKE_CURRENT_SOURCE_DIR}/components/*) + file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/${components} ${CMAKE_CURRENT_SOURCE_DIR}/${components}/*) # Link all subprojects to the ${TARGETNAME} foreach(child ${children}) - if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/components/${child}) - target_link_component(${TARGETNAME} ${CMAKE_CURRENT_SOURCE_DIR}/components/${child}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${components}/${child}) + target_link_component(${TARGETNAME} ${CMAKE_CURRENT_SOURCE_DIR}/${components}/${child}) endif() endforeach() @@ -22,9 +28,10 @@ endfunction() # Install the target near the build directory # @param TARGETNAME - name of the target to install # @param DESTINATION - path to the destination directory inside the install dir -function(_target_install_near_build TARGETNAME DESTINATION) +function(_target_install TARGETNAME DESTINATION) # install directory - set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/../install" + _get_abc_install(install_dir) + set (CMAKE_INSTALL_PREFIX ${install_dir} CACHE PATH "default install path" FORCE) install(TARGETS ${TARGETNAME} DESTINATION ${DESTINATION}) endfunction() @@ -43,12 +50,10 @@ function(_target_init_abcmake TARGETNAME INCLUDE_DIR SOURCE_DIR) endif () # Report version - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY - ABCMAKE_VERSION ${ABCMAKE_VERSION}) + _set_abcprop_curdir("VERSION" ${ABCMAKE_VERSION}) # Add target to the target list - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} APPEND PROPERTY - ABCMAKE_TARGETS ${TARGETNAME}) + _append_abcprop_curdir("TARGETS" ${TARGETNAME}) target_sources_directory(${TARGETNAME} ${SOURCE_DIR}) target_include_directories(${TARGETNAME} PUBLIC ${INCLUDE_DIR}) @@ -67,16 +72,16 @@ function(add_main_component TARGETNAME) cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) if (NOT arg_SOURCE_DIR) - set(arg_SOURCE_DIR "src") + _get_abc_src(arg_SOURCE_DIR) endif() if (NOT arg_INCLUDE_DIR) - set(arg_INCLUDE_DIR "include") + _get_abc_include(arg_INCLUDE_DIR) endif() add_executable(${TARGETNAME}) _target_init_abcmake(${TARGETNAME} ${arg_INCLUDE_DIR} ${arg_SOURCE_DIR}) - _target_install_near_build(${TARGETNAME} ".") + _target_install(${TARGETNAME} ${ABC_INSTALL_EXE_SUBDIR}) endfunction() # Add a shared or static library component to the project @@ -91,11 +96,11 @@ function(add_component TARGETNAME) cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) if (NOT arg_SOURCE_DIR) - set(arg_SOURCE_DIR "src") + _get_abc_src(arg_SOURCE_DIR) endif() if (NOT arg_INCLUDE_DIR) - set(arg_INCLUDE_DIR "include") + _get_abc_include(arg_INCLUDE_DIR) endif() if (arg_SHARED) @@ -105,10 +110,9 @@ function(add_component TARGETNAME) endif() _target_init_abcmake(${TARGETNAME} ${arg_INCLUDE_DIR} ${arg_SOURCE_DIR}) - _target_install_near_build(${TARGETNAME} "lib") + _target_install(${TARGETNAME} ${ABC_INSTALL_LIB_SUBDIR}) endfunction() # add_component.cmake ========================================================== # ============================================================================== - diff --git a/src/abcmake/constants.cmake b/src/abcmake/constants.cmake new file mode 100644 index 0000000..e69de29 diff --git a/src/abcmake/set_abcmake_config.cmake b/src/abcmake/set_abcmake_config.cmake new file mode 100644 index 0000000..8facf38 --- /dev/null +++ b/src/abcmake/set_abcmake_config.cmake @@ -0,0 +1,47 @@ +# ============================================================================== +# set_abcmake_project_structure.cmake ========================================== + +# Configures the project structure for the project and subprojects. +# @param COMPONENTS_DIR: Optional. The directory where the components are stored. +# @param SRC_DIR: Optional. The directory where the source files are stored. +# @param INCLUDE_DIR: Optional. The directory where the include files are stored. +# @param INSTALL_DIR: Optional. The directory where the project is installed. +function (set_abcmake_project_structure) + set(flags SHARED) + set(args) + set(listArgs COMPONENTS_DIR + SRC_DIR + INCLUDE_DIR + INSTALL_DIR) + cmake_parse_arguments(arg "${flags}" "${args}" "${listArgs}" ${ARGN}) + + if (arg_COMPONENTS_DIR) + _set_abcprop(COMPONENTS_DIR ${arg_COMPONENTS_DIR}) + endif() + + if (arg_SRC_DIR) + _set_abcprop(SRC_DIR ${arg_SRC_DIR}) + endif() + + if (arg_INCLUDE_DIR) + _set_abcprop(INCLUDE_DIR ${arg_INCLUDE_DIR}) + endif() + + if (arg_INSTALL_DIR) + _set_abcprop(INSTALL_DIR ${arg_INSTALL_DIR}) + endif() + + _get_abc_components("current_components") + _get_abc_src("current_src") + _get_abc_include("current_include") + _get_abc_install("current_install") + message(STATUS "🔤 New project structure applied") + message(STATUS " 📁 Components: ${current_components}") + message(STATUS " 📁 Sources: ${current_src}") + message(STATUS " 📁 Include: ${current_include}") + message(STATUS " 📁 Install: ${current_install}") + +endfunction() + +# set_abcmake_project_structure.cmake ========================================== +# ============================================================================== diff --git a/src/abcmake/target_link_component.cmake b/src/abcmake/target_link_component.cmake index e660535..94d029e 100644 --- a/src/abcmake/target_link_component.cmake +++ b/src/abcmake/target_link_component.cmake @@ -5,14 +5,14 @@ function(_add_subdirectory PATH) # ABCMAKE_ADDED_PROJECTS is an interface, it may break compatibility if changed! - get_property(projects GLOBAL PROPERTY ABCMAKE_ADDED_PROJECTS) + _get_abcprop("ADDED_PROJECTS" projects) # Resolve relative path get_filename_component(PATH "${PATH}" ABSOLUTE) if (NOT PATH IN_LIST projects) # Add PATH to the global list - set_property(GLOBAL APPEND PROPERTY ABCMAKE_ADDED_PROJECTS ${PATH}) + _set_abcprop("ADDED_PROJECTS" ${PATH}) # Use the last directory name for a binary directory name get_filename_component(last_dir "${PATH}" NAME) @@ -26,7 +26,7 @@ function(_abc_AddProject PATH OUT_ABCMAKE_VER) message(DEBUG "Adding project ${PATH}") _add_subdirectory(${PATH}) - get_directory_property(version DIRECTORY ${PATH} ABCMAKE_VERSION) + _get_abcprop_dir(${PATH} "VERSION" version) set(${OUT_ABCMAKE_VER} ${version} PARENT_SCOPE) if (NOT version) message (STATUS " 🔶 ${PATH} is not an ABCMAKE project. Link it manually.") @@ -43,7 +43,7 @@ endfunction() function (target_link_component TARGETNAME COMPONENTPATH) _abc_AddProject(${COMPONENTPATH} ver) if (ver) - get_directory_property(to_link DIRECTORY ${COMPONENTPATH} ABCMAKE_TARGETS) + _get_abcprop_dir(${COMPONENTPATH} "TARGETS" to_link) message (STATUS " ✅ Linking ${to_link} to ${TARGETNAME}") target_link_libraries(${TARGETNAME} PRIVATE ${to_link}) endif() diff --git a/src/version.cmake b/src/version.cmake index b1097ff..b993c0c 100644 --- a/src/version.cmake +++ b/src/version.cmake @@ -1,4 +1,4 @@ set(ABCMAKE_VERSION_MAJOR 5) -set(ABCMAKE_VERSION_MINOR 1) -set(ABCMAKE_VERSION_PATCH 2) +set(ABCMAKE_VERSION_MINOR 2) +set(ABCMAKE_VERSION_PATCH 0) set(ABCMAKE_VERSION "${ABCMAKE_VERSION_MAJOR}.${ABCMAKE_VERSION_MINOR}.${ABCMAKE_VERSION_PATCH}") diff --git a/tests/project_custom/CMakeLists.txt b/tests/project_custom/CMakeLists.txt index 9046213..63a49b4 100644 --- a/tests/project_custom/CMakeLists.txt +++ b/tests/project_custom/CMakeLists.txt @@ -1,12 +1,15 @@ cmake_minimum_required(VERSION 3.5) include($ENV{ABCMAKE_PATH}/ab.cmake) +set_abcmake_project_structure( + INCLUDE_DIR "headers" + SRC_DIR "sources" + COMPONENTS_DIR "libs" +) project(HelloWorld) -add_main_component(${PROJECT_NAME} - INCLUDE_DIR "./includes" - SOURCE_DIR "./sources") +add_main_component(${PROJECT_NAME}) target_link_component(${PROJECT_NAME} ./lib_world) target_link_component(${PROJECT_NAME} ./lib_exclamation) diff --git a/tests/project_custom/includes/app.hpp b/tests/project_custom/headers/app.hpp similarity index 100% rename from tests/project_custom/includes/app.hpp rename to tests/project_custom/headers/app.hpp diff --git a/tests/project_custom/includes/hello.hpp b/tests/project_custom/headers/hello.hpp similarity index 100% rename from tests/project_custom/includes/hello.hpp rename to tests/project_custom/headers/hello.hpp diff --git a/tests/project_custom/lib_exclamation/CMakeLists.txt b/tests/project_custom/lib_exclamation/CMakeLists.txt index 559ce51..2621621 100644 --- a/tests/project_custom/lib_exclamation/CMakeLists.txt +++ b/tests/project_custom/lib_exclamation/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.15.0) project("exclamation") # Library -add_library(${PROJECT_NAME}) -target_sources(${PROJECT_NAME} PRIVATE "src/exclamation.cpp") -target_include_directories(${PROJECT_NAME} PUBLIC "include") + +include($ENV{ABCMAKE_PATH}/ab.cmake) +add_component(${PROJECT_NAME} + INCLUDE_DIR "./interface" + SOURCE_DIR "./source_code") diff --git a/tests/project_custom/lib_exclamation/include/exclamation.hpp b/tests/project_custom/lib_exclamation/interface/exclamation.hpp similarity index 100% rename from tests/project_custom/lib_exclamation/include/exclamation.hpp rename to tests/project_custom/lib_exclamation/interface/exclamation.hpp diff --git a/tests/project_custom/lib_exclamation/src/exclamation.cpp b/tests/project_custom/lib_exclamation/source_code/exclamation.cpp similarity index 100% rename from tests/project_custom/lib_exclamation/src/exclamation.cpp rename to tests/project_custom/lib_exclamation/source_code/exclamation.cpp diff --git a/tests/project_custom/lib_world/include/world.hpp b/tests/project_custom/lib_world/headers/world.hpp similarity index 100% rename from tests/project_custom/lib_world/include/world.hpp rename to tests/project_custom/lib_world/headers/world.hpp diff --git a/tests/project_custom/lib_world/src/world.cpp b/tests/project_custom/lib_world/sources/world.cpp similarity index 100% rename from tests/project_custom/lib_world/src/world.cpp rename to tests/project_custom/lib_world/sources/world.cpp