Skip to content
Snippets Groups Projects
Commit b590f8a9 authored by Jan Uhlík's avatar Jan Uhlík Committed by Jan Trávníček
Browse files

add CMake building option by Jan Uhlik

parent f904b670
No related branches found
No related tags found
No related merge requests found
...@@ -95,6 +95,10 @@ docs/userGuide/res/* ...@@ -95,6 +95,10 @@ docs/userGuide/res/*
# CMake # CMake
cmake-build-debug/ cmake-build-debug/
   
# CMakeList.txt files are generated
**/CMakeLists.txt
CMakeLists.txt
# Mongo Explorer plugin: # Mongo Explorer plugin:
.idea/**/mongoSettings.xml .idea/**/mongoSettings.xml
   
......
...@@ -47,6 +47,19 @@ build-gcc: ...@@ -47,6 +47,19 @@ build-gcc:
build-clang: build-clang:
<<: *build <<: *build
   
build-cmake:
variables:
EXTRA_PKGS: cmake python3 py3-click
script:
- cd CMake
- ./alib_cmake.py -w -m
- cd ..
- mkdir release
- cd release
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make
stage: build
build-doc: build-doc:
variables: variables:
EXTRA_PKGS: doxygen graphviz EXTRA_PKGS: doxygen graphviz
......
project({project_name})
set(PROJECT_NAME {project_name})
set(SOURCE_FILES
{source_files} )
# Add executable target
add_executable(${{PROJECT_NAME}} ${{SOURCE_FILES}})
# Target link libraries
target_link_libraries(${{PROJECT_NAME}} {target_test_libs} {target_libs})
set_target_properties(${{PROJECT_NAME}} PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
LINKER_LANGUAGE CXX
INTERFACE_POSITION_INDEPENDENT_CODE ON
)
# Install
install(TARGETS ${{PROJECT_NAME}} RUNTIME DESTINATION bin)
project({project_name})
set(PROJECT_NAME {project_name})
set(SOURCE_FILES
{source_files} )
# Add library target
add_library(${{PROJECT_NAME}} SHARED ${{SOURCE_FILES}})
# Target link libraries
target_link_libraries(${{PROJECT_NAME}} LINK_PUBLIC {target_libs})
# Include dependencies directories
target_include_directories(${{PROJECT_NAME}}
PUBLIC ${{CMAKE_CURRENT_SOURCE_DIR}}/src # anything that depends on this should include src also, hence public
{xml_dep} # place for XML dependency
)
set_target_properties(${{PROJECT_NAME}} PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
LINKER_LANGUAGE CXX
INTERFACE_POSITION_INDEPENDENT_CODE ON
)
# Install
install(TARGETS ${{PROJECT_NAME}} LIBRARY DESTINATION bin)
########################################################################################################################
# cppunit tests
set(PROJECT_NAME_TEST test-{project_name})
set(SOURCE_FILES_TEST
{source_files_test} )
add_executable(${{PROJECT_NAME_TEST}} ${{SOURCE_FILES_TEST}})
set_target_properties(${{PROJECT_NAME_TEST}} PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
)
target_link_libraries(${{PROJECT_NAME_TEST}} ${{PROJECT_NAME}} {target_test_libs} ${{CPPUNIT_LIBRARY}})
enable_testing()
add_test(NAME ${{PROJECT_NAME}}
COMMAND $<TARGET_FILE:${{PROJECT_NAME_TEST}}>
)
cmake_minimum_required(VERSION 3.8)
# Project name
project(alib2)
################
# Immediately fail if not UNIX
# TODO: Add suport for other platforms
# FIXME: Apple is subset of UNIX, check.
if (NOT UNIX)
message(FATAL_ERROR "Unavailable if not Unix")
endif ()
#################
# ALIB Versioning
set(ALIB_VERSION_MAJOR 2)
set(ALIB_VERSION_MINOR 0)
set(ALIB_VERSION_PATCH 0)
set(ALIB_VERSION ${{ALIB_VERSION_MAJOR}}.${{ALIB_VERSION_MINOR}}.${{ALIB_VERSION_PATCH}})
mark_as_advanced(ALIB_VERSION)
######################
# Some Makefile tuning
set(CMAKE_COLOR_MAKEFILE ON)
# set(CMAKE_VERBOSE_MAKEFILE ON)
####################
# CMake include path
set(CMAKE_MODULE_PATH ${{CMAKE_SOURCE_DIR}}/CMake)
# set(CMAKE_TEMPLATE_PATH ${{CMAKE_SOURCE_DIR}}/CMakeTemplates)
#########################################################
# If not specified whether Debug or Release, select debug
# cmake -DCMAKE_BUILD_TYPE=Release
# cmake -DCMAKE_BUILD_TYPE=Debug
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif ()
###########################################
# Flags according to Debug/Release decision
# - CMake uses -g on Debug implicitly
# - fPIC for libraries will be enabled explicitly
set(ALIB_BUILD_FLAGS_COMMON -Wall -pedantic -pipe -Wextra -Werror)
set(ALIB_BUILD_FLAGS_DEBUG ${{ALIB_BUILD_FLAGS_COMMON}} -Og)
set(ALIB_BUILD_FLAGS_RELEASE ${{ALIB_BUILD_FLAGS_COMMON}} -O3)
if (${{CMAKE_CXX_COMPILER_ID}} STREQUAL "Clang")
set(ALIB_BUILD_FLAGS_DEBUG ${{ALIB_BUILD_FLAGS_COMMON}} -O0)
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG)
add_compile_options(${{ALIB_BUILD_FLAGS_DEBUG}})
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
remove_definitions(-DNDEBUG)
add_definitions(-DRELEASE)
add_compile_options(${{ALIB_BUILD_FLAGS_RELEASE}})
endif ()
######################################
# check required external dependencies
# - we will deal with includes and library links in each project explicitly
find_package(LibXml2 REQUIRED)
find_package(cppunit REQUIRED)
find_package(tclap REQUIRED)
find_package(readline REQUIRED)
# Cpp version
set(CMAKE_CXX_STANDARD {{cpp_version}})
set(ALIB_MODULES_LIB
{alib_modules_lib}
)
set(ALIB_MODULES_EXE
{alib_modules_exe}
)
##################
# Register modules
foreach (module ${{ALIB_MODULES_LIB}} ${{ALIB_MODULES_EXE}})
add_subdirectory(${{module}})
endforeach ()
#######
# Tests
# - enable
enable_testing()
# include(CTest) # we do not need full CTest support now
# - try to find cppunit library
#
# Cache Variables: (probably not for direct use in your scripts)
# CPPUNIT_INCLUDE_DIR
# CPPUNIT_LIBRARY
#
# Non-cache variables you might use in your CMakeLists.txt:
# CPPUNIT_FOUND
# CPPUNIT_INCLUDE_DIRS
# CPPUNIT_LIBRARIES
#
# Requires these CMake modules:
# SelectLibraryConfigurations (included with CMake >= 2.8.0)
# FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
#
# Original Author:
# 2009-2011 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2011.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(CPPUNIT_ROOT_DIR
"${CPPUNIT_ROOT_DIR}"
CACHE
PATH
"Directory to search")
find_library(CPPUNIT_LIBRARY_RELEASE
NAMES
cppunit
HINTS
"${CPPUNIT_ROOT_DIR}")
find_library(CPPUNIT_LIBRARY_DEBUG
NAMES
cppunitd
HINTS
"${CPPUNIT_ROOT_DIR}")
include(SelectLibraryConfigurations)
select_library_configurations(CPPUNIT)
# Might want to look close to the library first for the includes.
get_filename_component(_libdir "${CPPUNIT_LIBRARY_RELEASE}" PATH)
find_path(CPPUNIT_INCLUDE_DIR
NAMES
cppunit/TestCase.h
HINTS
"${_libdir}/.."
PATHS
"${CPPUNIT_ROOT_DIR}"
PATH_SUFFIXES
include/)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(cppunit
DEFAULT_MSG
CPPUNIT_LIBRARY
CPPUNIT_INCLUDE_DIR)
if (CPPUNIT_FOUND)
set(CPPUNIT_LIBRARIES ${CPPUNIT_LIBRARY} ${CMAKE_DL_LIBS})
set(CPPUNIT_INCLUDE_DIRS "${CPPUNIT_INCLUDE_DIR}")
mark_as_advanced(CPPUNIT_ROOT_DIR)
endif ()
mark_as_advanced(CPPUNIT_INCLUDE_DIR
CPPUNIT_LIBRARY_RELEASE
CPPUNIT_LIBRARY_DEBUG)
# - Try to find readline include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(Readline)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# Readline_ROOT_DIR Set this variable to the root installation of
# readline if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# READLINE_FOUND System has readline, include and lib dirs found
# Readline_INCLUDE_DIR The readline include directories.
# Readline_LIBRARY The readline library.
find_path(Readline_ROOT_DIR
NAMES include/readline/readline.h
)
find_path(Readline_INCLUDE_DIR
NAMES readline/readline.h
HINTS ${Readline_ROOT_DIR}/include
)
find_library(Readline_LIBRARY
NAMES readline
HINTS ${Readline_ROOT_DIR}/lib
)
if (Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
set(READLINE_FOUND TRUE)
else (Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
FIND_LIBRARY(Readline_LIBRARY NAMES readline)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY)
MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
endif (Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
mark_as_advanced(
Readline_ROOT_DIR
Readline_INCLUDE_DIR
Readline_LIBRARY
)
find_path(TCLAP_INCLUDE_DIR CmdLine.h PATHS
$ENV{HOME}/build/include
PATH_SUFFIXES
tclap
include/)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(TCLAP
DEFAULT_MSG
TCLAP_INCLUDE_DIR)
MIT License
Copyright (c) 2017 ctu-fit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
CMake extension
===============
This module is a support module for compiling with `cmake` which is neccesary for correct syntax highlight in `CLion`. `CMakeLists.txt` can be generated with simple python script [`alib-cmake`]. Original author is Jan Uhlík and the script is available on [`gitlab`](https://gitlab.com/ctu-fit/alib-cmake).
# CMakeLists generator for Algorithms library
This package generate `CMakeLists.txt` for *Algorithms library*.
Library dependencies are parsed from `makefile.conf`.
## Run
```
alib-cmake -w
```
See `--help` for details.
from alib_cmake import main
main()
#!/usr/bin/env python3
import os
import sys
import click
alib_path = '..'
alib_modules_lib = [
# Libraries
'alib2algo',
'alib2algo_experimental',
'alib2aux',
'alib2cli',
'alib2common',
'alib2data',
'alib2data_experimental',
'alib2elgo',
'alib2measure',
'alib2raw',
'alib2raw_cli_integration',
'alib2std',
'alib2str',
'alib2str_cli_integration',
'alib2xml',
'alib2abstraction',
'alib2dummy',
'alib2graph_data',
'alib2graph_algo',
]
alib_modules_exe = [
# Binaries
'aaccess2',
'aarbology2',
'acast2',
'acompaction2',
'acompare2',
'aconversions2',
'aconvert2',
'aderivation2',
'adeterminize2',
'aecho2',
'aepsilon2',
'agenerate2',
'aintegral2',
'aintrospection2',
'alangop2',
'aminimize2',
'anormalize2',
'aql2',
'aquery2',
'arand2',
'araw2',
'arename2',
'areverse2',
'arun2',
'astat2',
'astringology2',
'atrim2',
'tniceprint',
]
root_template = open(os.path.join(os.path.dirname(__file__), "CMakeLists_root.txt"), 'r').read()
library_template = open(os.path.join(os.path.dirname(__file__), "CMakeLists_library.txt"), 'r').read()
executable_template = open(os.path.join(os.path.dirname(__file__), "CMakeLists_executable.txt"), 'r').read()
separate_size = 20
# ----------------------------------------------------------------------------------------------------------------------
def create_root_cmakelist(debug):
alib_modules_exe_str = '\n '.join(alib_modules_exe)
alib_modules_lib_str = '\n '.join(alib_modules_lib)
if not debug:
print('CMakeLists.txt')
print('-' * separate_size)
print(root_template.format(
alib_modules_lib=alib_modules_lib_str,
alib_modules_exe=alib_modules_exe_str
))
print('-' * separate_size)
else:
with open(f'{alib_path}/CMakeLists.txt', 'w') as file:
file.write(root_template.format(
alib_modules_lib=alib_modules_lib_str,
alib_modules_exe=alib_modules_exe_str
))
# ----------------------------------------------------------------------------------------------------------------------
def get_source_files(project_name, directory):
# Recursively find all source file(s) and directories
source_files = []
for dp, dn, fn in os.walk(f'{alib_path}/{project_name}/{directory}'):
for file in fn:
if file.endswith(".cxx") or file.endswith(".hxx") or file.endswith(".txx"):
continue
source_files.append(os.path.join(dp, file))
# Create strings from lists for file(s)
source_files_str = ""
for file in source_files:
source_files_str += f' {file[len(alib_path)+1+len(project_name)+1:]}\n'
return source_files_str
# ----------------------------------------------------------------------------------------------------------------------
def parse_makeconfig(file):
link_libs = []
link_test_libs = []
xml_dep = ''
# Read and parse makefile.conf
with open(file, 'r') as file:
for line in file:
if line.startswith('LINK_LIBRARIES'):
link_libs = line[len('LINK_LIBRARIES='):].split()
elif line.startswith('SYSTEM_LIBRARIES'):
sys_libs = line[len('SYSTEM_LIBRARIES='):].split()
for lib in sys_libs:
if lib == 'xml2':
link_libs.append('${LIBXML2_LIBRARIES}')
xml_dep = 'PUBLIC ${LIBXML2_INCLUDE_DIR}'
else:
link_libs.append(lib)
elif line.startswith('TEST_LINK_LIBRARIES'):
link_test_libs = line[len('TEST_LINK_LIBRARIES='):].split()
return ' '.join(link_libs), ' '.join(link_test_libs), xml_dep
# ----------------------------------------------------------------------------------------------------------------------
def create_library_package(project_name, write):
# Parse config file
link_libs, link_test_libs, xml_dep = parse_makeconfig(f'{alib_path}/{project_name}/makefile.conf')
# Get source files
source_files = get_source_files(project_name, 'src')
# Get source files test
source_files_test = get_source_files(project_name, 'test-src')
if not write:
print(f'{project_name}/CMakeLists.txt')
print('-' * separate_size)
print(library_template.format(
project_name=project_name,
target_libs=link_libs,
target_test_libs=link_test_libs,
xml_dep=xml_dep,
source_files=source_files,
source_files_test=source_files_test,
))
print('-' * separate_size)
else:
with open(f'{alib_path}/{project_name}/CMakeLists.txt', 'w') as file:
file.write(library_template.format(
project_name=project_name,
target_libs=link_libs,
target_test_libs=link_test_libs,
xml_dep=xml_dep,
source_files=source_files,
source_files_test=source_files_test,
))
# ----------------------------------------------------------------------------------------------------------------------
def create_executable_package(project_name, write):
# Parse config file
link_libs, link_test_libs, xml_dep = parse_makeconfig(f'{alib_path}/{project_name}/makefile.conf')
# Get source files
source_files = get_source_files(project_name, 'src')
if not write:
print(f'{project_name}/CMakeLists.txt')
print('-' * separate_size)
print(executable_template.format(
project_name=project_name,
target_libs=link_libs,
target_test_libs=link_test_libs,
xml_dep=xml_dep,
source_files=source_files,
))
print('-' * separate_size)
else:
with open(f'{alib_path}/{project_name}/CMakeLists.txt', 'w') as file:
file.write(executable_template.format(
project_name=project_name,
target_libs=link_libs,
target_test_libs=link_test_libs,
xml_dep=xml_dep,
source_files=source_files,
))
# ----------------------------------------------------------------------------------------------------------------------
@click.command()
@click.option('--packages', '-p', help='Specify packages', default=alib_modules_lib + alib_modules_exe, multiple=True)
@click.option('--write', '-w', help='Write output to file(s).', is_flag=True, default=False)
@click.option('--main_file', '-m', help='Generate also main CMakeLists.txt', is_flag=True, default=False)
def main(write, main_file, packages):
packages_cnt = len(packages)
libs_cnt = len(list(set(packages) & set(alib_modules_lib)))
exes_cnt = len(list(set(packages) & set(alib_modules_exe)))
# Increment counter
if main_file:
packages_cnt += 1
# Generate for library package
for i, package in enumerate(list(set(packages) & set(alib_modules_lib)), 1):
try:
create_library_package(package, write)
print(f'[{i}/{packages_cnt}] Generated library package {package}', file=sys.stderr)
except FileNotFoundError as e:
print(f'[{i}/{packages_cnt}] Skipping library package {package}: {e}', file=sys.stderr)
# Generate for executable package
for i, package in enumerate(list(set(packages) & set(alib_modules_exe)), libs_cnt + 1):
try:
create_executable_package(package, write)
print(f'[{i}/{packages_cnt}] Generated executable package {package}', file=sys.stderr)
except FileNotFoundError as e:
print(f'[{i}/{packages_cnt}] Skipping executable package {package}: {e}', file=sys.stderr)
# Generate root file
if main_file:
create_root_cmakelist(write)
print(f'[{packages_cnt}/{packages_cnt}] Generated main CMakeLists.txt', file=sys.stderr)
# ----------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
main()
click==6.7
THREADS=${1:-5}
cd CMake
./alib_cmake.py -w -m
cd ..
if [ ! -d debug ]; then
mkdir debug
fi
if [ -L debug ]; then
DIRECTORY=$(pwd)
cd $(readlink debug)
cmake ${DIRECTORY}
cd ${DIRECTORY}
cd debug
else
cd debug
cmake ..
fi
CXX=clang++ make -j${THREADS}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment