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