pkgforge 0.2.2 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/pkgforge.rb +14 -9
- data/lib/pkgforge/base.rb +43 -0
- data/lib/pkgforge/components/build.rb +72 -0
- data/lib/pkgforge/components/cflags.rb +57 -0
- data/lib/pkgforge/components/configure.rb +35 -0
- data/lib/pkgforge/components/deps.rb +38 -0
- data/lib/pkgforge/components/dirs.rb +41 -0
- data/lib/pkgforge/components/metadata.rb +60 -0
- data/lib/pkgforge/components/patch.rb +34 -0
- data/lib/pkgforge/components/run.rb +31 -0
- data/lib/pkgforge/components/source.rb +23 -0
- data/lib/pkgforge/components/test.rb +44 -0
- data/lib/pkgforge/{push.rb → components/upload.rb} +17 -4
- data/lib/pkgforge/components/version.rb +52 -0
- data/lib/pkgforge/version.rb +1 -1
- metadata +15 -10
- data/lib/pkgforge/builddsl.rb +0 -55
- data/lib/pkgforge/forge.rb +0 -57
- data/lib/pkgforge/forgedsl.rb +0 -110
- data/lib/pkgforge/helpers.rb +0 -78
- data/lib/pkgforge/prepare.rb +0 -62
- data/lib/pkgforge/testdsl.rb +0 -26
- data/lib/pkgforge/versiondsl.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db7f41b90da9053a2afaa72620879e7edc44f860
|
4
|
+
data.tar.gz: 6bdddd3a26207ef02fa8ae5836886b9d5dffd022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7896cebed55fb4301058c26801cce22c4a606b9b5fac57ec33fbc24920157cc6b213baf05f5cd2acef385811214584618be3a012bb5f24ffe6875b1d92aee38d
|
7
|
+
data.tar.gz: b7212896f57b374944d7bfb1e1b216b31d16c8fddbc8eff65a8fd135c6f934079a4183473cb26ca9d3a88687b357fb81f97d3978fe9ff8b9d1dd5184e2f0d4b4
|
data/lib/pkgforge.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
require 'contracts'
|
2
2
|
|
3
|
+
require 'pkgforge/base'
|
3
4
|
require 'pkgforge/version'
|
4
|
-
require 'pkgforge/
|
5
|
-
require 'pkgforge/
|
6
|
-
require 'pkgforge/
|
7
|
-
require 'pkgforge/
|
8
|
-
require 'pkgforge/
|
9
|
-
require 'pkgforge/
|
10
|
-
require 'pkgforge/
|
11
|
-
require 'pkgforge/
|
5
|
+
require 'pkgforge/components/build'
|
6
|
+
require 'pkgforge/components/cflags'
|
7
|
+
require 'pkgforge/components/configure'
|
8
|
+
require 'pkgforge/components/deps'
|
9
|
+
require 'pkgforge/components/dirs'
|
10
|
+
require 'pkgforge/components/metadata'
|
11
|
+
require 'pkgforge/components/patch'
|
12
|
+
require 'pkgforge/components/run'
|
13
|
+
require 'pkgforge/components/source'
|
14
|
+
require 'pkgforge/components/test'
|
15
|
+
require 'pkgforge/components/upload'
|
16
|
+
require 'pkgforge/components/version'
|
12
17
|
|
13
18
|
##
|
14
19
|
# DSL engine for compiling Arch packages
|
@@ -31,7 +36,7 @@ module PkgForge
|
|
31
36
|
def load_from_file(params = {})
|
32
37
|
file = params[:file] || DEFAULT_FILE
|
33
38
|
forge = Forge.new(params)
|
34
|
-
dsl =
|
39
|
+
dsl = DSL::Forge.new(forge)
|
35
40
|
dsl.instance_eval(File.read(file), file)
|
36
41
|
forge
|
37
42
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Starter Forge object
|
6
|
+
class Forge
|
7
|
+
include Contracts::Core
|
8
|
+
include Contracts::Builtin
|
9
|
+
|
10
|
+
Contract Maybe[HashOf[Symbol => Any]] => nil
|
11
|
+
def initialize(params = {})
|
12
|
+
@options = params
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Base engine structure
|
19
|
+
class Base
|
20
|
+
include Contracts::Core
|
21
|
+
include Contracts::Builtin
|
22
|
+
|
23
|
+
Contract PkgForge::Forge => nil
|
24
|
+
def initialize(forge)
|
25
|
+
@forge = forge
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module DSL
|
31
|
+
class Forge < PkgForge::Base
|
32
|
+
end
|
33
|
+
|
34
|
+
class Build < PkgForge::Base
|
35
|
+
end
|
36
|
+
|
37
|
+
class Test < PkgForge::Base
|
38
|
+
end
|
39
|
+
|
40
|
+
class Version < PkgForge::Base
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Add build methods to Forge
|
6
|
+
class Forge
|
7
|
+
attr_writer :build_block
|
8
|
+
|
9
|
+
Contract None => Proc
|
10
|
+
def build_block
|
11
|
+
@build_block ||= proc { raise 'No build block provided' }
|
12
|
+
end
|
13
|
+
|
14
|
+
Contract None => nil
|
15
|
+
def build!
|
16
|
+
prepare_source!
|
17
|
+
patch_source!
|
18
|
+
prepare_deps!
|
19
|
+
builder = PkgForge::DSL::Build.new(self)
|
20
|
+
builder.instance_eval(&build_block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module DSL
|
25
|
+
##
|
26
|
+
# Add build method to Forge DSL
|
27
|
+
class Forge
|
28
|
+
Contract Func[None => nil] => nil
|
29
|
+
def build(&block)
|
30
|
+
@forge.build_block = block
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Add build methods to Build DSL
|
37
|
+
class Build
|
38
|
+
Contract Or[String, Array], Or[HashOf[String => String], {}, nil] => nil
|
39
|
+
def run(*args)
|
40
|
+
@forge.run(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
Contract None => nil
|
44
|
+
def configure
|
45
|
+
env = {
|
46
|
+
'CC' => 'musl-gcc',
|
47
|
+
'CFLAGS' => @forge.cflags.join(' '),
|
48
|
+
'LIBS' => @forge.libs.join(' ')
|
49
|
+
}
|
50
|
+
run ['./configure'] + configure_flag_strings, env
|
51
|
+
end
|
52
|
+
|
53
|
+
Contract None => nil
|
54
|
+
def make
|
55
|
+
run 'make'
|
56
|
+
end
|
57
|
+
|
58
|
+
Contract None => nil
|
59
|
+
def install
|
60
|
+
run "make DESTDIR=#{@forge.releasedir} install"
|
61
|
+
end
|
62
|
+
|
63
|
+
Contract Or[String, ArrayOf[String]] => nil
|
64
|
+
def rm(paths)
|
65
|
+
paths = [paths] if paths.is_a? String
|
66
|
+
paths.map { |x| File.join(@forge.releasedir, x) }
|
67
|
+
FileUtils.rm_r paths
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module PkgForge
|
2
|
+
##
|
3
|
+
# Add cflag options to Forge
|
4
|
+
class Forge
|
5
|
+
attr_writer :cflags, :libs
|
6
|
+
|
7
|
+
Contract None => ArrayOf[String]
|
8
|
+
def cflags
|
9
|
+
@cflags ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
Contract None => ArrayOf[String]
|
13
|
+
def libs
|
14
|
+
@libs ||= []
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module DSL
|
19
|
+
##
|
20
|
+
# Add cflag options to Forge DSL
|
21
|
+
class Forge
|
22
|
+
Contract Maybe[String] => nil
|
23
|
+
def cflags(value = nil)
|
24
|
+
default = '-I%{dep}/usr/include -L%{dep}/usr/lib'
|
25
|
+
value ||= @forge.deps.map { |x, _| default % { dep: dep(x) }.split }
|
26
|
+
@forge.cflags += value.flatten
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
Contract Maybe[String] => nil
|
31
|
+
def libs(value = nil)
|
32
|
+
value ||= @forge.deps.map { |x, _| '-l' + x }
|
33
|
+
@forge.libs += value
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shamelessly sourced from:
|
38
|
+
# https://blog.mayflower.de/5800-Hardening-Compiler-Flags-for-NixOS.html
|
39
|
+
ALL_HARDEN_OPTS = {
|
40
|
+
format: %w(-Wformat -Wformat-security -Werror=format-security),
|
41
|
+
stackprotector: %w(-fstack-protector-strong --param ssp-buffer-size=4),
|
42
|
+
fortify: %w(-O2 -D_FORTIFY_SOURCE=2),
|
43
|
+
pic: '-fPIC',
|
44
|
+
strictoverflow: '-fno-strict-overflow',
|
45
|
+
relro: '-z=relro',
|
46
|
+
bindnow: '-z=bindnow',
|
47
|
+
pie: %w(-fPIE -pie)
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
Contract Maybe[Array[String]] => nil
|
51
|
+
def harden(list = [])
|
52
|
+
harden_opts = ALL_HARDEN_OPTS.reject { |k, _| list.include? k.to_s }
|
53
|
+
@forge.cflags += harden_opts.flatten
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PkgForge
|
2
|
+
##
|
3
|
+
# Add configure flag options to Forge
|
4
|
+
class Forge
|
5
|
+
attr_writer :configure_flags
|
6
|
+
|
7
|
+
Contract None => HashOf[Symbol => Maybe[String]]
|
8
|
+
def configure_flags
|
9
|
+
@configure_flags ||= {}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module DSL
|
14
|
+
##
|
15
|
+
# Add configure flag options to Forge DSL
|
16
|
+
class Forge
|
17
|
+
Contract HashOf[Symbol => Maybe[String]] => nil
|
18
|
+
def configure_flags(value)
|
19
|
+
@forge.configure_flags = value
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Add configure flag options to Build DSL
|
26
|
+
class Build
|
27
|
+
Contract None => ArrayOf[String]
|
28
|
+
def configure_flag_strings
|
29
|
+
@forge.configure_flags.map do |flag, value|
|
30
|
+
"--#{flag}#{'=' if value}#{value}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Add dep methods to Forge
|
6
|
+
class Forge
|
7
|
+
attr_writer :deps
|
8
|
+
|
9
|
+
Contract None => HashOf[Symbol => String]
|
10
|
+
def deps
|
11
|
+
@deps ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
Contract None => nil
|
17
|
+
def prepare_deps!
|
18
|
+
deps.each do |dep_name, dep_version|
|
19
|
+
url = "https://github.com/#{org}/#{dep_name}/releases/download/#{dep_version}/#{dep_name}.tar.gz" # rubocop:disable Metrics/LineLength
|
20
|
+
open(tmpfile(dep_name), 'wb') { |fh| fh << open(url, 'rb').read }
|
21
|
+
run_local "tar -x -C #{tmpdir(dep_name)} -f #{tmpfile(dep_name)}"
|
22
|
+
end
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module DSL
|
28
|
+
##
|
29
|
+
# Add dep methods to Forge DSL
|
30
|
+
class Forge
|
31
|
+
Contract HashOf[Symbol => String] => nil
|
32
|
+
def deps(value)
|
33
|
+
@forge.deps = value
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module PkgForge
|
5
|
+
##
|
6
|
+
# Add dir methods to Forge
|
7
|
+
class Forge
|
8
|
+
Contract String => String
|
9
|
+
def dep(package)
|
10
|
+
tmpdir(package.to_sym)
|
11
|
+
end
|
12
|
+
|
13
|
+
Contract None => String
|
14
|
+
def releasedir
|
15
|
+
tmpdir(:release)
|
16
|
+
end
|
17
|
+
|
18
|
+
Contract Symbol => String
|
19
|
+
def tmpdir(id)
|
20
|
+
@tmpdirs ||= {}
|
21
|
+
@tmpdirs[id] ||= Dir.mktmpdir(id.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
Contract Symbol => String
|
25
|
+
def tmpfile(id)
|
26
|
+
@tmpfiles ||= {}
|
27
|
+
@tmpfiles[id] ||= Tempfile.create(id.to_s).path
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module DSL
|
32
|
+
##
|
33
|
+
# Add dir methods to Forge DSL
|
34
|
+
class Forge
|
35
|
+
Contract String => String
|
36
|
+
def dep(dep_name)
|
37
|
+
@forge.dep(dep_name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Add metadata methods to Forge
|
6
|
+
class Forge
|
7
|
+
attr_writer :name, :org, :license
|
8
|
+
|
9
|
+
Contract None => String
|
10
|
+
def name
|
11
|
+
@name || raise('No name provided')
|
12
|
+
end
|
13
|
+
|
14
|
+
Contract None => String
|
15
|
+
def org
|
16
|
+
@org || raise('No org provided')
|
17
|
+
end
|
18
|
+
|
19
|
+
Contract None => String
|
20
|
+
def license
|
21
|
+
@license ||= 'LICENSE'
|
22
|
+
end
|
23
|
+
|
24
|
+
Contract None => nil
|
25
|
+
def add_license!
|
26
|
+
src_file = File.join(tmpdir(:build), license)
|
27
|
+
dest_dir = File.join(
|
28
|
+
tmpdir(:release), 'usr', 'share', 'licenses', name
|
29
|
+
)
|
30
|
+
dest_file = File.join(dest_dir, 'LICENSE')
|
31
|
+
FileUtils.mkdir_p dest_dir
|
32
|
+
FileUtils.cp src_file, dest_file
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module DSL
|
38
|
+
##
|
39
|
+
# Add metadata methods to Forge DSL
|
40
|
+
class Forge
|
41
|
+
Contract String => nil
|
42
|
+
def name(value)
|
43
|
+
@forge.name = value
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
Contract String => nil
|
48
|
+
def org(value)
|
49
|
+
@forge.org = value
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
Contract String => nil
|
54
|
+
def license(file)
|
55
|
+
@forge.license = file
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module PkgForge
|
2
|
+
##
|
3
|
+
# Add patch methods to Forge
|
4
|
+
class Forge
|
5
|
+
attr_writer :patches
|
6
|
+
|
7
|
+
Contract None => ArrayOf[String]
|
8
|
+
def patches
|
9
|
+
@patches ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
Contract None => nil
|
15
|
+
def patch_source!
|
16
|
+
patches.each do |patch|
|
17
|
+
run_local "patch -d #{tmpdir(:build)} -p1 < patches/#{patch}"
|
18
|
+
end
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module DSL
|
24
|
+
##
|
25
|
+
# Add patch methods to Forge DSL
|
26
|
+
class Forge
|
27
|
+
Contract String => nil
|
28
|
+
def patch(file)
|
29
|
+
@forge.patches << file
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module PkgForge
|
2
|
+
##
|
3
|
+
# Add run methods to Forge
|
4
|
+
class Forge
|
5
|
+
Contract Or[String, Array], Or[HashOf[String => String], {}, nil] => nil
|
6
|
+
def run(cmd, env = {})
|
7
|
+
Dir.chdir(tmpdir(:build)) do
|
8
|
+
run_local(cmd, env)
|
9
|
+
end
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
Contract Or[String, Array], Or[HashOf[String => String], {}, nil] => nil
|
14
|
+
def test_run(cmd, env = {})
|
15
|
+
Dir.chdir(tmpdir(:release)) do
|
16
|
+
run_local(cmd, env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
Contract Or[String, Array], Or[HashOf[String => String], {}, nil] => nil
|
23
|
+
def run_local(cmd, env = {})
|
24
|
+
puts "Running command in #{Dir.pwd}: #{cmd}"
|
25
|
+
puts "Using env: #{env}" unless env.empty?
|
26
|
+
res = system env, *cmd
|
27
|
+
raise('Command failed!') unless res
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Add source methods to Forge
|
6
|
+
class Forge
|
7
|
+
private
|
8
|
+
|
9
|
+
Contract None => nil
|
10
|
+
def prepare_source!
|
11
|
+
dest = tmpdir(:build)
|
12
|
+
dest_git = File.join(dest, '.git')
|
13
|
+
dest_git_config = File.join(dest_git, 'config')
|
14
|
+
run_local 'git submodule update --init'
|
15
|
+
FileUtils.cp_r 'upstream/.', dest
|
16
|
+
FileUtils.rm_r dest_git
|
17
|
+
FileUtils.cp_r '.git/modules/upstream', dest_git
|
18
|
+
new_config = File.readlines(dest_git_config).grep_v(/worktree =/).join
|
19
|
+
File.open(dest_git_config, 'w') { |fh| fh << new_config }
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module PkgForge
|
4
|
+
##
|
5
|
+
# Add test methods to Forge
|
6
|
+
class Forge
|
7
|
+
attr_writer :test_block
|
8
|
+
|
9
|
+
Contract None => Proc
|
10
|
+
def test_block
|
11
|
+
@test_block ||= proc { raise 'No test block provided' }
|
12
|
+
end
|
13
|
+
|
14
|
+
Contract None => nil
|
15
|
+
def test!
|
16
|
+
tester = PkgForge::DSL::Test.new(self)
|
17
|
+
tester.instance_eval(&test_block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module DSL
|
22
|
+
##
|
23
|
+
# Add test methods to Forge DSL
|
24
|
+
class Forge
|
25
|
+
Contract Func[None => nil] => nil
|
26
|
+
def test(&block)
|
27
|
+
@forge.test_block = block
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Add test methods to Test DSL
|
34
|
+
class Test
|
35
|
+
Contract Or[String, Array], Or[HashOf[String => String], {}, nil] => nil
|
36
|
+
def run(cmd, env = {})
|
37
|
+
cmd.unshift('/usr/bin/env') if cmd.is_a? Array
|
38
|
+
cmd << ';' if cmd.is_a? String
|
39
|
+
env['PATH'] ||= './usr/bin'
|
40
|
+
@forge.test_run(cmd, env)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,12 +1,25 @@
|
|
1
1
|
module PkgForge
|
2
2
|
##
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# Add upload methods to Forge
|
4
|
+
class Forge
|
5
|
+
Contract None => nil
|
6
|
+
def push!
|
7
|
+
add_license!
|
8
|
+
make_tarball!
|
9
|
+
update_repo!
|
10
|
+
upload_artifact!
|
11
|
+
end
|
7
12
|
|
8
13
|
private
|
9
14
|
|
15
|
+
Contract None => nil
|
16
|
+
def make_tarball!
|
17
|
+
Dir.chdir(tmpdir(:release)) do
|
18
|
+
run_local "tar -czvf #{tmpfile(:tarball)} *"
|
19
|
+
end
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
10
23
|
Contract None => nil
|
11
24
|
def update_repo!
|
12
25
|
run_local "git tag -f '#{full_version}'"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module PkgForge
|
2
|
+
##
|
3
|
+
# Add version methods to Forge
|
4
|
+
class Forge
|
5
|
+
attr_writer :version_block
|
6
|
+
|
7
|
+
Contract None => Proc
|
8
|
+
def version_block
|
9
|
+
@version_block ||= proc { raise 'No version block provided' }
|
10
|
+
end
|
11
|
+
|
12
|
+
Contract None => String
|
13
|
+
def version
|
14
|
+
@version ||= Dir.chdir(tmpdir(:build)) do
|
15
|
+
PkgForge::DSL::Version.new(self).instance_eval(&version_block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Contract None => Num
|
20
|
+
def revision
|
21
|
+
@revision ||= `git describe --abbrev=0 --tags`.split('-').last.to_i + 1
|
22
|
+
end
|
23
|
+
|
24
|
+
Contract None => String
|
25
|
+
def full_version
|
26
|
+
"#{version}-#{revision}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module DSL
|
31
|
+
##
|
32
|
+
# Add version methods to Forge DSL
|
33
|
+
class Forge
|
34
|
+
Contract Func[None => Maybe[String]] => nil
|
35
|
+
def version(&block)
|
36
|
+
@forge.version_block = block
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Add version methods to Version DSL
|
43
|
+
class Version
|
44
|
+
Contract Maybe[Regexp], Maybe[String] => String
|
45
|
+
def git_tag(regex = nil, replace = '\1')
|
46
|
+
tag = `git describe --tags`.rstrip
|
47
|
+
tag.gsub!(regex, replace) if regex
|
48
|
+
tag
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/pkgforge/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pkgforge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Les Aker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mercenary
|
@@ -127,15 +127,20 @@ files:
|
|
127
127
|
- bin/pkgforge
|
128
128
|
- circle.yml
|
129
129
|
- lib/pkgforge.rb
|
130
|
-
- lib/pkgforge/
|
131
|
-
- lib/pkgforge/
|
132
|
-
- lib/pkgforge/
|
133
|
-
- lib/pkgforge/
|
134
|
-
- lib/pkgforge/
|
135
|
-
- lib/pkgforge/
|
136
|
-
- lib/pkgforge/
|
130
|
+
- lib/pkgforge/base.rb
|
131
|
+
- lib/pkgforge/components/build.rb
|
132
|
+
- lib/pkgforge/components/cflags.rb
|
133
|
+
- lib/pkgforge/components/configure.rb
|
134
|
+
- lib/pkgforge/components/deps.rb
|
135
|
+
- lib/pkgforge/components/dirs.rb
|
136
|
+
- lib/pkgforge/components/metadata.rb
|
137
|
+
- lib/pkgforge/components/patch.rb
|
138
|
+
- lib/pkgforge/components/run.rb
|
139
|
+
- lib/pkgforge/components/source.rb
|
140
|
+
- lib/pkgforge/components/test.rb
|
141
|
+
- lib/pkgforge/components/upload.rb
|
142
|
+
- lib/pkgforge/components/version.rb
|
137
143
|
- lib/pkgforge/version.rb
|
138
|
-
- lib/pkgforge/versiondsl.rb
|
139
144
|
- pkgforge.gemspec
|
140
145
|
- spec/pkgforge_spec.rb
|
141
146
|
- spec/spec_helper.rb
|
data/lib/pkgforge/builddsl.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module PkgForge
|
4
|
-
##
|
5
|
-
# Builder engine
|
6
|
-
class BuildDSL
|
7
|
-
include Contracts::Core
|
8
|
-
include Contracts::Builtin
|
9
|
-
|
10
|
-
Contract PkgForge::Forge => nil
|
11
|
-
def initialize(forge)
|
12
|
-
@forge = forge
|
13
|
-
nil
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
Contract Or[String, Array], Or[Hash[String => String], {}, nil] => nil
|
19
|
-
def run(*args)
|
20
|
-
@forge.run(*args)
|
21
|
-
end
|
22
|
-
|
23
|
-
Contract None => nil
|
24
|
-
def configure
|
25
|
-
flag_strings = @forge.configure_flags.map do |flag, value|
|
26
|
-
"--#{flag}#{'=' if value}#{value}"
|
27
|
-
end
|
28
|
-
env = {
|
29
|
-
'CC' => 'musl-gcc',
|
30
|
-
'CFLAGS' => @forge.all_cflags,
|
31
|
-
'LDFLAGS' => @forge.all_cflags,
|
32
|
-
'LIBS' => @forge.libs
|
33
|
-
}
|
34
|
-
run ['./configure'] + flag_strings, env
|
35
|
-
end
|
36
|
-
|
37
|
-
Contract None => nil
|
38
|
-
def make
|
39
|
-
run 'make'
|
40
|
-
end
|
41
|
-
|
42
|
-
Contract None => nil
|
43
|
-
def install
|
44
|
-
run "make DESTDIR=#{@forge.releasedir} install"
|
45
|
-
end
|
46
|
-
|
47
|
-
Contract Or[String, Array[String]] => nil
|
48
|
-
def rm(paths)
|
49
|
-
paths = [paths] if paths.is_a? String
|
50
|
-
paths.map { |x| File.join(@forge.releasedir, x) }
|
51
|
-
FileUtils.rm_r paths
|
52
|
-
nil
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/lib/pkgforge/forge.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require 'tempfile'
|
3
|
-
require 'fileutils'
|
4
|
-
require 'open-uri'
|
5
|
-
|
6
|
-
##
|
7
|
-
# Declare actual Forge with package-building
|
8
|
-
module PkgForge
|
9
|
-
##
|
10
|
-
# Real Forge object
|
11
|
-
class Forge
|
12
|
-
include Contracts::Core
|
13
|
-
include Contracts::Builtin
|
14
|
-
include PkgForge::Helpers
|
15
|
-
include PkgForge::Prepare
|
16
|
-
include PkgForge::Push
|
17
|
-
|
18
|
-
attr_accessor :name, :org, :deps, :configure_flags, :version_block,
|
19
|
-
:patches, :build_block, :test_block, :license, :cflags,
|
20
|
-
:libs, :harden_flags
|
21
|
-
|
22
|
-
Contract Maybe[HashOf[Symbol => Any]] => nil
|
23
|
-
def initialize(params = {})
|
24
|
-
@options = params
|
25
|
-
@license = 'LICENSE'
|
26
|
-
@deps = {}
|
27
|
-
@flags = {}
|
28
|
-
@patches = []
|
29
|
-
@build_block = proc { raise('No build block provided') }
|
30
|
-
@test_block = proc { raise('No test block provided') }
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
|
34
|
-
Contract None => nil
|
35
|
-
def build!
|
36
|
-
prepare_source!
|
37
|
-
patch_source!
|
38
|
-
prepare_deps!
|
39
|
-
builder = BuildDSL.new(self)
|
40
|
-
builder.instance_eval(&build_block)
|
41
|
-
end
|
42
|
-
|
43
|
-
Contract None => nil
|
44
|
-
def test!
|
45
|
-
tester = TestDSL.new(self)
|
46
|
-
tester.instance_eval(&test_block)
|
47
|
-
end
|
48
|
-
|
49
|
-
Contract None => nil
|
50
|
-
def push!
|
51
|
-
add_license!
|
52
|
-
make_tarball!
|
53
|
-
update_repo!
|
54
|
-
upload_artifact!
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/pkgforge/forgedsl.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Declare DSL for Forge objects
|
3
|
-
module PkgForge
|
4
|
-
##
|
5
|
-
# DSL for generating a Forge
|
6
|
-
class ForgeDSL
|
7
|
-
include Contracts::Core
|
8
|
-
include Contracts::Builtin
|
9
|
-
|
10
|
-
Contract Forge, Maybe[Hash] => nil
|
11
|
-
def initialize(forge, params = {})
|
12
|
-
@forge = forge
|
13
|
-
@options = params
|
14
|
-
nil
|
15
|
-
end
|
16
|
-
|
17
|
-
Contract String => nil
|
18
|
-
def name(value)
|
19
|
-
@forge.name = value
|
20
|
-
nil
|
21
|
-
end
|
22
|
-
|
23
|
-
Contract String => nil
|
24
|
-
def org(value)
|
25
|
-
@forge.org = value
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
|
-
Contract HashOf[Symbol => String] => nil
|
30
|
-
def deps(value)
|
31
|
-
@forge.deps = value
|
32
|
-
nil
|
33
|
-
end
|
34
|
-
|
35
|
-
Contract HashOf[Symbol => String] => nil
|
36
|
-
def configure_flags(value)
|
37
|
-
@forge.configure_flags = value
|
38
|
-
nil
|
39
|
-
end
|
40
|
-
|
41
|
-
Contract Func[None => Maybe[String]] => nil
|
42
|
-
def version(&block)
|
43
|
-
@forge.version_block = block
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
|
47
|
-
Contract String => nil
|
48
|
-
def patch(file)
|
49
|
-
@forge.patches ||= []
|
50
|
-
@forge.patches << file
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
|
-
Contract Func[None => nil] => nil
|
55
|
-
def build(&block)
|
56
|
-
@forge.build_block = block
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
|
60
|
-
Contract Func[None => nil] => nil
|
61
|
-
def test(&block)
|
62
|
-
@forge.test_block = block
|
63
|
-
nil
|
64
|
-
end
|
65
|
-
|
66
|
-
Contract String => nil
|
67
|
-
def license(file)
|
68
|
-
@forge.license = file
|
69
|
-
nil
|
70
|
-
end
|
71
|
-
|
72
|
-
Contract String => String
|
73
|
-
def dep(dep_name)
|
74
|
-
@forge.dep(dep_name)
|
75
|
-
end
|
76
|
-
|
77
|
-
Contract Maybe[String] => nil
|
78
|
-
def cflags(value = nil)
|
79
|
-
default = '-I%{dep}/usr/include -L%{dep}/usr/lib'
|
80
|
-
value ||= @forge.deps.map { |x, _| default % { dep: dep(x) }.split }
|
81
|
-
@forge.cflags = value.flatten
|
82
|
-
nil
|
83
|
-
end
|
84
|
-
|
85
|
-
Contract Maybe[String] => nil
|
86
|
-
def libs(value = nil)
|
87
|
-
value ||= @forge.deps.map { |x, _| '-l' + x }
|
88
|
-
@forge.libs = value
|
89
|
-
nil
|
90
|
-
end
|
91
|
-
|
92
|
-
# hamelessly sourced from:
|
93
|
-
# https://blog.mayflower.de/5800-Hardening-Compiler-Flags-for-NixOS.html
|
94
|
-
HARDEN_OPTS = {
|
95
|
-
format: %w(-Wformat -Wformat-security -Werror=format-security),
|
96
|
-
stackprotector: %w(-fstack-protector-strong --param ssp-buffer-size=4),
|
97
|
-
fortify: %w(-O2 -D_FORTIFY_SOURCE=2),
|
98
|
-
pic: '-fPIC',
|
99
|
-
strictoverflow: '-fno-strict-overflow',
|
100
|
-
relro: '-z=relro',
|
101
|
-
bindnow: '-z=bindnow',
|
102
|
-
pie: %w(-fPIE -pie)
|
103
|
-
}.freeze
|
104
|
-
|
105
|
-
Contract Maybe[Array[String]] => nil
|
106
|
-
def harden(list = [])
|
107
|
-
@forge.harden_flags = HARDEN_OPTS.reject { |k, _| list.include? k.to_s }
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
data/lib/pkgforge/helpers.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
module PkgForge
|
2
|
-
##
|
3
|
-
# Helper functions for building packages
|
4
|
-
module Helpers
|
5
|
-
include Contracts::Core
|
6
|
-
include Contracts::Builtin
|
7
|
-
|
8
|
-
Contract String => String
|
9
|
-
def dep(package)
|
10
|
-
tmpdir(package.to_sym)
|
11
|
-
end
|
12
|
-
|
13
|
-
Contract None => String
|
14
|
-
def releasedir
|
15
|
-
tmpdir(:release)
|
16
|
-
end
|
17
|
-
|
18
|
-
Contract Or[String, Array], Or[Hash[String => String], {}, nil] => nil
|
19
|
-
def run(cmd, env = {})
|
20
|
-
Dir.chdir(tmpdir(:build)) do
|
21
|
-
run_local(cmd, env)
|
22
|
-
end
|
23
|
-
nil
|
24
|
-
end
|
25
|
-
|
26
|
-
Contract Or[String, Array], Or[Hash[String => String], {}, nil] => nil
|
27
|
-
def test_run(cmd, env = {})
|
28
|
-
Dir.chdir(tmpdir(:release)) do
|
29
|
-
run_local(cmd, env)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
Contract None => Array[String]
|
34
|
-
def all_cflags
|
35
|
-
cflags + harden_flags
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
Contract Symbol => String
|
41
|
-
def tmpdir(id)
|
42
|
-
@tmpdirs ||= {}
|
43
|
-
@tmpdirs[id] ||= Dir.mktmpdir(id.to_s)
|
44
|
-
end
|
45
|
-
|
46
|
-
Contract Symbol => String
|
47
|
-
def tmpfile(id)
|
48
|
-
@tmpfiles ||= {}
|
49
|
-
@tmpfiles[id] ||= Tempfile.create(id.to_s).path
|
50
|
-
end
|
51
|
-
|
52
|
-
Contract Or[String, Array], Or[Hash[String => String], {}, nil] => nil
|
53
|
-
def run_local(cmd, env = {})
|
54
|
-
puts "Running command in #{Dir.pwd}: #{cmd}"
|
55
|
-
puts "Using env: #{env}" unless env.empty?
|
56
|
-
res = system env, *cmd
|
57
|
-
raise('Command failed!') unless res
|
58
|
-
nil
|
59
|
-
end
|
60
|
-
|
61
|
-
Contract None => String
|
62
|
-
def version
|
63
|
-
@version ||= Dir.chdir(tmpdir(:build)) do
|
64
|
-
VersionDSL.new(self).instance_eval(&version_block)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
Contract None => Num
|
69
|
-
def revision
|
70
|
-
@revision ||= `git describe --abbrev=0 --tags`.split('-').last.to_i + 1
|
71
|
-
end
|
72
|
-
|
73
|
-
Contract None => String
|
74
|
-
def full_version
|
75
|
-
"#{version}-#{revision}"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
data/lib/pkgforge/prepare.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
module PkgForge
|
2
|
-
##
|
3
|
-
# Preparation methods
|
4
|
-
module Prepare
|
5
|
-
include Contracts::Core
|
6
|
-
include Contracts::Builtin
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
Contract None => nil
|
11
|
-
def prepare_source!
|
12
|
-
dest = tmpdir(:build)
|
13
|
-
dest_git = File.join(dest, '.git')
|
14
|
-
dest_git_config = File.join(dest_git, 'config')
|
15
|
-
run_local 'git submodule update --init'
|
16
|
-
FileUtils.cp_r 'upstream/.', dest
|
17
|
-
FileUtils.rm_r dest_git
|
18
|
-
FileUtils.cp_r '.git/modules/upstream', dest_git
|
19
|
-
new_config = File.readlines(dest_git_config).grep_v(/worktree =/).join
|
20
|
-
File.open(dest_git_config, 'w') { |fh| fh << new_config }
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
|
24
|
-
Contract None => nil
|
25
|
-
def patch_source!
|
26
|
-
patches.each do |patch|
|
27
|
-
run_local "patch -d #{tmpdir(:build)} -p1 < patches/#{patch}"
|
28
|
-
end
|
29
|
-
nil
|
30
|
-
end
|
31
|
-
|
32
|
-
Contract None => nil
|
33
|
-
def prepare_deps!
|
34
|
-
deps.each do |dep_name, dep_version|
|
35
|
-
url = "https://github.com/#{org}/#{dep_name}/releases/download/#{dep_version}/#{dep_name}.tar.gz" # rubocop:disable Metrics/LineLength
|
36
|
-
open(tmpfile(dep_name), 'wb') { |fh| fh << open(url, 'rb').read }
|
37
|
-
run_local "tar -x -C #{tmpdir(dep_name)} -f #{tmpfile(dep_name)}"
|
38
|
-
end
|
39
|
-
nil
|
40
|
-
end
|
41
|
-
|
42
|
-
Contract None => nil
|
43
|
-
def add_license!
|
44
|
-
src_file = File.join(tmpdir(:build), license)
|
45
|
-
dest_dir = File.join(
|
46
|
-
tmpdir(:release), 'usr', 'share', 'licenses', name
|
47
|
-
)
|
48
|
-
dest_file = File.join(dest_dir, 'LICENSE')
|
49
|
-
FileUtils.mkdir_p dest_dir
|
50
|
-
FileUtils.cp src_file, dest_file
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
|
-
Contract None => nil
|
55
|
-
def make_tarball!
|
56
|
-
Dir.chdir(tmpdir(:release)) do
|
57
|
-
run_local "tar -czvf #{tmpfile(:tarball)} *"
|
58
|
-
end
|
59
|
-
nil
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
data/lib/pkgforge/testdsl.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module PkgForge
|
4
|
-
##
|
5
|
-
# Test engine
|
6
|
-
class TestDSL
|
7
|
-
include Contracts::Core
|
8
|
-
include Contracts::Builtin
|
9
|
-
|
10
|
-
Contract PkgForge::Forge => nil
|
11
|
-
def initialize(forge)
|
12
|
-
@forge = forge
|
13
|
-
nil
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
Contract Or[String, Array], Or[Hash[String => String], {}, nil] => nil
|
19
|
-
def run(cmd, env = {})
|
20
|
-
cmd.unshift('/usr/bin/env') if cmd.is_a? Array
|
21
|
-
cmd << ';' if cmd.is_a? String
|
22
|
-
env['PATH'] ||= './usr/bin'
|
23
|
-
@forge.test_run(cmd, env)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/pkgforge/versiondsl.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module PkgForge
|
2
|
-
##
|
3
|
-
# Version engine
|
4
|
-
class VersionDSL
|
5
|
-
include Contracts::Core
|
6
|
-
include Contracts::Builtin
|
7
|
-
|
8
|
-
Contract PkgForge::Forge => nil
|
9
|
-
def initialize(forge)
|
10
|
-
@forge = forge
|
11
|
-
nil
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
Contract Maybe[Regexp], Maybe[String] => String
|
17
|
-
def git_tag(regex = nil, replace = '\1')
|
18
|
-
tag = `git describe --tags`.rstrip
|
19
|
-
tag.gsub!(regex, replace) if regex
|
20
|
-
tag
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|