1 # Copyright (c) 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
3 # Permission is hereby granted, free of charge, to any person obtaining a copy
4 # of this software and associated documentation files (the "Software"), to deal
5 # in the Software without restriction, including without limitation the rights
6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 # copies of the Software, and to permit persons to whom the Software is
8 # furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice shall be included in all
11 # copies or substantial portions of the Software.
13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 import lttng_ivc
.settings
as Settings
30 from lttng_ivc
.utils
.utils
import sha256_checksum
31 from lttng_ivc
.utils
.utils
import find_dir
, find_file
33 _logger
= logging
.getLogger('project')
35 class Project(object):
37 def __init__(self
, label
, git_path
, sha1
, tmpdir
):
39 self
.git_path
= git_path
42 """ Custom configure flags in the for of ['-x', 'arg']"""
43 self
.custom_configure_flags
= []
44 ccache
= shutil
.which("ccache")
45 if ccache
is not None:
46 self
.custom_configure_flags
.append("CC={} gcc".format(ccache
))
47 self
.custom_configure_flags
.append("CXX={} g++".format(ccache
))
48 self
.custom_configure_flags
.append("CFLAGS=-g -O0".format(ccache
))
50 """ A collection of Project dependencies """
51 self
.dependencies
= {}
52 # used for project cache and pickle validation
53 self
._immutable
= False
54 self
._py
_file
_checksum
= sha256_checksum(Settings
.project_py_file_location
)
58 self
.isConfigured
= False
59 self
.isInstalled
= False
63 self
.log_path
= os
.path
.join(tmpdir
, "log")
64 self
.source_path
= os
.path
.join(tmpdir
, "source")
65 self
.installation_path
= os
.path
.join(tmpdir
, "install")
67 if os
.path
.isdir(self
.basedir
):
68 # Perform cleanup since it should not happen
69 shutil
.rmtree(self
.basedir
)
71 os
.makedirs(self
.log_path
)
72 os
.makedirs(self
.source_path
)
73 os
.makedirs(self
.installation_path
)
75 self
.special_env_variables
= {}
77 # Init the repo for work
81 def add_special_env_variable(self
, key
, value
):
82 if key
in self
.special_env_variables
:
83 _logger
.warning("{} Special var {} is already defined".format(
85 raise Exception("Multiple definition of a special environment variable")
86 self
.special_env_variables
[key
] = value
88 def get_cppflags(self
):
89 cppflags
= ["-I{}/include".format(self
.installation_path
)]
90 for key
, dep
in self
.dependencies
.items():
91 cppflags
.append(dep
.get_cppflags())
93 return " ".join(cppflags
)
95 def get_ldflags(self
):
96 ldflags
= ["-L{}/lib".format(self
.installation_path
)]
97 for key
, dep
in self
.dependencies
.items():
98 ldflags
.append(dep
.get_ldflags())
99 return " ".join(ldflags
)
101 def get_ld_library_path(self
):
102 library_path
= ["{}/lib".format(self
.installation_path
)]
103 for key
, dep
in self
.dependencies
.items():
104 library_path
.append(dep
.get_ld_library_path())
105 return ":".join(library_path
)
107 def get_bin_path(self
):
108 bin_path
= ["{}/bin".format(self
.installation_path
)]
109 for key
, dep
in self
.dependencies
.items():
110 bin_path
.append(dep
.get_bin_path())
111 return ":".join(bin_path
)
114 """Modify environment to reflect dependency"""
115 env_var
= {"CPPFLAGS": (self
.get_cppflags(), " "),
116 "LDFLAGS": (self
.get_ldflags(), " "),
117 "LD_LIBRARY_PATH": (self
.get_ld_library_path(), ":"),
120 env
= os
.environ
.copy()
122 for var
, value
in self
.special_env_variables
.items():
124 if var
== "LD_LIBRARY_PATH":
125 env
[var
] = ":".join([env
[var
], value
])
126 elif var
== "CPPFLAGS" or var
== "CFLAGS" or var
== "LDFLAGS":
127 env
[var
] = " ".join([env
[var
], value
])
129 _logger
.warning("{} Special var {} is already defined".format(
131 raise Exception("Multiple definition of a special environment variable")
135 for key
, dep
in self
.dependencies
.items():
136 # Extra space just in case
137 for var
, value
in dep
.special_env_variables
.items():
139 # Raise for now since no special cases is known
140 _logger
.warning("{} Special var {} is already defined".format(
142 raise Exception("Multiple definition of a special environment variable")
146 for var
, (value
, delimiter
) in env_var
.items():
150 env
[var
] = delimiter
.join(tmp
)
156 Perform the bootstrap, configuration, build and install the
157 project. Build dependencies if not already built
159 if (self
.isConfigured
and self
.isBuilt
and self
.isInstalled
):
163 raise Exception("Object is immutable. Illegal autobuild")
165 for key
, dep
in self
.dependencies
.items():
168 if self
.isConfigured ^ self
.isBuilt ^ self
.isInstalled
:
169 raise Exception("Project steps where manually triggered. Can't autobuild")
170 _logger
.debug("{} Autobuild configure".format(self
.label
))
173 except subprocess
.CalledProcessError
as e
:
174 _logger
.error("{} Configure failed. See {} for more details.".format(self
.label
, self
.log_path
))
177 _logger
.debug("{} Autobuild build".format(self
.label
))
180 except subprocess
.CalledProcessError
as e
:
181 _logger
.error("{} Build failed. See {} for more details.".format(self
.label
, self
.log_path
))
184 _logger
.debug("{} Autobuild install".format(self
.label
))
187 except subprocess
.CalledProcessError
as e
:
188 _logger
.error("{} Install failed. See {} for more details.".format(self
.label
, self
.log_path
))
191 _logger
.debug("{} Autobuild rpath strip".format(self
.label
))
194 except subprocess
.CalledProcessError
as e
:
195 _logger
.error("{} Rpath stripping failed. See {} for more details.".format(self
.label
, self
.log_path
))
200 raise Exception("Object is immutable. Illegal checkout")
202 repo
= git
.Repo
.clone_from(self
.git_path
, self
.source_path
)
203 commit
= repo
.commit(self
.sha1
)
204 repo
.head
.reference
= commit
205 assert repo
.head
.is_detached
206 repo
.head
.reset(index
=True, working_tree
=True)
210 Bootstap the project. Raise subprocess.CalledProcessError on
214 raise Exception("Object is immutable. Illegal bootstrap")
216 out
= os
.path
.join(self
.log_path
, "bootstrap.out")
217 err
= os
.path
.join(self
.log_path
, "bootstrap.err")
219 os
.chdir(self
.source_path
)
220 with
open(out
, 'w') as stdout
, open(err
, 'w') as stderr
:
221 p
= subprocess
.run(['./bootstrap'], stdout
=stdout
, stderr
=stderr
)
227 Configure the project.
228 Raises subprocess.CalledProcessError on configure error
231 raise Exception("Object is immutable. Illegal configure")
233 # Check that all our dependencies were actually installed
234 for key
, dep
in self
.dependencies
.items():
235 if not dep
.isInstalled
:
236 # TODO: Custom exception here Dependency Error
237 raise Exception("Dependency project flagged as not installed")
239 out
= os
.path
.join(self
.log_path
, "configure.out")
240 err
= os
.path
.join(self
.log_path
, "configure.err")
241 env_file
= os
.path
.join(self
.log_path
, "configure.env")
245 with
open(env_file
, 'w') as tmp
:
246 pprint
.pprint(env
, stream
=tmp
)
248 os
.chdir(self
.source_path
)
249 args
= ['./configure']
250 prefix
= '--prefix={}'.format(self
.installation_path
)
252 args
.extend(self
.custom_configure_flags
)
254 # TODO: log output and add INFO log point
255 with
open(out
, 'w') as stdout
, open(err
, 'w') as stderr
:
256 p
= subprocess
.run(args
, env
=env
, stdout
=stdout
,
259 self
.isConfigured
= True
264 Build the project. Raise subprocess.CalledProcessError on build
268 raise Exception("Object is immutable. Illegal build")
270 out
= os
.path
.join(self
.log_path
, "build.out")
271 err
= os
.path
.join(self
.log_path
, "build.err")
273 os
.chdir(self
.source_path
)
277 # Number of usable cpu
278 # https://docs.python.org/3/library/os.html#os.cpu_count
279 num_cpu
= str(len(os
.sched_getaffinity(0)))
284 # TODO: log output and add INFO log point with args
285 with
open(out
, 'w') as stdout
, open(err
, 'w') as stderr
:
286 p
= subprocess
.run(args
, env
=env
, stdout
=stdout
,
294 Install the project. Raise subprocess.CalledProcessError on
298 raise Exception("Object is immutable. Illegal install")
300 out
= os
.path
.join(self
.log_path
, "install.out")
301 err
= os
.path
.join(self
.log_path
, "install.err")
303 os
.chdir(self
.source_path
)
304 args
= ['make', 'install']
306 # TODO: log output and add INFO log point
307 with
open(out
, 'w') as stdout
, open(err
, 'w') as stderr
:
308 p
= subprocess
.run(args
, env
=self
.get_env(), stdout
=stdout
,
311 self
.isInstalled
= True
314 def rpath_strip(self
):
315 to_strip
= [os
.path
.join(self
.installation_path
, "bin"),
316 os
.path
.join(self
.installation_path
, "lib")]
318 out
= os
.path
.join(self
.log_path
, "rpath-strip.out")
319 err
= os
.path
.join(self
.log_path
, "rpath-strip.err")
321 for path
in to_strip
:
322 for base
, dirs
, files
in os
.walk(path
):
324 abs_path
= os
.path
.abspath(os
.path
.join(base
, tmp
))
325 magic_str
= magic
.from_file(abs_path
)
326 # Skip all non-elf file
327 if "ELF" not in magic_str
.split():
328 with
open(err
, 'a') as stderr
:
329 stderr
.write("{} skip, is not an ELF, file type: {}\n".format(abs_path
, magic_str
))
331 cmd
= ["chrpath", "-d", abs_path
]
332 with
open(out
, 'a') as stdout
, open(err
, 'a') as stderr
:
333 stdout
.write("Running {}\n".format(cmd
))
334 stderr
.write("Running {}\n".format(cmd
))
335 p
= subprocess
.run(cmd
, stdout
=stdout
, stderr
=stderr
)
339 if os
.path
.exists(self
.source_path
):
340 shutil
.rmtree(self
.source_path
)
341 if os
.path
.exists(self
.installation_path
):
342 shutil
.rmtree(self
.installation_path
)
345 class Lttng_modules(Project
):
346 def __init__(self
, label
, git_path
, sha1
, tmpdir
):
347 super(Lttng_modules
, self
).__init
__(label
=label
, git_path
=git_path
,
348 sha1
=sha1
, tmpdir
=tmpdir
)
349 self
.add_special_env_variable("MODPROBE_OPTIONS","-v -d {}".format(self
.installation_path
))
359 raise Exception("Object is immutable. Illegal install")
360 os
.chdir(self
.source_path
)
361 args
= ['make', 'INSTALL_MOD_PATH={}'.format(self
.installation_path
),
363 p
= subprocess
.run(args
, env
=self
.get_env(), stdout
=subprocess
.PIPE
,
364 stderr
=subprocess
.PIPE
)
367 # Perform a local depmod
368 args
= ['depmod', '-b', self
.installation_path
]
369 p
= subprocess
.run(args
, env
=self
.get_env())
371 self
.isInstalled
= True
375 super(Lttng_modules
, self
).autobuild()
376 except subprocess
.CalledProcessError
as e
:
379 def rpath_strip(self
):
383 class Lttng_ust(Project
):
384 def __init__(self
, label
, git_path
, sha1
, tmpdir
):
385 super(Lttng_ust
, self
).__init
__(label
=label
, git_path
=git_path
,
386 sha1
=sha1
, tmpdir
=tmpdir
)
387 self
.custom_configure_flags
.extend(['--disable-man-pages'])
388 self
.custom_configure_flags
.extend(['--enable-python-agent'])
389 self
.custom_configure_flags
.extend(['--enable-java-agent-jul'])
391 jul_path
= os
.path
.join(self
.installation_path
,
392 "share/java/liblttng-ust-agent.jar")
393 classpath
= ":".join([jul_path
, '.'])
394 self
.add_special_env_variable("CLASSPATH", classpath
)
397 super(Lttng_ust
, self
).install()
398 python_path
= find_dir(self
.installation_path
, "lttngust")
400 # Fetch the parent of lttngust folder
401 python_path
= os
.path
.dirname(python_path
)
402 self
.add_special_env_variable("PYTHONPATH", python_path
)
406 class Lttng_tools(Project
):
407 def __init__(self
, label
, git_path
, sha1
, tmpdir
):
408 super(Lttng_tools
, self
).__init
__(label
=label
, git_path
=git_path
,
409 sha1
=sha1
, tmpdir
=tmpdir
)
410 self
.add_special_env_variable("LTTNG_SESSION_CONFIG_XSD_PATH",
411 os
.path
.join(self
.installation_path
, "share/xml/lttng/"))
414 for xsd
in Settings
.mi_xsd_file_name
:
415 mi
= find_file(self
.source_path
, xsd
)
419 raise Exception("MI xsd not found")
423 class Babeltrace(Project
):
This page took 0.076413 seconds and 5 git commands to generate.