ckick 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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