Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

Just extraction #818

Open
wants to merge 56 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c71736a
output folder WiP
thegecko Aug 21, 2017
37a8d3a
gitignore idea
davidhyman Aug 23, 2017
79d208f
common path manipulation tools
davidhyman Aug 23, 2017
b36dcb7
use the generator rather than assertions
davidhyman Aug 23, 2017
97b8d0f
unused variables
davidhyman Aug 23, 2017
e6ed1f6
relative paths for CMakeLists
davidhyman Aug 24, 2017
1826a31
protect paths code from argparser Namespace missing keys
davidhyman Aug 24, 2017
abfeeb2
tidy up installAndBuild
davidhyman Aug 24, 2017
403d6aa
explicit flag for performing a full export (?)
davidhyman Aug 24, 2017
e5e503c
print debug traceback on exception
davidhyman Aug 25, 2017
d317d59
'export mode' added (but broken)
davidhyman Aug 25, 2017
78fbe0b
works for very simple examples.
davidhyman Aug 25, 2017
75792e9
successfully builds `ble` + `deps`
davidhyman Aug 25, 2017
56c3f9b
stop using args namespaces (some more)
davidhyman Aug 29, 2017
0fdbef4
use unittest assertions properly, update for ym->modules
davidhyman Aug 29, 2017
8bb65d6
update docs
davidhyman Aug 29, 2017
7cc282f
toolchain path, build cli clarification
davidhyman Aug 29, 2017
3ce22b2
debugging circle using print statements. great.
davidhyman Aug 29, 2017
0f3e277
in toolchain, force a string replace on toolchain include files
davidhyman Aug 30, 2017
f5fbca1
...
davidhyman Aug 30, 2017
afc8202
toolchain with absolute paths?
davidhyman Aug 30, 2017
fa11631
Revert "toolchain with absolute paths?"
davidhyman Aug 30, 2017
e9d0423
add a dockerfile for testing
davidhyman Aug 30, 2017
7309123
Templated replacement for yotta header files
davidhyman Sep 6, 2017
a4e1722
yotta self reference
davidhyman Sep 7, 2017
b494095
test_debug relpath
davidhyman Sep 7, 2017
fae3e20
tweak template comments
davidhyman Sep 7, 2017
f4098b2
dockerfile updates
davidhyman Sep 8, 2017
4f18ae3
Fixes test_testCustomCMake
davidhyman Sep 12, 2017
a394342
unicode is bad for the environment
davidhyman Sep 13, 2017
baecb75
tweaks for dev docker
davidhyman Sep 14, 2017
f4530a8
clarify depend_subdirs
davidhyman Sep 14, 2017
efb829f
fix add_own_subdirs
davidhyman Sep 14, 2017
d90625c
improve tempfile handling
davidhyman Sep 14, 2017
066b164
add a test for export behaviour
davidhyman Sep 14, 2017
71d683d
python3 print statement
davidhyman Sep 14, 2017
ce7e458
inconsistent docs
davidhyman Sep 14, 2017
4da9861
remove paths & dockerfile for this branch
davidhyman Sep 14, 2017
c235600
circleci: give tox more time
davidhyman Sep 14, 2017
398dbb0
fix for noop test for relative/non-relative paths
davidhyman Sep 14, 2017
2942916
re-add `ym` as a default for backwards-compatibility
davidhyman Sep 14, 2017
28e046e
timeouts on test export subprocess commands
davidhyman Sep 15, 2017
9b61e1a
speculative grep fix
davidhyman Sep 15, 2017
ba14037
fix test_test_subcommand
davidhyman Sep 15, 2017
bed35b8
remove the subprocess32 stuff
davidhyman Sep 15, 2017
0557159
oops, need that bit
davidhyman Sep 15, 2017
da8f188
unused imports
davidhyman Sep 15, 2017
b87ac7f
drop tox timeout
thegecko Sep 15, 2017
a5bed51
revert references to ym
davidhyman Sep 15, 2017
0313a51
tweak export helpstring
davidhyman Sep 15, 2017
6784962
Merge branch 'master' into just_extraction
Sep 15, 2017
caff88d
Add a couple of references to `export` in the docs
davidhyman Sep 18, 2017
e42079f
'vendor_modules' -> 'modules' + black->white list
davidhyman Sep 19, 2017
09cc9a3
i) tidy up after exporting ii) builddir for export closer to top level
davidhyman Sep 19, 2017
e1f1399
Fix for extraneous quotes
Dec 4, 2017
e5e112f
update from master (0.18.4) - cryptography install fixes
davidhyman Jan 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ dist
git-access-testing
github-access-testing
*~
*.idea
.tox
*nosetests.xml
16 changes: 16 additions & 0 deletions docs/reference/buildsystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,19 @@ subdirectory. Within this directory build products are further divided by the
name of the [target](tutorial/targets.html) being built. This makes it safe to
switch between building for different targets without cleaning.


## <a href="#export-builds" name="export-builds">#</a> Exporting Builds

Yotta can export the generated file structure to be later built elsewhere using:

```
yotta build -g -x some/output/path
```

In this case `-g` is used to stop the local compile from happening immediately,
and `-x` copies the build files to the specified directory.

To build and link your project you would then have to run the cmake commands
against that output directory. The generated files use relative paths,
making them portable; for example to send to an independent build server.

2 changes: 2 additions & 0 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Options:
This option is deprecated because it is now the default, unless
`--debug-build` is specified.

* **`--export`, `-x`**: export mode. If flag is set, generates a buildable directory structure at the specified path.

* **`--cmake-generator`, `-G`**: specify the CMake Generator. CMake can generate project files for various editors and IDEs.

* **`name ...`**: one or more modules may be specified, in which case only these
Expand Down
94 changes: 81 additions & 13 deletions yotta/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# standard library modules, , ,
import os
import logging
import shutil


# validate, , validate things, internal
Expand All @@ -16,6 +17,11 @@
from yotta.lib import cmakegen
# Target, , represents an installed target, internal
from yotta.lib import target
# settings, , load and save settings, internal
from yotta.lib import settings
# paths
from yotta.lib import paths
from yotta.lib import fsutils
# install, , install subcommand, internal
from yotta import install
# --config option, , , internal
Expand All @@ -27,6 +33,12 @@ def addOptions(parser, add_build_targets=True):
action='store_true', default=False,
help='Only generate CMakeLists, don\'t run CMake or build'
)
parser.add_argument('-x', '--export', dest='export',
default=False, const=True, nargs='?',
help=(
'Export mode. If flag is set, generates a buildable directory structure at the specified path.'
)
)
parser.add_argument('-r', '--release-build', dest='release_build', action='store_true', default=True)
parser.add_argument('-d', '--debug-build', dest='release_build', action='store_false', default=True)
parser.add_argument('-r0', '--release-no-debug-info-build', dest='release_no_debug_info_build', action='store_true', default=False)
Expand Down Expand Up @@ -57,16 +69,36 @@ def installAndBuild(args, following_args):
If status: is nonzero there was some sort of error. Other properties
are optional, and may not be set if that step was not attempted.
'''
build_status = generate_status = install_status = 0

if not hasattr(args, 'build_targets'):
vars(args)['build_targets'] = []
build_status = 0
generate_status = 0
error = None
args_dict = vars(args)
export_mode_or_path = args_dict.get('export')

if export_mode_or_path:
logging.info('this build will be configured for exporting')
new_modules = settings.getProperty('build', 'vendor_modules_directory') or 'modules'
new_targets = settings.getProperty('build', 'vendor_targets_directory') or 'targets'
new_build_modules = settings.getProperty('build', 'built_modules_directory') or 'modules'
# to save downloading the cached files, copy the old cache
try:
if not os.path.exists(new_modules):
shutil.copytree(paths.Modules_Folder, new_modules)
shutil.copytree(paths.Targets_Folder, new_targets)
except Exception as e:
logging.error(e)
logging.error('failed to use existing cache; rebuilding')

paths.Modules_Folder = new_modules
paths.Targets_Folder = new_targets
paths.BUILT_MODULES_DIR = new_build_modules

args_dict.setdefault('build_targets', [])

if 'test' in args.build_targets:
logging.error('Cannot build "test". Use "yotta test" to run tests.')
return {'status':1}

cwd = os.getcwd()
c = validate.currentDirectoryModule()
if not c:
return {'status':1}
Expand All @@ -83,26 +115,27 @@ def installAndBuild(args, following_args):

# run the install command before building, we need to add some options the
# install command expects to be present to do this:
vars(args)['component'] = None
vars(args)['act_globally'] = False
args_dict['component'] = None
args_dict['act_globally'] = False
if not hasattr(args, 'install_test_deps'):
if 'all_tests' in args.build_targets:
vars(args)['install_test_deps'] = 'all'
args_dict['install_test_deps'] = 'all'
elif not len(args.build_targets):
vars(args)['install_test_deps'] = 'own'
args_dict['install_test_deps'] = 'own'
else:
# If the named build targets include tests from other modules, we
# need to install the deps for those modules. To do this we need to
# be able to tell which module a library belongs to, which is not
# straightforward (especially if there is custom cmake involved).
# That's why this is 'all', and not 'none'.
vars(args)['install_test_deps'] = 'all'
args_dict['install_test_deps'] = 'all'

# install may exit non-zero for non-fatal errors (such as incompatible
# version specs), which it will display
install_status = install.execCommand(args, [])

builddir = os.path.join(cwd, 'build', target.getName())
builddir = os.path.join(os.getcwd(), paths.DEFAULT_BUILD_DIR, target.getName()) if not export_mode_or_path else \
os.path.join(os.getcwd(), paths.DEFAULT_EXPORT_BUILD_RELPATH)

all_deps = c.getDependenciesRecursive(
target = target,
Expand All @@ -126,7 +159,7 @@ def installAndBuild(args, following_args):
logging.debug("config done, merged config: %s", config['merged_config_json'])

script_environment = {
'YOTTA_MERGED_CONFIG_FILE': config['merged_config_json']
'YOTTA_MERGED_CONFIG_FILE': str(config['merged_config_json'])
}
# run pre-generate scripts for all components:
runScriptWithModules(c, all_deps.values(), 'preGenerate', script_environment)
Expand All @@ -140,7 +173,42 @@ def installAndBuild(args, following_args):
# run pre-build scripts for all components:
runScriptWithModules(c, all_deps.values(), 'preBuild', script_environment)

if (not hasattr(args, 'generate_only')) or (not args.generate_only):
if export_mode_or_path and export_mode_or_path is not True:
# includes relative to cwd / project top level
includes = {
'source',
paths.DEFAULT_EXPORT_BUILD_RELPATH,
paths.Modules_Folder,
paths.Targets_Folder,
'yotta-cloud-client', # not sure about whitelisting... where is this coming from?
}

def ignore_on_copy(current_dir, local_paths):
# only at the project root
if current_dir == '.':
# exclude = !include
return [p for p in local_paths if p not in includes]
return []
export_to = os.path.abspath(export_mode_or_path)
logging.info('exporting unbuilt project source and dependencies to %s', export_to)
check = os.path.join(export_to, 'source') # this might be insufficient, or indeed misleading.
if os.path.exists(export_to) and os.listdir(export_to) and not os.path.exists(check):
# as the export can be any path we do a sanity check before calling 'rmRf'
raise Exception(
'Aborting export: directory is not empty and does not look like a previous export'
' (expecting: %s)'
% (check)
)
fsutils.rmRf(export_to)
shutil.copytree(src='.', dst=export_to, ignore=ignore_on_copy)
fsutils.rmRf(builddir)
fsutils.rmRf(paths.Modules_Folder)
fsutils.rmRf(paths.Targets_Folder)

if args_dict.get('generate_only'):
logging.info('skipping build step')
else:
# build in the current directory
error = target.build(
builddir, c, args, release_build=args.release_build,
build_args=following_args, targets=args.build_targets,
Expand Down
1 change: 0 additions & 1 deletion yotta/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ def execCommand(args, following_args):
return 1

fsutils.rmRf(os.path.join(c.path, 'build'))

5 changes: 4 additions & 1 deletion yotta/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

# validate, , validate things, internal
from yotta.lib import validate
# settings, , load and save settings, internal
# paths
from yotta.lib import paths
# --config option, , , internal
from yotta import options

Expand All @@ -33,7 +36,7 @@ def execCommand(args, following_args):
logging.error(error)
return 1

builddir = os.path.join(cwd, 'build', target.getName())
builddir = os.path.join(os.getcwd(), paths.DEFAULT_BUILD_DIR, target.getName())

if args.program is None:
if c.isApplication():
Expand Down
3 changes: 2 additions & 1 deletion yotta/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

# Component, , represents an installed component, internal
from yotta.lib import component
from yotta.lib import paths
# version, , represent versions and specifications, internal
from yotta.lib import version
# validate, , validate various things, internal
Expand Down Expand Up @@ -67,7 +68,7 @@ def yesNo(string):
yesNo.__allowed_message = ' Please reply "Yes", or "No".'

def isBannedName(name):
return name in ('test', 'source', 'include', 'yotta_modules', 'yotta_targets')
return name in ('test', 'source', 'include', paths.Modules_Folder, paths.Targets_Folder)

def notBannedName(s):
if isBannedName(s):
Expand Down
Loading