Conversation
| 'dirs': [], | ||
| } | ||
| super(EB_MXNet, self).sanity_check_step(custom_paths=custom_paths) | ||
| self.py_ext.sanity_check_step() |
There was a problem hiding this comment.
This one fails:
== 2017-03-14 10:54:04,601 run.py:137 DEBUG run_cmd: running cmd /apps/brussel/broadwell/software/Python/2.7.12-foss-2016b/bin/python -c "import mxnet" (in /svub4/wapoelma/.local/easybuild/software/MXNet/0.9.3-foss-2016b-Python-2.7.12)
== 2017-03-14 10:54:04,601 run.py:162 INFO running cmd: /apps/brussel/broadwell/software/Python/2.7.12-foss-2016b/bin/python -c "import mxnet"
== 2017-03-14 10:54:04,691 run.py:444 DEBUG cmd "/apps/brussel/broadwell/software/Python/2.7.12-foss-2016b/bin/python -c "import mxnet"" exited with exitcode 1 and output:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named mxnet
== 2017-03-14 10:54:04,692 extension.py:163 WARNING Extension: mxnet failed to install, cmd '/apps/brussel/broadwell/software/Python/2.7.12-foss-2016b/bin/python -c "import mxnet"' (stdin: None) output: Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named mxnet
== 2017-03-14 10:54:04,692 extensioneasyblock.py:137 WARNING Sanity check for mxnet failed: mxnet failed to install, cmd '/apps/brussel/broadwell/software/Python/2.7.12-foss-2016b/bin/python -c "import mxnet"' (stdin: None) output: Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named mxnet
== 2017-03-14 10:54:04,692 easyconfig.py:1208 WARNING Unable to resolve template value library(%(ext_name)s) with dict {'nameletterlower': 'm', 'pyshortver': '2.7', 'versionsuffix': '-Python-2.7.12', 'rshortver': '3.3', 'toolchain_name': 'foss', 'namelower': 'mxnet', 'version_minor': '9', 'name': 'MXNet', 'versionprefix': '', 'version_major': '0', 'nameletter': 'M', 'version_major_minor': '0.9', 'pyver': '2.7.12', 'version': '0.9.3', 'rver': '3.3.3', 'toolchain_version': '2016b'}
== 2017-03-14 10:54:04,693 extensioneasyblock.py:114 DEBUG starting sanity check for extension with filter ('R -q --no-save', 'library(%(ext_name)s)')
but it continues nevertheless. The extension works if you load the final module so I'm guessing the issue is that the PYTHONPATH is not set?
There was a problem hiding this comment.
@wpoely86 You need to check the return value of sanity_check_step for extensions, or maybe just call the ones for the extensions first, and then call to super
| txt = super(EB_MXNet, self).make_module_extra(*args, **kwargs) | ||
| txt += self.py_ext.make_module_extra(*args, **kwargs) | ||
| txt += self.r_ext.make_module_extra(*args, **kwargs) | ||
| return txt |
There was a problem hiding this comment.
this gives:
prepend-path CPATH $root/include
prepend-path LD_LIBRARY_PATH $root/lib
prepend-path LIBRARY_PATH $root/lib
prepend-path PATH $root/bin
setenv EBROOTMXNET "$root"
setenv EBVERSIONMXNET "0.9.3"
setenv EBDEVELMXNET "$root/easybuild/MXNet-0.9.3-foss-2016b-Python-2.7.12-easybuild-devel"
setenv EBROOTMXNET "$root"
setenv EBVERSIONMXNET None
setenv EBDEVELMXNET "$root/easybuild/mxnet-None-foss-2016b-Python-2.7.12-easybuild-devel"
prepend-path PYTHONPATH $root/lib/python2.7/site-packages
setenv EBROOTMXNET "$root"
setenv EBVERSIONMXNET None
setenv EBDEVELMXNET "$root/easybuild/mxnet-None-foss-2016b-Python-2.7.12-easybuild-devel"
prepend-path R_LIBS $rootAny way to use the logic from the extensions easyblock to figure out the PYTHONPATH and R_LIBS without have duplicate entries?
There was a problem hiding this comment.
The way you're using it is (clearly) not how it's intended to be used, since make_module_extra also defines $EBROOT* and $EBVERSION*.
You should just extend txt with update statements for $PYTHONPATH and $R_LIBS yourself, we don't have a better way of dealing with that unless we do some refactoring (e.g. flesh out the bit that defines $PYTHONPATH into a separate method that we can call, etc.)
| """Build & Install both Python and R extension""" | ||
| # we start with the python bindings | ||
| self.py_ext.src = os.path.join(self.mxnet_src_dir, "python") | ||
| os.chdir(self.py_ext.src) |
There was a problem hiding this comment.
use change_dir? requires easybuilders/easybuild-framework#2155
| from easybuild.easyblocks.generic.rpackage import RPackage | ||
| from easybuild.framework.easyconfig import CUSTOM | ||
| from easybuild.tools.build_log import EasyBuildError | ||
| from easybuild.tools.filetools import apply_regex_substitutions, copy_file, symlink, write_file, mkdir |
| super(EB_MXNet, self).__init__(*args, **kwargs) | ||
|
|
||
| self.mxnet_src_dir = None | ||
| self.py_ext = PythonPackage(self, {'name': 'mxnet'}) |
There was a problem hiding this comment.
use self.name rather than hardcoding 'mxnet', and also specify version?
| if self.mxnet_src_dir is None: | ||
| raise EasyBuildError("Could not find the MXNet source directory") | ||
|
|
||
| self.log.debug("MXNet dir is: %s", self.mxnet_src_dir) |
There was a problem hiding this comment.
mxnet_dirs = glob.glob(os.path.join(self.builddir, 'mxnet-*'))
if len(mxnet_dirs) == 1:
self.mxnet_src_dir = mxnet_dirs[0]
self.log.debug("MXNet dir is: %s", self.mxnet_src_dir)
else:
raise EasyBuildError("Failed to find/isolate MXNet source directory: %s", mxnet_dirs)| for srcdir in os.listdir(self.builddir): | ||
| if srcdir.startswith("mxnet-"): | ||
| continue | ||
| else: |
There was a problem hiding this comment.
if not srcdir.startswith('mxnet-'):or
if srcdir != os.path.basename(self.mxnet_src_dir):| elif toolchain_blas == 'OpenBLAS': | ||
| blas = "openblas" | ||
| elif toolchain_blas is None: | ||
| # This toolchain has no BLAS library |
There was a problem hiding this comment.
this comment is not really needed, situation is pretty clear?
|
|
||
| def install_step(self): | ||
| """Specify list of files to copy""" | ||
| self.cfg['files_to_copy'] = ['bin', 'include', 'lib', |
There was a problem hiding this comment.
if files_to_copy would be specified in the easyconfig, you're hard overwriting it here?
There was a problem hiding this comment.
yes. You're the one always telling me to put stuff in the block 😉
There was a problem hiding this comment.
at least issue a warning if files_to_copy was specified and you're hard overwriting it now?
There was a problem hiding this comment.
We don't do that in any of the blocks that have a similar approach?
There was a problem hiding this comment.
Which doesn't mean we shouldn't... ;)
There was a problem hiding this comment.
yeah maybe.
I can extend if that makes you happy
There was a problem hiding this comment.
I would, just to avoid surprises if people try to specify files_to_copy in the easyconfig (which would get bluntly ignored right now)
| # next up, the R bindings | ||
| self.r_ext.src = os.path.join(self.mxnet_src_dir, "R-package") | ||
| try: | ||
| os.chdir(self.r_ext.src) |
| try: | ||
| os.chdir(self.r_ext.src) | ||
| mkdir("inst") | ||
| symlink(os.path.join(self.installdir, "lib"), "inst/libs") |
There was a problem hiding this comment.
be consistent about using os.path.join
| def sanity_check_step(self): | ||
| """Check for main library files for MXNet""" | ||
| custom_paths = { | ||
| 'files': ["lib/libmxnet.%s" % ext for ext in ['a', get_shared_lib_ext()]], |
It's horrible!
* origin/develop: BUG: don't set $FPATH environment variable SAMtools: Modifications for version 1.4: errmod.h and kprobaln.h are mo longer provided nor needed. Fix typo Rename member variable to avoid conflict with identically named member of base class EasyBlock Make unpacking Python extensions optional modified trinity sanity check for versions 2.3 and above simplified code simplified some code fixed missing comma Modified petsc.py to make it more flexible for downloading packages Fix typo Auto-disable quad-precision on ARM/POWER Adding an option 'downloadinstall' that makes the installation directory before the configure, and keep it after removed patch file for FFTW easyblock disables attempts to build libquadmath versions of FFTW on Power disables attempts to build libquadmath versions of FFTW on Power
|
This one is ready @boegel |
| raise EasyBuildError("Failed to find/isolate MXNet source directory: %s", mxnet_dirs) | ||
|
|
||
| for srcdir in os.listdir(self.builddir): | ||
| if not srcdir.startswith('mxnet-'): |
There was a problem hiding this comment.
collapse to:
for srcdir in [d for d in os.listdir(self.builddir) if not d.startswith('mxnet-')]:since you're using os.listdir here, better wrap the whole thing in try/except (IOError, OSError) as err?
| newdir = os.path.join(self.mxnet_src_dir, submodule) | ||
| olddir = os.path.join(self.builddir, srcdir) | ||
| # first remove empty existing directory | ||
| rmtree2(newdir) |
There was a problem hiding this comment.
It's always empty? Else the submodules won't work.
| # first remove empty existing directory | ||
| rmtree2(newdir) | ||
| try: | ||
| shutil.move(olddir, newdir) |
There was a problem hiding this comment.
why not just symlink these too like you do for nnvm?
There was a problem hiding this comment.
I guess it's a matter of taste? I move because that it what it would look like if you did real git submodules?
There was a problem hiding this comment.
well, ok, but we should be using a filetools function here...
There was a problem hiding this comment.
There isn't one.
Let's not block this PR for that. If we add it we should use it in all blocks.
There was a problem hiding this comment.
I agree to not blocking this PR for it, but then we'll never end up adding it. ;)
| (r"export CXX = g\+\+", r"# \g<0>"), | ||
| (r"(?P<var>ADD_CFLAGS\s*=)\s*$", r"\g<var> %s" % os.environ['CFLAGS']), | ||
| (r"(?P<var>ADD_LDFLAGS\s*=)\s*$", r"\g<var> %s" % os.environ['LDFLAGS']), | ||
| ] |
There was a problem hiding this comment.
use buildopts instead to override these, no need to do runtime patching?
for (var, env_var) in [('CC', 'CC'), ('CXX', 'CXX'), ('ADD_CFLAGS', 'CFLAGS'), ('ADD_LDFLAGS', 'LDFLAGS')]:
self.update.cfg('buildopts', '%s="%s"' % (var, os.getenv(env_var)))There was a problem hiding this comment.
Then you need to patch the build system to respect these. Patching their own config file is the easiest way.
And we need to patch it anyway for other stuff too (see below)
There was a problem hiding this comment.
Howso? You're deriving from MakeCp and not customising the build_step, so this is standard make?
| imkl_version = get_software_version('imkl') | ||
| if LooseVersion(imkl_version) >= LooseVersion('17'): | ||
| regex_subs.append(("USE_MKL2017 = 0", "USE_MKL2017 = 1")) | ||
| regex_subs.append((r"(?P<var>MKLML_ROOT=).*$", r"# \g<var>%s" % os.environ["MKLROOT"])) |
There was a problem hiding this comment.
same here, do this via buildopts?
| symlink(os.path.join(self.installdir, "include"), os.path.join("inst", "include")) | ||
|
|
||
| # MXNet doesn't provide a list of its R dependencies by default | ||
| namespace = """# Export all names |
There was a problem hiding this comment.
this should be a constant defined outside of the class?
|
|
||
| def sanity_check_step(self): | ||
| """Check for main library files for MXNet""" | ||
| # for the extension we are doing the loading of the fake module ourself |
There was a problem hiding this comment.
also mention why you are sanity checking the extensions first?
| self.clean_up_fake_module(fake_mod_data) | ||
|
|
||
| custom_paths = { | ||
| 'files': ["lib/libmxnet.%s" % ext for ext in ['a', get_shared_lib_ext()]], |
There was a problem hiding this comment.
I'd go with
'files': ['lib/libmxnet.a', 'lib/libmxnet.%s' % get_shared_lib_ext()],| """Custom variables for MXNet module.""" | ||
| txt = super(EB_MXNet, self).make_module_extra(*args, **kwargs) | ||
|
|
||
| self.py_ext.set_pylibdirs() |
There was a problem hiding this comment.
hmm, do this right in prepare_step, since it's now being done twice now (when fake module is created, and again when real module is created)
There was a problem hiding this comment.
That's no different then any other Python Extension?
| txt = super(EB_MXNet, self).make_module_extra(*args, **kwargs) | ||
|
|
||
| self.py_ext.set_pylibdirs() | ||
| for path in self.py_ext.all_pylibdirs: |
|
@boegel done |
|
@boegel Can you have another look at this? |
| from easybuild.tools.systemtools import get_shared_lib_ext | ||
|
|
||
| # the namespace file for the R extension | ||
| r_namespace = """# Export all names |
There was a problem hiding this comment.
constants should be all caps, so R_NAMESPACE or MXNET_R_NAMESPACE
|
|
||
| # Import all packages listed as Imports or Depends | ||
| import( | ||
| methods, |
There was a problem hiding this comment.
I'd just make this a single line? There's no big advantage here in spreading this vertically?
There was a problem hiding this comment.
well, pfft, who cares in this case...
Also, I actually find it less readable almost :P
There was a problem hiding this comment.
Indeed, who cares? Let's keep it like it is. Doesn't make any difference
| shutil.move(olddir, newdir) | ||
| except IOError, err: | ||
| raise EasyBuildError("Failed to move %s to %s: %s", olddir, newdir, err) | ||
| except (IOError, OSError) as err: |
| # correctly filled and some mappings are done | ||
| # - Reinstal the exported version | ||
| self.r_ext.run() | ||
| run_cmd("R_LIBS=%s Rscript -e \"require(mxnet); mxnet:::mxnet.export(\\\"R-package\\\")\"" % self.installdir) |
There was a problem hiding this comment.
wrap the cmd in single quotes to avoid the escaping (a least partially)?
There was a problem hiding this comment.
If you really insist but it was a pain to get working and I'm sure this one works.
| raise EasyBuildError("Loading fake module failed: %s", err) | ||
|
|
||
| if not self.py_ext.sanity_check_step(): | ||
| raise EasyBuildError("The sanity check of the Python bindings failed") |
| fullpath = os.path.join(self.installdir, path) | ||
| # only extend $PYTHONPATH with existing, non-empty directories | ||
| if os.path.exists(fullpath) and os.listdir(fullpath): | ||
| txt += self.module_generator.prepend_paths('PYTHONPATH', path) |
There was a problem hiding this comment.
this is just copy-pasting from the PythonPackage easyblock, we should hoist this into a separate method we can just call out to with txt += self.py_ext.prepend_pythonpath() or something?
or can we just all txt += self.py_ext.make_module_extra()?
There was a problem hiding this comment.
tried that. It's copy&pasted for a reason.
| if os.path.exists(fullpath) and os.listdir(fullpath): | ||
| txt += self.module_generator.prepend_paths('PYTHONPATH', path) | ||
|
|
||
| txt += self.module_generator.prepend_paths("R_LIBS", ['']) # prepend R_LIBS with install path |
There was a problem hiding this comment.
same here, call out to self.r_ext.make_module_extra() rather than copy-pasting?
|
tested with easybuilders/easybuild-easyconfigs#4765, good to go, thanks @wpoely86! |
@hajgato this works
It needs #1134To Do:
PYTHONPATHis missing.