ckick 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/path"
6
+
7
+ module CKick
8
+
9
+ class IncludePath < Path
10
+ def raw_flag
11
+ "-I#{@path}"
12
+ end
13
+
14
+ def cmake
15
+ %Q{include_directories(#{@path})}
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,37 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/target"
6
+
7
+ module CKick
8
+
9
+ class Library < Target
10
+ def initialize args={}
11
+ super args
12
+
13
+ @shared = args[:shared] || false
14
+ end
15
+
16
+ def to_hash
17
+ if @shared
18
+ return super
19
+ else
20
+ return super.without(:shared)
21
+ end
22
+ end
23
+
24
+ def cmake
25
+ res = []
26
+
27
+ res << "add_library(#{@name}#{@shared ? " SHARED " : " "}#{@source.join(' ')})"
28
+
29
+ unless @libs.empty?
30
+ res << "target_link_libraries(#{@name} #{@libs.join(' ')})"
31
+ end
32
+
33
+ res.join("\n")
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,32 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ module CKick
6
+
7
+ class LibraryLink
8
+
9
+ def initialize args={}
10
+ name = args[:name] || ""
11
+ raise CKick::IllegalInitializationError, "No name provided to library link" unless name.is_a?(String) && !name.empty?
12
+ @name = name
13
+ end
14
+
15
+ def to_hash_element
16
+ @name
17
+ end
18
+
19
+ def to_s
20
+ @name
21
+ end
22
+
23
+ def raw_flag
24
+ "-l#{@name}"
25
+ end
26
+
27
+ def cmake
28
+ @name
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,19 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/path"
6
+
7
+ module CKick
8
+
9
+ class LibraryPath < Path
10
+ def raw_flag
11
+ "-L#{@path}"
12
+ end
13
+
14
+ def cmake
15
+ "link_directories(#{@path})"
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,8 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ class NilClass
6
+ def each &block
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ module CKick
6
+
7
+ class Path
8
+ attr_reader :path
9
+
10
+ def initialize args={}
11
+ raise IllegalInitializationError, "needs :path parameter" unless args.is_a?(Hash) && args[:path].is_a?(String)
12
+ raise NoSuchDirectoryError, "invalid path #{args[:path]}" unless Dir.exist?(args[:path])
13
+
14
+ @path = args[:path]
15
+ end
16
+
17
+ def to_s
18
+ @path
19
+ end
20
+
21
+ def to_hash_element
22
+ @path
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,29 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "fileutils"
6
+
7
+ module CKick
8
+
9
+ module PathDelegate
10
+
11
+ def self.create_directory(dirpath)
12
+ FileUtils.mkdir_p(dirpath)
13
+ end
14
+
15
+ def self.write_file(dirpath, filename, content)
16
+ raise BadFileContentError, "content does not respond to to_s" unless content.respond_to?(:to_s)
17
+ filepath = File.join(dirpath, filename)
18
+ file = File.new(filepath, "w")
19
+ file << content.to_s
20
+ file.close
21
+ end
22
+
23
+ def self.touch_file(filepath)
24
+ FileUtils.touch(filepath)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,47 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ module CKick
6
+
7
+ class Plugin
8
+ def initialize args
9
+ end
10
+
11
+ # Plugin's name, defaults to class name
12
+ def name
13
+ self.class.name
14
+ end
15
+
16
+ # Plugin to hash is :name => "class name"
17
+ def to_hash
18
+ {name: self.class.name}
19
+ end
20
+
21
+ # Plugin's output to add to main CMakeLists.txt
22
+ def cmake
23
+ ""
24
+ end
25
+
26
+ # Ran before project's structure creation
27
+ def run(project)
28
+ nil
29
+ end
30
+
31
+ # Ran after project's structure creation (create_structure)
32
+ def call(project)
33
+ nil
34
+ end
35
+
36
+ # Appends project's includes path before structure creation
37
+ def include(project)
38
+ []
39
+ end
40
+
41
+ # Appends project's libraries path before structure creation
42
+ def lib(project)
43
+ []
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,19 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/plugin"
6
+
7
+ class ClangComplete < CKick::Plugin
8
+ # Creates a .clang_complete file for clang auto completion
9
+
10
+ def call(project)
11
+ def clang_complete project
12
+ project.dependencies.flags.join("\n")
13
+ end
14
+
15
+ file = File.new(File.join(project.path, ".clang_complete"), 'w')
16
+ file << clang_complete(project) << "\n"
17
+ file.close
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/plugin"
6
+ require "fileutils"
7
+
8
+ class GTest < CKick::Plugin
9
+ LIBS_VARIABLE = "${GTEST_LIBRARIES}"
10
+
11
+ def initialize args={}
12
+ @optional = args[:optional] || false
13
+ @resource_file = "build-gtest.cmake"
14
+ end
15
+
16
+ def cmake
17
+ res = ''
18
+ res << %Q(option(BUILD_TESTS OFF "whether to build tests or not")\n) \
19
+ << "if(BUILD_TESTS)\n\t" if @optional
20
+
21
+ res << "include(#{@resource_file})"
22
+
23
+ res << "\nendif()" if @optional
24
+ res
25
+ end
26
+
27
+ def call(project)
28
+ file = File.new(File.join(project.root, @resource_file), 'w')
29
+ file << File.new(File.join(File.dirname(__FILE__), "resource", @resource_file), 'r').read
30
+ file.close
31
+ end
32
+
33
+ def include(project)
34
+ res = []
35
+ [
36
+ File.join(project.build_dir, "gtest", "src", "libgtest", "googletest", "include"),
37
+ File.join(project.build_dir, "gtest", "src", "libgtest", "googlemock", "include")
38
+ ].each do |path|
39
+ FileUtils.mkdir_p path
40
+ res << CKick::IncludePath.new(path: path)
41
+ end
42
+ res
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ find_package(Threads REQUIRED)
2
+ include(ExternalProject)
3
+
4
+ ExternalProject_Add(
5
+ libgtest
6
+ URL https://github.com/google/googletest/archive/release-1.8.0.zip
7
+ PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
8
+ INSTALL_COMMAND ""
9
+ )
10
+
11
+ include_directories("${CMAKE_CURRENT_BINARY_DIR}/gtest/src/libgtest/googletest/include")
12
+ include_directories("${CMAKE_CURRENT_BINARY_DIR}/gtest/src/libgtest/googlemock/include")
13
+
14
+ link_directories("${CMAKE_CURRENT_BINARY_DIR}/gtest/src/libgtest-build/googlemock/gtest")
15
+ link_directories("${CMAKE_CURRENT_BINARY_DIR}/gtest/src/libgtest-build/googlemock")
16
+
17
+ set(GTEST_LIBRARIES gtest gtest_main gmock gmock_main pthread)
@@ -0,0 +1,15 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ module CKick
6
+
7
+ module PluginDelegate
8
+
9
+ def self.find(plugin)
10
+ Object.const_get(plugin[:name]).new(plugin[:args] || {})
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,173 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ require "ckick/nil_class"
6
+ require "ckick/dependencies"
7
+ require "ckick/sub_directory"
8
+ require "ckick/hashable"
9
+ require "ckick/path_delegate"
10
+ require "ckick/plugin_delegate"
11
+
12
+ module CKick
13
+
14
+ class Project
15
+ include Hashable
16
+ attr_reader :subdirs, :dependencies, :root, :build_dir
17
+
18
+ NAME_MATCH = /^[[A-Z][a-z]_[0-9]]+$/
19
+ CMAKE_VERSION_MATCH = /^[0-9](\.[0-9]){0,2}$/
20
+
21
+ def initialize args
22
+ name = args[:name] || ""
23
+ raise IllegalInitializationError, "name must be a non-empty string only containing alphanumeric characters" unless name.is_a?(String) && name.match(NAME_MATCH)
24
+
25
+ min_v = args[:cmake_min_version] || '3'
26
+ raise IllegalInitializationError, "cmake_min_version is non-String" unless min_v.is_a?(String)
27
+ raise IllegalInitializationError, "cmake_min_version has non working pattern x or x.y or x.y.z" unless min_v.match(CMAKE_VERSION_MATCH)
28
+
29
+ root = args[:root] || ""
30
+ raise IllegalInitializationError, "root directory is non-String" unless root.is_a?(String)
31
+ raise IllegalInitializationError, "root directory is empty" if root.empty?
32
+
33
+ build_dir = args[:build_dir] || ""
34
+ raise IllegalInitializationError, "build directory is non-String" unless build_dir.is_a?(String)
35
+ raise IllegalInitializationError, "build directory is empty" if build_dir.empty?
36
+
37
+ @name = name
38
+ @cmake_min_version = min_v
39
+ @root = root
40
+ @build_dir = build_dir
41
+ @dependencies = Dependencies.new(args[:dependencies] || {})
42
+
43
+ @plugins = []
44
+ args[:plugins].each do |plugin|
45
+ @plugins << PluginDelegate.find(plugin)
46
+ end
47
+
48
+ @subdirs = []
49
+ args[:subdirs].each do |subdir|
50
+ @subdirs << SubDirectory.new(subdir)
51
+ end
52
+
53
+ @subdirs_initiated = false
54
+ init_subdirs
55
+ end
56
+
57
+ def set_name(name)
58
+ raise BadProjectNameError, "project name must be a non-empty alphanumeric string" unless name.is_a?(String) && name.match(NAME_MATCH)
59
+ @name = name
60
+ end
61
+
62
+ def to_s
63
+ @name
64
+ end
65
+
66
+ def to_hash
67
+ to_no_empty_value_hash.without(:subdirs_initiated)
68
+ end
69
+
70
+ def path
71
+ @root
72
+ end
73
+
74
+ def create_structure
75
+ raise "SubDirectories have not been initiated" unless @subdirs_initiated
76
+
77
+ run_plugins
78
+
79
+ PathDelegate.create_directory path
80
+ PathDelegate.write_file(path, "CMakeLists.txt", cmake)
81
+
82
+ @subdirs.each do |subdir|
83
+ subdir.create_structure
84
+ end
85
+
86
+ call_plugins
87
+ end
88
+
89
+ def register_plugin(plugin=nil, &block)
90
+ raise ArgumentError, "" unless plugin.is_a?(::CKick::Plugin) || block
91
+
92
+ if plugin.is_a?(::CKick::Plugin)
93
+ @plugins << plugin
94
+ elsif plugin.nil? && block
95
+ @plugins << block
96
+ end
97
+ end
98
+
99
+ def cmake
100
+ append_plugin_paths
101
+
102
+ res = "project(#{@name})\n" +
103
+ "cmake_minimum_required(VERSION #{@cmake_min_version})\n\n"
104
+
105
+ res << "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)\n" \
106
+ "set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)\n" \
107
+ "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)\n\n"
108
+
109
+ res << @dependencies.cmake << "\n\n"
110
+
111
+ res << plugins_cmake << "\n\n" unless @plugins.empty?
112
+
113
+ @subdirs.each do |dir|
114
+ res << "add_subdirectory(#{dir.name})\n" if dir.has_cmake
115
+ end
116
+
117
+ res
118
+ end
119
+
120
+ private
121
+
122
+ def init_subdirs
123
+ @subdirs.each do |subdir|
124
+ subdir.__send__ :set_parent, path
125
+ end
126
+
127
+ @subdirs_initiated = true
128
+ end
129
+
130
+ def append_plugin_paths
131
+ @plugins.each do |plugin|
132
+ plugin.include(self).each do |path|
133
+ @dependencies.add_include path
134
+ end
135
+ plugin.lib(self).each do |path|
136
+ @dependencies.add_lib path
137
+ end
138
+ end
139
+ end
140
+
141
+ def run_plugins
142
+ @plugins.each do |plugin|
143
+ plugin.run(self) if plugin.respond_to? :run
144
+ end
145
+ end
146
+
147
+ def call_plugins
148
+ @plugins.each do |plugin|
149
+ plugin.call self
150
+ end
151
+ end
152
+
153
+ def plugins_cmake
154
+ res = "##ckick plugins section##\n"
155
+
156
+ def plugin_name(plugin)
157
+ if plugin.respond_to?(:name)
158
+ return plugin.name
159
+ else
160
+ return "<inline plugin>"
161
+ end
162
+ end
163
+
164
+ @plugins.each do |plugin|
165
+ res << "#ckick plugin: #{plugin_name(plugin)}\n"
166
+ res << plugin.cmake << "\n" if plugin.respond_to? :cmake
167
+ end
168
+
169
+ res << "##end plugin section##"
170
+ end
171
+ end
172
+
173
+ end