view cmake/MalikaniaFunctions.cmake @ 47:7097a91b08a8

Tools: add mlk-bcc tool, closes #596
author David Demelier <markand@malikania.fr>
date Wed, 07 Dec 2016 20:51:19 +0100
parents f30c84b4b9ed
children
line wrap: on
line source

#
# CMakeLists.txt -- CMake build system for malikania
#
# Copyright (c) 2013-2016 Malikania Authors
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

include(CMakeParseArguments)

# ---------------------------------------------------------
# The following macros are available:
#
# malikania_build_assets
# ----------------------
#
# malikania_build_assets(inputs outputs)
#
# Create binary data as C++ arrays for inclusion in source code. Static assets
# increases the executable size so use this when really needed.
#
# The macro iterates over the input data which can be any files and generates
# outputs file in the form CMAKE_CURRENT_BINARY_DIR/assets/basename.cpp.
#
# The macro removes the extension from the filename and create a static array
# with that name, thus you need to specify a filename that is compatible with
# C++ identifiers!
#
# Correct:
#   - myfile.png
#   - startup_logo.png
#
# Incorrect:
#   - useful-code.ogg
#   - archive.tar.xz
#
# malikania_define_executable
# ---------------------------
#
# malikania_define_executable(
#    TARGET             The target name
#    SOURCES            The list of sources
#    FLAGS              (Optional) List of flags
#    INCLUDES           (Optional) List of include directories
#    LIBRARIES          (Optional) List of libraries
# )
#
# Create an executable. Be sure to quote SOURCES, if not only the first file will be passed.
# If you need flags, just pass them without -D or /D, this is automatically done for you.
#
# malikania_create_library
# ------------------------
#
# malikania_create_library(
#    TARGET            The target name
#    SOURCES           The sources
#    ASSETS            (Optional) Additional assets files
#    FLAGS             (Optional) List of flags
#    PRIVATE_INCLUDES  (Optional) List of includes only for building the library
#    PUBLIC_INCLUDES   (Optional) List of public includes to share with the library users
#    LIBRARIES         (Optional) List of libraries to link against
# )
#
# Create a shared library. Follow the same specification as malikania_define_executable.
# However, additional PRIVATE_INCLUDES and PUBLIC_INCLUDES are available.
#
# malikania_create_test
# ---------------------
#
# malikania_create_test(
#    NAME              Test name (must be lowercase)
#    SOURCES           Test sources files
#    LIBRARIES         (Optional) Libraries to link to
#    RESOURCES         (Optional) Resources files to copy verbatim
# )
#
# This will generate a target named test-<name> where name is the parameter NAME. The test is created
# under CMAKE_BINARY_DIR/test/<NAME> and resources are copied there with the same hierarchy.
#
# setg
# ----
#
# setg(var value)
#
# Set a cache variable internal with name var.
#
# ---------------------------------------------------------

function(apply_flags target flags)
    # Add MALIKANIA_BUILD to enable declspec(dllexport) on Windows
    if (${flags})
        target_compile_definitions(
            ${target}
            PRIVATE ${flags}
            PRIVATE "MALIKANIA_BUILD"
        )
    endif ()
endfunction()

function(apply_public_includes target var)
    if (${var})
        target_include_directories(${target} PUBLIC ${${var}})
    endif ()

    target_include_directories(
        ${target}
        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/malikania/${WITH_BACKEND_DIRECTORY}
        PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
    )
endfunction()

function(apply_private_includes target var)
    if (${var})
        target_include_directories(${target} PRIVATE ${${var}})
    endif ()
endfunction()

function(apply_includes target var)
    if (${var})
        target_include_directories(${target} PRIVATE ${${var}})
    endif ()
endfunction()

function(apply_libraries target libs)
    if (${libs})
        target_link_libraries(${target} ${${libs}})
    endif ()
endfunction()

function(check_args prefix list)
    foreach (e ${list})
        if (NOT ${prefix}_${e})
            message(FATAL_ERROR "Please set `${e}' parameter")
        endif ()
    endforeach ()
endfunction()

macro(malikania_build_assets inputs outputs)
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/assets)

    foreach (in ${inputs})
        get_filename_component(basename ${in} NAME_WE)
        set(out ${CMAKE_CURRENT_BINARY_DIR}/assets/${basename}.cpp)
        add_custom_command(
            OUTPUT ${out}
            COMMENT "Generating binary data from ${in}"
            DEPENDS ${in}
            COMMAND
                $<TARGET_FILE:mlk-bcc> ${basename} ${in} ${out}
        )
        list(APPEND ${outputs} ${out})
    endforeach ()
endmacro()

function(malikania_define_executable)
    set(singleArgs TARGET)
    set(multiArgs SOURCES FLAGS INCLUDES LIBRARIES)
    set(mandatory TARGET SOURCES)

    cmake_parse_arguments(EXE "" "${singleArgs}" "${multiArgs}" ${ARGN})
    check_args(EXE ${mandatory})

    add_executable(${EXE_TARGET} ${EXE_SOURCES})

    apply_libraries(${EXE_TARGET} EXE_LIBRARIES)
    apply_includes(${EXE_TARGET} EXE_INCLUDES)
    apply_flags(${EXE_TARGET} EXE_FLAGS)
endfunction()

function(malikania_create_library)
    set(singleArgs TARGET)
    set(multiArgs ASSETS SOURCES FLAGS PRIVATE_INCLUDES PUBLIC_INCLUDES LIBRARIES)
    set(mandatory TARGET SOURCES)

    cmake_parse_arguments(LIB "" "${singleArgs}" "${multiArgs}" ${ARGN})
    check_args(LIB ${mandatory})

    # Enable assets for libraries.
    malikania_build_assets("${LIB_ASSETS}" assets)

    add_library(${LIB_TARGET} SHARED ${LIB_SOURCES} ${assets})
    target_include_directories(${LIB_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/assets)

    # Remove lib suffix to avoid conflict with client and libclient targets
    set_target_properties(
        ${LIB_TARGET}
        PROPERTIES
        PREFIX ""
    )

    list(APPEND LIB_LIBRARIES duktape)

    apply_libraries(${LIB_TARGET} LIB_LIBRARIES)
    apply_private_includes(${LIB_TARGET} LIB_PRIVATE_INCLUDES)
    apply_public_includes(${LIB_TARGET} LIB_PUBLIC_INCLUDES)
    apply_flags(${LIB_TARGET} LIB_FLAGS)
endfunction()

function(malikania_create_test)
    set(singleArgs NAME)
    set(multiArgs LIBRARIES SOURCES RESOURCES)

    set(mandatory NAME SOURCES)

    cmake_parse_arguments(TEST "" "${singleArgs}" "${multiArgs}" ${ARGN})
    check_args(TEST ${mandatory})

    file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/test/${TEST_NAME})

    if (UNIX)
        list(APPEND TEST_LIBRARIES pthread)
    endif ()

    # Resources files added before as custom output
    foreach (f ${TEST_RESOURCES})
        get_filename_component(absolute ${f} ABSOLUTE)
        file(RELATIVE_PATH basename ${CMAKE_CURRENT_SOURCE_DIR} ${absolute})
        set(output ${CMAKE_BINARY_DIR}/test/${TEST_NAME}/${basename})

        add_custom_command(
            OUTPUT ${output}
            COMMAND ${CMAKE_COMMAND} -E copy ${absolute} ${output}
            DEPENDS ${absolute}
        )

        list(APPEND TEST_SOURCES ${absolute})
        list(APPEND outputs ${output})
    endforeach ()

    add_executable(test-${TEST_NAME} ${TEST_SOURCES} ${outputs})
    source_group(private\\Resources FILES ${outputs})
    target_compile_definitions(
        test-${TEST_NAME}
        PRIVATE
            BOOST_TEST_DYN_LINK
            SOURCE_DIRECTORY=\"${CMAKE_BINARY_DIR}/test/${TEST_NAME}\"
    )
    set_target_properties(
        test-${TEST_NAME}
        PROPERTIES
            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
            RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
            RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
            RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
            RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
    )
    add_test(
        NAME ${TEST_NAME}
        COMMAND $<TARGET_FILE:test-${TEST_NAME}>
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test/${TEST_NAME}
    )

    target_link_libraries(
        test-${TEST_NAME}
        ${TEST_LIBRARIES}
        ${Boost_unit_test_framework_LIBRARY}
    )

    add_dependencies(tests test-${TEST_NAME})
endfunction()

macro(setg var value)
    set(${var} ${value} CACHE INTERNAL "" FORCE)
endmacro()